mirror of
https://github.com/filecoin-project/slate.git
synced 2024-11-22 21:45:56 +03:00
removing design system
This commit is contained in:
parent
7ae2151fcd
commit
088b9bf2b1
@ -100,12 +100,12 @@ npm run dev
|
||||
- Visit `localhost:1337` in a browser.
|
||||
- You should have 3 terminal screens open unless you don't want real time updates and file upload support.
|
||||
|
||||
## Design System
|
||||
<!-- ## Design System
|
||||
|
||||
Our design system is out of date and could use an update.
|
||||
|
||||
- [Use our components](https://slate.host/_/system)
|
||||
- [Design System Release Repository](https://github.com/filecoin-project/slate-react-system)
|
||||
- [Design System Release Repository](https://github.com/filecoin-project/slate-react-system) -->
|
||||
|
||||
## Developer API
|
||||
|
||||
|
@ -1,825 +0,0 @@
|
||||
import * as THREE from "three";
|
||||
|
||||
export const BufferGeometryUtils = {
|
||||
computeTangents: function (geometry) {
|
||||
geometry.computeTangents();
|
||||
console.warn(
|
||||
"THREE.BufferGeometryUtils: .computeTangents() has been removed. Use BufferGeometry.computeTangents() instead."
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<THREE.BufferGeometry>} geometries
|
||||
* @param {Boolean} useGroups
|
||||
* @return {THREE.BufferGeometry}
|
||||
*/
|
||||
mergeBufferGeometries: function (geometries, useGroups) {
|
||||
var isIndexed = geometries[0].index !== null;
|
||||
|
||||
var attributesUsed = new Set(Object.keys(geometries[0].attributes));
|
||||
var morphAttributesUsed = new Set(Object.keys(geometries[0].morphAttributes));
|
||||
|
||||
var attributes = {};
|
||||
var morphAttributes = {};
|
||||
|
||||
var morphTargetsRelative = geometries[0].morphTargetsRelative;
|
||||
|
||||
var mergedGeometry = new THREE.BufferGeometry();
|
||||
|
||||
var offset = 0;
|
||||
|
||||
for (var i = 0; i < geometries.length; ++i) {
|
||||
var geometry = geometries[i];
|
||||
var attributesCount = 0;
|
||||
|
||||
// ensure that all geometries are indexed, or none
|
||||
|
||||
if (isIndexed !== (geometry.index !== null)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " +
|
||||
i +
|
||||
". All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// gather attributes, exit early if they're different
|
||||
|
||||
for (var name in geometry.attributes) {
|
||||
if (!attributesUsed.has(name)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " +
|
||||
i +
|
||||
'. All geometries must have compatible attributes; make sure "' +
|
||||
name +
|
||||
'" attribute exists among all geometries, or in none of them.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (attributes[name] === undefined) attributes[name] = [];
|
||||
|
||||
attributes[name].push(geometry.attributes[name]);
|
||||
|
||||
attributesCount++;
|
||||
}
|
||||
|
||||
// ensure geometries have the same number of attributes
|
||||
|
||||
if (attributesCount !== attributesUsed.size) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " +
|
||||
i +
|
||||
". Make sure all geometries have the same number of attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// gather morph attributes, exit early if they're different
|
||||
|
||||
if (morphTargetsRelative !== geometry.morphTargetsRelative) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " +
|
||||
i +
|
||||
". .morphTargetsRelative must be consistent throughout all geometries."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
for (var name in geometry.morphAttributes) {
|
||||
if (!morphAttributesUsed.has(name)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " +
|
||||
i +
|
||||
". .morphAttributes must be consistent throughout all geometries."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (morphAttributes[name] === undefined) morphAttributes[name] = [];
|
||||
|
||||
morphAttributes[name].push(geometry.morphAttributes[name]);
|
||||
}
|
||||
|
||||
// gather .userData
|
||||
|
||||
mergedGeometry.userData.mergedUserData = mergedGeometry.userData.mergedUserData || [];
|
||||
mergedGeometry.userData.mergedUserData.push(geometry.userData);
|
||||
|
||||
if (useGroups) {
|
||||
var count;
|
||||
|
||||
if (isIndexed) {
|
||||
count = geometry.index.count;
|
||||
} else if (geometry.attributes.position !== undefined) {
|
||||
count = geometry.attributes.position.count;
|
||||
} else {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " +
|
||||
i +
|
||||
". The geometry must have either an index or a position attribute"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
mergedGeometry.addGroup(offset, count, i);
|
||||
|
||||
offset += count;
|
||||
}
|
||||
}
|
||||
|
||||
// merge indices
|
||||
|
||||
if (isIndexed) {
|
||||
var indexOffset = 0;
|
||||
var mergedIndex = [];
|
||||
|
||||
for (var i = 0; i < geometries.length; ++i) {
|
||||
var index = geometries[i].index;
|
||||
|
||||
for (var j = 0; j < index.count; ++j) {
|
||||
mergedIndex.push(index.getX(j) + indexOffset);
|
||||
}
|
||||
|
||||
indexOffset += geometries[i].attributes.position.count;
|
||||
}
|
||||
|
||||
mergedGeometry.setIndex(mergedIndex);
|
||||
}
|
||||
|
||||
// merge attributes
|
||||
|
||||
for (var name in attributes) {
|
||||
var mergedAttribute = this.mergeBufferAttributes(attributes[name]);
|
||||
|
||||
if (!mergedAttribute) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the " +
|
||||
name +
|
||||
" attribute."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
mergedGeometry.setAttribute(name, mergedAttribute);
|
||||
}
|
||||
|
||||
// merge morph attributes
|
||||
|
||||
for (var name in morphAttributes) {
|
||||
var numMorphTargets = morphAttributes[name][0].length;
|
||||
|
||||
if (numMorphTargets === 0) break;
|
||||
|
||||
mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
|
||||
mergedGeometry.morphAttributes[name] = [];
|
||||
|
||||
for (var i = 0; i < numMorphTargets; ++i) {
|
||||
var morphAttributesToMerge = [];
|
||||
|
||||
for (var j = 0; j < morphAttributes[name].length; ++j) {
|
||||
morphAttributesToMerge.push(morphAttributes[name][j][i]);
|
||||
}
|
||||
|
||||
var mergedMorphAttribute = this.mergeBufferAttributes(morphAttributesToMerge);
|
||||
|
||||
if (!mergedMorphAttribute) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the " +
|
||||
name +
|
||||
" morphAttribute."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
mergedGeometry.morphAttributes[name].push(mergedMorphAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
return mergedGeometry;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<THREE.BufferAttribute>} attributes
|
||||
* @return {THREE.BufferAttribute}
|
||||
*/
|
||||
mergeBufferAttributes: function (attributes) {
|
||||
var TypedArray;
|
||||
var itemSize;
|
||||
var normalized;
|
||||
var arrayLength = 0;
|
||||
|
||||
for (var i = 0; i < attributes.length; ++i) {
|
||||
var attribute = attributes[i];
|
||||
|
||||
if (attribute.isInterleavedBufferAttribute) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. InterleavedBufferAttributes are not supported."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (TypedArray === undefined) TypedArray = attribute.array.constructor;
|
||||
if (TypedArray !== attribute.array.constructor) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (itemSize === undefined) itemSize = attribute.itemSize;
|
||||
if (itemSize !== attribute.itemSize) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (normalized === undefined) normalized = attribute.normalized;
|
||||
if (normalized !== attribute.normalized) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
arrayLength += attribute.array.length;
|
||||
}
|
||||
|
||||
var array = new TypedArray(arrayLength);
|
||||
var offset = 0;
|
||||
|
||||
for (var i = 0; i < attributes.length; ++i) {
|
||||
array.set(attributes[i].array, offset);
|
||||
|
||||
offset += attributes[i].array.length;
|
||||
}
|
||||
|
||||
return new THREE.BufferAttribute(array, itemSize, normalized);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<THREE.BufferAttribute>} attributes
|
||||
* @return {Array<THREE.InterleavedBufferAttribute>}
|
||||
*/
|
||||
interleaveAttributes: function (attributes) {
|
||||
// Interleaves the provided attributes into an InterleavedBuffer and returns
|
||||
// a set of InterleavedBufferAttributes for each attribute
|
||||
var TypedArray;
|
||||
var arrayLength = 0;
|
||||
var stride = 0;
|
||||
|
||||
// calculate the the length and type of the interleavedBuffer
|
||||
for (var i = 0, l = attributes.length; i < l; ++i) {
|
||||
var attribute = attributes[i];
|
||||
|
||||
if (TypedArray === undefined) TypedArray = attribute.array.constructor;
|
||||
if (TypedArray !== attribute.array.constructor) {
|
||||
console.error("AttributeBuffers of different types cannot be interleaved");
|
||||
return null;
|
||||
}
|
||||
|
||||
arrayLength += attribute.array.length;
|
||||
stride += attribute.itemSize;
|
||||
}
|
||||
|
||||
// Create the set of buffer attributes
|
||||
var interleavedBuffer = new THREE.InterleavedBuffer(new TypedArray(arrayLength), stride);
|
||||
var offset = 0;
|
||||
var res = [];
|
||||
var getters = ["getX", "getY", "getZ", "getW"];
|
||||
var setters = ["setX", "setY", "setZ", "setW"];
|
||||
|
||||
for (var j = 0, l = attributes.length; j < l; j++) {
|
||||
var attribute = attributes[j];
|
||||
var itemSize = attribute.itemSize;
|
||||
var count = attribute.count;
|
||||
var iba = new THREE.InterleavedBufferAttribute(
|
||||
interleavedBuffer,
|
||||
itemSize,
|
||||
offset,
|
||||
attribute.normalized
|
||||
);
|
||||
res.push(iba);
|
||||
|
||||
offset += itemSize;
|
||||
|
||||
// Move the data for each attribute into the new interleavedBuffer
|
||||
// at the appropriate offset
|
||||
for (var c = 0; c < count; c++) {
|
||||
for (var k = 0; k < itemSize; k++) {
|
||||
iba[setters[k]](c, attribute[getters[k]](c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<THREE.BufferGeometry>} geometry
|
||||
* @return {number}
|
||||
*/
|
||||
estimateBytesUsed: function (geometry) {
|
||||
// Return the estimated memory used by this geometry in bytes
|
||||
// Calculate using itemSize, count, and BYTES_PER_ELEMENT to account
|
||||
// for InterleavedBufferAttributes.
|
||||
var mem = 0;
|
||||
for (var name in geometry.attributes) {
|
||||
var attr = geometry.getAttribute(name);
|
||||
mem += attr.count * attr.itemSize * attr.array.BYTES_PER_ELEMENT;
|
||||
}
|
||||
|
||||
var indices = geometry.getIndex();
|
||||
mem += indices ? indices.count * indices.itemSize * indices.array.BYTES_PER_ELEMENT : 0;
|
||||
return mem;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {THREE.BufferGeometry} geometry
|
||||
* @param {number} tolerance
|
||||
* @return {THREE.BufferGeometry>}
|
||||
*/
|
||||
mergeVertices: function (geometry, tolerance = 1e-4) {
|
||||
tolerance = Math.max(tolerance, Number.EPSILON);
|
||||
|
||||
// Generate an index buffer if the geometry doesn't have one, or optimize it
|
||||
// if it's already available.
|
||||
var hashToIndex = {};
|
||||
var indices = geometry.getIndex();
|
||||
var positions = geometry.getAttribute("position");
|
||||
var vertexCount = indices ? indices.count : positions.count;
|
||||
|
||||
// next value for triangle indices
|
||||
var nextIndex = 0;
|
||||
|
||||
// attributes and new attribute arrays
|
||||
var attributeNames = Object.keys(geometry.attributes);
|
||||
var attrArrays = {};
|
||||
var morphAttrsArrays = {};
|
||||
var newIndices = [];
|
||||
var getters = ["getX", "getY", "getZ", "getW"];
|
||||
|
||||
// initialize the arrays
|
||||
for (var i = 0, l = attributeNames.length; i < l; i++) {
|
||||
var name = attributeNames[i];
|
||||
|
||||
attrArrays[name] = [];
|
||||
|
||||
var morphAttr = geometry.morphAttributes[name];
|
||||
if (morphAttr) {
|
||||
morphAttrsArrays[name] = new Array(morphAttr.length).fill().map(() => []);
|
||||
}
|
||||
}
|
||||
|
||||
// convert the error tolerance to an amount of decimal places to truncate to
|
||||
var decimalShift = Math.log10(1 / tolerance);
|
||||
var shiftMultiplier = Math.pow(10, decimalShift);
|
||||
for (var i = 0; i < vertexCount; i++) {
|
||||
var index = indices ? indices.getX(i) : i;
|
||||
|
||||
// Generate a hash for the vertex attributes at the current index 'i'
|
||||
var hash = "";
|
||||
for (var j = 0, l = attributeNames.length; j < l; j++) {
|
||||
var name = attributeNames[j];
|
||||
var attribute = geometry.getAttribute(name);
|
||||
var itemSize = attribute.itemSize;
|
||||
|
||||
for (var k = 0; k < itemSize; k++) {
|
||||
// double tilde truncates the decimal value
|
||||
hash += `${~~(attribute[getters[k]](index) * shiftMultiplier)},`;
|
||||
}
|
||||
}
|
||||
|
||||
// Add another reference to the vertex if it's already
|
||||
// used by another index
|
||||
if (hash in hashToIndex) {
|
||||
newIndices.push(hashToIndex[hash]);
|
||||
} else {
|
||||
// copy data to the new index in the attribute arrays
|
||||
for (var j = 0, l = attributeNames.length; j < l; j++) {
|
||||
var name = attributeNames[j];
|
||||
var attribute = geometry.getAttribute(name);
|
||||
var morphAttr = geometry.morphAttributes[name];
|
||||
var itemSize = attribute.itemSize;
|
||||
var newarray = attrArrays[name];
|
||||
var newMorphArrays = morphAttrsArrays[name];
|
||||
|
||||
for (var k = 0; k < itemSize; k++) {
|
||||
var getterFunc = getters[k];
|
||||
newarray.push(attribute[getterFunc](index));
|
||||
|
||||
if (morphAttr) {
|
||||
for (var m = 0, ml = morphAttr.length; m < ml; m++) {
|
||||
newMorphArrays[m].push(morphAttr[m][getterFunc](index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hashToIndex[hash] = nextIndex;
|
||||
newIndices.push(nextIndex);
|
||||
nextIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate typed arrays from new attribute arrays and update
|
||||
// the attributeBuffers
|
||||
const result = geometry.clone();
|
||||
for (var i = 0, l = attributeNames.length; i < l; i++) {
|
||||
var name = attributeNames[i];
|
||||
var oldAttribute = geometry.getAttribute(name);
|
||||
|
||||
var buffer = new oldAttribute.array.constructor(attrArrays[name]);
|
||||
var attribute = new THREE.BufferAttribute(
|
||||
buffer,
|
||||
oldAttribute.itemSize,
|
||||
oldAttribute.normalized
|
||||
);
|
||||
|
||||
result.setAttribute(name, attribute);
|
||||
|
||||
// Update the attribute arrays
|
||||
if (name in morphAttrsArrays) {
|
||||
for (var j = 0; j < morphAttrsArrays[name].length; j++) {
|
||||
var oldMorphAttribute = geometry.morphAttributes[name][j];
|
||||
|
||||
var buffer = new oldMorphAttribute.array.constructor(morphAttrsArrays[name][j]);
|
||||
var morphAttribute = new THREE.BufferAttribute(
|
||||
buffer,
|
||||
oldMorphAttribute.itemSize,
|
||||
oldMorphAttribute.normalized
|
||||
);
|
||||
result.morphAttributes[name][j] = morphAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// indices
|
||||
|
||||
result.setIndex(newIndices);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {THREE.BufferGeometry} geometry
|
||||
* @param {number} drawMode
|
||||
* @return {THREE.BufferGeometry>}
|
||||
*/
|
||||
toTrianglesDrawMode: function (geometry, drawMode) {
|
||||
if (drawMode === THREE.TrianglesDrawMode) {
|
||||
console.warn(
|
||||
"THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."
|
||||
);
|
||||
return geometry;
|
||||
}
|
||||
|
||||
if (drawMode === THREE.TriangleFanDrawMode || drawMode === THREE.TriangleStripDrawMode) {
|
||||
var index = geometry.getIndex();
|
||||
|
||||
// generate index if not present
|
||||
|
||||
if (index === null) {
|
||||
var indices = [];
|
||||
|
||||
var position = geometry.getAttribute("position");
|
||||
|
||||
if (position !== undefined) {
|
||||
for (var i = 0; i < position.count; i++) {
|
||||
indices.push(i);
|
||||
}
|
||||
|
||||
geometry.setIndex(indices);
|
||||
index = geometry.getIndex();
|
||||
} else {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."
|
||||
);
|
||||
return geometry;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var numberOfTriangles = index.count - 2;
|
||||
var newIndices = [];
|
||||
|
||||
if (drawMode === THREE.TriangleFanDrawMode) {
|
||||
// gl.TRIANGLE_FAN
|
||||
|
||||
for (var i = 1; i <= numberOfTriangles; i++) {
|
||||
newIndices.push(index.getX(0));
|
||||
newIndices.push(index.getX(i));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
}
|
||||
} else {
|
||||
// gl.TRIANGLE_STRIP
|
||||
|
||||
for (var i = 0; i < numberOfTriangles; i++) {
|
||||
if (i % 2 === 0) {
|
||||
newIndices.push(index.getX(i));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
newIndices.push(index.getX(i + 2));
|
||||
} else {
|
||||
newIndices.push(index.getX(i + 2));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
newIndices.push(index.getX(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newIndices.length / 3 !== numberOfTriangles) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles."
|
||||
);
|
||||
}
|
||||
|
||||
// build final geometry
|
||||
|
||||
var newGeometry = geometry.clone();
|
||||
newGeometry.setIndex(newIndices);
|
||||
newGeometry.clearGroups();
|
||||
|
||||
return newGeometry;
|
||||
} else {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",
|
||||
drawMode
|
||||
);
|
||||
return geometry;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates the morphed attributes of a morphed/skinned BufferGeometry.
|
||||
* Helpful for Raytracing or Decals.
|
||||
* @param {Mesh | Line | Points} object An instance of Mesh, Line or Points.
|
||||
* @return {Object} An Object with original position/normal attributes and morphed ones.
|
||||
*/
|
||||
computeMorphedAttributes: function (object) {
|
||||
if (object.geometry.isBufferGeometry !== true) {
|
||||
console.error("THREE.BufferGeometryUtils: Geometry is not of type THREE.BufferGeometry.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var _vA = new THREE.Vector3();
|
||||
var _vB = new THREE.Vector3();
|
||||
var _vC = new THREE.Vector3();
|
||||
|
||||
var _tempA = new THREE.Vector3();
|
||||
var _tempB = new THREE.Vector3();
|
||||
var _tempC = new THREE.Vector3();
|
||||
|
||||
var _morphA = new THREE.Vector3();
|
||||
var _morphB = new THREE.Vector3();
|
||||
var _morphC = new THREE.Vector3();
|
||||
|
||||
function _calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
attribute,
|
||||
morphAttribute,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedAttributeArray
|
||||
) {
|
||||
_vA.fromBufferAttribute(attribute, a);
|
||||
_vB.fromBufferAttribute(attribute, b);
|
||||
_vC.fromBufferAttribute(attribute, c);
|
||||
|
||||
var morphInfluences = object.morphTargetInfluences;
|
||||
|
||||
if (material.morphTargets && morphAttribute && morphInfluences) {
|
||||
_morphA.set(0, 0, 0);
|
||||
_morphB.set(0, 0, 0);
|
||||
_morphC.set(0, 0, 0);
|
||||
|
||||
for (var i = 0, il = morphAttribute.length; i < il; i++) {
|
||||
var influence = morphInfluences[i];
|
||||
var morph = morphAttribute[i];
|
||||
|
||||
if (influence === 0) continue;
|
||||
|
||||
_tempA.fromBufferAttribute(morph, a);
|
||||
_tempB.fromBufferAttribute(morph, b);
|
||||
_tempC.fromBufferAttribute(morph, c);
|
||||
|
||||
if (morphTargetsRelative) {
|
||||
_morphA.addScaledVector(_tempA, influence);
|
||||
_morphB.addScaledVector(_tempB, influence);
|
||||
_morphC.addScaledVector(_tempC, influence);
|
||||
} else {
|
||||
_morphA.addScaledVector(_tempA.sub(_vA), influence);
|
||||
_morphB.addScaledVector(_tempB.sub(_vB), influence);
|
||||
_morphC.addScaledVector(_tempC.sub(_vC), influence);
|
||||
}
|
||||
}
|
||||
|
||||
_vA.add(_morphA);
|
||||
_vB.add(_morphB);
|
||||
_vC.add(_morphC);
|
||||
}
|
||||
|
||||
if (object.isSkinnedMesh) {
|
||||
object.boneTransform(a, _vA);
|
||||
object.boneTransform(b, _vB);
|
||||
object.boneTransform(c, _vC);
|
||||
}
|
||||
|
||||
modifiedAttributeArray[a * 3 + 0] = _vA.x;
|
||||
modifiedAttributeArray[a * 3 + 1] = _vA.y;
|
||||
modifiedAttributeArray[a * 3 + 2] = _vA.z;
|
||||
modifiedAttributeArray[b * 3 + 0] = _vB.x;
|
||||
modifiedAttributeArray[b * 3 + 1] = _vB.y;
|
||||
modifiedAttributeArray[b * 3 + 2] = _vB.z;
|
||||
modifiedAttributeArray[c * 3 + 0] = _vC.x;
|
||||
modifiedAttributeArray[c * 3 + 1] = _vC.y;
|
||||
modifiedAttributeArray[c * 3 + 2] = _vC.z;
|
||||
}
|
||||
|
||||
var geometry = object.geometry;
|
||||
var material = object.material;
|
||||
|
||||
var a, b, c;
|
||||
var index = geometry.index;
|
||||
var positionAttribute = geometry.attributes.position;
|
||||
var morphPosition = geometry.morphAttributes.position;
|
||||
var morphTargetsRelative = geometry.morphTargetsRelative;
|
||||
var normalAttribute = geometry.attributes.normal;
|
||||
var morphNormal = geometry.morphAttributes.position;
|
||||
|
||||
var groups = geometry.groups;
|
||||
var drawRange = geometry.drawRange;
|
||||
var i, j, il, jl;
|
||||
var group, groupMaterial;
|
||||
var start, end;
|
||||
|
||||
var modifiedPosition = new Float32Array(positionAttribute.count * positionAttribute.itemSize);
|
||||
var modifiedNormal = new Float32Array(normalAttribute.count * normalAttribute.itemSize);
|
||||
|
||||
if (index !== null) {
|
||||
// indexed buffer geometry
|
||||
|
||||
if (Array.isArray(material)) {
|
||||
for (i = 0, il = groups.length; i < il; i++) {
|
||||
group = groups[i];
|
||||
groupMaterial = material[group.materialIndex];
|
||||
|
||||
start = Math.max(group.start, drawRange.start);
|
||||
end = Math.min(group.start + group.count, drawRange.start + drawRange.count);
|
||||
|
||||
for (j = start, jl = end; j < jl; j += 3) {
|
||||
a = index.getX(j);
|
||||
b = index.getX(j + 1);
|
||||
c = index.getX(j + 2);
|
||||
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start = Math.max(0, drawRange.start);
|
||||
end = Math.min(index.count, drawRange.start + drawRange.count);
|
||||
|
||||
for (i = start, il = end; i < il; i += 3) {
|
||||
a = index.getX(i);
|
||||
b = index.getX(i + 1);
|
||||
c = index.getX(i + 2);
|
||||
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (positionAttribute !== undefined) {
|
||||
// non-indexed buffer geometry
|
||||
|
||||
if (Array.isArray(material)) {
|
||||
for (i = 0, il = groups.length; i < il; i++) {
|
||||
group = groups[i];
|
||||
groupMaterial = material[group.materialIndex];
|
||||
|
||||
start = Math.max(group.start, drawRange.start);
|
||||
end = Math.min(group.start + group.count, drawRange.start + drawRange.count);
|
||||
|
||||
for (j = start, jl = end; j < jl; j += 3) {
|
||||
a = j;
|
||||
b = j + 1;
|
||||
c = j + 2;
|
||||
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start = Math.max(0, drawRange.start);
|
||||
end = Math.min(positionAttribute.count, drawRange.start + drawRange.count);
|
||||
|
||||
for (i = start, il = end; i < il; i += 3) {
|
||||
a = i;
|
||||
b = i + 1;
|
||||
c = i + 2;
|
||||
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var morphedPositionAttribute = new THREE.Float32BufferAttribute(modifiedPosition, 3);
|
||||
var morphedNormalAttribute = new THREE.Float32BufferAttribute(modifiedNormal, 3);
|
||||
|
||||
return {
|
||||
positionAttribute: positionAttribute,
|
||||
normalAttribute: normalAttribute,
|
||||
morphedPositionAttribute: morphedPositionAttribute,
|
||||
morphedNormalAttribute: morphedNormalAttribute,
|
||||
};
|
||||
},
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
||||
const FRAMES_PER_SECOND = 60;
|
||||
const SECOND = 1000;
|
||||
|
||||
export default class AnimationLoop {
|
||||
_subscribers = [];
|
||||
_loopId = null;
|
||||
_timeNow = null;
|
||||
_timeThen = null;
|
||||
|
||||
loop = () => {
|
||||
this._timeNow = Date.now();
|
||||
const timeDelta = this._timeNow - this._timeThen;
|
||||
|
||||
if (timeDelta > SECOND / FRAMES_PER_SECOND) {
|
||||
this._timeThen =
|
||||
this._timeNow - (timeDelta % (SECOND / FRAMES_PER_SECOND));
|
||||
|
||||
this._subscribers.forEach((callback) => {
|
||||
callback.call();
|
||||
});
|
||||
}
|
||||
|
||||
this._loopID = window.requestAnimationFrame(this.loop);
|
||||
};
|
||||
|
||||
start() {
|
||||
this._timeThen = Date.now();
|
||||
if (!this._loopID) {
|
||||
this.loop();
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
this._timeThen = null;
|
||||
this._timeNow = null;
|
||||
window.cancelAnimationFrame(this._loopId);
|
||||
}
|
||||
|
||||
subscribe(callback) {
|
||||
return this._subscribers.push(callback);
|
||||
}
|
||||
|
||||
unsubscribeAll() {
|
||||
this._subscribers = [];
|
||||
}
|
||||
}
|
@ -1,481 +0,0 @@
|
||||
{
|
||||
"points": [
|
||||
{ "lat": 12.5, "lon": 0, "country": "Aruba", "code": "AW" },
|
||||
{ "lat": 33, "lon": 65, "country": "Afghanistan", "code": "AF" },
|
||||
{ "lat": -12.5, "lon": 18.5, "country": "Angola", "code": "AO" },
|
||||
{ "lat": 18.25, "lon": -63.16666666, "country": "Anguilla", "code": "AI" },
|
||||
{ "lat": 60.116667, "lon": 19.9, "country": "Åland Islands", "code": "AX" },
|
||||
{ "lat": 41, "lon": 20, "country": "Albania", "code": "AL" },
|
||||
{ "lat": 42.5, "lon": 1.5, "country": "Andorra", "code": "AD" },
|
||||
{ "lat": 24, "lon": 54, "country": "United Arab Emirates", "code": "AE" },
|
||||
{ "lat": -34, "lon": -64, "country": "Argentina", "code": "AR" },
|
||||
{ "lat": 40, "lon": 45, "country": "Armenia", "code": "AM" },
|
||||
{
|
||||
"lat": -14.33333333,
|
||||
"lon": -170,
|
||||
"country": "American Samoa",
|
||||
"code": "AS"
|
||||
},
|
||||
{ "lat": -90, "lon": 0, "country": "Antarctica", "code": "AQ" },
|
||||
{
|
||||
"lat": -49.25,
|
||||
"lon": 69.167,
|
||||
"country": "French Southern and Antarctic Lands",
|
||||
"code": "TF"
|
||||
},
|
||||
{
|
||||
"lat": 17.05,
|
||||
"lon": -61.8,
|
||||
"country": "Antigua and Barbuda",
|
||||
"code": "AG"
|
||||
},
|
||||
{ "lat": -27, "lon": 133, "country": "Australia", "code": "AU" },
|
||||
{
|
||||
"lat": 47.33333333,
|
||||
"lon": 13.33333333,
|
||||
"country": "Austria",
|
||||
"code": "AT"
|
||||
},
|
||||
{ "lat": 40.5, "lon": 47.5, "country": "Azerbaijan", "code": "AZ" },
|
||||
{ "lat": -3.5, "lon": 30, "country": "Burundi", "code": "BI" },
|
||||
{ "lat": 50.83333333, "lon": 4, "country": "Belgium", "code": "BE" },
|
||||
{ "lat": 9.5, "lon": 2.25, "country": "Benin", "code": "BJ" },
|
||||
{ "lat": 13, "lon": -2, "country": "Burkina Faso", "code": "BF" },
|
||||
{ "lat": 24, "lon": 90, "country": "Bangladesh", "code": "BD" },
|
||||
{ "lat": 43, "lon": 25, "country": "Bulgaria", "code": "BG" },
|
||||
{ "lat": 26, "lon": 50.55, "country": "Bahrain", "code": "BH" },
|
||||
{ "lat": 24.25, "lon": -76, "country": "Bahamas", "code": "BS" },
|
||||
{ "lat": 44, "lon": 18, "country": "Bosnia and Herzegovina", "code": "BA" },
|
||||
{
|
||||
"lat": 18.5,
|
||||
"lon": -63.41666666,
|
||||
"country": "Saint Barthélemy",
|
||||
"code": "BL"
|
||||
},
|
||||
{ "lat": 53, "lon": 28, "country": "Belarus", "code": "BY" },
|
||||
{ "lat": 17.25, "lon": -88.75, "country": "Belize", "code": "BZ" },
|
||||
{ "lat": 32.33333333, "lon": -64.75, "country": "Bermuda", "code": "BM" },
|
||||
{ "lat": -17, "lon": -65, "country": "Bolivia", "code": "BO" },
|
||||
{ "lat": -10, "lon": -55, "country": "Brazil", "code": "BR" },
|
||||
{
|
||||
"lat": 13.16666666,
|
||||
"lon": -59.53333333,
|
||||
"country": "Barbados",
|
||||
"code": "BB"
|
||||
},
|
||||
{ "lat": 4.5, "lon": 114.66666666, "country": "Brunei", "code": "BN" },
|
||||
{ "lat": 27.5, "lon": 90.5, "country": "Bhutan", "code": "BT" },
|
||||
{
|
||||
"lat": -54.43333333,
|
||||
"lon": 3.4,
|
||||
"country": "Bouvet Island",
|
||||
"code": "BV"
|
||||
},
|
||||
{ "lat": -22, "lon": 24, "country": "Botswana", "code": "BW" },
|
||||
{
|
||||
"lat": 7,
|
||||
"lon": 21,
|
||||
"country": "Central African Republic",
|
||||
"code": "CF"
|
||||
},
|
||||
{ "lat": 60, "lon": -95, "country": "Canada", "code": "CA" },
|
||||
{
|
||||
"lat": -12.5,
|
||||
"lon": 96.83333333,
|
||||
"country": "Cocos (Keeling) Islands",
|
||||
"code": "CC"
|
||||
},
|
||||
{ "lat": 47, "lon": 8, "country": "Switzerland", "code": "CH" },
|
||||
{ "lat": -30, "lon": -71, "country": "Chile", "code": "CL" },
|
||||
{ "lat": 35, "lon": 105, "country": "China", "code": "CN" },
|
||||
{ "lat": 8, "lon": -5, "country": "Ivory Coast", "code": "CI" },
|
||||
{ "lat": 6, "lon": 12, "country": "Cameroon", "code": "CM" },
|
||||
{ "lat": 0, "lon": 25, "country": "DR Congo", "code": "CD" },
|
||||
{ "lat": -1, "lon": 15, "country": "Republic of the Congo", "code": "CG" },
|
||||
{
|
||||
"lat": -21.23333333,
|
||||
"lon": -159.76666666,
|
||||
"country": "Cook Islands",
|
||||
"code": "CK"
|
||||
},
|
||||
{ "lat": 4, "lon": -72, "country": "Colombia", "code": "CO" },
|
||||
{ "lat": -12.16666666, "lon": 44.25, "country": "Comoros", "code": "KM" },
|
||||
{ "lat": 16, "lon": -24, "country": "Cape Verde", "code": "CV" },
|
||||
{ "lat": 10, "lon": -84, "country": "Costa Rica", "code": "CR" },
|
||||
{ "lat": 21.5, "lon": -80, "country": "Cuba", "code": "CU" },
|
||||
{ "lat": 12.116667, "lon": -68.933333, "country": "Curaçao", "code": "CW" },
|
||||
{
|
||||
"lat": -10.5,
|
||||
"lon": 105.66666666,
|
||||
"country": "Christmas Island",
|
||||
"code": "CX"
|
||||
},
|
||||
{ "lat": 19.5, "lon": -80.5, "country": "Cayman Islands", "code": "KY" },
|
||||
{ "lat": 35, "lon": 33, "country": "Cyprus", "code": "CY" },
|
||||
{ "lat": 49.75, "lon": 15.5, "country": "Czech Republic", "code": "CZ" },
|
||||
{ "lat": 51, "lon": 9, "country": "Germany", "code": "DE" },
|
||||
{ "lat": 11.5, "lon": 43, "country": "Djibouti", "code": "DJ" },
|
||||
{
|
||||
"lat": 15.41666666,
|
||||
"lon": -61.33333333,
|
||||
"country": "Dominica",
|
||||
"code": "DM"
|
||||
},
|
||||
{ "lat": 56, "lon": 10, "country": "Denmark", "code": "DK" },
|
||||
{
|
||||
"lat": 19,
|
||||
"lon": -70.66666666,
|
||||
"country": "Dominican Republic",
|
||||
"code": "DO"
|
||||
},
|
||||
{ "lat": 28, "lon": 3, "country": "Algeria", "code": "DZ" },
|
||||
{ "lat": -2, "lon": -77.5, "country": "Ecuador", "code": "EC" },
|
||||
{ "lat": 27, "lon": 30, "country": "Egypt", "code": "EG" },
|
||||
{ "lat": 15, "lon": 39, "country": "Eritrea", "code": "ER" },
|
||||
{ "lat": 24.5, "lon": -13, "country": "Western Sahara", "code": "EH" },
|
||||
{ "lat": 40, "lon": -4, "country": "Spain", "code": "ES" },
|
||||
{ "lat": 59, "lon": 26, "country": "Estonia", "code": "EE" },
|
||||
{ "lat": 8, "lon": 38, "country": "Ethiopia", "code": "ET" },
|
||||
{ "lat": 64, "lon": 26, "country": "Finland", "code": "FI" },
|
||||
{ "lat": -18, "lon": 175, "country": "Fiji", "code": "FJ" },
|
||||
{ "lat": -51.75, "lon": -59, "country": "Falkland Islands", "code": "FK" },
|
||||
{ "lat": 46, "lon": 2, "country": "France", "code": "FR" },
|
||||
{ "lat": 62, "lon": -7, "country": "Faroe Islands", "code": "FO" },
|
||||
{ "lat": 6.91666666, "lon": 158.25, "country": "Micronesia", "code": "FM" },
|
||||
{ "lat": -1, "lon": 11.75, "country": "Gabon", "code": "GA" },
|
||||
{ "lat": 54, "lon": -2, "country": "United Kingdom", "code": "GB" },
|
||||
{ "lat": 42, "lon": 43.5, "country": "Georgia", "code": "GE" },
|
||||
{
|
||||
"lat": 49.46666666,
|
||||
"lon": -2.58333333,
|
||||
"country": "Guernsey",
|
||||
"code": "GG"
|
||||
},
|
||||
{ "lat": 8, "lon": -2, "country": "Ghana", "code": "GH" },
|
||||
{ "lat": 36.13333333, "lon": -5.35, "country": "Gibraltar", "code": "GI" },
|
||||
{ "lat": 11, "lon": -10, "country": "Guinea", "code": "GN" },
|
||||
{ "lat": 16.25, "lon": -61.583333, "country": "Guadeloupe", "code": "GP" },
|
||||
{
|
||||
"lat": 13.46666666,
|
||||
"lon": -16.56666666,
|
||||
"country": "Gambia",
|
||||
"code": "GM"
|
||||
},
|
||||
{ "lat": 12, "lon": -15, "country": "Guinea-Bissau", "code": "GW" },
|
||||
{ "lat": 2, "lon": 10, "country": "Equatorial Guinea", "code": "GQ" },
|
||||
{ "lat": 39, "lon": 22, "country": "Greece", "code": "GR" },
|
||||
{
|
||||
"lat": 12.11666666,
|
||||
"lon": -61.66666666,
|
||||
"country": "Grenada",
|
||||
"code": "GD"
|
||||
},
|
||||
{ "lat": 72, "lon": -40, "country": "Greenland", "code": "GL" },
|
||||
{ "lat": 15.5, "lon": -90.25, "country": "Guatemala", "code": "GT" },
|
||||
{ "lat": 4, "lon": -53, "country": "French Guiana", "code": "GF" },
|
||||
{
|
||||
"lat": 13.46666666,
|
||||
"lon": 144.78333333,
|
||||
"country": "Guam",
|
||||
"code": "GU"
|
||||
},
|
||||
{ "lat": 5, "lon": -59, "country": "Guyana", "code": "GY" },
|
||||
{ "lat": 22.267, "lon": 114.188, "country": "Hong Kong", "code": "HK" },
|
||||
{ "lat": 15, "lon": -86.5, "country": "Honduras", "code": "HN" },
|
||||
{ "lat": 45.16666666, "lon": 15.5, "country": "Croatia", "code": "HR" },
|
||||
{ "lat": 19, "lon": -72.41666666, "country": "Haiti", "code": "HT" },
|
||||
{ "lat": 47, "lon": 20, "country": "Hungary", "code": "HU" },
|
||||
{ "lat": -5, "lon": 120, "country": "Indonesia", "code": "ID" },
|
||||
{ "lat": 54.25, "lon": -4.5, "country": "Isle of Man", "code": "IM" },
|
||||
{ "lat": 20, "lon": 77, "country": "India", "code": "IN" },
|
||||
{
|
||||
"lat": -6,
|
||||
"lon": 71.5,
|
||||
"country": "British Indian Ocean Territory",
|
||||
"code": "IO"
|
||||
},
|
||||
{ "lat": 53, "lon": -8, "country": "Ireland", "code": "IE" },
|
||||
{ "lat": 32, "lon": 53, "country": "Iran", "code": "IR" },
|
||||
{ "lat": 33, "lon": 44, "country": "Iraq", "code": "IQ" },
|
||||
{ "lat": 65, "lon": -18, "country": "Iceland", "code": "IS" },
|
||||
{ "lat": 31.47, "lon": 35.13, "country": "Israel", "code": "IL" },
|
||||
{
|
||||
"lat": 42.83333333,
|
||||
"lon": 12.83333333,
|
||||
"country": "Italy",
|
||||
"code": "IT"
|
||||
},
|
||||
{ "lat": 18.25, "lon": -77.5, "country": "Jamaica", "code": "JM" },
|
||||
{ "lat": 49.25, "lon": -2.16666666, "country": "Jersey", "code": "JE" },
|
||||
{ "lat": 31, "lon": 36, "country": "Jordan", "code": "JO" },
|
||||
{ "lat": 36, "lon": 138, "country": "Japan", "code": "JP" },
|
||||
{ "lat": 48, "lon": 68, "country": "Kazakhstan", "code": "KZ" },
|
||||
{ "lat": 1, "lon": 38, "country": "Kenya", "code": "KE" },
|
||||
{ "lat": 41, "lon": 75, "country": "Kyrgyzstan", "code": "KG" },
|
||||
{ "lat": 13, "lon": 105, "country": "Cambodia", "code": "KH" },
|
||||
{ "lat": 1.41666666, "lon": 173, "country": "Kiribati", "code": "KI" },
|
||||
{
|
||||
"lat": 17.33333333,
|
||||
"lon": -62.75,
|
||||
"country": "Saint Kitts and Nevis",
|
||||
"code": "KN"
|
||||
},
|
||||
{ "lat": 37, "lon": 127.5, "country": "South Korea", "code": "KR" },
|
||||
{ "lat": 42.666667, "lon": 21.166667, "country": "Kosovo", "code": "XK" },
|
||||
{ "lat": 29.5, "lon": 45.75, "country": "Kuwait", "code": "KW" },
|
||||
{ "lat": 18, "lon": 105, "country": "Laos", "code": "LA" },
|
||||
{
|
||||
"lat": 33.83333333,
|
||||
"lon": 35.83333333,
|
||||
"country": "Lebanon",
|
||||
"code": "LB"
|
||||
},
|
||||
{ "lat": 6.5, "lon": -9.5, "country": "Liberia", "code": "LR" },
|
||||
{ "lat": 25, "lon": 17, "country": "Libya", "code": "LY" },
|
||||
{
|
||||
"lat": 13.88333333,
|
||||
"lon": -60.96666666,
|
||||
"country": "Saint Lucia",
|
||||
"code": "LC"
|
||||
},
|
||||
{
|
||||
"lat": 47.26666666,
|
||||
"lon": 9.53333333,
|
||||
"country": "Liechtenstein",
|
||||
"code": "LI"
|
||||
},
|
||||
{ "lat": 7, "lon": 81, "country": "Sri Lanka", "code": "LK" },
|
||||
{ "lat": -29.5, "lon": 28.5, "country": "Lesotho", "code": "LS" },
|
||||
{ "lat": 56, "lon": 24, "country": "Lithuania", "code": "LT" },
|
||||
{ "lat": 49.75, "lon": 6.16666666, "country": "Luxembourg", "code": "LU" },
|
||||
{ "lat": 57, "lon": 25, "country": "Latvia", "code": "LV" },
|
||||
{ "lat": 22.16666666, "lon": 113.55, "country": "Macau", "code": "MO" },
|
||||
{
|
||||
"lat": 18.08333333,
|
||||
"lon": -63.95,
|
||||
"country": "Saint Martin",
|
||||
"code": "MF"
|
||||
},
|
||||
{ "lat": 32, "lon": -5, "country": "Morocco", "code": "MA" },
|
||||
{ "lat": 43.73333333, "lon": 7.4, "country": "Monaco", "code": "MC" },
|
||||
{ "lat": 47, "lon": 29, "country": "Moldova", "code": "MD" },
|
||||
{ "lat": -20, "lon": 47, "country": "Madagascar", "code": "MG" },
|
||||
{ "lat": 3.25, "lon": 73, "country": "Maldives", "code": "MV" },
|
||||
{ "lat": 23, "lon": -102, "country": "Mexico", "code": "MX" },
|
||||
{ "lat": 9, "lon": 168, "country": "Marshall Islands", "code": "MH" },
|
||||
{ "lat": 41.83333333, "lon": 22, "country": "Macedonia", "code": "MK" },
|
||||
{ "lat": 17, "lon": -4, "country": "Mali", "code": "ML" },
|
||||
{
|
||||
"lat": 35.83333333,
|
||||
"lon": 14.58333333,
|
||||
"country": "Malta",
|
||||
"code": "MT"
|
||||
},
|
||||
{ "lat": 22, "lon": 98, "country": "Myanmar", "code": "MM" },
|
||||
{ "lat": 42.5, "lon": 19.3, "country": "Montenegro", "code": "ME" },
|
||||
{ "lat": 46, "lon": 105, "country": "Mongolia", "code": "MN" },
|
||||
{
|
||||
"lat": 15.2,
|
||||
"lon": 145.75,
|
||||
"country": "Northern Mariana Islands",
|
||||
"code": "MP"
|
||||
},
|
||||
{ "lat": -18.25, "lon": 35, "country": "Mozambique", "code": "MZ" },
|
||||
{ "lat": 20, "lon": -12, "country": "Mauritania", "code": "MR" },
|
||||
{ "lat": 16.75, "lon": -62.2, "country": "Montserrat", "code": "MS" },
|
||||
{ "lat": 14.666667, "lon": -61, "country": "Martinique", "code": "MQ" },
|
||||
{ "lat": -20.28333333, "lon": 57.55, "country": "Mauritius", "code": "MU" },
|
||||
{ "lat": -13.5, "lon": 34, "country": "Malawi", "code": "MW" },
|
||||
{ "lat": 2.5, "lon": 112.5, "country": "Malaysia", "code": "MY" },
|
||||
{
|
||||
"lat": -12.83333333,
|
||||
"lon": 45.16666666,
|
||||
"country": "Mayotte",
|
||||
"code": "YT"
|
||||
},
|
||||
{ "lat": -22, "lon": 17, "country": "Namibia", "code": "NA" },
|
||||
{ "lat": -21.5, "lon": 165.5, "country": "New Caledonia", "code": "NC" },
|
||||
{ "lat": 16, "lon": 8, "country": "Niger", "code": "NE" },
|
||||
{
|
||||
"lat": -29.03333333,
|
||||
"lon": 167.95,
|
||||
"country": "Norfolk Island",
|
||||
"code": "NF"
|
||||
},
|
||||
{ "lat": 10, "lon": 8, "country": "Nigeria", "code": "NG" },
|
||||
{ "lat": 13, "lon": -85, "country": "Nicaragua", "code": "NI" },
|
||||
{
|
||||
"lat": -19.03333333,
|
||||
"lon": -169.86666666,
|
||||
"country": "Niue",
|
||||
"code": "NU"
|
||||
},
|
||||
{ "lat": 52.5, "lon": 5.75, "country": "Netherlands", "code": "NL" },
|
||||
{ "lat": 62, "lon": 10, "country": "Norway", "code": "NO" },
|
||||
{ "lat": 28, "lon": 84, "country": "Nepal", "code": "NP" },
|
||||
{
|
||||
"lat": -0.53333333,
|
||||
"lon": 166.91666666,
|
||||
"country": "Nauru",
|
||||
"code": "NR"
|
||||
},
|
||||
{ "lat": -41, "lon": 174, "country": "New Zealand", "code": "NZ" },
|
||||
{ "lat": 21, "lon": 57, "country": "Oman", "code": "OM" },
|
||||
{ "lat": 30, "lon": 70, "country": "Pakistan", "code": "PK" },
|
||||
{ "lat": 9, "lon": -80, "country": "Panama", "code": "PA" },
|
||||
{
|
||||
"lat": -25.06666666,
|
||||
"lon": -130.1,
|
||||
"country": "Pitcairn Islands",
|
||||
"code": "PN"
|
||||
},
|
||||
{ "lat": -10, "lon": -76, "country": "Peru", "code": "PE" },
|
||||
{ "lat": 13, "lon": 122, "country": "Philippines", "code": "PH" },
|
||||
{ "lat": 7.5, "lon": 134.5, "country": "Palau", "code": "PW" },
|
||||
{ "lat": -6, "lon": 147, "country": "Papua New Guinea", "code": "PG" },
|
||||
{ "lat": 52, "lon": 20, "country": "Poland", "code": "PL" },
|
||||
{ "lat": 18.25, "lon": -66.5, "country": "Puerto Rico", "code": "PR" },
|
||||
{ "lat": 40, "lon": 127, "country": "North Korea", "code": "KP" },
|
||||
{ "lat": 39.5, "lon": -8, "country": "Portugal", "code": "PT" },
|
||||
{ "lat": -23, "lon": -58, "country": "Paraguay", "code": "PY" },
|
||||
{ "lat": 31.9, "lon": 35.2, "country": "Palestine", "code": "PS" },
|
||||
{ "lat": -15, "lon": -140, "country": "French Polynesia", "code": "PF" },
|
||||
{ "lat": 25.5, "lon": 51.25, "country": "Qatar", "code": "QA" },
|
||||
{ "lat": -21.15, "lon": 55.5, "country": "Réunion", "code": "RE" },
|
||||
{ "lat": 46, "lon": 25, "country": "Romania", "code": "RO" },
|
||||
{ "lat": 60, "lon": 100, "country": "Russia", "code": "RU" },
|
||||
{ "lat": -2, "lon": 30, "country": "Rwanda", "code": "RW" },
|
||||
{ "lat": 25, "lon": 45, "country": "Saudi Arabia", "code": "SA" },
|
||||
{ "lat": 15, "lon": 30, "country": "Sudan", "code": "SD" },
|
||||
{ "lat": 14, "lon": -14, "country": "Senegal", "code": "SN" },
|
||||
{ "lat": 1.36666666, "lon": 103.8, "country": "Singapore", "code": "SG" },
|
||||
{ "lat": -54.5, "lon": -37, "country": "South Georgia", "code": "GS" },
|
||||
{ "lat": 78, "lon": 20, "country": "Svalbard and Jan Mayen", "code": "SJ" },
|
||||
{ "lat": -8, "lon": 159, "country": "Solomon Islands", "code": "SB" },
|
||||
{ "lat": 8.5, "lon": -11.5, "country": "Sierra Leone", "code": "SL" },
|
||||
{
|
||||
"lat": 13.83333333,
|
||||
"lon": -88.91666666,
|
||||
"country": "El Salvador",
|
||||
"code": "SV"
|
||||
},
|
||||
{
|
||||
"lat": 43.76666666,
|
||||
"lon": 12.41666666,
|
||||
"country": "San Marino",
|
||||
"code": "SM"
|
||||
},
|
||||
{ "lat": 10, "lon": 49, "country": "Somalia", "code": "SO" },
|
||||
{
|
||||
"lat": 46.83333333,
|
||||
"lon": -56.33333333,
|
||||
"country": "Saint Pierre and Miquelon",
|
||||
"code": "PM"
|
||||
},
|
||||
{ "lat": 44, "lon": 21, "country": "Serbia", "code": "RS" },
|
||||
{ "lat": 7, "lon": 30, "country": "South Sudan", "code": "SS" },
|
||||
{ "lat": 1, "lon": 7, "country": "São Tomé and Príncipe", "code": "ST" },
|
||||
{ "lat": 4, "lon": -56, "country": "Suriname", "code": "SR" },
|
||||
{ "lat": 48.66666666, "lon": 19.5, "country": "Slovakia", "code": "SK" },
|
||||
{
|
||||
"lat": 46.11666666,
|
||||
"lon": 14.81666666,
|
||||
"country": "Slovenia",
|
||||
"code": "SI"
|
||||
},
|
||||
{ "lat": 62, "lon": 15, "country": "Sweden", "code": "SE" },
|
||||
{ "lat": -26.5, "lon": 31.5, "country": "Swaziland", "code": "SZ" },
|
||||
{
|
||||
"lat": 18.033333,
|
||||
"lon": -63.05,
|
||||
"country": "Sint Maarten",
|
||||
"code": "SX"
|
||||
},
|
||||
{
|
||||
"lat": -4.58333333,
|
||||
"lon": 55.66666666,
|
||||
"country": "Seychelles",
|
||||
"code": "SC"
|
||||
},
|
||||
{ "lat": 35, "lon": 38, "country": "Syria", "code": "SY" },
|
||||
{
|
||||
"lat": 21.75,
|
||||
"lon": -71.58333333,
|
||||
"country": "Turks and Caicos Islands",
|
||||
"code": "TC"
|
||||
},
|
||||
{ "lat": 15, "lon": 19, "country": "Chad", "code": "TD" },
|
||||
{ "lat": 8, "lon": 1.16666666, "country": "Togo", "code": "TG" },
|
||||
{ "lat": 15, "lon": 100, "country": "Thailand", "code": "TH" },
|
||||
{ "lat": 39, "lon": 71, "country": "Tajikistan", "code": "TJ" },
|
||||
{ "lat": -9, "lon": -172, "country": "Tokelau", "code": "TK" },
|
||||
{ "lat": 40, "lon": 60, "country": "Turkmenistan", "code": "TM" },
|
||||
{
|
||||
"lat": -8.83333333,
|
||||
"lon": 125.91666666,
|
||||
"country": "Timor-Leste",
|
||||
"code": "TL"
|
||||
},
|
||||
{ "lat": -20, "lon": -175, "country": "Tonga", "code": "TO" },
|
||||
{ "lat": 11, "lon": -61, "country": "Trinidad and Tobago", "code": "TT" },
|
||||
{ "lat": 34, "lon": 9, "country": "Tunisia", "code": "TN" },
|
||||
{ "lat": 39, "lon": 35, "country": "Turkey", "code": "TR" },
|
||||
{ "lat": -8, "lon": 178, "country": "Tuvalu", "code": "TV" },
|
||||
{ "lat": 23.5, "lon": 121, "country": "Taiwan", "code": "TW" },
|
||||
{ "lat": -6, "lon": 35, "country": "Tanzania", "code": "TZ" },
|
||||
{ "lat": 1, "lon": 32, "country": "Uganda", "code": "UG" },
|
||||
{ "lat": 49, "lon": 32, "country": "Ukraine", "code": "UA" },
|
||||
{
|
||||
"lat": 19.2911437,
|
||||
"lon": 166.618332,
|
||||
"country": "United States Minor Outlying Islands",
|
||||
"code": "UM"
|
||||
},
|
||||
{ "lat": -33, "lon": -56, "country": "Uruguay", "code": "UY" },
|
||||
{ "lat": 38, "lon": -97, "country": "United States", "code": "US" },
|
||||
{ "lat": 41, "lon": 64, "country": "Uzbekistan", "code": "UZ" },
|
||||
{ "lat": 41.9, "lon": 12.45, "country": "Vatican City", "code": "VA" },
|
||||
{
|
||||
"lat": 13.25,
|
||||
"lon": -61.2,
|
||||
"country": "Saint Vincent and the Grenadines",
|
||||
"code": "VC"
|
||||
},
|
||||
{ "lat": 8, "lon": -66, "country": "Venezuela", "code": "VE" },
|
||||
{
|
||||
"lat": 18.431383,
|
||||
"lon": -64.62305,
|
||||
"country": "British Virgin Islands",
|
||||
"code": "VG"
|
||||
},
|
||||
{
|
||||
"lat": 18.35,
|
||||
"lon": -64.933333,
|
||||
"country": "United States Virgin Islands",
|
||||
"code": "VI"
|
||||
},
|
||||
{
|
||||
"lat": 16.16666666,
|
||||
"lon": 107.83333333,
|
||||
"country": "Vietnam",
|
||||
"code": "VN"
|
||||
},
|
||||
{ "lat": -16, "lon": 167, "country": "Vanuatu", "code": "VU" },
|
||||
{
|
||||
"lat": -13.3,
|
||||
"lon": -176.2,
|
||||
"country": "Wallis and Futuna",
|
||||
"code": "WF"
|
||||
},
|
||||
{
|
||||
"lat": -13.58333333,
|
||||
"lon": -172.33333333,
|
||||
"country": "Samoa",
|
||||
"code": "WS"
|
||||
},
|
||||
{ "lat": 15, "lon": 48, "country": "Yemen", "code": "YE" },
|
||||
{ "lat": -29, "lon": 24, "country": "South Africa", "code": "ZA" },
|
||||
{ "lat": -15, "lon": 30, "country": "Zambia", "code": "ZM" },
|
||||
{ "lat": -20, "lon": 30, "country": "Zimbabwe", "code": "ZW" }
|
||||
]
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
import * as THREE from "three";
|
||||
import { Geometry } from "~/common/three/126-geometry";
|
||||
import { BufferGeometryUtils } from "~/common/three/126-buffer-geometry-utils";
|
||||
|
||||
import OrbitControls from "~/common/three/orbital.js";
|
||||
import GlobePoints from "~/common/three/points.json";
|
||||
import CountryPoints from "~/common/three/countries.json";
|
||||
|
||||
const convertFlatCoordsToSphereCoords = ({ globe, x, y }) => {
|
||||
let latitude = ((x - globe.width) / globe.width) * -180;
|
||||
let longitude = ((y - globe.height) / globe.height) * -90;
|
||||
latitude = (latitude * Math.PI) / 180;
|
||||
longitude = (longitude * Math.PI) / 180;
|
||||
const radius = Math.cos(longitude) * globe.radius;
|
||||
|
||||
return {
|
||||
x: Math.cos(latitude) * radius,
|
||||
y: Math.sin(longitude) * globe.radius,
|
||||
z: Math.sin(latitude) * radius,
|
||||
};
|
||||
};
|
||||
|
||||
const convertLatLonToSphereCoords = ({ globe, lon, lat }) => {
|
||||
let latitude = (-lat * Math.PI) / 180;
|
||||
let longitude = (lon * Math.PI) / 180;
|
||||
const radius = Math.cos(longitude) * globe.radius;
|
||||
|
||||
return {
|
||||
x: Math.cos(latitude) * radius,
|
||||
y: Math.sin(longitude) * globe.radius,
|
||||
z: Math.sin(latitude) * radius,
|
||||
};
|
||||
};
|
||||
|
||||
const getViewportData = (width, height) => {
|
||||
const viewSize = height;
|
||||
const aspectRatio = width / height;
|
||||
|
||||
return {
|
||||
viewSize: viewSize,
|
||||
aspectRatio: aspectRatio,
|
||||
left: (-aspectRatio * viewSize) / 2,
|
||||
right: (aspectRatio * viewSize) / 2,
|
||||
top: viewSize / 2,
|
||||
bottom: viewSize / -2,
|
||||
near: -2048,
|
||||
far: 2048,
|
||||
};
|
||||
};
|
||||
|
||||
export default class GLComponent {
|
||||
constructor(props) {
|
||||
this.state = {
|
||||
mountedNodes: [],
|
||||
width: props.width,
|
||||
height: props.height,
|
||||
scene: undefined,
|
||||
renderer: undefined,
|
||||
container: undefined,
|
||||
camera: undefined,
|
||||
controls: undefined,
|
||||
measurements: undefined,
|
||||
...props,
|
||||
};
|
||||
}
|
||||
|
||||
setState(newProps) {
|
||||
this.state = { ...this.state, ...newProps };
|
||||
}
|
||||
|
||||
unmount() {
|
||||
this.state.mountedNodes = null;
|
||||
this.state.width = null;
|
||||
this.state.height = null;
|
||||
this.state.scene = null;
|
||||
this.state.renderer = null;
|
||||
this.state.container = null;
|
||||
this.state.camera = null;
|
||||
this.state.controls = null;
|
||||
this.state.measurements = null;
|
||||
this.render = () => {
|
||||
console.log("Error: If this is getting called, that is bad.");
|
||||
};
|
||||
}
|
||||
|
||||
async mount() {
|
||||
this.state.renderer = new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
alpha: true,
|
||||
});
|
||||
this.state.renderer.shadowMap.enabled = true;
|
||||
this.state.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||
this.state.renderer.physicallyBasedShading = true;
|
||||
this.state.renderer.setClearColor(0x000000, 0);
|
||||
this.state.renderer.setPixelRatio(window.devicePixelRatio);
|
||||
this.state.renderer.setSize(this.state.width, this.state.height);
|
||||
this.state.scene = new THREE.Scene();
|
||||
this.state.container.appendChild(this.state.renderer.domElement);
|
||||
|
||||
const viewport = getViewportData(this.state.width, this.state.height);
|
||||
|
||||
this.state.camera = new THREE.OrthographicCamera(
|
||||
viewport.left,
|
||||
viewport.right,
|
||||
viewport.top,
|
||||
viewport.bottom,
|
||||
viewport.near,
|
||||
viewport.far
|
||||
);
|
||||
|
||||
this.state.camera.position.x = 0.2;
|
||||
this.state.camera.position.y = 0.25;
|
||||
this.state.camera.position.z = 0.2;
|
||||
|
||||
this.state.controls = new OrbitControls(this.state.camera, this.state.renderer.domElement);
|
||||
|
||||
const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x888888, 0.9);
|
||||
this.state.scene.add(hemisphereLight);
|
||||
|
||||
const ambientLight = new THREE.AmbientLight(0x888888, 0.7);
|
||||
this.state.scene.add(ambientLight);
|
||||
}
|
||||
|
||||
firstRender() {
|
||||
const pointGeometry = new THREE.SphereGeometry(2, 1, 1);
|
||||
const pointMaterial = new THREE.MeshBasicMaterial({
|
||||
color: "#0047FF",
|
||||
});
|
||||
|
||||
let { points } = GlobePoints;
|
||||
for (let point of points) {
|
||||
const { x, y, z } = convertFlatCoordsToSphereCoords({
|
||||
x: point.x,
|
||||
y: point.y,
|
||||
globe: { radius: 188, width: 4098 / 2, height: 1968 / 2 },
|
||||
});
|
||||
|
||||
pointGeometry.translate(x, y, z);
|
||||
pointGeometry.translate(-x, -y, -z);
|
||||
}
|
||||
|
||||
const globeShape = new THREE.Mesh(pointGeometry, pointMaterial);
|
||||
this.state.mountedNodes.push(globeShape);
|
||||
this.state.scene.add(globeShape);
|
||||
|
||||
if (this.state.countries) {
|
||||
const pointCountryGeometry = new THREE.SphereGeometry(4, 7, 7);
|
||||
const countryMaterial = new THREE.MeshBasicMaterial({
|
||||
color: "black",
|
||||
});
|
||||
|
||||
points = CountryPoints.points;
|
||||
for (let point of points) {
|
||||
const { x, y, z } = convertLatLonToSphereCoords({
|
||||
lat: point.lon,
|
||||
lon: point.lat,
|
||||
globe: { radius: 188, width: 4098 / 2, height: 1968 / 2 },
|
||||
});
|
||||
|
||||
pointCountryGeometry.translate(x, y, z);
|
||||
pointCountryGeometry.translate(-x, -y, -z);
|
||||
}
|
||||
|
||||
const countryShape = new THREE.Mesh(pointCountryGeometry, countryMaterial);
|
||||
this.state.mountedNodes.push(countryShape);
|
||||
this.state.scene.add(countryShape);
|
||||
}
|
||||
}
|
||||
|
||||
axis = new THREE.Vector3(0, 1, 0).normalize();
|
||||
|
||||
render() {
|
||||
this.state.mountedNodes.forEach((n) => {
|
||||
const object = this.state.scene.getObjectById(n.id);
|
||||
object.rotateOnAxis(this.axis, Math.PI * 0.001);
|
||||
});
|
||||
|
||||
this.state.renderer.render(this.state.scene, this.state.camera);
|
||||
}
|
||||
}
|
@ -1,912 +0,0 @@
|
||||
import {
|
||||
Vector3,
|
||||
MOUSE,
|
||||
Quaternion,
|
||||
Spherical,
|
||||
Vector2,
|
||||
EventDispatcher,
|
||||
} from "three";
|
||||
|
||||
/**
|
||||
* @author qiao / https://github.com/qiao
|
||||
* @author mrdoob / http://mrdoob.com
|
||||
* @author alteredq / http://alteredqualia.com/
|
||||
* @author WestLangley / http://github.com/WestLangley
|
||||
* @author erich666 / http://erichaines.com
|
||||
*/
|
||||
|
||||
class OrbitControls extends EventDispatcher {
|
||||
constructor(object, domElement) {
|
||||
super();
|
||||
|
||||
this.object = object;
|
||||
|
||||
this.domElement = domElement !== undefined ? domElement : document;
|
||||
|
||||
// Set to false to disable this control
|
||||
this.enabled = true;
|
||||
|
||||
// "target" sets the location of focus, where the object orbits around
|
||||
this.target = new Vector3();
|
||||
|
||||
// How far you can dolly in and out ( PerspectiveCamera only )
|
||||
this.minDistance = 0;
|
||||
this.maxDistance = Infinity;
|
||||
|
||||
// How far you can zoom in and out ( OrthographicCamera only )
|
||||
this.minZoom = 0;
|
||||
this.maxZoom = Infinity;
|
||||
|
||||
// How far you can orbit vertically, upper and lower limits.
|
||||
// Range is 0 to Math.PI radians.
|
||||
this.minPolarAngle = 0; // radians
|
||||
this.maxPolarAngle = Math.PI; // radians
|
||||
|
||||
// How far you can orbit horizontally, upper and lower limits.
|
||||
// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
|
||||
this.minAzimuthAngle = -Infinity; // radians
|
||||
this.maxAzimuthAngle = Infinity; // radians
|
||||
|
||||
// Set to true to enable damping (inertia)
|
||||
// If damping is enabled, you must call controls.update() in your animation loop
|
||||
this.enableDamping = false;
|
||||
this.dampingFactor = 0.25;
|
||||
|
||||
// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
|
||||
// Set to false to disable zooming
|
||||
this.enableZoom = false;
|
||||
this.zoomSpeed = 1.0;
|
||||
|
||||
// Set to false to disable rotating
|
||||
this.enableRotate = true;
|
||||
this.rotateSpeed = 1.0;
|
||||
|
||||
// Set to false to disable panning
|
||||
this.enablePan = false;
|
||||
this.keyPanSpeed = 7.0; // pixels moved per arrow key push
|
||||
|
||||
// Set to true to automatically rotate around the target
|
||||
// If auto-rotate is enabled, you must call controls.update() in your animation loop
|
||||
this.autoRotate = false;
|
||||
this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
|
||||
|
||||
// Set to false to disable use of the keys
|
||||
this.enableKeys = true;
|
||||
|
||||
// The four arrow keys
|
||||
this.keys = {
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
BOTTOM: 40,
|
||||
};
|
||||
|
||||
// Mouse buttons
|
||||
this.mouseButtons = {
|
||||
ORBIT: MOUSE.LEFT,
|
||||
ZOOM: MOUSE.MIDDLE,
|
||||
PAN: MOUSE.RIGHT,
|
||||
};
|
||||
|
||||
// for reset
|
||||
this.target0 = this.target.clone();
|
||||
this.position0 = this.object.position.clone();
|
||||
this.zoom0 = this.object.zoom;
|
||||
|
||||
//
|
||||
// public methods
|
||||
//
|
||||
|
||||
this.getPolarAngle = () => spherical.phi;
|
||||
|
||||
this.getAzimuthalAngle = () => spherical.theta;
|
||||
|
||||
this.reset = function() {
|
||||
scope.target.copy(scope.target0);
|
||||
scope.object.position.copy(scope.position0);
|
||||
scope.object.zoom = scope.zoom0;
|
||||
|
||||
scope.object.updateProjectionMatrix();
|
||||
scope.dispatchEvent(changeEvent);
|
||||
|
||||
scope.update();
|
||||
|
||||
state = STATE.NONE;
|
||||
};
|
||||
|
||||
// this method is exposed, but perhaps it would be better if we can make it private...
|
||||
this.update = (function() {
|
||||
var offset = new Vector3();
|
||||
|
||||
// so camera.up is the orbit axis
|
||||
var quat = new Quaternion().setFromUnitVectors(
|
||||
object.up,
|
||||
new Vector3(0, 1, 0)
|
||||
);
|
||||
var quatInverse = quat.clone().inverse();
|
||||
|
||||
var lastPosition = new Vector3();
|
||||
var lastQuaternion = new Quaternion();
|
||||
|
||||
return function update() {
|
||||
var position = scope.object.position;
|
||||
|
||||
offset.copy(position).sub(scope.target);
|
||||
|
||||
// rotate offset to "y-axis-is-up" space
|
||||
offset.applyQuaternion(quat);
|
||||
|
||||
// angle from z-axis around y-axis
|
||||
spherical.setFromVector3(offset);
|
||||
|
||||
if (scope.autoRotate && state === STATE.NONE) {
|
||||
rotateLeft(getAutoRotationAngle());
|
||||
}
|
||||
|
||||
spherical.theta += sphericalDelta.theta;
|
||||
spherical.phi += sphericalDelta.phi;
|
||||
|
||||
// restrict theta to be between desired limits
|
||||
spherical.theta = Math.max(
|
||||
scope.minAzimuthAngle,
|
||||
Math.min(scope.maxAzimuthAngle, spherical.theta)
|
||||
);
|
||||
|
||||
// restrict phi to be between desired limits
|
||||
spherical.phi = Math.max(
|
||||
scope.minPolarAngle,
|
||||
Math.min(scope.maxPolarAngle, spherical.phi)
|
||||
);
|
||||
|
||||
spherical.makeSafe();
|
||||
|
||||
spherical.radius *= scale;
|
||||
|
||||
// restrict radius to be between desired limits
|
||||
spherical.radius = Math.max(
|
||||
scope.minDistance,
|
||||
Math.min(scope.maxDistance, spherical.radius)
|
||||
);
|
||||
|
||||
// move target to panned location
|
||||
scope.target.add(panOffset);
|
||||
|
||||
offset.setFromSpherical(spherical);
|
||||
|
||||
// rotate offset back to "camera-up-vector-is-up" space
|
||||
offset.applyQuaternion(quatInverse);
|
||||
|
||||
position.copy(scope.target).add(offset);
|
||||
|
||||
scope.object.lookAt(scope.target);
|
||||
|
||||
if (scope.enableDamping === true) {
|
||||
sphericalDelta.theta *= 1 - scope.dampingFactor;
|
||||
sphericalDelta.phi *= 1 - scope.dampingFactor;
|
||||
} else {
|
||||
sphericalDelta.set(0, 0, 0);
|
||||
}
|
||||
|
||||
scale = 1;
|
||||
panOffset.set(0, 0, 0);
|
||||
|
||||
// update condition is:
|
||||
// min(camera displacement, camera rotation in radians)^2 > EPS
|
||||
// using small-angle approximation cos(x/2) = 1 - x^2 / 8
|
||||
|
||||
if (
|
||||
zoomChanged ||
|
||||
lastPosition.distanceToSquared(scope.object.position) > EPS ||
|
||||
8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS
|
||||
) {
|
||||
scope.dispatchEvent(changeEvent);
|
||||
|
||||
lastPosition.copy(scope.object.position);
|
||||
lastQuaternion.copy(scope.object.quaternion);
|
||||
zoomChanged = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
})();
|
||||
|
||||
this.dispose = function() {
|
||||
scope.domElement.removeEventListener("contextmenu", onContextMenu, false);
|
||||
scope.domElement.removeEventListener("mousedown", onMouseDown, false);
|
||||
scope.domElement.removeEventListener("wheel", onMouseWheel, false);
|
||||
|
||||
scope.domElement.removeEventListener("touchstart", onTouchStart, false);
|
||||
scope.domElement.removeEventListener("touchend", onTouchEnd, false);
|
||||
scope.domElement.removeEventListener("touchmove", onTouchMove, false);
|
||||
|
||||
document.removeEventListener("mousemove", onMouseMove, false);
|
||||
document.removeEventListener("mouseup", onMouseUp, false);
|
||||
|
||||
window.removeEventListener("keydown", onKeyDown, false);
|
||||
|
||||
// scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
|
||||
};
|
||||
|
||||
//
|
||||
// internals
|
||||
//
|
||||
|
||||
var scope = this;
|
||||
|
||||
var changeEvent = {
|
||||
type: "change",
|
||||
};
|
||||
var startEvent = {
|
||||
type: "start",
|
||||
};
|
||||
var endEvent = {
|
||||
type: "end",
|
||||
};
|
||||
|
||||
var STATE = {
|
||||
NONE: -1,
|
||||
ROTATE: 0,
|
||||
DOLLY: 1,
|
||||
PAN: 2,
|
||||
TOUCH_ROTATE: 3,
|
||||
TOUCH_DOLLY: 4,
|
||||
TOUCH_PAN: 5,
|
||||
};
|
||||
|
||||
var state = STATE.NONE;
|
||||
|
||||
var EPS = 0.000001;
|
||||
|
||||
// current position in spherical coordinates
|
||||
var spherical = new Spherical();
|
||||
var sphericalDelta = new Spherical();
|
||||
|
||||
var scale = 1;
|
||||
var panOffset = new Vector3();
|
||||
var zoomChanged = false;
|
||||
|
||||
var rotateStart = new Vector2();
|
||||
var rotateEnd = new Vector2();
|
||||
var rotateDelta = new Vector2();
|
||||
|
||||
var panStart = new Vector2();
|
||||
var panEnd = new Vector2();
|
||||
var panDelta = new Vector2();
|
||||
|
||||
var dollyStart = new Vector2();
|
||||
var dollyEnd = new Vector2();
|
||||
var dollyDelta = new Vector2();
|
||||
|
||||
function getAutoRotationAngle() {
|
||||
return ((2 * Math.PI) / 60 / 60) * scope.autoRotateSpeed;
|
||||
}
|
||||
|
||||
function getZoomScale() {
|
||||
return Math.pow(0.95, scope.zoomSpeed);
|
||||
}
|
||||
|
||||
function rotateLeft(angle) {
|
||||
sphericalDelta.theta -= angle;
|
||||
}
|
||||
|
||||
function rotateUp(angle) {
|
||||
sphericalDelta.phi -= angle;
|
||||
}
|
||||
|
||||
var panLeft = (function() {
|
||||
var v = new Vector3();
|
||||
|
||||
return function panLeft(distance, objectMatrix) {
|
||||
v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix
|
||||
v.multiplyScalar(-distance);
|
||||
|
||||
panOffset.add(v);
|
||||
};
|
||||
})();
|
||||
|
||||
var panUp = (function() {
|
||||
var v = new Vector3();
|
||||
|
||||
return function panUp(distance, objectMatrix) {
|
||||
v.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix
|
||||
v.multiplyScalar(distance);
|
||||
|
||||
panOffset.add(v);
|
||||
};
|
||||
})();
|
||||
|
||||
// deltaX and deltaY are in pixels; right and down are positive
|
||||
var pan = (function() {
|
||||
var offset = new Vector3();
|
||||
|
||||
return function pan(deltaX, deltaY) {
|
||||
var element =
|
||||
scope.domElement === document
|
||||
? scope.domElement.body
|
||||
: scope.domElement;
|
||||
|
||||
if (Object.getPrototypeOf(scope.object).isPerspectiveCamera) {
|
||||
// perspective
|
||||
var position = scope.object.position;
|
||||
offset.copy(position).sub(scope.target);
|
||||
var targetDistance = offset.length();
|
||||
|
||||
// half of the fov is center to top of screen
|
||||
targetDistance *= Math.tan(
|
||||
((scope.object.fov / 2) * Math.PI) / 180.0
|
||||
);
|
||||
|
||||
// we actually don't use screenWidth, since perspective camera is fixed to screen height
|
||||
panLeft(
|
||||
(2 * deltaX * targetDistance) / element.clientHeight,
|
||||
scope.object.matrix
|
||||
);
|
||||
panUp(
|
||||
(2 * deltaY * targetDistance) / element.clientHeight,
|
||||
scope.object.matrix
|
||||
);
|
||||
} else if (Object.getPrototypeOf(scope.object).isOrthographicCamera) {
|
||||
// orthographic
|
||||
panLeft(
|
||||
(deltaX * (scope.object.right - scope.object.left)) /
|
||||
scope.object.zoom /
|
||||
element.clientWidth,
|
||||
scope.object.matrix
|
||||
);
|
||||
panUp(
|
||||
(deltaY * (scope.object.top - scope.object.bottom)) /
|
||||
scope.object.zoom /
|
||||
element.clientHeight,
|
||||
scope.object.matrix
|
||||
);
|
||||
} else {
|
||||
// camera neither orthographic nor perspective
|
||||
console.warn(
|
||||
"WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."
|
||||
);
|
||||
scope.enablePan = false;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
function dollyIn(dollyScale) {
|
||||
if (Object.getPrototypeOf(scope.object).isPerspectiveCamera) {
|
||||
scale /= dollyScale;
|
||||
} else if (Object.getPrototypeOf(scope.object).isOrthographicCamera) {
|
||||
scope.object.zoom = Math.max(
|
||||
scope.minZoom,
|
||||
Math.min(scope.maxZoom, scope.object.zoom * dollyScale)
|
||||
);
|
||||
scope.object.updateProjectionMatrix();
|
||||
zoomChanged = true;
|
||||
} else {
|
||||
console.warn(
|
||||
"WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."
|
||||
);
|
||||
scope.enableZoom = false;
|
||||
}
|
||||
}
|
||||
|
||||
function dollyOut(dollyScale) {
|
||||
if (Object.getPrototypeOf(scope.object).isPerspectiveCamera) {
|
||||
scale *= dollyScale;
|
||||
} else if (Object.getPrototypeOf(scope.object).isOrthographicCamera) {
|
||||
scope.object.zoom = Math.max(
|
||||
scope.minZoom,
|
||||
Math.min(scope.maxZoom, scope.object.zoom / dollyScale)
|
||||
);
|
||||
scope.object.updateProjectionMatrix();
|
||||
zoomChanged = true;
|
||||
} else {
|
||||
console.warn(
|
||||
"WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."
|
||||
);
|
||||
scope.enableZoom = false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// event callbacks - update the object state
|
||||
//
|
||||
|
||||
function handleMouseDownRotate(event) {
|
||||
// console.log( 'handleMouseDownRotate' );
|
||||
|
||||
rotateStart.set(event.clientX, event.clientY);
|
||||
}
|
||||
|
||||
function handleMouseDownDolly(event) {
|
||||
// console.log( 'handleMouseDownDolly' );
|
||||
|
||||
dollyStart.set(event.clientX, event.clientY);
|
||||
}
|
||||
|
||||
function handleMouseDownPan(event) {
|
||||
// console.log( 'handleMouseDownPan' );
|
||||
|
||||
panStart.set(event.clientX, event.clientY);
|
||||
}
|
||||
|
||||
function handleMouseMoveRotate(event) {
|
||||
// console.log( 'handleMouseMoveRotate' );
|
||||
|
||||
rotateEnd.set(event.clientX, event.clientY);
|
||||
rotateDelta.subVectors(rotateEnd, rotateStart);
|
||||
|
||||
var element =
|
||||
scope.domElement === document
|
||||
? scope.domElement.body
|
||||
: scope.domElement;
|
||||
|
||||
// rotating across whole screen goes 360 degrees around
|
||||
rotateLeft(
|
||||
((2 * Math.PI * rotateDelta.x) / element.clientWidth) *
|
||||
scope.rotateSpeed
|
||||
);
|
||||
|
||||
// rotating up and down along whole screen attempts to go 360, but limited to 180
|
||||
rotateUp(
|
||||
((2 * Math.PI * rotateDelta.y) / element.clientHeight) *
|
||||
scope.rotateSpeed
|
||||
);
|
||||
|
||||
rotateStart.copy(rotateEnd);
|
||||
|
||||
scope.update();
|
||||
}
|
||||
|
||||
function handleMouseMoveDolly(event) {
|
||||
// console.log( 'handleMouseMoveDolly' );
|
||||
|
||||
dollyEnd.set(event.clientX, event.clientY);
|
||||
|
||||
dollyDelta.subVectors(dollyEnd, dollyStart);
|
||||
|
||||
if (dollyDelta.y > 0) {
|
||||
dollyIn(getZoomScale());
|
||||
} else if (dollyDelta.y < 0) {
|
||||
dollyOut(getZoomScale());
|
||||
}
|
||||
|
||||
dollyStart.copy(dollyEnd);
|
||||
|
||||
scope.update();
|
||||
}
|
||||
|
||||
function handleMouseMovePan(event) {
|
||||
// console.log( 'handleMouseMovePan' );
|
||||
|
||||
panEnd.set(event.clientX, event.clientY);
|
||||
|
||||
panDelta.subVectors(panEnd, panStart);
|
||||
|
||||
pan(panDelta.x, panDelta.y);
|
||||
|
||||
panStart.copy(panEnd);
|
||||
|
||||
scope.update();
|
||||
}
|
||||
|
||||
function handleMouseWheel(event) {
|
||||
// console.log( 'handleMouseWheel' );
|
||||
|
||||
if (event.deltaY < 0) {
|
||||
dollyOut(getZoomScale());
|
||||
} else if (event.deltaY > 0) {
|
||||
dollyIn(getZoomScale());
|
||||
}
|
||||
|
||||
scope.update();
|
||||
}
|
||||
|
||||
function handleKeyDown(event) {
|
||||
// console.log( 'handleKeyDown' );
|
||||
|
||||
switch (event.keyCode) {
|
||||
case scope.keys.UP:
|
||||
pan(0, scope.keyPanSpeed);
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
case scope.keys.BOTTOM:
|
||||
pan(0, -scope.keyPanSpeed);
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
case scope.keys.LEFT:
|
||||
pan(scope.keyPanSpeed, 0);
|
||||
scope.update();
|
||||
break;
|
||||
|
||||
case scope.keys.RIGHT:
|
||||
pan(-scope.keyPanSpeed, 0);
|
||||
scope.update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handleTouchStartRotate(event) {
|
||||
// console.log( 'handleTouchStartRotate' );
|
||||
|
||||
rotateStart.set(event.touches[0].pageX, event.touches[0].pageY);
|
||||
}
|
||||
|
||||
function handleTouchStartDolly(event) {
|
||||
// console.log( 'handleTouchStartDolly' );
|
||||
|
||||
var dx = event.touches[0].pageX - event.touches[1].pageX;
|
||||
var dy = event.touches[0].pageY - event.touches[1].pageY;
|
||||
|
||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
dollyStart.set(0, distance);
|
||||
}
|
||||
|
||||
function handleTouchStartPan(event) {
|
||||
// console.log( 'handleTouchStartPan' );
|
||||
|
||||
panStart.set(event.touches[0].pageX, event.touches[0].pageY);
|
||||
}
|
||||
|
||||
function handleTouchMoveRotate(event) {
|
||||
// console.log( 'handleTouchMoveRotate' );
|
||||
|
||||
rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
|
||||
rotateDelta.subVectors(rotateEnd, rotateStart);
|
||||
|
||||
var element =
|
||||
scope.domElement === document
|
||||
? scope.domElement.body
|
||||
: scope.domElement;
|
||||
|
||||
// rotating across whole screen goes 360 degrees around
|
||||
rotateLeft(
|
||||
((2 * Math.PI * rotateDelta.x) / element.clientWidth) *
|
||||
scope.rotateSpeed
|
||||
);
|
||||
|
||||
// rotating up and down along whole screen attempts to go 360, but limited to 180
|
||||
rotateUp(
|
||||
((2 * Math.PI * rotateDelta.y) / element.clientHeight) *
|
||||
scope.rotateSpeed
|
||||
);
|
||||
|
||||
rotateStart.copy(rotateEnd);
|
||||
|
||||
scope.update();
|
||||
}
|
||||
|
||||
function handleTouchMoveDolly(event) {
|
||||
// console.log( 'handleTouchMoveDolly' );
|
||||
|
||||
var dx = event.touches[0].pageX - event.touches[1].pageX;
|
||||
var dy = event.touches[0].pageY - event.touches[1].pageY;
|
||||
|
||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
dollyEnd.set(0, distance);
|
||||
|
||||
dollyDelta.subVectors(dollyEnd, dollyStart);
|
||||
|
||||
if (dollyDelta.y > 0) {
|
||||
dollyOut(getZoomScale());
|
||||
} else if (dollyDelta.y < 0) {
|
||||
dollyIn(getZoomScale());
|
||||
}
|
||||
|
||||
dollyStart.copy(dollyEnd);
|
||||
|
||||
scope.update();
|
||||
}
|
||||
|
||||
function handleTouchMovePan(event) {
|
||||
// console.log( 'handleTouchMovePan' );
|
||||
|
||||
panEnd.set(event.touches[0].pageX, event.touches[0].pageY);
|
||||
|
||||
panDelta.subVectors(panEnd, panStart);
|
||||
|
||||
pan(panDelta.x, panDelta.y);
|
||||
|
||||
panStart.copy(panEnd);
|
||||
|
||||
scope.update();
|
||||
}
|
||||
|
||||
//
|
||||
// event handlers - FSM: listen for events and reset state
|
||||
//
|
||||
|
||||
function onMouseDown(event) {
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (event.button === scope.mouseButtons.ORBIT) {
|
||||
if (scope.enableRotate === false) return;
|
||||
|
||||
handleMouseDownRotate(event);
|
||||
|
||||
state = STATE.ROTATE;
|
||||
} else if (event.button === scope.mouseButtons.ZOOM) {
|
||||
if (scope.enableZoom === false) return;
|
||||
|
||||
handleMouseDownDolly(event);
|
||||
|
||||
state = STATE.DOLLY;
|
||||
} else if (event.button === scope.mouseButtons.PAN) {
|
||||
if (scope.enablePan === false) return;
|
||||
|
||||
handleMouseDownPan(event);
|
||||
|
||||
state = STATE.PAN;
|
||||
}
|
||||
|
||||
if (state !== STATE.NONE) {
|
||||
document.addEventListener("mousemove", onMouseMove, false);
|
||||
document.addEventListener("mouseup", onMouseUp, false);
|
||||
|
||||
scope.dispatchEvent(startEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseMove(event) {
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (state === STATE.ROTATE) {
|
||||
if (scope.enableRotate === false) return;
|
||||
|
||||
handleMouseMoveRotate(event);
|
||||
} else if (state === STATE.DOLLY) {
|
||||
if (scope.enableZoom === false) return;
|
||||
|
||||
handleMouseMoveDolly(event);
|
||||
} else if (state === STATE.PAN) {
|
||||
if (scope.enablePan === false) return;
|
||||
|
||||
handleMouseMovePan(event);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseUp(event) {
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
document.removeEventListener("mousemove", onMouseMove, false);
|
||||
document.removeEventListener("mouseup", onMouseUp, false);
|
||||
|
||||
scope.dispatchEvent(endEvent);
|
||||
|
||||
state = STATE.NONE;
|
||||
}
|
||||
|
||||
function onMouseWheel(event) {
|
||||
if (
|
||||
scope.enabled === false ||
|
||||
scope.enableZoom === false ||
|
||||
(state !== STATE.NONE && state !== STATE.ROTATE)
|
||||
)
|
||||
return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
handleMouseWheel(event);
|
||||
|
||||
scope.dispatchEvent(startEvent); // not sure why these are here...
|
||||
scope.dispatchEvent(endEvent);
|
||||
}
|
||||
|
||||
function onKeyDown(event) {
|
||||
if (
|
||||
scope.enabled === false ||
|
||||
scope.enableKeys === false ||
|
||||
scope.enablePan === false
|
||||
)
|
||||
return;
|
||||
|
||||
handleKeyDown(event);
|
||||
}
|
||||
|
||||
function onTouchStart(event) {
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
switch (event.touches.length) {
|
||||
case 1: // one-fingered touch: rotate
|
||||
if (scope.enableRotate === false) return;
|
||||
|
||||
handleTouchStartRotate(event);
|
||||
|
||||
state = STATE.TOUCH_ROTATE;
|
||||
|
||||
break;
|
||||
|
||||
case 2: // two-fingered touch: dolly
|
||||
if (scope.enableZoom === false) return;
|
||||
|
||||
handleTouchStartDolly(event);
|
||||
|
||||
state = STATE.TOUCH_DOLLY;
|
||||
|
||||
break;
|
||||
|
||||
case 3: // three-fingered touch: pan
|
||||
if (scope.enablePan === false) return;
|
||||
|
||||
handleTouchStartPan(event);
|
||||
|
||||
state = STATE.TOUCH_PAN;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
state = STATE.NONE;
|
||||
}
|
||||
|
||||
if (state !== STATE.NONE) {
|
||||
scope.dispatchEvent(startEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function onTouchMove(event) {
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
switch (event.touches.length) {
|
||||
case 1: // one-fingered touch: rotate
|
||||
if (scope.enableRotate === false) return;
|
||||
if (state !== STATE.TOUCH_ROTATE) return; // is this needed?...
|
||||
|
||||
handleTouchMoveRotate(event);
|
||||
|
||||
break;
|
||||
|
||||
case 2: // two-fingered touch: dolly
|
||||
if (scope.enableZoom === false) return;
|
||||
if (state !== STATE.TOUCH_DOLLY) return; // is this needed?...
|
||||
|
||||
handleTouchMoveDolly(event);
|
||||
|
||||
break;
|
||||
|
||||
case 3: // three-fingered touch: pan
|
||||
if (scope.enablePan === false) return;
|
||||
if (state !== STATE.TOUCH_PAN) return; // is this needed?...
|
||||
|
||||
handleTouchMovePan(event);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
state = STATE.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
function onTouchEnd(event) {
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
scope.dispatchEvent(endEvent);
|
||||
|
||||
state = STATE.NONE;
|
||||
}
|
||||
|
||||
function onContextMenu(event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
scope.domElement.addEventListener("contextmenu", onContextMenu, false);
|
||||
|
||||
scope.domElement.addEventListener("mousedown", onMouseDown, false);
|
||||
scope.domElement.addEventListener("wheel", onMouseWheel, false);
|
||||
|
||||
scope.domElement.addEventListener("touchstart", onTouchStart, false);
|
||||
scope.domElement.addEventListener("touchend", onTouchEnd, false);
|
||||
scope.domElement.addEventListener("touchmove", onTouchMove, false);
|
||||
|
||||
window.addEventListener("keydown", onKeyDown, false);
|
||||
|
||||
// force an update at start
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
get center() {
|
||||
console.warn("OrbitControls: .center has been renamed to .target");
|
||||
return this.target;
|
||||
}
|
||||
|
||||
// backward compatibility
|
||||
|
||||
get noZoom() {
|
||||
console.warn(
|
||||
"OrbitControls: .noZoom has been deprecated. Use .enableZoom instead."
|
||||
);
|
||||
return !this.enableZoom;
|
||||
}
|
||||
|
||||
set noZoom(value) {
|
||||
console.warn(
|
||||
"OrbitControls: .noZoom has been deprecated. Use .enableZoom instead."
|
||||
);
|
||||
this.enableZoom = !value;
|
||||
}
|
||||
|
||||
get noRotate() {
|
||||
console.warn(
|
||||
"OrbitControls: .noRotate has been deprecated. Use .enableRotate instead."
|
||||
);
|
||||
return !this.enableRotate;
|
||||
}
|
||||
|
||||
set noRotate(value) {
|
||||
console.warn(
|
||||
"OrbitControls: .noRotate has been deprecated. Use .enableRotate instead."
|
||||
);
|
||||
this.enableRotate = !value;
|
||||
}
|
||||
|
||||
get noPan() {
|
||||
console.warn(
|
||||
"OrbitControls: .noPan has been deprecated. Use .enablePan instead."
|
||||
);
|
||||
return !this.enablePan;
|
||||
}
|
||||
|
||||
set noPan(value) {
|
||||
console.warn(
|
||||
"OrbitControls: .noPan has been deprecated. Use .enablePan instead."
|
||||
);
|
||||
this.enablePan = !value;
|
||||
}
|
||||
|
||||
get noKeys() {
|
||||
console.warn(
|
||||
"OrbitControls: .noKeys has been deprecated. Use .enableKeys instead."
|
||||
);
|
||||
return !this.enableKeys;
|
||||
}
|
||||
|
||||
set noKeys(value) {
|
||||
console.warn(
|
||||
"OrbitControls: .noKeys has been deprecated. Use .enableKeys instead."
|
||||
);
|
||||
this.enableKeys = !value;
|
||||
}
|
||||
|
||||
get staticMoving() {
|
||||
console.warn(
|
||||
"OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead."
|
||||
);
|
||||
return !this.enableDamping;
|
||||
}
|
||||
|
||||
set staticMoving(value) {
|
||||
console.warn(
|
||||
"OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead."
|
||||
);
|
||||
this.enableDamping = !value;
|
||||
}
|
||||
|
||||
get dynamicDampingFactor() {
|
||||
console.warn(
|
||||
"OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead."
|
||||
);
|
||||
return this.dampingFactor;
|
||||
}
|
||||
|
||||
set dynamicDampingFactor(value) {
|
||||
console.warn(
|
||||
"OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead."
|
||||
);
|
||||
this.dampingFactor = value;
|
||||
}
|
||||
}
|
||||
|
||||
export default OrbitControls;
|
File diff suppressed because one or more lines are too long
52220
common/three/points.json
52220
common/three/points.json
File diff suppressed because it is too large
Load Diff
@ -138,9 +138,9 @@ export const NewWebsitePrototypeFooter = (props) => {
|
||||
Community
|
||||
</a>
|
||||
<br />
|
||||
<a css={STYLES_LINK} href="/_/system">
|
||||
{/* <a css={STYLES_LINK} href="/_/system">
|
||||
Design system
|
||||
</a>
|
||||
</a> */}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
|
@ -73,9 +73,9 @@ export const WebsitePrototypeFooter = (props) => {
|
||||
>
|
||||
Contribute
|
||||
</a>
|
||||
<a css={STYLES_LINK} href="/_/system">
|
||||
{/* <a css={STYLES_LINK} href="/_/system">
|
||||
Design System
|
||||
</a>
|
||||
</a> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,55 +0,0 @@
|
||||
import * as React from "react";
|
||||
|
||||
import GLComponent from "~/common/three/gl-component";
|
||||
import AnimationLoop from "~/common/three/animation-loop";
|
||||
|
||||
export default class GLRenderer extends React.Component {
|
||||
_GLComponent = undefined;
|
||||
_AnimationLoop = undefined;
|
||||
|
||||
async componentDidMount() {
|
||||
this._GLComponent = new GLComponent({
|
||||
width: this.props.width,
|
||||
height: this.props.height,
|
||||
container: this.refs.canvas,
|
||||
countries: this.props.countries,
|
||||
});
|
||||
|
||||
this._AnimationLoop = new AnimationLoop();
|
||||
|
||||
await this._GLComponent.mount();
|
||||
this._GLComponent.firstRender();
|
||||
this._AnimationLoop.subscribe(() => {
|
||||
this._GLComponent.render();
|
||||
});
|
||||
this._AnimationLoop.start();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
pause() {
|
||||
this._AnimationLoop.stop();
|
||||
}
|
||||
|
||||
resume() {
|
||||
if (!this._GLComponent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this._AnimationLoop.start();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._AnimationLoop.stop();
|
||||
this._AnimationLoop.unsubscribeAll();
|
||||
this._AnimationLoop = null;
|
||||
this._GLComponent.unmount();
|
||||
this._GLComponent = null;
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div ref="canvas" />;
|
||||
}
|
||||
}
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -9257,11 +9257,6 @@
|
||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"three": {
|
||||
"version": "0.126.1",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.126.1.tgz",
|
||||
"integrity": "sha512-eOEXnZeE1FDV0XgL1u08auIP13jxdN9LQBAEmlErYzMxtIIfuGIAZbijOyookALUhqVzVOx0Tywj6n192VM+nQ=="
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
|
@ -71,7 +71,6 @@
|
||||
"remark-linkify-regex": "^1.0.0",
|
||||
"remark-parse": "^9.0.0",
|
||||
"remark-react": "^8.0.0",
|
||||
"three": "^0.126.1",
|
||||
"unified": "^9.2.0",
|
||||
"universal-cookie": "^4.0.4",
|
||||
"uuid": "^8.3.2",
|
||||
|
@ -1,75 +0,0 @@
|
||||
import * as React from "react";
|
||||
import * as System from "~/components/system";
|
||||
|
||||
import GLRenderer from "~/components/three/GLRenderer";
|
||||
import SystemPage from "~/components/system/SystemPage";
|
||||
import ViewSourceLink from "~/components/system/ViewSourceLink";
|
||||
import CodeBlock from "~/components/system/CodeBlock";
|
||||
|
||||
export default class SystemPageGlobe extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<SystemPage
|
||||
title="SDS: Globe"
|
||||
description="..."
|
||||
url="https://slate.host/_/system/globe"
|
||||
>
|
||||
<System.H1>
|
||||
Globe <ViewSourceLink file="system/globe.js" />
|
||||
</System.H1>
|
||||
<br />
|
||||
<br />
|
||||
<System.P>
|
||||
The Globe component is used to show peers and file transfers on the
|
||||
Filecoin network.
|
||||
</System.P>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<System.H2>Imports</System.H2>
|
||||
<hr />
|
||||
<br />
|
||||
<System.P>
|
||||
Import React and the GLRenderer Components. Unfortunately the
|
||||
GLRenderer is not usable outside of this application.
|
||||
</System.P>
|
||||
<br />
|
||||
<br />
|
||||
<CodeBlock>
|
||||
{`import * as React from "react";
|
||||
import GLRenderer from "~/components/three/GLRenderer";`}
|
||||
</CodeBlock>
|
||||
<br />
|
||||
<br />
|
||||
<System.H2>Usage</System.H2>
|
||||
<hr />
|
||||
<br />
|
||||
<System.P>
|
||||
Declare the Globe component. Specify{" "}
|
||||
<System.CodeText>countries</System.CodeText> to be true to include
|
||||
markers for each country.
|
||||
</System.P>
|
||||
<br />
|
||||
<CodeBlock>
|
||||
{`class ExampleOne extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<GLRenderer width={768} height={480} />
|
||||
<GLRenderer countries width={768} height={480} />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}`}
|
||||
</CodeBlock>
|
||||
<br />
|
||||
<br />
|
||||
<System.H2>Output</System.H2>
|
||||
<hr />
|
||||
<br />
|
||||
<GLRenderer width={768} height={480} />
|
||||
<GLRenderer countries width={768} height={480} />
|
||||
</SystemPage>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
import * as React from "react";
|
||||
import * as System from "~/components/system";
|
||||
|
||||
import GLRenderer from "~/components/three/GLRenderer";
|
||||
import Section from "~/components/core/Section";
|
||||
import ScenePage from "~/components/core/ScenePage";
|
||||
|
||||
export default class ScenePeers extends React.Component {
|
||||
state = {};
|
||||
|
||||
_handleChange = (e) => {
|
||||
this.setState({ [e.target.name]: e.target.value });
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ScenePage>
|
||||
<System.H1>Peers</System.H1>
|
||||
<GLRenderer width={1200} height={480} />
|
||||
<Section
|
||||
onAction={this.props.onAction}
|
||||
title="Peers"
|
||||
buttons={[
|
||||
{
|
||||
name: "Add peer",
|
||||
type: "SIDEBAR",
|
||||
value: "SIDEBAR_ADD_PEER",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<System.Table
|
||||
onAction={this.props.onAction}
|
||||
data={{
|
||||
columns: [
|
||||
{
|
||||
key: "peer-avatar",
|
||||
hideLabel: true,
|
||||
width: "56px",
|
||||
type: "AVATAR",
|
||||
},
|
||||
{
|
||||
key: "chain-head",
|
||||
name: "Chain Head",
|
||||
tooltip: "What is a Chain Head?",
|
||||
width: "224px",
|
||||
},
|
||||
{
|
||||
key: "height",
|
||||
name: "Height",
|
||||
tooltip: "Height",
|
||||
width: "120px",
|
||||
},
|
||||
{
|
||||
key: "location",
|
||||
name: "Location",
|
||||
width: "100%",
|
||||
type: "LOCATION",
|
||||
},
|
||||
{
|
||||
key: "upload",
|
||||
name: "Upload",
|
||||
width: "120px",
|
||||
type: "BANDWIDTH_UPLOAD",
|
||||
},
|
||||
{
|
||||
key: "download",
|
||||
name: "Download",
|
||||
width: "120px",
|
||||
type: "BANDWIDTH_DOWNLOAD",
|
||||
},
|
||||
],
|
||||
rows: this.props.viewer.peers,
|
||||
}}
|
||||
selectedRowId={this.state.table_peers}
|
||||
onChange={this._handleChange}
|
||||
name="table_peers"
|
||||
/>
|
||||
</Section>
|
||||
</ScenePage>
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user