Sfoglia il codice sorgente

Ray casting gives texture intersection in uv coordinates

Mesh.js raycast method is updated to calculate intersection point in uv
coordinates. The calculus is done in the new inner method
textureIntersection and added to the object returned as the uv property.

Texture.js has a new public method, transformUv, that convert the
coordinates from uv (range 0 to 1) to the real texture coordinates. The
input parameter is modified on output. Useful to have the intersection
point in texture coordinates.

There is no example in this commit because I only have example with
canvas, no with plain image.
rfm1201 10 anni fa
parent
commit
61ec551932
2 ha cambiato i file con 102 aggiunte e 0 eliminazioni
  1. 52 0
      src/objects/Mesh.js
  2. 50 0
      src/textures/Texture.js

+ 52 - 0
src/objects/Mesh.js

@@ -70,6 +70,10 @@ THREE.Mesh.prototype.raycast = ( function () {
 	var tempB = new THREE.Vector3();
 	var tempC = new THREE.Vector3();
 
+	var uvA = new THREE.Vector2();
+	var uvB = new THREE.Vector2();
+	var uvC = new THREE.Vector2();
+
 	return function raycast( raycaster, intersects ) {
 
 		var geometry = this.geometry;
@@ -107,6 +111,21 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 		var a, b, c;
 
+		var textureIntersection = function ( pIntersection, p1, p2, p3, uv1, uv2, uv3 ) {
+
+			var bary = THREE.Triangle.barycoordFromPoint( pIntersection, p1, p2, p3 );
+
+			uv1.multiplyScalar( bary.x );
+			uv2.multiplyScalar( bary.y );
+			uv3.multiplyScalar( bary.z );
+
+			uv1.add( uv2 );
+			uv1.add( uv3 );
+
+			return uv1.clone();
+
+		};
+
 		if ( geometry instanceof THREE.BufferGeometry ) {
 
 			var attributes = geometry.attributes;
@@ -152,6 +171,16 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 						if ( intersectionPoint === null ) continue;
 
+						// intersectionPoint in UV coordinates.
+						var uv = undefined;
+						if ( material.map && attributes.uv !== undefined ) {
+							var uvs = attributes.uv.array;
+							uvA.fromArray( uvs, a * 2 );
+							uvB.fromArray( uvs, b * 2 );
+							uvC.fromArray( uvs, c * 2 );
+							uv = textureIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC )
+						}
+
 						intersectionPoint.applyMatrix4( this.matrixWorld );
 
 						var distance = raycaster.ray.origin.distanceTo( intersectionPoint );
@@ -162,6 +191,7 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 							distance: distance,
 							point: intersectionPoint,
+							uv: uv,
 							face: new THREE.Face3( a, b, c, THREE.Triangle.normal( vA, vB, vC ) ),
 							faceIndex: Math.floor( i / 3 ), // triangle number in indices buffer semantics
 							object: this
@@ -194,6 +224,16 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 					if ( intersectionPoint === null ) continue;
 
+					// intersectionPoint in UV coordinates.
+					var uv = undefined;
+					if ( material.map && attributes.uv !== undefined ) {
+						var uvs = attributes.uv.array;
+						uvA.fromArray( uvs, i );
+						uvB.fromArray( uvs, i + 2 );
+						uvC.fromArray( uvs, i + 4 );
+						uv = textureIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC )
+					}
+
 					intersectionPoint.applyMatrix4( this.matrixWorld );
 
 					var distance = raycaster.ray.origin.distanceTo( intersectionPoint );
@@ -208,6 +248,7 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 						distance: distance,
 						point: intersectionPoint,
+						uv: uv,
 						face: new THREE.Face3( a, b, c, THREE.Triangle.normal( vA, vB, vC ) ),
 						index: a, // triangle number in positions buffer semantics
 						object: this
@@ -282,6 +323,16 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 				if ( intersectionPoint === null ) continue;
 
+				// intersectionPoint in UV coordinates.
+				var uv = undefined;
+				if ( material.map && geometry.faceVertexUvs[ 0 ] !== undefined ) {
+					var uvs = geometry.faceVertexUvs[ 0 ][ f ];
+					uvA.copy( uvs[ 0 ] );
+					uvB.copy( uvs[ 1 ] );
+					uvC.copy( uvs[ 2 ] );
+					uv = textureIntersection( intersectionPoint, a, b, c, uvA, uvB, uvC )
+				}
+
 				intersectionPoint.applyMatrix4( this.matrixWorld );
 
 				var distance = raycaster.ray.origin.distanceTo( intersectionPoint );
@@ -292,6 +343,7 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 					distance: distance,
 					point: intersectionPoint,
+					uv: uv,
 					face: face,
 					faceIndex: f,
 					object: this

+ 50 - 0
src/textures/Texture.js

@@ -185,6 +185,56 @@ THREE.Texture.prototype = {
 
 		this.dispatchEvent( { type: 'dispose' } );
 
+	},
+
+	transformUv: function ( uv ) {
+
+		if ( this.mapping !== THREE.UVMapping ) {
+			return;
+		}
+
+		uv.multiply( this.repeat );
+		uv.add( this.offset );
+
+		if ( uv.x < 0 || uv.x > 1 ) {
+			switch ( this.wrapS ) {
+				case THREE.RepeatWrapping:
+					uv.x = uv.x - Math.floor( uv.x );
+					break;
+				case THREE.ClampToEdgeWrapping:
+					uv.x = uv.x < 0 ? 0 : 1;
+					break;
+				case THREE.MirroredRepeatWrapping:
+					if ( Math.abs(Math.floor( uv.x ) % 2) === 1 ) {
+						uv.x = Math.ceil( uv.x ) - uv.x;
+					} else {
+						uv.x = uv.x - Math.floor( uv.x );
+					}
+				break;
+			}
+		}
+
+		if ( uv.y < 0 || uv.y > 1 ) {
+			switch ( this.wrapT ) {
+				case THREE.RepeatWrapping:
+					uv.y = uv.y - Math.floor( uv.y );
+					break;
+				case THREE.ClampToEdgeWrapping:
+					uv.y = uv.y < 0 ? 0 : 1;
+					break;
+				case THREE.MirroredRepeatWrapping:
+					if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
+						uv.y = Math.ceil( uv.y ) - uv.y;
+					} else {
+						uv.y = uv.y - Math.floor( uv.y );
+					}
+					break;
+			}
+		}
+
+		if ( this.flipY ) {
+			uv.y = 1 - uv.y;
+		}
 	}
 
 };