فهرست منبع

Brief:Implementing raycasting for dynamic buffergeometry
Summary:
BufferGeometry allows faster loading (direct buffer loading)
but not ray casting. This adds that (if it is dynamic)

Kevin Schmidt 12 سال پیش
والد
کامیت
96437a641e
1فایلهای تغییر یافته به همراه118 افزوده شده و 0 حذف شده
  1. 118 0
      src/core/Raycaster.js

+ 118 - 0
src/core/Raycaster.js

@@ -64,6 +64,124 @@
 
 			intersectObject( object.getObjectForDistance( distance ), raycaster, intersects );
 
+		} else if (object instanceof THREE.Mesh && object.geometry instanceof THREE.BufferGeometry) {
+
+			// Checking boundingSphere distance to ray
+			matrixPosition.getPositionFromMatrix(object.matrixWorld);
+			sphere.set(matrixPosition,
+				object.geometry.boundingSphere.radius * object.matrixWorld.getMaxScaleOnAxis());
+
+			if (!raycaster.ray.isIntersectionSphere(sphere)) {
+
+				return intersects;
+
+			}
+
+			// Checking faces
+
+			var geometry = object.geometry;
+			var vertices = geometry.vertices;
+
+			var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
+			var objectMaterials = isFaceMaterial === true ? object.material.materials : null;
+
+			var side = object.material.side;
+
+			var a, b, c;
+			var precision = raycaster.precision;
+
+			inverseMatrix.getInverse(object.matrixWorld);
+
+			localRay.copy(raycaster.ray).applyMatrix4(inverseMatrix);
+
+			if (!geometry.dynamic) return intersects;
+
+			var fl;
+			var indexed = false;
+			if (geometry.attributes.index) {
+				indexed = true;
+				fl = geometry.attributes.index.numItems / 3;
+			} else {
+				fl = geometry.attributes.position.numItems / 9;
+			}
+
+			for (var f = 0; f < fl; f++) {
+
+				if (indexed) {
+					a = geometry.attributes.index.array[f * 3];
+					b = geometry.attributes.index.array[f * 3 + 1];
+					c = geometry.attributes.index.array[f * 3 + 2];
+				} else {
+					a = f * 3;
+					b = f * 3 + 1;
+					c = f * 3 + 2;
+				}
+
+				var v1 = [geometry.attributes.position.array[a * 3],
+							geometry.attributes.position.array[a * 3 + 1],
+							geometry.attributes.position.array[a * 3 + 2]];
+				var v2 = [geometry.attributes.position.array[b * 3],
+							geometry.attributes.position.array[b * 3 + 1],
+							geometry.attributes.position.array[b * 3 + 2]];
+				var v3 = [geometry.attributes.position.array[c * 3],
+							geometry.attributes.position.array[c * 3 + 1],
+							geometry.attributes.position.array[c * 3 + 2]];
+
+				var material = object.material;
+				if (material === undefined) continue;
+
+				var cb = new THREE.Vector3(), ab = new THREE.Vector3();
+				var vA = new THREE.Vector3(v1[0], v1[1], v1[2]);
+				var vB = new THREE.Vector3(v2[0], v2[1], v2[2]);
+				var vC = new THREE.Vector3(v3[0], v3[1], v3[2]);
+
+				cb.subVectors(vC, vB);
+				ab.subVectors(vA, vB);
+				cb.cross(ab);
+				cb.normalize();
+
+				facePlane.setFromNormalAndCoplanarPoint(cb, vA);
+
+				var planeDistance = localRay.distanceToPlane(facePlane);
+
+				// bail if raycaster and plane are parallel
+				if (Math.abs(planeDistance) < precision) continue;
+
+				// if negative distance, then plane is behind raycaster
+				if (planeDistance < 0) continue;
+
+				// check if we hit the wrong side of a single sided face
+				side = material.side;
+				if (side !== THREE.DoubleSide) {
+
+					var planeSign = localRay.direction.dot(facePlane.normal);
+
+					if (!(side === THREE.FrontSide ? planeSign < 0 : planeSign > 0)) continue;
+
+				}
+
+				// this can be done using the planeDistance from localRay because localRay wasn't normalized, but ray was
+				if (planeDistance < raycaster.near || planeDistance > raycaster.far) continue;
+
+				intersectPoint = localRay.at(planeDistance, intersectPoint); // passing in intersectPoint avoids a copy
+
+				if (!THREE.Triangle.containsPoint(intersectPoint, vA, vB, vC)) continue;
+
+				var face = new THREE.Face3(a, b, c);
+				var colors = geometry.attributes.color.array;
+				face.vertexColors[0] = new THREE.Color(colors[a * 3], colors[a * 3 + 1], colors[a * 3 + 2]);
+				face.vertexColors[1] = new THREE.Color(colors[b * 3], colors[b * 3 + 1], colors[b * 3 + 2]);
+				face.vertexColors[2] = new THREE.Color(colors[c * 3], colors[c * 3 + 1], colors[c * 3 + 2]);
+				intersects.push({
+					distance: planeDistance, // this works because the original ray was normalized, and the transformed localRay wasn't
+					point: raycaster.ray.at(planeDistance),
+					face: face,
+					faceIndex: f,
+					object: object
+				});
+
+			}
+
 		} else if ( object instanceof THREE.Mesh ) {
 
 			// Checking boundingSphere distance to ray