Skip to content

Commit 341a5c9

Browse files
authored
Merge pull request #20855 from Mcgode/edge-split-upgrade
EdgeSplitModifier - Support other attributes
2 parents 606b7f0 + a78bfb1 commit 341a5c9

File tree

3 files changed

+143
-39
lines changed

3 files changed

+143
-39
lines changed

examples/js/modifiers/EdgeSplitModifier.js

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
THREE.EdgeSplitModifier = function () {
32

43
var A = new THREE.Vector3();
@@ -153,13 +152,27 @@ THREE.EdgeSplitModifier = function () {
153152

154153
this.modify = function ( geometry, cutOffAngle ) {
155154

155+
const wasNotBufferGeometry = geometry.isBufferGeometry === undefined;
156156
if ( ! geometry.isBufferGeometry ) {
157157

158158
geometry = new THREE.BufferGeometry().fromGeometry( geometry );
159159

160160
}
161161

162162

163+
let hadNormals = false;
164+
if ( geometry.attributes.normal ) {
165+
166+
hadNormals = true;
167+
168+
if ( wasNotBufferGeometry === false )
169+
geometry = geometry.clone();
170+
171+
geometry.deleteAttribute( 'normal' );
172+
173+
}
174+
175+
163176
if ( geometry.index == null ) {
164177

165178
if ( THREE.BufferGeometryUtils === undefined ) {
@@ -178,7 +191,6 @@ THREE.EdgeSplitModifier = function () {
178191
computeNormals();
179192
mapPositionsToIndexes();
180193

181-
182194
splitIndexes = [];
183195

184196
for ( var vertexIndexes of pointToIndexMap ) {
@@ -187,9 +199,15 @@ THREE.EdgeSplitModifier = function () {
187199

188200
}
189201

190-
var newPositions = new Float32Array( positions.length + 3 * splitIndexes.length );
191-
newPositions.set( positions );
192-
var offset = positions.length;
202+
const newAttributes = {};
203+
for ( const name of Object.keys( geometry.attributes ) ) {
204+
205+
const oldAttribute = geometry.attributes[ name ];
206+
const newArray = new oldAttribute.array.constructor( ( indexes.length + splitIndexes.length ) * oldAttribute.itemSize );
207+
newArray.set( oldAttribute.array );
208+
newAttributes[ name ] = new THREE.BufferAttribute( newArray, oldAttribute.itemSize, oldAttribute.normalized );
209+
210+
}
193211

194212
var newIndexes = new Uint32Array( indexes.length );
195213
newIndexes.set( indexes );
@@ -199,22 +217,40 @@ THREE.EdgeSplitModifier = function () {
199217
var split = splitIndexes[ i ];
200218
var index = indexes[ split.original ];
201219

202-
newPositions[ offset + 3 * i ] = positions[ 3 * index ];
203-
newPositions[ offset + 3 * i + 1 ] = positions[ 3 * index + 1 ];
204-
newPositions[ offset + 3 * i + 2 ] = positions[ 3 * index + 2 ];
220+
for ( const attribute of Object.values( newAttributes ) ) {
221+
222+
for ( let j = 0; j < attribute.itemSize; j ++ ) {
223+
224+
attribute.array[ ( indexes.length + i ) * attribute.itemSize + j ] =
225+
attribute.array[ index * attribute.itemSize + j ];
226+
227+
}
228+
229+
}
205230

206231
for ( var j of split.indexes ) {
207232

208-
newIndexes[ j ] = offset / 3 + i;
233+
newIndexes[ j ] = indexes.length + i;
209234

210235
}
211236

212237
}
213238

214239
geometry = new THREE.BufferGeometry();
215-
geometry.setAttribute( 'position', new THREE.BufferAttribute( newPositions, 3, true ) );
216240
geometry.setIndex( new THREE.BufferAttribute( newIndexes, 1 ) );
217241

242+
for ( const name of Object.keys( newAttributes ) ) {
243+
244+
geometry.setAttribute( name, newAttributes[ name ] );
245+
246+
}
247+
248+
if ( hadNormals ) {
249+
250+
geometry.computeVertexNormals();
251+
252+
}
253+
218254
return geometry;
219255

220256
};

examples/jsm/modifiers/EdgeSplitModifier.js

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,28 @@ var EdgeSplitModifier = function () {
160160

161161
this.modify = function ( geometry, cutOffAngle ) {
162162

163+
const wasNotBufferGeometry = geometry.isBufferGeometry === undefined;
163164
if ( ! geometry.isBufferGeometry ) {
164165

165166
geometry = new BufferGeometry().fromGeometry( geometry );
166167

167168
}
168169

169170

170-
if ( geometry.index == null ) {
171+
let hadNormals = false;
172+
if ( geometry.attributes.normal ) {
173+
174+
hadNormals = true;
175+
176+
if ( wasNotBufferGeometry === false )
177+
geometry = geometry.clone();
178+
179+
geometry.deleteAttribute( 'normal' );
180+
181+
}
182+
183+
184+
if ( ! geometry.index ) {
171185

172186
if ( BufferGeometryUtils === undefined ) {
173187

@@ -185,7 +199,6 @@ var EdgeSplitModifier = function () {
185199
computeNormals();
186200
mapPositionsToIndexes();
187201

188-
189202
splitIndexes = [];
190203

191204
for ( var vertexIndexes of pointToIndexMap ) {
@@ -194,9 +207,15 @@ var EdgeSplitModifier = function () {
194207

195208
}
196209

197-
var newPositions = new Float32Array( positions.length + 3 * splitIndexes.length );
198-
newPositions.set( positions );
199-
var offset = positions.length;
210+
const newAttributes = {};
211+
for ( const name of Object.keys( geometry.attributes ) ) {
212+
213+
const oldAttribute = geometry.attributes[ name ];
214+
const newArray = new oldAttribute.array.constructor( ( indexes.length + splitIndexes.length ) * oldAttribute.itemSize );
215+
newArray.set( oldAttribute.array );
216+
newAttributes[ name ] = new BufferAttribute( newArray, oldAttribute.itemSize, oldAttribute.normalized );
217+
218+
}
200219

201220
var newIndexes = new Uint32Array( indexes.length );
202221
newIndexes.set( indexes );
@@ -206,22 +225,40 @@ var EdgeSplitModifier = function () {
206225
var split = splitIndexes[ i ];
207226
var index = indexes[ split.original ];
208227

209-
newPositions[ offset + 3 * i ] = positions[ 3 * index ];
210-
newPositions[ offset + 3 * i + 1 ] = positions[ 3 * index + 1 ];
211-
newPositions[ offset + 3 * i + 2 ] = positions[ 3 * index + 2 ];
228+
for ( const attribute of Object.values( newAttributes ) ) {
229+
230+
for ( let j = 0; j < attribute.itemSize; j ++ ) {
231+
232+
attribute.array[ ( indexes.length + i ) * attribute.itemSize + j ] =
233+
attribute.array[ index * attribute.itemSize + j ];
234+
235+
}
236+
237+
}
212238

213239
for ( var j of split.indexes ) {
214240

215-
newIndexes[ j ] = offset / 3 + i;
241+
newIndexes[ j ] = indexes.length + i;
216242

217243
}
218244

219245
}
220246

221247
geometry = new BufferGeometry();
222-
geometry.setAttribute( 'position', new BufferAttribute( newPositions, 3, true ) );
223248
geometry.setIndex( new BufferAttribute( newIndexes, 1 ) );
224249

250+
for ( const name of Object.keys( newAttributes ) ) {
251+
252+
geometry.setAttribute( name, newAttributes[ name ] );
253+
254+
}
255+
256+
if ( hadNormals ) {
257+
258+
geometry.computeVertexNormals();
259+
260+
}
261+
225262
return geometry;
226263

227264
};

examples/webgl_modifier_edgesplit.html

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,20 @@
1313
import * as THREE from '../build/three.module.js';
1414

1515
import { OrbitControls } from './jsm/controls/OrbitControls.js';
16-
import { OBJLoader } from "./jsm/loaders/OBJLoader.js";
17-
import { BufferGeometryUtils } from "./jsm/utils/BufferGeometryUtils.js";
18-
import { EdgeSplitModifier } from "./jsm/modifiers/EdgeSplitModifier.js";
16+
import { OBJLoader } from './jsm/loaders/OBJLoader.js';
17+
import { EdgeSplitModifier } from './jsm/modifiers/EdgeSplitModifier.js';
1918

20-
import { GUI } from "./jsm/libs/dat.gui.module.js";
19+
import { GUI } from './jsm/libs/dat.gui.module.js';
2120

2221
let renderer, scene, camera;
2322
let modifier, mesh, baseGeometry;
23+
let map;
2424

2525
const params = {
2626
smoothShading: true,
2727
edgeSplit: true,
2828
cutOffAngle: 20,
29+
showMap: false,
2930
};
3031

3132
init();
@@ -63,10 +64,8 @@
6364
'./models/obj/cerberus/Cerberus.obj',
6465
function ( group ) {
6566

66-
// Retrieve Cerberus vertex positions only
67-
const modelGeometry = group.children[ 0 ].geometry;
68-
modelGeometry.deleteAttribute( 'normal' );
69-
modelGeometry.deleteAttribute( 'uv' );
67+
const cerberus = group.children[ 0 ];
68+
const modelGeometry = cerberus.geometry;
7069

7170
modifier = new EdgeSplitModifier();
7271
baseGeometry = modelGeometry;
@@ -78,19 +77,40 @@
7877
mesh.translateZ( 1.5 );
7978
scene.add( mesh );
8079

80+
if ( map !== undefined && params.showMap ) {
81+
82+
mesh.material.map = map;
83+
mesh.material.needsUpdate = true;
84+
85+
}
86+
8187
render();
8288

8389
}
8490
);
8591

8692
window.addEventListener( 'resize', onWindowResize, false );
8793

94+
new THREE.TextureLoader().load( './models/obj/cerberus/Cerberus_A.jpg', function ( texture ) {
95+
96+
map = texture;
97+
98+
if ( mesh !== undefined && params.showMap ) {
99+
100+
mesh.material.map = map;
101+
mesh.material.needsUpdate = true;
102+
103+
}
104+
105+
} );
106+
88107

89-
const gui = new GUI( { name: "Edge split modifier parameters" } );
108+
const gui = new GUI( { name: 'Edge split modifier parameters' } );
90109

91-
gui.add( params, "smoothShading" ).onFinishChange( updateMesh );
92-
gui.add( params, "edgeSplit" ).onFinishChange( updateMesh );
93-
gui.add( params, "cutOffAngle" ).min( 0 ).max( 180 ).onFinishChange( updateMesh );
110+
gui.add( params, 'showMap' ).onFinishChange( updateMesh );
111+
gui.add( params, 'smoothShading' ).onFinishChange( updateMesh );
112+
gui.add( params, 'edgeSplit' ).onFinishChange( updateMesh );
113+
gui.add( params, 'cutOffAngle' ).min( 0 ).max( 180 ).onFinishChange( updateMesh );
94114

95115
}
96116

@@ -116,25 +136,36 @@
116136

117137
} else {
118138

119-
geometry = BufferGeometryUtils.mergeVertices( baseGeometry );
139+
geometry = baseGeometry;
120140

121141
}
122142

123-
geometry.computeVertexNormals();
124-
125143
return geometry;
126144

127145
}
128146

129147

130148
function updateMesh() {
131149

132-
mesh.geometry = getGeometry();
150+
if ( mesh !== undefined ) {
133151

134-
mesh.material.flatShading = params.smoothShading === false;
135-
mesh.material.needsUpdate = true;
152+
mesh.geometry = getGeometry();
136153

137-
render();
154+
let needsUpdate = mesh.material.flatShading === params.smoothShading;
155+
mesh.material.flatShading = params.smoothShading === false;
156+
157+
if ( map !== undefined ) {
158+
159+
needsUpdate = needsUpdate || mesh.material.map !== ( params.showMap ? map : null );
160+
mesh.material.map = params.showMap ? map : null;
161+
162+
}
163+
164+
mesh.material.needsUpdate = needsUpdate;
165+
166+
render();
167+
168+
}
138169

139170
}
140171

0 commit comments

Comments
 (0)