Skip to content

Commit ecf862c

Browse files
authored
Merge pull request #20903 from Mcgode/edge-split-keep-normals
EdgeSplitModifier - Keep normals
2 parents 341a5c9 + a003059 commit ecf862c

File tree

5 files changed

+80
-6
lines changed

5 files changed

+80
-6
lines changed

examples/js/modifiers/EdgeSplitModifier.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ THREE.EdgeSplitModifier = function () {
77
var positions, normals;
88
var indexes;
99
var pointToIndexMap, splitIndexes;
10+
let oldNormals;
1011

1112

1213
function computeNormals() {
@@ -150,7 +151,7 @@ THREE.EdgeSplitModifier = function () {
150151
}
151152

152153

153-
this.modify = function ( geometry, cutOffAngle ) {
154+
this.modify = function ( geometry, cutOffAngle, tryKeepNormals = true ) {
154155

155156
const wasNotBufferGeometry = geometry.isBufferGeometry === undefined;
156157
if ( ! geometry.isBufferGeometry ) {
@@ -161,13 +162,17 @@ THREE.EdgeSplitModifier = function () {
161162

162163

163164
let hadNormals = false;
165+
oldNormals = null;
164166
if ( geometry.attributes.normal ) {
165167

166168
hadNormals = true;
167169

168170
if ( wasNotBufferGeometry === false )
169171
geometry = geometry.clone();
170172

173+
if ( tryKeepNormals && geometry.index )
174+
oldNormals = geometry.attributes.normal.array;
175+
171176
geometry.deleteAttribute( 'normal' );
172177

173178
}
@@ -249,6 +254,27 @@ THREE.EdgeSplitModifier = function () {
249254

250255
geometry.computeVertexNormals();
251256

257+
if ( oldNormals !== null ) {
258+
259+
const changedNormals = new Array( oldNormals.length / 3 ).fill( false );
260+
261+
for ( const splitData of splitIndexes )
262+
changedNormals[ splitData.original ] = true;
263+
264+
for ( let i = 0; i < changedNormals.length; i ++ ) {
265+
266+
if ( changedNormals[ i ] === false ) {
267+
268+
for ( let j = 0; j < 3; j ++ )
269+
geometry.attributes.normal.array[ 3 * i + j ] = oldNormals[ 3 * i + j ];
270+
271+
}
272+
273+
}
274+
275+
276+
}
277+
252278
}
253279

254280
return geometry;

examples/jsm/modifiers/EdgeSplitModifier.d.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,20 @@ import { BufferGeometry, Geometry } from '../../../src/Three';
33
export class EdgeSplitModifier {
44

55
constructor();
6-
modify( geometry: Geometry, cutOffPoint: number ): BufferGeometry;
6+
7+
8+
/**
9+
* @param geometry The geometry to modify by splitting edges.
10+
* This geometry can be any of any type: Geometry or BufferGeometry, indexed or
11+
* not...
12+
*
13+
* @param cutOffPoint The cutoff angle in radians. If the angle between two face normals is higher
14+
* than this value, a split will be made.
15+
*
16+
* @param [tryKeepNormals = true] Set to true to keep the normal values for vertices that won't be split.
17+
* To use this feature, you also need to pass an indexed geometry with a 'normal'
18+
* BufferAttribute.
19+
*/
20+
modify( geometry: Geometry, cutOffPoint: number, tryKeepNormals: boolean ): BufferGeometry;
721

822
}

examples/jsm/modifiers/EdgeSplitModifier.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ var EdgeSplitModifier = function () {
1616
var indexes;
1717
var pointToIndexMap, splitIndexes;
1818

19+
let oldNormals;
20+
1921

2022
function computeNormals() {
2123

@@ -158,7 +160,7 @@ var EdgeSplitModifier = function () {
158160
}
159161

160162

161-
this.modify = function ( geometry, cutOffAngle ) {
163+
this.modify = function ( geometry, cutOffAngle, tryKeepNormals = true ) {
162164

163165
const wasNotBufferGeometry = geometry.isBufferGeometry === undefined;
164166
if ( ! geometry.isBufferGeometry ) {
@@ -169,13 +171,17 @@ var EdgeSplitModifier = function () {
169171

170172

171173
let hadNormals = false;
174+
oldNormals = null;
172175
if ( geometry.attributes.normal ) {
173176

174177
hadNormals = true;
175178

176179
if ( wasNotBufferGeometry === false )
177180
geometry = geometry.clone();
178181

182+
if ( tryKeepNormals && geometry.index )
183+
oldNormals = geometry.attributes.normal.array;
184+
179185
geometry.deleteAttribute( 'normal' );
180186

181187
}
@@ -257,6 +263,27 @@ var EdgeSplitModifier = function () {
257263

258264
geometry.computeVertexNormals();
259265

266+
if ( oldNormals !== null ) {
267+
268+
const changedNormals = new Array( oldNormals.length / 3 ).fill( false );
269+
270+
for ( const splitData of splitIndexes )
271+
changedNormals[ splitData.original ] = true;
272+
273+
for ( let i = 0; i < changedNormals.length; i ++ ) {
274+
275+
if ( changedNormals[ i ] === false ) {
276+
277+
for ( let j = 0; j < 3; j ++ )
278+
geometry.attributes.normal.array[ 3 * i + j ] = oldNormals[ 3 * i + j ];
279+
280+
}
281+
282+
}
283+
284+
285+
}
286+
260287
}
261288

262289
return geometry;

examples/webgl_modifier_edgesplit.html

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import { OrbitControls } from './jsm/controls/OrbitControls.js';
1616
import { OBJLoader } from './jsm/loaders/OBJLoader.js';
1717
import { EdgeSplitModifier } from './jsm/modifiers/EdgeSplitModifier.js';
18+
import { BufferGeometryUtils } from './jsm/utils/BufferGeometryUtils.js';
1819

1920
import { GUI } from './jsm/libs/dat.gui.module.js';
2021

@@ -27,6 +28,7 @@
2728
edgeSplit: true,
2829
cutOffAngle: 20,
2930
showMap: false,
31+
tryKeepNormals: true,
3032
};
3133

3234
init();
@@ -68,7 +70,7 @@
6870
const modelGeometry = cerberus.geometry;
6971

7072
modifier = new EdgeSplitModifier();
71-
baseGeometry = modelGeometry;
73+
baseGeometry = BufferGeometryUtils.mergeVertices( modelGeometry );
7274

7375
mesh = new THREE.Mesh( getGeometry(), new THREE.MeshStandardMaterial() );
7476
mesh.material.flatShading = ! params.smoothShading;
@@ -111,6 +113,7 @@
111113
gui.add( params, 'smoothShading' ).onFinishChange( updateMesh );
112114
gui.add( params, 'edgeSplit' ).onFinishChange( updateMesh );
113115
gui.add( params, 'cutOffAngle' ).min( 0 ).max( 180 ).onFinishChange( updateMesh );
116+
gui.add( params, 'tryKeepNormals' ).onFinishChange( updateMesh );
114117

115118
}
116119

@@ -132,7 +135,11 @@
132135

133136
if ( params.edgeSplit ) {
134137

135-
geometry = modifier.modify( baseGeometry, params.cutOffAngle * Math.PI / 180 );
138+
geometry = modifier.modify(
139+
baseGeometry,
140+
params.cutOffAngle * Math.PI / 180,
141+
params.tryKeepNormals
142+
);
136143

137144
} else {
138145

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)