@@ -17,11 +17,7 @@ public class BevelEdgesModifier implements IMeshModifier {
1717
1818 public enum WidthType {
1919
20- OFFSET ,
21-
22- WIDTH ,
23-
24- DEPTH ,
20+ OFFSET , WIDTH , DEPTH
2521
2622 }
2723
@@ -37,14 +33,11 @@ public enum WidthType {
3733
3834 private List <Vector3f > verticesToAdd ;
3935
40- private HashMap <Edge3D , Edge3D > oldEdgeToNewEdge ;
41-
42- private HashSet <Edge3D > processed ;
36+ private EdgeProcessor edgeProcessor ;
4337
4438 public BevelEdgesModifier (float amount ) {
4539 setAmount (amount );
46- processed = new HashSet <>();
47- oldEdgeToNewEdge = new HashMap <>();
40+ edgeProcessor = new EdgeProcessor ();
4841 verticesToAdd = new ArrayList <Vector3f >();
4942 facesToAdd = new ArrayList <Face3D >();
5043 }
@@ -55,81 +48,26 @@ public BevelEdgesModifier() {
5548
5649 @ Override
5750 public Mesh3D modify (Mesh3D mesh ) {
58- if (amount == 0 )
51+ validateMesh (mesh );
52+ if (canExitEarly (mesh )) {
5953 return mesh ;
54+ }
55+
6056 setMesh (mesh );
6157 clearAll ();
58+
6259 createInsetFaces ();
60+
6361 createFacesForOldEdges ();
6462 createFacesVertex ();
63+
6564 clearOriginalFaces ();
6665 clearOriginalVertices ();
66+
6767 addNewVertices ();
6868 addNewFaces ();
69- return mesh ;
70- }
71-
72- private void createInsetFaces () {
73- for (Face3D face : mesh .faces )
74- insetFace (mesh , face );
75- }
76-
77- private void insetFace (Mesh3D mesh , Face3D face ) {
78- int nextVertexIndex = verticesToAdd .size ();
79- int [] indices = createIndices (face .indices .length , nextVertexIndex );
80- List <Vector3f > vertices = new ArrayList <Vector3f >();
81- extracted (face , vertices );
82- extracted (vertices );
83- mapOldEdgesToNewEdges (face , indices );
84- addNewFace (indices );
85- }
86-
87- private void extracted (Face3D face , List <Vector3f > vertices ) {
88- for (int i = 0 ; i < face .indices .length ; i ++) {
89- Vector3f from = getVertexAt (face , i );
90- Vector3f to = getVertexAt (face , i + 1 );
91-
92- float distance = to .distance (from );
93- float a = 1 / distance * getAmountByWidthType ();
94-
95- Vector3f v4 = to .subtract (from ).mult (a ).add (from );
96- Vector3f v5 = to .add (to .subtract (from ).mult (-a ));
9769
98- vertices .add (v4 );
99- vertices .add (v5 );
100- }
101- }
102-
103- private float getAmountByWidthType () {
104- float a ;
105- switch (widthType ) {
106- case OFFSET :
107- // amount is offset of new edges from original
108- a = amount * 2 ;
109- break ;
110- case WIDTH :
111- // amount is width of new faces
112- a = inset ;
113- break ;
114- case DEPTH :
115- a = inset * 2 ;
116- break ;
117- default :
118- // default width type offset
119- a = amount * 2 ;
120- break ;
121- }
122- return a ;
123- }
124-
125- private void extracted (List <Vector3f > vertices ) {
126- for (int i = 1 ; i < vertices .size (); i += 2 ) {
127- int a = vertices .size () - 2 + i ;
128- Vector3f v0 = vertices .get (a % vertices .size ());
129- Vector3f v1 = vertices .get ((a + 1 ) % vertices .size ());
130- Vector3f v = v1 .add (v0 ).mult (0.5f );
131- verticesToAdd .add (v );
132- }
70+ return mesh ;
13371 }
13472
13573 private void createFacesVertex () {
@@ -139,7 +77,7 @@ private void createFacesVertex() {
13977 Edge3D edge = outgoingEdge ;
14078 List <Integer > indices = new ArrayList <Integer >();
14179 do {
142- Edge3D newEdge = oldEdgeToNewEdge . get (edge );
80+ Edge3D newEdge = edgeProcessor . getMappedEdge (edge );
14381 int index = newEdge .fromIndex ;
14482 indices .add (index );
14583 edge = helper .getPairNext (edge .fromIndex , edge .toIndex );
@@ -155,33 +93,46 @@ private void createFacesForOldEdges() {
15593 }
15694
15795 private void createFaceForOldEdgeAt (Face3D face , int i ) {
158- Edge3D edge = getMappedEdge (createEdgeAt (face .indices , i ));
159- Edge3D pair = getMappedEdge (createEdgeAt (face .indices , i ).createPair ());
96+ Edge3D edge = edgeProcessor
97+ .getMappedEdge (edgeProcessor .createEdge (face .indices , i ));
98+ Edge3D pair = edgeProcessor
99+ .getMappedEdge (edgeProcessor .createEdge (face .indices , i ).createPair ());
160100
161- if (isProcessed (edge ) || isProcessed (pair ))
101+ if (edgeProcessor . isProcessed (edge ) || edgeProcessor . isProcessed (pair ))
162102 return ;
163103
164- addNewFace (new int [] { edge .toIndex , edge .fromIndex , pair .toIndex ,
165- pair .fromIndex });
104+ createFaceForEdge (edge , pair );
166105
167- markAsProcessed (edge );
168- markAsProcessed (pair );
106+ edgeProcessor . markProcessed (edge );
107+ edgeProcessor . markProcessed (pair );
169108 }
170109
171- private void mapOldEdgesToNewEdges (Face3D face , int [] indices ) {
172- for (int i = 0 ; i < indices .length ; i ++) {
173- Edge3D oldEdge = createEdgeAt (face .indices , i );
174- Edge3D newEdge = createEdgeAt (indices , i );
175- oldEdgeToNewEdge .put (oldEdge , newEdge );
176- }
110+ private void createFaceForEdge (Edge3D edge , Edge3D pair ) {
111+ addNewFace (edge .toIndex , edge .fromIndex , pair .toIndex , pair .fromIndex );
177112 }
178113
179- private Edge3D getMappedEdge (Edge3D edge ) {
180- return oldEdgeToNewEdge .get (edge );
114+ private int [] toReverseArray (List <Integer > values ) {
115+ Collections .reverse (values );
116+ return values .stream ().mapToInt (x -> x ).toArray ();
181117 }
182118
183- private Edge3D createEdgeAt (int [] indices , int i ) {
184- return new Edge3D (indices [i ], indices [(i + 1 ) % indices .length ]);
119+ private void clearAll () {
120+ edgeProcessor .clearAll ();
121+ verticesToAdd .clear ();
122+ facesToAdd .clear ();
123+ }
124+
125+ private void createInsetFaces () {
126+ for (Face3D face : mesh .faces )
127+ insetFace (mesh , face );
128+ }
129+
130+ private void insetFace (Mesh3D mesh , Face3D face ) {
131+ int nextVertexIndex = verticesToAdd .size ();
132+ int [] indices = createIndices (face .indices .length , nextVertexIndex );
133+ createInsetVertices (processFaceEdges (face ));
134+ edgeProcessor .mapOldEdgesToNewEdges (face , indices );
135+ addNewFace (indices );
185136 }
186137
187138 private int [] createIndices (int size , int nextVertexIndex ) {
@@ -191,24 +142,75 @@ private int[] createIndices(int size, int nextVertexIndex) {
191142 return indices ;
192143 }
193144
194- private int [] toReverseArray (List <Integer > values ) {
195- return values .stream ().sorted (Collections .reverseOrder ()).mapToInt (x -> x )
196- .toArray ();
145+ /**
146+ * Processes the edges of a face to calculate the new inset vertices.
147+ *
148+ * @param face the face to process.
149+ * @return a list of inset vertices.
150+ */
151+ private List <Vector3f > processFaceEdges (Face3D face ) {
152+ List <Vector3f > vertices = new ArrayList <>();
153+ for (int i = 0 ; i < face .indices .length ; i ++) {
154+ Vector3f from = getVertexAt (face , i );
155+ Vector3f to = getVertexAt (face , i + 1 );
156+
157+ float edgeLength = to .distance (from );
158+ float insetFactor = calculateInsetFactor (edgeLength );
159+
160+ Vector3f v4 = to .subtract (from ).mult (insetFactor ).add (from );
161+ Vector3f v5 = to .add (to .subtract (from ).mult (-insetFactor ));
162+
163+ vertices .add (v4 );
164+ vertices .add (v5 );
165+ }
166+ return vertices ;
197167 }
198168
199- private void clearAll () {
200- processed .clear ();
201- oldEdgeToNewEdge .clear ();
202- verticesToAdd .clear ();
203- facesToAdd .clear ();
169+ /**
170+ * Creates the inset vertices from the processed edge vertices.
171+ *
172+ * @param vertices the processed edge vertices.
173+ */
174+ private void createInsetVertices (List <Vector3f > vertices ) {
175+ for (int i = 1 ; i < vertices .size (); i += 2 ) {
176+ int a = vertices .size () - 2 + i ;
177+ Vector3f v0 = vertices .get (a % vertices .size ());
178+ Vector3f v1 = vertices .get ((a + 1 ) % vertices .size ());
179+ Vector3f v = v1 .add (v0 ).mult (0.5f );
180+ verticesToAdd .add (v );
181+ }
204182 }
205183
206- private void markAsProcessed (Edge3D edge ) {
207- processed .add (edge );
184+ /**
185+ * Calculates the inset factor based on the edge length and
186+ * #{@link WidthType}.
187+ *
188+ * @param edgeLength the length of the edge.
189+ * @return the inset factor.
190+ */
191+ private float calculateInsetFactor (float edgeLength ) {
192+ return edgeLength > 0 ? (1f / edgeLength ) * getAmountByWidthType () : 0f ;
208193 }
209194
210- private boolean isProcessed (Edge3D edge ) {
211- return processed .contains (edge );
195+ private float getAmountByWidthType () {
196+ float amount ;
197+ switch (widthType ) {
198+ case OFFSET -> amount = this .amount * 2 ;
199+ case WIDTH -> amount = inset ;
200+ case DEPTH -> amount = inset * 2 ;
201+ default -> amount = this .amount * 2 ;
202+ }
203+ return amount ;
204+ }
205+
206+ private boolean canExitEarly (Mesh3D mesh ) {
207+ return amount == 0 || mesh .faces .isEmpty ();
208+ }
209+
210+ private void validateMesh (Mesh3D mesh ) {
211+ if (mesh == null ) {
212+ throw new IllegalArgumentException ("Mesh cannot be null." );
213+ }
212214 }
213215
214216 private Vector3f getVertexAt (Face3D face , int index ) {
@@ -231,7 +233,7 @@ private void clearOriginalFaces() {
231233 mesh .faces .clear ();
232234 }
233235
234- private void addNewFace (int [] indices ) {
236+ private void addNewFace (int ... indices ) {
235237 facesToAdd .add (new Face3D (indices ));
236238 }
237239
@@ -256,4 +258,46 @@ public void setWidthType(WidthType widthType) {
256258 this .widthType = widthType ;
257259 }
258260
261+ private class EdgeProcessor {
262+
263+ private HashSet <Edge3D > processed ;
264+
265+ private HashMap <Edge3D , Edge3D > edgeMapping ;
266+
267+ public EdgeProcessor () {
268+ processed = new HashSet <Edge3D >();
269+ edgeMapping = new HashMap <Edge3D , Edge3D >();
270+ }
271+
272+ public void mapOldEdgesToNewEdges (Face3D face , int [] indices ) {
273+ for (int i = 0 ; i < indices .length ; i ++) {
274+ Edge3D oldEdge = createEdge (face .indices , i );
275+ Edge3D newEdge = createEdge (indices , i );
276+ edgeMapping .put (oldEdge , newEdge );
277+ }
278+ }
279+
280+ public Edge3D getMappedEdge (Edge3D edge ) {
281+ return edgeMapping .get (edge );
282+ }
283+
284+ public void markProcessed (Edge3D edge ) {
285+ processed .add (edge );
286+ }
287+
288+ public boolean isProcessed (Edge3D edge ) {
289+ return processed .contains (edge );
290+ }
291+
292+ public Edge3D createEdge (int [] indices , int i ) {
293+ return new Edge3D (indices [i ], indices [(i + 1 ) % indices .length ]);
294+ }
295+
296+ public void clearAll () {
297+ processed .clear ();
298+ edgeMapping .clear ();
299+ }
300+
301+ }
302+
259303}
0 commit comments