未验证 提交 341a5c94 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #20855 from Mcgode/edge-split-upgrade

EdgeSplitModifier - Support other attributes
THREE.EdgeSplitModifier = function () {
var A = new THREE.Vector3();
......@@ -153,6 +152,7 @@ THREE.EdgeSplitModifier = function () {
this.modify = function ( geometry, cutOffAngle ) {
const wasNotBufferGeometry = geometry.isBufferGeometry === undefined;
if ( ! geometry.isBufferGeometry ) {
geometry = new THREE.BufferGeometry().fromGeometry( geometry );
......@@ -160,6 +160,19 @@ THREE.EdgeSplitModifier = function () {
}
let hadNormals = false;
if ( geometry.attributes.normal ) {
hadNormals = true;
if ( wasNotBufferGeometry === false )
geometry = geometry.clone();
geometry.deleteAttribute( 'normal' );
}
if ( geometry.index == null ) {
if ( THREE.BufferGeometryUtils === undefined ) {
......@@ -178,7 +191,6 @@ THREE.EdgeSplitModifier = function () {
computeNormals();
mapPositionsToIndexes();
splitIndexes = [];
for ( var vertexIndexes of pointToIndexMap ) {
......@@ -187,9 +199,15 @@ THREE.EdgeSplitModifier = function () {
}
var newPositions = new Float32Array( positions.length + 3 * splitIndexes.length );
newPositions.set( positions );
var offset = positions.length;
const newAttributes = {};
for ( const name of Object.keys( geometry.attributes ) ) {
const oldAttribute = geometry.attributes[ name ];
const newArray = new oldAttribute.array.constructor( ( indexes.length + splitIndexes.length ) * oldAttribute.itemSize );
newArray.set( oldAttribute.array );
newAttributes[ name ] = new THREE.BufferAttribute( newArray, oldAttribute.itemSize, oldAttribute.normalized );
}
var newIndexes = new Uint32Array( indexes.length );
newIndexes.set( indexes );
......@@ -199,22 +217,40 @@ THREE.EdgeSplitModifier = function () {
var split = splitIndexes[ i ];
var index = indexes[ split.original ];
newPositions[ offset + 3 * i ] = positions[ 3 * index ];
newPositions[ offset + 3 * i + 1 ] = positions[ 3 * index + 1 ];
newPositions[ offset + 3 * i + 2 ] = positions[ 3 * index + 2 ];
for ( const attribute of Object.values( newAttributes ) ) {
for ( let j = 0; j < attribute.itemSize; j ++ ) {
attribute.array[ ( indexes.length + i ) * attribute.itemSize + j ] =
attribute.array[ index * attribute.itemSize + j ];
}
}
for ( var j of split.indexes ) {
newIndexes[ j ] = offset / 3 + i;
newIndexes[ j ] = indexes.length + i;
}
}
geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.BufferAttribute( newPositions, 3, true ) );
geometry.setIndex( new THREE.BufferAttribute( newIndexes, 1 ) );
for ( const name of Object.keys( newAttributes ) ) {
geometry.setAttribute( name, newAttributes[ name ] );
}
if ( hadNormals ) {
geometry.computeVertexNormals();
}
return geometry;
};
......
......@@ -160,6 +160,7 @@ var EdgeSplitModifier = function () {
this.modify = function ( geometry, cutOffAngle ) {
const wasNotBufferGeometry = geometry.isBufferGeometry === undefined;
if ( ! geometry.isBufferGeometry ) {
geometry = new BufferGeometry().fromGeometry( geometry );
......@@ -167,7 +168,20 @@ var EdgeSplitModifier = function () {
}
if ( geometry.index == null ) {
let hadNormals = false;
if ( geometry.attributes.normal ) {
hadNormals = true;
if ( wasNotBufferGeometry === false )
geometry = geometry.clone();
geometry.deleteAttribute( 'normal' );
}
if ( ! geometry.index ) {
if ( BufferGeometryUtils === undefined ) {
......@@ -185,7 +199,6 @@ var EdgeSplitModifier = function () {
computeNormals();
mapPositionsToIndexes();
splitIndexes = [];
for ( var vertexIndexes of pointToIndexMap ) {
......@@ -194,9 +207,15 @@ var EdgeSplitModifier = function () {
}
var newPositions = new Float32Array( positions.length + 3 * splitIndexes.length );
newPositions.set( positions );
var offset = positions.length;
const newAttributes = {};
for ( const name of Object.keys( geometry.attributes ) ) {
const oldAttribute = geometry.attributes[ name ];
const newArray = new oldAttribute.array.constructor( ( indexes.length + splitIndexes.length ) * oldAttribute.itemSize );
newArray.set( oldAttribute.array );
newAttributes[ name ] = new BufferAttribute( newArray, oldAttribute.itemSize, oldAttribute.normalized );
}
var newIndexes = new Uint32Array( indexes.length );
newIndexes.set( indexes );
......@@ -206,22 +225,40 @@ var EdgeSplitModifier = function () {
var split = splitIndexes[ i ];
var index = indexes[ split.original ];
newPositions[ offset + 3 * i ] = positions[ 3 * index ];
newPositions[ offset + 3 * i + 1 ] = positions[ 3 * index + 1 ];
newPositions[ offset + 3 * i + 2 ] = positions[ 3 * index + 2 ];
for ( const attribute of Object.values( newAttributes ) ) {
for ( let j = 0; j < attribute.itemSize; j ++ ) {
attribute.array[ ( indexes.length + i ) * attribute.itemSize + j ] =
attribute.array[ index * attribute.itemSize + j ];
}
}
for ( var j of split.indexes ) {
newIndexes[ j ] = offset / 3 + i;
newIndexes[ j ] = indexes.length + i;
}
}
geometry = new BufferGeometry();
geometry.setAttribute( 'position', new BufferAttribute( newPositions, 3, true ) );
geometry.setIndex( new BufferAttribute( newIndexes, 1 ) );
for ( const name of Object.keys( newAttributes ) ) {
geometry.setAttribute( name, newAttributes[ name ] );
}
if ( hadNormals ) {
geometry.computeVertexNormals();
}
return geometry;
};
......
......@@ -13,19 +13,20 @@
import * as THREE from '../build/three.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { OBJLoader } from "./jsm/loaders/OBJLoader.js";
import { BufferGeometryUtils } from "./jsm/utils/BufferGeometryUtils.js";
import { EdgeSplitModifier } from "./jsm/modifiers/EdgeSplitModifier.js";
import { OBJLoader } from './jsm/loaders/OBJLoader.js';
import { EdgeSplitModifier } from './jsm/modifiers/EdgeSplitModifier.js';
import { GUI } from "./jsm/libs/dat.gui.module.js";
import { GUI } from './jsm/libs/dat.gui.module.js';
let renderer, scene, camera;
let modifier, mesh, baseGeometry;
let map;
const params = {
smoothShading: true,
edgeSplit: true,
cutOffAngle: 20,
showMap: false,
};
init();
......@@ -63,10 +64,8 @@
'./models/obj/cerberus/Cerberus.obj',
function ( group ) {
// Retrieve Cerberus vertex positions only
const modelGeometry = group.children[ 0 ].geometry;
modelGeometry.deleteAttribute( 'normal' );
modelGeometry.deleteAttribute( 'uv' );
const cerberus = group.children[ 0 ];
const modelGeometry = cerberus.geometry;
modifier = new EdgeSplitModifier();
baseGeometry = modelGeometry;
......@@ -78,6 +77,13 @@
mesh.translateZ( 1.5 );
scene.add( mesh );
if ( map !== undefined && params.showMap ) {
mesh.material.map = map;
mesh.material.needsUpdate = true;
}
render();
}
......@@ -85,12 +91,26 @@
window.addEventListener( 'resize', onWindowResize, false );
new THREE.TextureLoader().load( './models/obj/cerberus/Cerberus_A.jpg', function ( texture ) {
map = texture;
if ( mesh !== undefined && params.showMap ) {
mesh.material.map = map;
mesh.material.needsUpdate = true;
}
} );
const gui = new GUI( { name: "Edge split modifier parameters" } );
const gui = new GUI( { name: 'Edge split modifier parameters' } );
gui.add( params, "smoothShading" ).onFinishChange( updateMesh );
gui.add( params, "edgeSplit" ).onFinishChange( updateMesh );
gui.add( params, "cutOffAngle" ).min( 0 ).max( 180 ).onFinishChange( updateMesh );
gui.add( params, 'showMap' ).onFinishChange( updateMesh );
gui.add( params, 'smoothShading' ).onFinishChange( updateMesh );
gui.add( params, 'edgeSplit' ).onFinishChange( updateMesh );
gui.add( params, 'cutOffAngle' ).min( 0 ).max( 180 ).onFinishChange( updateMesh );
}
......@@ -116,12 +136,10 @@
} else {
geometry = BufferGeometryUtils.mergeVertices( baseGeometry );
geometry = baseGeometry;
}
geometry.computeVertexNormals();
return geometry;
}
......@@ -129,12 +147,25 @@
function updateMesh() {
mesh.geometry = getGeometry();
if ( mesh !== undefined ) {
mesh.material.flatShading = params.smoothShading === false;
mesh.material.needsUpdate = true;
mesh.geometry = getGeometry();
render();
let needsUpdate = mesh.material.flatShading === params.smoothShading;
mesh.material.flatShading = params.smoothShading === false;
if ( map !== undefined ) {
needsUpdate = needsUpdate || mesh.material.map !== ( params.showMap ? map : null );
mesh.material.map = params.showMap ? map : null;
}
mesh.material.needsUpdate = needsUpdate;
render();
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册