提交 0d91aa4e 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #10876 from Mugen87/decal

New DecalGeometry
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<base href="../../" />
<script src="list.js"></script>
<script src="page.js"></script>
<link type="text/css" rel="stylesheet" href="page.css" />
</head>
<body>
[page:BufferGeometry] &rarr;
<h1>[name]</h1>
<div class="desc"> You can use this geometry to create a decal mesh, that serves different kinds of purposes e.g.:
adding unique details to models, performing dynamic visual environmental changes or covering seams. </div>
<h2>Example</h2>
[example:webgl_decals decals]
<code>var geometry = new THREE.DecalGeometry( mesh, position, orientation, size );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var decal = new THREE.Mesh( geometry, material );
scene.add( decal );
</code>
<h2>Constructor</h2>
<h3>[name]( [page:Mesh mesh], [page:Vector3 position], [page:Euler orientation], [page:Vector3 size] )</h3>
<div>
mesh — Any mesh object.<br />
position — Position of the decal projector.<br />
orientation — Orientation of the decal projector.<br />
size — Size of the decal projector.<br />
</div>
<h2>Source</h2>
[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
</body>
</html>
...@@ -140,6 +140,7 @@ var list = { ...@@ -140,6 +140,7 @@ var list = {
[ "ConeGeometry", "api/geometries/ConeGeometry" ], [ "ConeGeometry", "api/geometries/ConeGeometry" ],
[ "CylinderBufferGeometry", "api/geometries/CylinderBufferGeometry" ], [ "CylinderBufferGeometry", "api/geometries/CylinderBufferGeometry" ],
[ "CylinderGeometry", "api/geometries/CylinderGeometry" ], [ "CylinderGeometry", "api/geometries/CylinderGeometry" ],
[ "DecalGeometry", "api/geometries/DecalGeometry" ],
[ "DodecahedronBufferGeometry", "api/geometries/DodecahedronBufferGeometry" ], [ "DodecahedronBufferGeometry", "api/geometries/DodecahedronBufferGeometry" ],
[ "DodecahedronGeometry", "api/geometries/DodecahedronGeometry" ], [ "DodecahedronGeometry", "api/geometries/DodecahedronGeometry" ],
[ "EdgesGeometry", "api/geometries/EdgesGeometry" ], [ "EdgesGeometry", "api/geometries/EdgesGeometry" ],
......
THREE.DecalVertex = function( v, n ) {
this.vertex = v;
this.normal = n;
};
THREE.DecalVertex.prototype.clone = function() {
return new THREE.DecalVertex( this.vertex.clone(), this.normal.clone() );
};
THREE.DecalGeometry = function( mesh, position, rotation, dimensions, check ) {
THREE.Geometry.call( this );
if ( check === undefined ) check = null;
check = check || new THREE.Vector3( 1, 1, 1 );
this.uvs = [];
this.cube = new THREE.Mesh( new THREE.BoxGeometry( dimensions.x, dimensions.y, dimensions.z ), new THREE.MeshBasicMaterial() );
this.cube.rotation.set( rotation.x, rotation.y, rotation.z );
this.cube.position.copy( position );
this.cube.scale.set( 1, 1, 1 );
this.cube.updateMatrix();
this.iCubeMatrix = ( new THREE.Matrix4() ).getInverse( this.cube.matrix );
this.faceIndices = [ 'a', 'b', 'c', 'd' ];
this.clipFace = function( inVertices, plane ) {
var size = .5 * Math.abs( ( dimensions.clone() ).dot( plane ) );
function clip( v0, v1, p ) {
var d0 = v0.vertex.dot( p ) - size,
d1 = v1.vertex.dot( p ) - size;
var s = d0 / ( d0 - d1 );
var v = new THREE.DecalVertex(
new THREE.Vector3(
v0.vertex.x + s * ( v1.vertex.x - v0.vertex.x ),
v0.vertex.y + s * ( v1.vertex.y - v0.vertex.y ),
v0.vertex.z + s * ( v1.vertex.z - v0.vertex.z )
),
new THREE.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;
}
if ( inVertices.length === 0 ) return [];
var outVertices = [];
for ( var j = 0; j < inVertices.length; j += 3 ) {
var v1Out, v2Out, v3Out, total = 0;
var d1 = inVertices[ j + 0 ].vertex.dot( plane ) - size,
d2 = inVertices[ j + 1 ].vertex.dot( plane ) - size,
d3 = inVertices[ j + 2 ].vertex.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: {
var nV1, nV2, nV3, nV4;
if ( v1Out ) {
nV1 = inVertices[ j + 1 ];
nV2 = inVertices[ j + 2 ];
nV3 = clip( inVertices[ j ], nV1, plane );
nV4 = clip( inVertices[ j ], nV2, plane );
}
if ( v2Out ) {
nV1 = inVertices[ j ];
nV2 = inVertices[ j + 2 ];
nV3 = clip( inVertices[ j + 1 ], nV1, plane );
nV4 = clip( inVertices[ j + 1 ], nV2, plane );
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 );
nV4 = clip( inVertices[ j + 2 ], nV2, plane );
}
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: {
var nV1, nV2, nV3;
if ( ! v1Out ) {
nV1 = inVertices[ j ].clone();
nV2 = clip( nV1, inVertices[ j + 1 ], plane );
nV3 = clip( nV1, inVertices[ j + 2 ], plane );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
if ( ! v2Out ) {
nV1 = inVertices[ j + 1 ].clone();
nV2 = clip( nV1, inVertices[ j + 2 ], plane );
nV3 = clip( nV1, inVertices[ j ], plane );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
if ( ! v3Out ) {
nV1 = inVertices[ j + 2 ].clone();
nV2 = clip( nV1, inVertices[ j ], plane );
nV3 = clip( nV1, inVertices[ j + 1 ], plane );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
break;
}
case 3: {
break;
}
}
}
return outVertices;
};
this.pushVertex = function( vertices, id, n ) {
var v = mesh.geometry.vertices[ id ].clone();
v.applyMatrix4( mesh.matrix );
v.applyMatrix4( this.iCubeMatrix );
vertices.push( new THREE.DecalVertex( v, n.clone() ) );
};
this.computeDecal = function() {
var finalVertices = [];
for ( var i = 0; i < mesh.geometry.faces.length; i ++ ) {
var f = mesh.geometry.faces[ i ];
var vertices = [];
this.pushVertex( vertices, f[ this.faceIndices[ 0 ] ], f.vertexNormals[ 0 ] );
this.pushVertex( vertices, f[ this.faceIndices[ 1 ] ], f.vertexNormals[ 1 ] );
this.pushVertex( vertices, f[ this.faceIndices[ 2 ] ], f.vertexNormals[ 2 ] );
if ( check.x ) {
vertices = this.clipFace( vertices, new THREE.Vector3( 1, 0, 0 ) );
vertices = this.clipFace( vertices, new THREE.Vector3( - 1, 0, 0 ) );
}
if ( check.y ) {
vertices = this.clipFace( vertices, new THREE.Vector3( 0, 1, 0 ) );
vertices = this.clipFace( vertices, new THREE.Vector3( 0, - 1, 0 ) );
}
if ( check.z ) {
vertices = this.clipFace( vertices, new THREE.Vector3( 0, 0, 1 ) );
vertices = this.clipFace( vertices, new THREE.Vector3( 0, 0, - 1 ) );
}
for ( var j = 0; j < vertices.length; j ++ ) {
var v = vertices[ j ];
this.uvs.push( new THREE.Vector2(
.5 + ( v.vertex.x / dimensions.x ),
.5 + ( v.vertex.y / dimensions.y )
) );
vertices[ j ].vertex.applyMatrix4( this.cube.matrix );
}
if ( vertices.length === 0 ) continue;
finalVertices = finalVertices.concat( vertices );
}
for ( var k = 0; k < finalVertices.length; k += 3 ) {
this.vertices.push(
finalVertices[ k ].vertex,
finalVertices[ k + 1 ].vertex,
finalVertices[ k + 2 ].vertex
);
var f = new THREE.Face3(
k,
k + 1,
k + 2
);
f.vertexNormals.push( finalVertices[ k + 0 ].normal );
f.vertexNormals.push( finalVertices[ k + 1 ].normal );
f.vertexNormals.push( finalVertices[ k + 2 ].normal );
this.faces.push( f );
this.faceVertexUvs[ 0 ].push( [
this.uvs[ k ],
this.uvs[ k + 1 ],
this.uvs[ k + 2 ]
] );
}
this.verticesNeedUpdate = true;
this.elementsNeedUpdate = true;
this.morphTargetsNeedUpdate = true;
this.uvsNeedUpdate = true;
this.normalsNeedUpdate = true;
this.colorsNeedUpdate = true;
this.computeFaceNormals();
};
this.computeDecal();
};
THREE.DecalGeometry.prototype = Object.create( THREE.Geometry.prototype );
THREE.DecalGeometry.prototype.constructor = THREE.DecalGeometry;
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>WebGL decals</title> <title>three.js webgl - decals - Decal Splatter</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style> <style>
body { body {
color: #fff; background:#777;
padding:0;
margin:0;
font-weight: bold;
overflow:hidden;
}
#info {
position: absolute;
top: 0px;
width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace; font-family:Monospace;
font-size:13px; font-size:13px;
margin: 0px;
text-align:center; text-align:center;
overflow: hidden;
} }
#info{ position: absolute; width: 100%; padding: 5px; }
a {
color: #ffffff;
}
</style> </style>
</head> </head>
<body> <body>
<div id="container"></div> <div id="container"></div>
<div id="info"> <div id="info"><a href="https://threejs.org" target="_blank">three.js</a> - decals - Decal Splatter (click or tap to shoot)</div>
<p>
<strong>Decal Splatter</strong><br />
Click or tap to shoot.
</p>
</div>
<script src="../build/three.js"></script> <script src="../build/three.js"></script>
<script src="js/geometries/DecalGeometry.js"></script>
<script src="js/controls/OrbitControls.js"></script> <script src="js/controls/OrbitControls.js"></script>
<script src="js/libs/dat.gui.min.js"></script> <script src="js/libs/dat.gui.min.js"></script>
...@@ -67,15 +74,13 @@ ...@@ -67,15 +74,13 @@
} ); } );
var decals = []; var decals = [];
var decalHelper, mouseHelper; var mouseHelper;
var p = new THREE.Vector3( 0, 0, 0 ); var position = new THREE.Vector3();
var r = new THREE.Vector3( 0, 0, 0 ); var orientation = new THREE.Euler();
var s = new THREE.Vector3( 10, 10, 10 ); var size = new THREE.Vector3( 10, 10, 10 );
var up = new THREE.Vector3( 0, 1, 0 ); var up = new THREE.Vector3( 0, 1, 0 );
var check = new THREE.Vector3( 1, 1, 1 );
var params = { var params = {
projection: 'normal',
minScale: 10, minScale: 10,
maxScale: 20, maxScale: 20,
rotate: true, rotate: true,
...@@ -98,7 +103,7 @@ ...@@ -98,7 +103,7 @@
scene = new THREE.Scene(); scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 ); camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 100; camera.position.z = 120;
camera.target = new THREE.Vector3(); camera.target = new THREE.Vector3();
controls = new THREE.OrbitControls( camera, renderer.domElement ); controls = new THREE.OrbitControls( camera, renderer.domElement );
...@@ -148,7 +153,7 @@ ...@@ -148,7 +153,7 @@
window.addEventListener( 'mouseup', function() { window.addEventListener( 'mouseup', function() {
checkIntersection(); checkIntersection();
if ( ! moved ) shoot(); if ( ! moved && intersection.intersects ) shoot();
} ); } );
...@@ -213,7 +218,6 @@ ...@@ -213,7 +218,6 @@
var gui = new dat.GUI(); var gui = new dat.GUI();
gui.add( params, 'projection', { 'From cam to mesh': 'camera', 'Normal to mesh': 'normal' } );
gui.add( params, 'minScale', 1, 30 ); gui.add( params, 'minScale', 1, 30 );
gui.add( params, 'maxScale', 1, 30 ); gui.add( params, 'maxScale', 1, 30 );
gui.add( params, 'rotate' ); gui.add( params, 'rotate' );
...@@ -236,7 +240,6 @@ ...@@ -236,7 +240,6 @@
map: textureLoader.load( 'obj/leeperrysmith/Map-COL.jpg' ), map: textureLoader.load( 'obj/leeperrysmith/Map-COL.jpg' ),
specularMap: textureLoader.load( 'obj/leeperrysmith/Map-SPEC.jpg' ), specularMap: textureLoader.load( 'obj/leeperrysmith/Map-SPEC.jpg' ),
normalMap: textureLoader.load( 'obj/leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg' ), normalMap: textureLoader.load( 'obj/leeperrysmith/Infinite-Level_02_Tangent_SmoothUV.jpg' ),
normalScale: new THREE.Vector2( 0.75, 0.75 ),
shininess: 25 shininess: 25
} ); } );
...@@ -244,50 +247,25 @@ ...@@ -244,50 +247,25 @@
scene.add( mesh ); scene.add( mesh );
mesh.scale.set( 10, 10, 10 ); mesh.scale.set( 10, 10, 10 );
//scene.add( new THREE.FaceNormalsHelper( mesh, 1 ) );
//scene.add( new THREE.VertexNormalsHelper( mesh, 1 ) );
} ); } );
} }
function shoot() { function shoot() {
if ( params.projection == 'camera' ) { position.copy( intersection.point );
orientation.copy( mouseHelper.rotation );
var dir = camera.target.clone();
dir.sub( camera.position );
p = intersection.point;
var m = new THREE.Matrix4(); if ( params.rotate ) orientation.z = Math.random() * 2 * Math.PI;
var c = dir.clone();
c.negate();
c.multiplyScalar( 10 );
c.add( p );
m.lookAt( p, c, up );
m = m.extractRotation( m );
dummy = new THREE.Object3D();
dummy.rotation.setFromRotationMatrix( m );
r.set( dummy.rotation.x, dummy.rotation.y, dummy.rotation.z );
} else {
p = intersection.point;
r.copy( mouseHelper.rotation );
}
var scale = params.minScale + Math.random() * ( params.maxScale - params.minScale ); var scale = params.minScale + Math.random() * ( params.maxScale - params.minScale );
s.set( scale, scale, scale ); size.set( scale, scale, scale );
if ( params.rotate ) r.z = Math.random() * 2 * Math.PI;
var material = decalMaterial.clone(); var material = decalMaterial.clone();
material.color.setHex( Math.random() * 0xffffff ); material.color.setHex( Math.random() * 0xffffff );
var m = new THREE.Mesh( new THREE.DecalGeometry( mesh, p, r, s, check ), material ); var m = new THREE.Mesh( new THREE.DecalGeometry( mesh, position, orientation, size ), material );
decals.push( m ); decals.push( m );
scene.add( m ); scene.add( m );
...@@ -298,36 +276,10 @@ ...@@ -298,36 +276,10 @@
decals.forEach( function( d ) { decals.forEach( function( d ) {
scene.remove( d ); scene.remove( d );
d = null;
} ); } );
decals = [];
}
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 ) { decals = [];
var d = merge[ key ];
var mesh = new THREE.Mesh( d.geometry, d.material );
scene.add( mesh );
decals.push( mesh );
}
} }
......
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
* @author spite / https://github.com/spite
*
* reference: http://blog.wolfire.com/2009/06/how-to-project-decals/
*
*/
function DecalGeometry( mesh, position, orientation, size ) {
BufferGeometry.call( this );
this.type = 'DecalGeometry';
// buffers
var vertices = [];
var normals = [];
var uvs = [];
// helpers
var plane = new Vector3();
// this matrix represents the transformation of the decal projector
var projectorMatrix = new Matrix4();
projectorMatrix.makeRotationFromEuler( orientation );
projectorMatrix.setPosition( position );
var projectorMatrixInverse = new Matrix4().getInverse( projectorMatrix );
// 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;
var geometry = new BufferGeometry();
var decalVertices = [];
var vertex = new Vector3();
var normal = new Vector3();
// handle different geometry types
if ( mesh.geometry.isGeometry ) {
geometry.fromGeometry( mesh.geometry );
} else {
geometry.copy( mesh.geometry );
}
var positionAttribute = geometry.attributes.position;
var normalAttribute = geometry.attributes.normal;
// first, create an array of 'DecalVertex' objects
// three consecutive 'DecalVertex' objects represent a single face
//
// this data structure will be later used to perform the clipping
if ( geometry.index !== null ) {
// indexed BufferGeometry
var index = geometry.index;
for ( i = 0; i < index.count; i ++ ) {
vertex.fromBufferAttribute( positionAttribute, index[ i ] );
normal.fromBufferAttribute( normalAttribute, index[ i ] );
pushDecalVertex( decalVertices, vertex, normal );
}
} else {
// non-indexed BufferGeometry
for ( i = 0; i < positionAttribute.count; i ++ ) {
vertex.fromBufferAttribute( positionAttribute, i );
normal.fromBufferAttribute( normalAttribute, i );
pushDecalVertex( decalVertices, vertex, normal );
}
}
// second, clip the geometry so that it doesn't extend out from the projector
decalVertices = clipGeometry( decalVertices, plane.set( 1, 0, 0 ) );
decalVertices = clipGeometry( decalVertices, plane.set( - 1, 0, 0 ) );
decalVertices = clipGeometry( decalVertices, plane.set( 0, 1, 0 ) );
decalVertices = clipGeometry( decalVertices, plane.set( 0, - 1, 0 ) );
decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, 1 ) );
decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) );
// third, generate final vertices, normals and uvs
for ( i = 0; i < decalVertices.length; i ++ ) {
var decalVertex = decalVertices[ i ];
// create texture coordinates (we are still in projector space)
uvs.push(
0.5 + ( decalVertex.position.x / size.x ),
0.5 + ( decalVertex.position.y / size.y )
);
// transform the vertex back to world space
decalVertex.position.applyMatrix4( projectorMatrix );
// now create vertex and normal buffer data
vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z );
normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z );
}
}
function pushDecalVertex( decalVertices, vertex, normal ) {
// transform the vertex to world space, then to projector space
vertex.applyMatrix4( mesh.matrix );
vertex.applyMatrix4( projectorMatrixInverse );
decalVertices.push( new DecalVertex( vertex.clone(), normal.clone() ) );
}
function clipGeometry( inVertices, plane ) {
var outVertices = [];
var s = 0.5 * Math.abs( size.dot( plane ) );
// a single iteration clips one face,
// which consists of three consecutive 'DecalVertex' objects
for ( var i = 0; i < inVertices.length; i += 3 ) {
var v1Out, v2Out, v3Out, total = 0;
var nV1, nV2, nV3, nV4;
var d1 = inVertices[ i + 0 ].position.dot( plane ) - s;
var d2 = inVertices[ i + 1 ].position.dot( plane ) - s;
var d3 = inVertices[ i + 2 ].position.dot( plane ) - s;
v1Out = d1 > 0;
v2Out = d2 > 0;
v3Out = d3 > 0;
// calculate, how many vertices of the face lie outside of the clipping plane
total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 );
switch ( total ) {
case 0: {
// the entire face lies inside of the plane, no clipping needed
outVertices.push( inVertices[ i ] );
outVertices.push( inVertices[ i + 1 ] );
outVertices.push( inVertices[ i + 2 ] );
break;
}
case 1: {
// one vertex lies outside of the plane, perform clipping
if ( v1Out ) {
nV1 = inVertices[ i + 1 ];
nV2 = inVertices[ i + 2 ];
nV3 = clip( inVertices[ i ], nV1, plane, s );
nV4 = clip( inVertices[ i ], nV2, plane, s );
}
if ( v2Out ) {
nV1 = inVertices[ i ];
nV2 = inVertices[ i + 2 ];
nV3 = clip( inVertices[ i + 1 ], nV1, plane, s );
nV4 = clip( inVertices[ i + 1 ], nV2, plane, s );
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[ i ];
nV2 = inVertices[ i + 1 ];
nV3 = clip( inVertices[ i + 2 ], nV1, plane, s );
nV4 = clip( inVertices[ i + 2 ], nV2, plane, s );
}
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: {
// two vertices lies outside of the plane, perform clipping
if ( ! v1Out ) {
nV1 = inVertices[ i ].clone();
nV2 = clip( nV1, inVertices[ i + 1 ], plane, s );
nV3 = clip( nV1, inVertices[ i + 2 ], plane, s );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
if ( ! v2Out ) {
nV1 = inVertices[ i + 1 ].clone();
nV2 = clip( nV1, inVertices[ i + 2 ], plane, s );
nV3 = clip( nV1, inVertices[ i ], plane, s );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
if ( ! v3Out ) {
nV1 = inVertices[ i + 2 ].clone();
nV2 = clip( nV1, inVertices[ i ], plane, s );
nV3 = clip( nV1, inVertices[ i + 1 ], plane, s );
outVertices.push( nV1 );
outVertices.push( nV2 );
outVertices.push( nV3 );
}
break;
}
case 3: {
// the entire face lies outside of the plane, so let's discard the corresponding vertices
break;
}
}
}
return outVertices;
}
function clip( v0, v1, p, s ) {
var d0 = v0.position.dot( p ) - s;
var d1 = v1.position.dot( p ) - s;
var s0 = d0 / ( d0 - d1 );
var v = new DecalVertex(
new Vector3(
v0.position.x + s0 * ( v1.position.x - v0.position.x ),
v0.position.y + s0 * ( v1.position.y - v0.position.y ),
v0.position.z + s0 * ( v1.position.z - v0.position.z )
),
new Vector3(
v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ),
v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ),
v0.normal.z + s0 * ( 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 };
...@@ -20,3 +20,4 @@ export { ConeGeometry, ConeBufferGeometry } from './ConeGeometry.js'; ...@@ -20,3 +20,4 @@ export { ConeGeometry, ConeBufferGeometry } from './ConeGeometry.js';
export { CylinderGeometry, CylinderBufferGeometry } from './CylinderGeometry.js'; export { CylinderGeometry, CylinderBufferGeometry } from './CylinderGeometry.js';
export { CircleGeometry, CircleBufferGeometry } from './CircleGeometry.js'; export { CircleGeometry, CircleBufferGeometry } from './CircleGeometry.js';
export { BoxGeometry, BoxBufferGeometry } from './BoxGeometry.js'; export { BoxGeometry, BoxBufferGeometry } from './BoxGeometry.js';
export { DecalGeometry } from './DecalGeometry.js';
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册