jump() { this.velUp = 1; let vecToMove = vec3.create(); vec3.scale(vecToMove, this.up, this.moveSpeed * this.velUp); this.move(vecToMove); }
deform(featurePoints) { let displacement = featurePoints.map((p, i) => { let fp = this.standardFace.getFeatureVertex(i) return vec3.sub([], p, fp) }) let weight = this.standardFace.data.face.weight let position = this.positionAttribute.array for (let i = 0; i < weight.length; i++) { let p = vec3.create() let b = 0 weight[i].forEach((w) => { vec3.add(p, p, vec3.scale(vec3.create(), displacement[w[0]], w[1])) b += w[1] }) vec3.scale(p, p, 1 / b) vec3.add(p, p, this.standardFace.getVertex(i)) position[i * 3 + 0] = p[0] position[i * 3 + 1] = p[1] position[i * 3 + 2] = p[2] } this.standardFace.faceEyeIndex.forEach((index) => { let i0 = index[0] * 3 let i1 = index[1] * 3 position[i1 + 0] = position[i0 + 0] position[i1 + 1] = position[i0 + 1] position[i1 + 2] = position[i0 + 2] }) this.positionAttribute.needsUpdate = true }
export default function geometryRayIntersection(geometry, matrix, o, d) { // Handle the triangle only if (geometry.type !== 'triangles') return false; let minFaceId = null; let minFaceDist = Infinity; // Geometry MUST be Geometry3D object let indices = geometry.getIndices(); let vertices = geometry.getAttributes().aPosition; if (indices == null || vertices == null) return false; vertices = vertices.data; // TODO it'll be cheaper to cache each vertex. for (let faceId = 0; faceId < geometry.indices.length; faceId += 3) { const vertexId1 = indices[faceId]; const vertexId2 = indices[faceId + 1]; const vertexId3 = indices[faceId + 2]; let vertex1 = vertices.slice(vertexId1 * 3, vertexId1 * 3 + 3); let vertex2 = vertices.slice(vertexId2 * 3, vertexId2 * 3 + 3); let vertex3 = vertices.slice(vertexId3 * 3, vertexId3 * 3 + 3); vec3.transformMat4(vertex1, vertex1, matrix); vec3.transformMat4(vertex2, vertex2, matrix); vec3.transformMat4(vertex3, vertex3, matrix); let dist = triangleRayIntersection(vertex1, vertex2, vertex3, o, d); if (dist !== false && dist < minFaceDist) { minFaceId = faceId; minFaceDist = dist; } } if (minFaceId === null) return null; return { faceId: minFaceId, distance: minFaceDist }; }
getInitialDeformedVertices(featurePoints) { let displacement = featurePoints.map((c, i) => { let fp = this.getPosition(this.data.face.featurePoint[i]) let scale = (500 - fp[2] * 200) / 500 let p = vec3.clone(fp) p[0] = (c[0] - 0.5) * scale p[1] = (c[1] - 0.5) * scale return vec3.sub(p, p, fp) }) let n = this.data.face.position.length / 3 let position = new Float32Array(n * 3) for (let i = 0; i < n; i++) { let p = vec3.create() let b = 0 this.data.face.weight[i].forEach((w) => { vec3.add(p, p, vec3.scale(vec3.create(), displacement[w[0]], w[1])) b += w[1] }) vec3.scale(p, p, 1 / b) vec3.add(p, p, this.getPosition(i)) position[i * 3 + 0] = p[0] position[i * 3 + 1] = p[1] position[i * 3 + 2] = p[2] } return new THREE.BufferAttribute(position, 3) }
/** Compute rotation values (by updating the quaternion) */ rotate(mouseX, mouseY) { var axisRot = _TMP_VEC3; var diff = _TMP_VEC2; var normalizedMouseXY = Geometry.normalizedMouse(mouseX, mouseY, this._width, this._height); if (this._mode === Enums.CameraMode.ORBIT) { vec2.sub(diff, normalizedMouseXY, this._lastNormalizedMouseXY); this.setOrbit(this._rotX - diff[1] * 2, this._rotY + diff[0] * 2); this.rotateDelay([-diff[1] * 6, diff[0] * 6], DELAY_ROTATE); } else if (this._mode === Enums.CameraMode.PLANE) { var length = vec2.dist(this._lastNormalizedMouseXY, normalizedMouseXY); vec2.sub(diff, normalizedMouseXY, this._lastNormalizedMouseXY); vec3.normalize(axisRot, vec3.set(axisRot, -diff[1], diff[0], 0.0)); quat.mul(this._quatRot, quat.setAxisAngle(_TMP_QUAT, axisRot, length * 2.0), this._quatRot); this.rotateDelay([axisRot[0], axisRot[1], axisRot[2], length * 6], DELAY_ROTATE); } else if (this._mode === Enums.CameraMode.SPHERICAL) { var mouseOnSphereBefore = Geometry.mouseOnUnitSphere(this._lastNormalizedMouseXY); var mouseOnSphereAfter = Geometry.mouseOnUnitSphere(normalizedMouseXY); var angle = Math.acos(Math.min(1.0, vec3.dot(mouseOnSphereBefore, mouseOnSphereAfter))); vec3.normalize(axisRot, vec3.cross(axisRot, mouseOnSphereBefore, mouseOnSphereAfter)); quat.mul(this._quatRot, quat.setAxisAngle(_TMP_QUAT, axisRot, angle * 2.0), this._quatRot); this.rotateDelay([axisRot[0], axisRot[1], axisRot[2], angle * 6], DELAY_ROTATE); } this._lastNormalizedMouseXY = normalizedMouseXY; this.updateView(); }
return function arcFromForward(out, v) { if (!vec3_0) vec3_0 = vec3.create(); const norm = vec3.normalize(vec3_0, v); mat4.identity(out); if (norm[2] < -0.99999) { return out; } if (norm[2] > 0.99999) { out[5] = -1.0; out[10] = -1.0; return out; } const h = (1 + norm[2]) / (norm[0] * norm[0] + norm[1] * norm[1]); out[0] = h * norm[1] * norm[1] - norm[2]; out[1] = -h * norm[0] * norm[1]; out[2] = norm[0]; out[4] = out[1]; out[5] = h * norm[0] * norm[0] - norm[2]; out[6] = norm[1]; out[8] = -norm[0]; out[9] = -norm[1]; out[10] = -norm[2]; return out; };
export function projectPointOntoPlane (point, plane) { var diff = matrix.vec3.subtract([], point, plane.origin); var distanceToPlane = matrix.vec3.dot(diff, plane.normal); var scaled = matrix.vec3.scale([], plane.normal, distanceToPlane); var projectedPoint = matrix.vec3.subtract([], point, scaled); return projectedPoint; }
initialize: function(x, y, w, h, focalLength){ this.x = x; this.y = y; this.width = w; this.height = h; //projection vector this.vpx = x + w / 2; this.vpy = y + h / 2; this.focalLength = focalLength || 250; this.z = 0; this.rotation = { x: 0, y: 0, z: 0 }; this.tmpVec = vec3.create(); this.tmpVec2 = vec3.create(); this.viewMatrix = mat4.create(); this.tmpVec[2] = -10.; mat4.lookAt(this.viewMatrix, this.tmpVec, this.tmpVec2, vec3.fromValues(0, 1, 0)); this.projectionMatrix = mat4.create(); this.transformMatrix = mat4.create(); },
/** * Проверяет, находится ли {@link Box} в области frustum * @param {Box} box * @returns {Boolean} */ intersectsBox(box) { const p1 = vec3.create(); const p2 = vec3.create(); const planes = this.planes; for (let i = 0; i < 6; i++) { const plane = planes[i]; p1[0] = plane.normal[0] > 0 ? box.min[0] : box.max[0]; p2[0] = plane.normal[0] > 0 ? box.max[0] : box.min[0]; p1[1] = plane.normal[1] > 0 ? box.min[1] : box.max[1]; p2[1] = plane.normal[1] > 0 ? box.max[1] : box.min[1]; p1[2] = plane.normal[2] > 0 ? box.min[2] : box.max[2]; p2[2] = plane.normal[2] > 0 ? box.max[2] : box.min[2]; const d1 = plane.distanceToPoint(p1); const d2 = plane.distanceToPoint(p2); // if both outside plane, no intersection if (d1 < 0 && d2 < 0) { return false; } } return true; }
state.listen('up', (x, y) => { let movement = getMovementRelToCenter(x, y); let angle = vec3.length(movement) * 0.24; // Flip the movement vector perpendicular let rotationaxis = vec3.fromValues(movement[1], -movement[0], 0); applyRotationForce(angle, rotationaxis); })
_onDrag(evt) { if (this._dragStartPos) { const {pageX, pageY} = evt; const {width, height} = this.props; const dx = (pageX - this._dragStartPos[0]) / width; const dy = (pageY - this._dragStartPos[1]) / height; if (evt.shiftKey || evt.ctrlKey || evt.altKey || evt.metaKey) { // pan const {lookAt, distance, rotationX, rotationY, fov} = this.props; const unitsPerPixel = distance / Math.tan(fov / 180 * Math.PI / 2) / 2; const newLookAt = vec3.add([], lookAt, [-unitsPerPixel * dx, unitsPerPixel * dy, 0]); vec3.rotateX(newLookAt, newLookAt, lookAt, rotationX / 180 * Math.PI); vec3.rotateY(newLookAt, newLookAt, lookAt, rotationY / 180 * Math.PI); this.props.onChangeViewport({ lookAt: newLookAt }); } else { // rotate const {rotationX, rotationY} = this.props; const newRotationX = clamp(rotationX - dy * 180, -90, 90); const newRotationY = (rotationY - dx * 180) % 360; this.props.onChangeViewport({ rotationX: newRotationX, rotationY: newRotationY }); } this._dragStartPos = [pageX, pageY]; } }
return function (iTri, checkInsideSphere) { var mesh = SubData._mesh; var vAr = mesh.getVertices(); var fAr = mesh.getFaces(); var id = iTri * 4; var ind1 = fAr[id] * 3; var ind2 = fAr[id + 1] * 3; var ind3 = fAr[id + 2] * 3; v1[0] = vAr[ind1]; v1[1] = vAr[ind1 + 1]; v1[2] = vAr[ind1 + 2]; v2[0] = vAr[ind2]; v2[1] = vAr[ind2 + 1]; v2[2] = vAr[ind2 + 2]; v3[0] = vAr[ind3]; v3[1] = vAr[ind3 + 1]; v3[2] = vAr[ind3 + 2]; if (checkInsideSphere && !tis(SubData._center, SubData._radius2, v1, v2, v3) && !pit(SubData._center, v1, v2, v3)) return 0; var mAr = mesh.getMaterials(); var m1 = mAr[ind1 + 2]; var m2 = mAr[ind2 + 2]; var m3 = mAr[ind3 + 2]; var length1 = vec3.sqrDist(v1, v2); var length2 = vec3.sqrDist(v2, v3); var length3 = vec3.sqrDist(v1, v3); if (length1 > length2 && length1 > length3) return (m1 + m2) * 0.5 * length1 > SubData._edgeMax2 ? 1 : 0; else if (length2 > length3) return (m2 + m3) * 0.5 * length2 > SubData._edgeMax2 ? 2 : 0; else return (m1 + m3) * 0.5 * length3 > SubData._edgeMax2 ? 3 : 0; };
_computeVertexNormals() { // loop through all vertices let face; const sumNormal = vec3.create(); const normals = []; const { vertices } = this; for(let i = 0; i < vertices.length; i++) { vec3.set(sumNormal, 0, 0, 0); for(let j = 0; j < this._faces.length; j++) { face = this._faces[j]; // if vertex exist in the face, add the normal to sum normal if(face.indices.indexOf(i) >= 0) { sumNormal[0] += face.normal[0]; sumNormal[1] += face.normal[1]; sumNormal[2] += face.normal[2]; } } vec3.normalize(sumNormal, sumNormal); normals.push([sumNormal[0], sumNormal[1], sumNormal[2]]); } this.bufferNormal(normals); }
generateFaces() { let ia, ib, ic; let a, b, c; const vba = vec3.create(), vca = vec3.create(), vNormal = vec3.create(); const { vertices } = this; for(let i = 0; i < this._indices.length; i += 3) { ia = this._indices[i]; ib = this._indices[i + 1]; ic = this._indices[i + 2]; a = vertices[ia]; b = vertices[ib]; c = vertices[ic]; const face = { indices:[ia, ib, ic], vertices:[a, b, c], }; this._faces.push(face); } }
translate(dx, dy) { var factor = this._speed * this._trans[2] / 54; var delta = [-dx * factor, dy * factor, 0.0]; this.setTrans(vec3.add(this._trans, this._trans, delta)); vec3.scale(delta, delta, 5); this.translateDelay(delta, DELAY_TRANSLATE); }
renorm() { vec3.cross(this.right, this.forward, this.up); vec3.cross(this.up, this.right, this.forward); vec3.normalize(this.forward, this.forward); vec3.normalize(this.right, this.right); vec3.normalize(this.up, this.up); }
constructor(geometry) { this._v1 = vec3.create() this._v2 = vec3.create() this.geometry = geometry this.prepare() }
/** * Rotate around the given point. * Changes both the camera location and rotation. * * @param {quat} rotation * @param {vec3} point */ rotateAround(rotation, point) { this.rotate(rotation); quat.conjugate(quatHeap, quatHeap); vec3.sub(vectorHeap, this.location, point); vec3.transformQuat(vectorHeap, vectorHeap, rotation); vec3.add(this.location, vectorHeap, point); }
setUp(up: Vec3,lerp: ?number): void { if (lerp) { glm.vec3.lerp(this._up,this._up,up,lerp); } else { glm.vec3.copy(this._up,up); } glm.vec3.normalize(this._up,this._up); }
DraggableBehaviour.prototype.onMouseDown = function (element, event) { this.touches[-1] = { startPoint: glm.vec3.fromValues(event.pageX, event.pageY, 0), lastPoint: glm.vec3.fromValues(event.pageX, event.pageY, 0) }; };
Box.prototype.transform = function(mat) { if (this.isEmpty()) { return this; } vec3.transformMat4(this.min.data, this.min.data, mat.data ? mat.data : mat); vec3.transformMat4(this.max.data, this.max.data, mat.data ? mat.data : mat); return this; };
let displacement = featurePoints.map((c, i) => { let fp = this.getPosition(this.data.face.featurePoint[i]) let scale = (500 - fp[2] * 200) / 500 let p = vec3.clone(fp) p[0] = (c[0] - 0.5) * scale p[1] = (c[1] - 0.5) * scale return vec3.sub(p, p, fp) })
constructor() { this.position = vec3.create(); this.rotation = quat.create(); this.scale = vec3.create(); vec3.set(this.scale, 1, 1, 1); this.matrix = mat4.create(); this.valid = false; this.validate(); }
function setpMatCur() { const axis3 = vec3.create(); vec3.cross(axis3, mouseStart, mouseCur); var angle = Math.atan(vec3.len(axis3) / vec3.dot(mouseStart, mouseCur)); if (angle < 0) angle += Math.PI; const r = mat4.create(); mat4.rotate(r, r, angle, axis3); mat4.mul(pMatCur, r, pMatBase); }
/** Intersection between a ray the mouse position */ intersectionMouseMesh(mesh = this._main.getMesh(), mouseX = this._main._mouseX, mouseY = this._main._mouseY) { var vNear = this.unproject(mouseX, mouseY, 0.0); var vFar = this.unproject(mouseX, mouseY, 0.1); var matInverse = mat4.create(); mat4.invert(matInverse, mesh.getMatrix()); vec3.transformMat4(vNear, vNear, matInverse); vec3.transformMat4(vFar, vFar, matInverse); return this.intersectionRayMesh(mesh, vNear, vFar); }
function Mesh(vertexCount, faceCount) { this.vertices = new Array(vertexCount); this.faces = new Array(faceCount); this.position = glmatrix.vec3.fromValues(0, 0, 0); this.rotation = glmatrix.vec3.fromValues(0, 0, 0); // TODO: move this this._vColor = colors.red; }
/** * Set scale * * @param {number|Array.<number>} x Scale on X or an array with scale on each axis * @param {?number} y Scale on Y * @param {?number} z Scale on Z */ setScale(x, y = this.scale[1], z = this.scale[2]) { if (x.constructor === Array) glMatrix.vec3.copy(this.scale, x); else glMatrix.vec3.set(this.scale, x, y, z); this.needTransformUpdate = true; }
/** * Set position * * @param {number|Array.<number>} x Position on X or an array with position on each axis * @param {?number} y Position on Y * @param {?number} z Position on Z */ setPosition(x, y = this.position[1], z = this.position[2]) { if (x.constructor === Array) glMatrix.vec3.copy(this.position, x); else glMatrix.vec3.set(this.position, x, y, z); this.needTransformUpdate = true; }
function Player(world) { this.shape = new CapsuleY(0, 0, 0, 1.0, 0.75); this.world = world; this.aabb = new AABB(); this.position = vec3.create(); this.velocity = vec3.create(); this.acceleration = vec3.create(); this.hadContact = false; }
DraggableBehaviour.prototype.onMouseMove = function (element, event) { var touchInfo = this.touches[-1]; var touchPoint = glm.vec3.fromValues(event.pageX, event.pageY, 0); var translation = glm.vec3.sub(glm.vec3.create(), touchPoint, touchInfo.lastPoint); glm.vec3.add(this.translation, this.translation, translation); glm.vec3.copy(touchInfo.lastPoint, touchPoint); this.needsUpdate(); };