소스 검색

DecalGeometry: First commit

Mugen87 8 년 전
부모
커밋
d806ee0b1f
3개의 변경된 파일348개의 추가작업 그리고 30개의 파일을 삭제
  1. 3 30
      examples/webgl_decals.html
  2. 344 0
      src/geometries/DecalGeometry.js
  3. 1 0
      src/geometries/Geometries.js

+ 3 - 30
examples/webgl_decals.html

@@ -27,7 +27,6 @@
 		</div>
 
 		<script src="../build/three.js"></script>
-		<script src="js/geometries/DecalGeometry.js"></script>
 		<script src="js/controls/OrbitControls.js"></script>
 		<script src="js/libs/dat.gui.min.js"></script>
 
@@ -68,8 +67,8 @@
 
 		var decals = [];
 		var decalHelper, mouseHelper;
-		var p = new THREE.Vector3( 0, 0, 0 );
-		var r = new THREE.Vector3( 0, 0, 0 );
+		var p = new THREE.Vector3();
+		var r = new THREE.Euler();
 		var s = new THREE.Vector3( 10, 10, 10 );
 		var up = new THREE.Vector3( 0, 1, 0 );
 		var check = new THREE.Vector3( 1, 1, 1 );
@@ -270,7 +269,7 @@
 
 				dummy = new THREE.Object3D();
 				dummy.rotation.setFromRotationMatrix( m );
-				r.set( dummy.rotation.x, dummy.rotation.y, dummy.rotation.z );
+				r.copy( dummy.rotation );
 
 			} else {
 
@@ -305,32 +304,6 @@
 
 		}
 
-		function mergeDecals() {
-
-			var merge = {};
-			decals.forEach( function ( decal ) {
-
-				var uuid = decal.material.uuid;
-				var d = merge[ uuid ] = merge[ uuid ] || {};
-				d.material = d.material || decal.material;
-				d.geometry = d.geometry || new THREE.Geometry();
-				d.geometry.merge( decal.geometry, decal.matrix );
-
-			} );
-
-			removeDecals();
-
-			for ( var key in merge ) {
-
-				var d = merge[ key ];
-				var mesh = new THREE.Mesh( d.geometry, d.material );
-				scene.add( mesh );
-				decals.push( mesh );
-
-			}
-
-		}
-
 		function onWindowResize() {
 
 			camera.aspect = window.innerWidth / window.innerHeight;

+ 344 - 0
src/geometries/DecalGeometry.js

@@ -0,0 +1,344 @@
+import { BufferGeometry } from '../core/BufferGeometry';
+import { Float32BufferAttribute } from '../core/BufferAttribute';
+import { Vector3 } from '../math/Vector3';
+import { Matrix4 } from '../math/Matrix4';
+
+/**
+ * @author Mugen87 / https://github.com/Mugen87
+ */
+
+function DecalGeometry( mesh, position, rotation, dimensions, check ) {
+
+	BufferGeometry.call( this );
+
+	this.type = 'DecalGeometry';
+
+	check = check || new Vector3( 1, 1, 1 );
+
+	// buffers
+
+	var vertices = [];
+	var normals = [];
+	var uvs = [];
+
+	// helpers
+
+	var projectorMatrix = new Matrix4();
+	projectorMatrix.makeRotationFromEuler( rotation );
+	projectorMatrix.setPosition( position );
+
+	var projectorMatrixInverse = new Matrix4().getInverse( projectorMatrix );
+
+	var plane = new Vector3();
+
+	// generate buffers
+
+	generate();
+
+	// build geometry
+
+	this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
+	this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
+	this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
+
+	function generate() {
+
+		var i, j, faceVertices;
+		var geometry = new BufferGeometry();
+
+		var vertex = new Vector3();
+		var normal = new Vector3();
+
+		// handle Geometry
+
+		if ( mesh.geometry.isGeometry ) {
+
+			geometry.fromGeometry( mesh.geometry );
+
+		} else {
+
+			geometry.copy( mesh.geometry );
+
+		}
+
+		var positionAttribute = geometry.attributes.position;
+		var normalAttribute = geometry.attributes.normal;
+
+		if ( geometry.index !== null ) {
+
+			// indexed BufferGeometry
+
+			var index = geometry.index;
+
+			for ( i = 0; i < index.count; i += 3 ) {
+
+				faceVertices = [];
+
+				for ( j = 0; j < 3; j ++ ) {
+
+					vertex.fromBufferAttribute( positionAttribute, index[ i + j ] );
+					normal.fromBufferAttribute( normalAttribute, index[ i + j ] );
+
+					vertex.applyMatrix4( mesh.matrix );
+					vertex.applyMatrix4( projectorMatrixInverse );
+
+					faceVertices.push( new DecalVertex( vertex.clone(), normal.clone() ) );
+
+				}
+
+				processFace( faceVertices );
+
+			}
+
+		} else {
+
+			// non-indexed BufferGeometry
+
+			for ( i = 0; i < positionAttribute.count; i += 3 ) {
+
+				faceVertices = [];
+
+				for ( j = 0; j < 3; j ++ ) {
+
+					vertex.fromBufferAttribute( positionAttribute, i + j );
+					normal.fromBufferAttribute( normalAttribute, i + j );
+
+					vertex.applyMatrix4( mesh.matrix );
+					vertex.applyMatrix4( projectorMatrixInverse );
+
+					faceVertices.push( new DecalVertex( vertex.clone(), normal.clone() ) );
+
+				}
+
+				processFace( faceVertices );
+
+			}
+
+		}
+
+	}
+
+	function processFace( faceVertices ) {
+
+		if ( check.x ) {
+
+			faceVertices = clipFace( faceVertices, plane.set( 1, 0, 0 ) );
+			faceVertices = clipFace( faceVertices, plane.set( - 1, 0, 0 ) );
+
+		}
+		if ( check.y ) {
+
+			faceVertices = clipFace( faceVertices, plane.set( 0, 1, 0 ) );
+			faceVertices = clipFace( faceVertices, plane.set( 0, - 1, 0 ) );
+
+		}
+		if ( check.z ) {
+
+			faceVertices = clipFace( faceVertices, plane.set( 0, 0, 1 ) );
+			faceVertices = clipFace( faceVertices, plane.set( 0, 0, - 1 ) );
+
+		}
+
+		if ( faceVertices.length === 0 ) return;
+
+		// generate vertices, normals and uvs
+
+		for ( var i = 0; i < faceVertices.length; i ++ ) {
+
+			var decalVertex = faceVertices[ i ];
+
+			uvs.push(
+				0.5 + ( decalVertex.position.x / dimensions.x ),
+				0.5 + ( decalVertex.position.y / dimensions.y )
+			);
+
+			decalVertex.position.applyMatrix4( projectorMatrix );
+
+			vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z );
+			normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z );
+
+		}
+
+	}
+
+	function clipFace ( inVertices, plane ) {
+
+		var outVertices = [];
+
+		var size = 0.5 * Math.abs( dimensions.dot( plane ) );
+
+		for ( var j = 0; j < inVertices.length; j += 3 ) {
+
+			var v1Out, v2Out, v3Out, total = 0;
+			var nV1, nV2, nV3, nV4;
+
+			var d1 = inVertices[ j + 0 ].position.dot( plane ) - size;
+			var d2 = inVertices[ j + 1 ].position.dot( plane ) - size;
+			var d3 = inVertices[ j + 2 ].position.dot( plane ) - size;
+
+			v1Out = d1 > 0;
+			v2Out = d2 > 0;
+			v3Out = d3 > 0;
+
+			total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 );
+
+			switch ( total ) {
+
+				case 0: {
+
+					outVertices.push( inVertices[ j ] );
+					outVertices.push( inVertices[ j + 1 ] );
+					outVertices.push( inVertices[ j + 2 ] );
+					break;
+
+				}
+
+				case 1: {
+
+					if ( v1Out ) {
+
+						nV1 = inVertices[ j + 1 ];
+						nV2 = inVertices[ j + 2 ];
+						nV3 = clip( inVertices[ j ], nV1, plane, size );
+						nV4 = clip( inVertices[ j ], nV2, plane, size );
+
+					}
+
+					if ( v2Out ) {
+
+						nV1 = inVertices[ j ];
+						nV2 = inVertices[ j + 2 ];
+						nV3 = clip( inVertices[ j + 1 ], nV1, plane, size );
+						nV4 = clip( inVertices[ j + 1 ], nV2, plane, size );
+
+						outVertices.push( nV3 );
+						outVertices.push( nV2.clone() );
+						outVertices.push( nV1.clone() );
+
+						outVertices.push( nV2.clone() );
+						outVertices.push( nV3.clone() );
+						outVertices.push( nV4 );
+						break;
+
+					}
+
+					if ( v3Out ) {
+
+						nV1 = inVertices[ j ];
+						nV2 = inVertices[ j + 1 ];
+						nV3 = clip( inVertices[ j + 2 ], nV1, plane, size );
+						nV4 = clip( inVertices[ j + 2 ], nV2, plane, size );
+
+					}
+
+					outVertices.push( nV1.clone() );
+					outVertices.push( nV2.clone() );
+					outVertices.push( nV3 );
+
+					outVertices.push( nV4 );
+					outVertices.push( nV3.clone() );
+					outVertices.push( nV2.clone() );
+
+					break;
+
+				}
+
+				case 2: {
+
+					if ( ! v1Out ) {
+
+						nV1 = inVertices[ j ].clone();
+						nV2 = clip( nV1, inVertices[ j + 1 ], plane, size );
+						nV3 = clip( nV1, inVertices[ j + 2 ], plane, size );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
+
+					}
+
+					if ( ! v2Out ) {
+
+						nV1 = inVertices[ j + 1 ].clone();
+						nV2 = clip( nV1, inVertices[ j + 2 ], plane, size );
+						nV3 = clip( nV1, inVertices[ j ], plane, size );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
+
+					}
+
+					if ( ! v3Out ) {
+
+						nV1 = inVertices[ j + 2 ].clone();
+						nV2 = clip( nV1, inVertices[ j ], plane, size );
+						nV3 = clip( nV1, inVertices[ j + 1 ], plane, size );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
+
+					}
+
+					break;
+
+				}
+
+				case 3: {
+
+					break;
+
+				}
+
+			}
+
+		}
+
+		return outVertices;
+
+	}
+
+	function clip( v0, v1, p, size ) {
+
+		var d0 = v0.position.dot( p ) - size;
+		var d1 = v1.position.dot( p ) - size;
+
+		var s = d0 / ( d0 - d1 );
+		var v = new DecalVertex(
+			new Vector3(
+				v0.position.x + s * ( v1.position.x - v0.position.x ),
+				v0.position.y + s * ( v1.position.y - v0.position.y ),
+				v0.position.z + s * ( v1.position.z - v0.position.z )
+			),
+			new Vector3(
+				v0.normal.x + s * ( v1.normal.x - v0.normal.x ),
+				v0.normal.y + s * ( v1.normal.y - v0.normal.y ),
+				v0.normal.z + s * ( v1.normal.z - v0.normal.z )
+			)
+		);
+
+		// need to clip more values (texture coordinates)? do it this way:
+		// intersectpoint.value = a.value + s * ( b.value - a.value );
+
+		return v;
+
+	}
+
+}
+
+DecalGeometry.prototype = Object.create( BufferGeometry.prototype );
+DecalGeometry.prototype.constructor = DecalGeometry;
+
+function DecalVertex( position, normal ) {
+
+	this.position = position;
+	this.normal = normal;
+
+}
+
+DecalVertex.prototype.clone = function() {
+
+	return new DecalVertex( this.position.clone(), this.normal.clone() );
+
+};
+
+
+export { DecalGeometry };

+ 1 - 0
src/geometries/Geometries.js

@@ -20,3 +20,4 @@ export { ConeGeometry, ConeBufferGeometry } from './ConeGeometry.js';
 export { CylinderGeometry, CylinderBufferGeometry } from './CylinderGeometry.js';
 export { CircleGeometry, CircleBufferGeometry } from './CircleGeometry.js';
 export { BoxGeometry, BoxBufferGeometry } from './BoxGeometry.js';
+export { DecalGeometry } from './DecalGeometry.js';