| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- /**
- * @author mikael emtinger / http://gomo.se/
- */
- THREE.ShadowVolume = function( meshOrGeometry, isStatic ) {
- if( meshOrGeometry instanceof THREE.Mesh ) {
- THREE.Mesh.call( this, meshOrGeometry.geometry, isStatic ? [ new THREE.ShadowVolumeDynamicMaterial() ] : [ new THREE.ShadowVolumeDynamicMaterial() ] );
- meshOrGeometry.addChild( this );
- } else {
- THREE.Mesh.call( this, meshOrGeometry, isStatic ? [ new THREE.ShadowVolumeDynamicMaterial() ] : [ new THREE.ShadowVolumeDynamicMaterial() ] );
- }
- this.calculateShadowVolumeGeometry();
- };
- THREE.ShadowVolume.prototype = new THREE.Mesh();
- THREE.ShadowVolume.prototype.constructor = THREE.ShadowVolume;
- THREE.ShadowVolume.prototype.supr = THREE.Mesh.prototype;
- /*
- * Calculate Shadow Faces
- */
- THREE.ShadowVolume.prototype.calculateShadowVolumeGeometry = function() {
- if ( this.geometry.edges && this.geometry.edges.length ) {
- var f, fl, face, faceA, faceB, faceAIndex, faceBIndex, vertexA, vertexB;
- var faceACombination, faceBCombination;
- var faceAvertexAIndex, faceAvertexBIndex, faceBvertexAIndex, faceBvertexBIndex;
- var e, el, edge, temp;
- var newGeometry = new THREE.Geometry();
- var vertices = newGeometry.vertices = this.geometry.vertices;
- var faces = newGeometry.faces = this.geometry.faces;
- var edges = newGeometry.egdes = this.geometry.edges;
- var edgeFaces = newGeometry.edgeFaces = [];
- var vertexOffset = 0;
- var vertexOffsetPerFace = [];
- for( f = 0, fl = faces.length; f < fl; f++ ) {
- face = faces[ f ];
- // calculate faces vertex offset
- vertexOffsetPerFace.push( vertexOffset );
- vertexOffset += face instanceof THREE.Face3 ? 3 : 4;
- // set vertex normals to face normal
- face.vertexNormals[ 0 ] = face.normal;
- face.vertexNormals[ 1 ] = face.normal;
- face.vertexNormals[ 2 ] = face.normal;
- if( face instanceof THREE.Face4 ) face.vertexNormals[ 3 ] = face.normal;
- }
- // setup edge faces
- for( e = 0, el = edges.length; e < el; e++ ) {
- edge = edges[ e ];
- faceA = edge.faces[ 0 ];
- faceB = edge.faces[ 1 ];
- faceAIndex = edge.faceIndices[ 0 ];
- faceBIndex = edge.faceIndices[ 1 ];
- vertexA = edge.vertexIndices[ 0 ];
- vertexB = edge.vertexIndices[ 1 ];
- // find combination and processed vertex index (vertices are split up by renderer)
- if( faceA.a === vertexA ) { faceACombination = "a"; faceAvertexAIndex = vertexOffsetPerFace[ faceAIndex ] + 0; }
- else if( faceA.b === vertexA ) { faceACombination = "b"; faceAvertexAIndex = vertexOffsetPerFace[ faceAIndex ] + 1; }
- else if( faceA.c === vertexA ) { faceACombination = "c"; faceAvertexAIndex = vertexOffsetPerFace[ faceAIndex ] + 2; }
- else if( faceA.d === vertexA ) { faceACombination = "d"; faceAvertexAIndex = vertexOffsetPerFace[ faceAIndex ] + 3; }
- if( faceA.a === vertexB ) { faceACombination += "a"; faceAvertexBIndex = vertexOffsetPerFace[ faceAIndex ] + 0; }
- else if( faceA.b === vertexB ) { faceACombination += "b"; faceAvertexBIndex = vertexOffsetPerFace[ faceAIndex ] + 1; }
- else if( faceA.c === vertexB ) { faceACombination += "c"; faceAvertexBIndex = vertexOffsetPerFace[ faceAIndex ] + 2; }
- else if( faceA.d === vertexB ) { faceACombination += "d"; faceAvertexBIndex = vertexOffsetPerFace[ faceAIndex ] + 3; }
- if( faceB.a === vertexA ) { faceBCombination = "a"; faceBvertexAIndex = vertexOffsetPerFace[ faceBIndex ] + 0; }
- else if( faceB.b === vertexA ) { faceBCombination = "b"; faceBvertexAIndex = vertexOffsetPerFace[ faceBIndex ] + 1; }
- else if( faceB.c === vertexA ) { faceBCombination = "c"; faceBvertexAIndex = vertexOffsetPerFace[ faceBIndex ] + 2; }
- else if( faceB.d === vertexA ) { faceBCombination = "d"; faceBvertexAIndex = vertexOffsetPerFace[ faceBIndex ] + 3; }
- if( faceB.a === vertexB ) { faceBCombination += "a"; faceBvertexBIndex = vertexOffsetPerFace[ faceBIndex ] + 0; }
- else if( faceB.b === vertexB ) { faceBCombination += "b"; faceBvertexBIndex = vertexOffsetPerFace[ faceBIndex ] + 1; }
- else if( faceB.c === vertexB ) { faceBCombination += "c"; faceBvertexBIndex = vertexOffsetPerFace[ faceBIndex ] + 2; }
- else if( faceB.d === vertexB ) { faceBCombination += "d"; faceBvertexBIndex = vertexOffsetPerFace[ faceBIndex ] + 3; }
- if( faceACombination === "ac" ||
- faceACombination === "ad" ||
- faceACombination === "ca" ||
- faceACombination === "da" ) {
- if( faceAvertexAIndex > faceAvertexBIndex ) {
- temp = faceAvertexAIndex;
- faceAvertexAIndex = faceAvertexBIndex;
- faceAvertexBIndex = temp;
- }
- } else {
- if( faceAvertexAIndex < faceAvertexBIndex ) {
- temp = faceAvertexAIndex;
- faceAvertexAIndex = faceAvertexBIndex;
- faceAvertexBIndex = temp;
- }
- }
- if( faceBCombination === "ac" ||
- faceBCombination === "ad" ||
- faceBCombination === "ca" ||
- faceBCombination === "da" ) {
- if( faceBvertexAIndex > faceBvertexBIndex ) {
- temp = faceBvertexAIndex;
- faceBvertexAIndex = faceBvertexBIndex;
- faceBvertexBIndex = temp;
- }
- } else {
- if( faceBvertexAIndex < faceBvertexBIndex ) {
- temp = faceBvertexAIndex;
- faceBvertexAIndex = faceBvertexBIndex;
- faceBvertexBIndex = temp;
- }
- }
- face = new THREE.Face4( faceAvertexAIndex, faceAvertexBIndex, faceBvertexAIndex, faceBvertexBIndex );
- face.normal.set( 1, 0, 0 );
- edgeFaces.push( face );
- }
- this.geometry = newGeometry;
- } else {
- this.calculateShadowVolumeGeometryWithoutEdgeInfo( this.geometry );
- }
- }
- THREE.ShadowVolume.prototype.calculateShadowVolumeGeometryWithoutEdgeInfo = function( originalGeometry ) {
- // create geometry
- this.geometry = new THREE.Geometry();
- this.geometry.boundingSphere = originalGeometry.boundingSphere;
- this.geometry.edgeFaces = [];
- // copy vertices / faces from original mesh
- var vertexTypes = this.geometry.vertexTypes;
- var vertices = this.geometry.vertices;
- var faces = this.geometry.faces;
- var edgeFaces = this.geometry.edgeFaces;
- var originalFaces = originalGeometry.faces;
- var originalVertices = originalGeometry.vertices;
- var fl = originalFaces.length;
- var originalFace, face, i, f, n, vertex, numVertices;
- var indices = [ "a", "b", "c", "d" ];
- for( f = 0; f < fl; f++ ) {
- numVertices = vertices.length;
- originalFace = originalFaces[ f ];
- if ( originalFace instanceof THREE.Face4 ) {
- n = 4;
- face = new THREE.Face4( numVertices, numVertices + 1, numVertices + 2, numVertices + 3 );
- } else {
- n = 3;
- face = new THREE.Face3( numVertices, numVertices + 1, numVertices + 2 );
- }
- face.normal.copy( originalFace.normal );
- faces.push( face );
- for( i = 0; i < n; i++ ) {
- vertex = originalVertices[ originalFace[ indices[ i ]]];
- vertices.push( new THREE.Vertex( vertex.position.clone()));
- }
- }
- // calculate edge faces
- var result, faceA, faceB, v, vl;
- for( var fa = 0; fa < originalFaces.length - 1; fa++ ) {
- faceA = faces[ fa ];
- for( var fb = fa + 1; fb < originalFaces.length; fb++ ) {
- faceB = faces[ fb ];
- result = this.facesShareEdge( vertices, faceA, faceB );
- if( result !== undefined ) {
- numVertices = vertices.length;
- face = new THREE.Face4( result.indices[ 0 ], result.indices[ 3 ], result.indices[ 2 ], result.indices[ 1 ] );
- face.normal.set( 1, 0, 0 );
- edgeFaces.push( face );
- }
- }
- }
- };
- THREE.ShadowVolume.prototype.facesShareEdge = function( vertices, faceA, faceB ) {
- var indicesA,
- indicesB,
- indexA,
- indexB,
- vertexA,
- vertexB,
- savedVertexA,
- savedVertexB,
- savedIndexA,
- savedIndexB,
- indexLetters,
- a, b,
- numMatches = 0,
- indices = [ "a", "b", "c", "d" ];
- if( faceA instanceof THREE.Face4 ) indicesA = 4;
- else indicesA = 3;
- if( faceB instanceof THREE.Face4 ) indicesB = 4;
- else indicesB = 3;
- for( a = 0; a < indicesA; a++ ) {
- indexA = faceA[ indices[ a ] ];
- vertexA = vertices[ indexA ];
- for( b = 0; b < indicesB; b++ ) {
- indexB = faceB[ indices[ b ] ];
- vertexB = vertices[ indexB ];
- if( Math.abs( vertexA.position.x - vertexB.position.x ) < 0.0001 &&
- Math.abs( vertexA.position.y - vertexB.position.y ) < 0.0001 &&
- Math.abs( vertexA.position.z - vertexB.position.z ) < 0.0001 ) {
- numMatches++;
- if( numMatches === 1 ) {
- savedVertexA = vertexA;
- savedVertexB = vertexB;
- savedIndexA = indexA;
- savedIndexB = indexB;
- indexLetters = indices[ a ];
- }
- if( numMatches === 2 ) {
- indexLetters += indices[ a ];
- if( indexLetters === "ad" || indexLetters === "ac" ) {
- return {
- faces : [ faceA, faceB ],
- vertices : [ savedVertexA, savedVertexB, vertexB, vertexA ],
- indices : [ savedIndexA, savedIndexB, indexB, indexA ],
- vertexTypes : [ 1, 2, 2, 1 ],
- extrudable : true
- };
- } else {
- return {
- faces : [ faceA, faceB ],
- vertices : [ savedVertexA, vertexA, vertexB, savedVertexB ],
- indices : [ savedIndexA, indexA, indexB, savedIndexB ],
- vertexTypes : [ 1, 1, 2, 2 ],
- extrudable : true
- };
- }
- }
- }
- }
- }
- return undefined;
- };
|