Revision 94690c11
Added by Leszek Koltunski 2 days ago
src/main/java/org/distorted/library/mesh/DeferredJobs.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2020 Leszek Koltunski leszek@koltunski.pl // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// This library is free software; you can redistribute it and/or // |
|
7 |
// modify it under the terms of the GNU Lesser General Public // |
|
8 |
// License as published by the Free Software Foundation; either // |
|
9 |
// version 2.1 of the License, or (at your option) any later version. // |
|
10 |
// // |
|
11 |
// This library is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // |
|
14 |
// Lesser General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU Lesser General Public // |
|
17 |
// License along with this library; if not, write to the Free Software // |
|
18 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // |
|
19 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
20 |
|
|
21 |
package org.distorted.library.mesh; |
|
22 |
|
|
23 |
import org.distorted.library.effect.MatrixEffect; |
|
24 |
import org.distorted.library.effect.VertexEffect; |
|
25 |
import org.distorted.library.effectqueue.EffectQueueVertex; |
|
26 |
import org.distorted.library.main.DistortedLibrary; |
|
27 |
import org.distorted.library.type.Static4D; |
|
28 |
|
|
29 |
import java.util.ArrayList; |
|
30 |
|
|
31 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
32 |
/** |
|
33 |
* Not part of public API, do not document (public only because has to be cleaned from the main package) |
|
34 |
* |
|
35 |
* @y.exclude |
|
36 |
*/ |
|
37 |
public class DeferredJobs |
|
38 |
{ |
|
39 |
private static final int JOB_TYPE_VERTEX = 0; |
|
40 |
private static final int JOB_TYPE_MATRIX = 1; |
|
41 |
private static final int JOB_TYPE_MERGE_TEX = 2; |
|
42 |
private static final int JOB_TYPE_MERGE_EFF = 3; |
|
43 |
private static final int JOB_TYPE_JOIN = 4; |
|
44 |
private static final int JOB_TYPE_COPY = 5; |
|
45 |
private static final int JOB_TYPE_TEXTURE = 6; |
|
46 |
private static final int JOB_TYPE_ASSOC = 7; |
|
47 |
private static final int JOB_TYPE_CENTER = 8; |
|
48 |
private static final int JOB_TYPE_ADD_EMPTY_TEX= 9; |
|
49 |
private static final int JOB_TYPE_NOT_AFFECTED = 10; |
|
50 |
|
|
51 |
private static final ArrayList<JobNode> mJobs = new ArrayList<>(); |
|
52 |
|
|
53 |
////////////////////////////////////////////////////////////////////////// |
|
54 |
|
|
55 |
private static class Job |
|
56 |
{ |
|
57 |
private final int mType; |
|
58 |
private final MeshBase mTarget; |
|
59 |
private final MeshBase[] mSource; |
|
60 |
private final MatrixEffect mMatrixEffect; |
|
61 |
private final Static4D[] mMaps; |
|
62 |
private final int mComp, mAndAssoc, mEquAssoc; |
|
63 |
private final float mX,mY,mZ; |
|
64 |
private final int[] mComps; |
|
65 |
|
|
66 |
private EffectQueueVertex mVertexEffects; |
|
67 |
|
|
68 |
Job(int type, MeshBase target, MeshBase[] source, VertexEffect vEff, MatrixEffect mEff, |
|
69 |
Static4D[] maps, int comp, int and, int equ, float x, float y, float z, int[] comps) |
|
70 |
{ |
|
71 |
mType = type; |
|
72 |
mTarget = target; |
|
73 |
mSource = source; |
|
74 |
mMaps = maps; |
|
75 |
mComp = comp; |
|
76 |
mAndAssoc = and; |
|
77 |
mEquAssoc = equ; |
|
78 |
mX = x; |
|
79 |
mY = y; |
|
80 |
mZ = z; |
|
81 |
mComps = comps; |
|
82 |
|
|
83 |
if( vEff!=null ) |
|
84 |
{ |
|
85 |
mVertexEffects= new EffectQueueVertex(); |
|
86 |
mVertexEffects.add(vEff); |
|
87 |
} |
|
88 |
|
|
89 |
mMatrixEffect = mEff; |
|
90 |
} |
|
91 |
|
|
92 |
void addEffect(VertexEffect effect) |
|
93 |
{ |
|
94 |
mVertexEffects.add(effect); |
|
95 |
} |
|
96 |
|
|
97 |
void execute() |
|
98 |
{ |
|
99 |
switch(mType) |
|
100 |
{ |
|
101 |
case JOB_TYPE_VERTEX : DistortedLibrary.adjustVertices(mTarget, mVertexEffects); |
|
102 |
break; |
|
103 |
case JOB_TYPE_MATRIX : mTarget.applyMatrix(mMatrixEffect,mAndAssoc,mEquAssoc); |
|
104 |
break; |
|
105 |
case JOB_TYPE_MERGE_TEX : mTarget.mergeTexComponentsNow(); |
|
106 |
break; |
|
107 |
case JOB_TYPE_MERGE_EFF : mTarget.mergeEffComponentsNow(); |
|
108 |
break; |
|
109 |
case JOB_TYPE_JOIN : mTarget.joinAttribs(mSource); |
|
110 |
break; |
|
111 |
case JOB_TYPE_COPY : mTarget.copy(mSource[0]); |
|
112 |
break; |
|
113 |
case JOB_TYPE_TEXTURE : mTarget.textureMap(mMaps,mComp); |
|
114 |
break; |
|
115 |
case JOB_TYPE_ASSOC : mTarget.setEffectAssociationNow(mComp,mAndAssoc,mEquAssoc); |
|
116 |
break; |
|
117 |
case JOB_TYPE_CENTER : mTarget.setComponentCenterNow(mComp,mX,mY,mZ); |
|
118 |
break; |
|
119 |
case JOB_TYPE_ADD_EMPTY_TEX: mTarget.addEmptyTexComponentNow(); |
|
120 |
break; |
|
121 |
case JOB_TYPE_NOT_AFFECTED: mTarget.setNotAffectedComponentsNow(mComps); |
|
122 |
} |
|
123 |
} |
|
124 |
|
|
125 |
void clear() |
|
126 |
{ |
|
127 |
if( mVertexEffects!=null ) mVertexEffects.removeAll(false); |
|
128 |
} |
|
129 |
|
|
130 |
String print() |
|
131 |
{ |
|
132 |
switch(mType) |
|
133 |
{ |
|
134 |
case JOB_TYPE_VERTEX : return "VERTEX"; |
|
135 |
case JOB_TYPE_MATRIX : return "MATRIX"; |
|
136 |
case JOB_TYPE_MERGE_TEX : return "MERGE_TEX"; |
|
137 |
case JOB_TYPE_MERGE_EFF : return "MERGE_EFF"; |
|
138 |
case JOB_TYPE_JOIN : return "JOIN"; |
|
139 |
case JOB_TYPE_COPY : return "COPY"; |
|
140 |
case JOB_TYPE_TEXTURE : return "TEXTURE"; |
|
141 |
case JOB_TYPE_ASSOC : return "ASSOC"; |
|
142 |
case JOB_TYPE_CENTER : return "CENTER"; |
|
143 |
case JOB_TYPE_ADD_EMPTY_TEX: return "ADD_EMPTY_TEX"; |
|
144 |
case JOB_TYPE_NOT_AFFECTED : return "POSTPROC COMPS"; |
|
145 |
} |
|
146 |
|
|
147 |
return null; |
|
148 |
} |
|
149 |
} |
|
150 |
|
|
151 |
////////////////////////////////////////////////////////////////////////// |
|
152 |
|
|
153 |
static class JobNode |
|
154 |
{ |
|
155 |
private ArrayList<JobNode> mPrevJobs; |
|
156 |
private ArrayList<JobNode> mNextJobs; |
|
157 |
private Job mJob; |
|
158 |
|
|
159 |
JobNode(Job job) |
|
160 |
{ |
|
161 |
mPrevJobs = new ArrayList<>(); |
|
162 |
mNextJobs = new ArrayList<>(); |
|
163 |
mJob = job; |
|
164 |
} |
|
165 |
|
|
166 |
synchronized void execute() |
|
167 |
{ |
|
168 |
if( mPrevJobs!=null ) |
|
169 |
{ |
|
170 |
JobNode node; |
|
171 |
int numPrev = mPrevJobs.size(); |
|
172 |
|
|
173 |
for(int i=0; i<numPrev; i++) |
|
174 |
{ |
|
175 |
node = mPrevJobs.get(0); // removeNode() rips the executed job out, thus the 0 |
|
176 |
node.execute(); |
|
177 |
} |
|
178 |
|
|
179 |
removeNode(this); |
|
180 |
mJob.execute(); |
|
181 |
} |
|
182 |
} |
|
183 |
|
|
184 |
synchronized void clear() |
|
185 |
{ |
|
186 |
mPrevJobs.clear(); |
|
187 |
mPrevJobs = null; |
|
188 |
mNextJobs.clear(); |
|
189 |
mNextJobs = null; |
|
190 |
|
|
191 |
mJob.clear(); |
|
192 |
mJob = null; |
|
193 |
} |
|
194 |
|
|
195 |
void print(int level) |
|
196 |
{ |
|
197 |
int numPrev = mPrevJobs.size(); |
|
198 |
int numNext = mNextJobs.size(); |
|
199 |
|
|
200 |
String str = ""; |
|
201 |
for(int i=0; i<level; i++) str+=" "; |
|
202 |
|
|
203 |
str += mJob.print(); |
|
204 |
|
|
205 |
str += (" next: "+numNext+" prev: "+numPrev); |
|
206 |
|
|
207 |
DistortedLibrary.logMessage("DeferredJobs: "+str); |
|
208 |
|
|
209 |
for(int i=0; i<numPrev; i++) |
|
210 |
{ |
|
211 |
JobNode node = mPrevJobs.get(i); |
|
212 |
node.print(level+1); |
|
213 |
} |
|
214 |
} |
|
215 |
} |
|
216 |
|
|
217 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
218 |
|
|
219 |
private static void removeNode(JobNode node) |
|
220 |
{ |
|
221 |
mJobs.remove(node); |
|
222 |
JobNode jn; |
|
223 |
|
|
224 |
int numPrev = node.mPrevJobs.size(); |
|
225 |
|
|
226 |
for(int i=0; i<numPrev; i++) |
|
227 |
{ |
|
228 |
jn = node.mPrevJobs.get(i); |
|
229 |
jn.mNextJobs.remove(node); |
|
230 |
} |
|
231 |
|
|
232 |
int numNext = node.mNextJobs.size(); |
|
233 |
|
|
234 |
for(int i=0; i<numNext; i++) |
|
235 |
{ |
|
236 |
jn = node.mNextJobs.get(i); |
|
237 |
jn.mPrevJobs.remove(node); |
|
238 |
} |
|
239 |
|
|
240 |
node.mJob.mTarget.mJobNode[0] = null; |
|
241 |
} |
|
242 |
|
|
243 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
244 |
|
|
245 |
static JobNode vertex(MeshBase target, VertexEffect effect) |
|
246 |
{ |
|
247 |
JobNode jn = target.mJobNode[0]; |
|
248 |
|
|
249 |
if( jn==null ) |
|
250 |
{ |
|
251 |
Job job = new Job(JOB_TYPE_VERTEX,target,null,effect,null,null,0,0,0,0,0,0,null); |
|
252 |
JobNode node = new JobNode(job); |
|
253 |
mJobs.add(node); |
|
254 |
return node; |
|
255 |
} |
|
256 |
else |
|
257 |
{ |
|
258 |
if( jn.mJob.mType==JOB_TYPE_VERTEX ) |
|
259 |
{ |
|
260 |
jn.mJob.addEffect(effect); |
|
261 |
return jn; |
|
262 |
} |
|
263 |
else |
|
264 |
{ |
|
265 |
Job job = new Job(JOB_TYPE_VERTEX,target,null,effect,null,null,0,0,0,0,0,0,null); |
|
266 |
JobNode node = new JobNode(job); |
|
267 |
node.mPrevJobs.add(jn); |
|
268 |
jn.mNextJobs.add(node); |
|
269 |
mJobs.add(node); |
|
270 |
return node; |
|
271 |
} |
|
272 |
} |
|
273 |
} |
|
274 |
|
|
275 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
276 |
|
|
277 |
static JobNode matrix(MeshBase target, MatrixEffect effect, int andAssoc, int ecuAssoc) |
|
278 |
{ |
|
279 |
JobNode jn = target.mJobNode[0]; |
|
280 |
Job job = new Job(JOB_TYPE_MATRIX,target,null,null,effect,null,0,andAssoc,ecuAssoc,0,0,0,null); |
|
281 |
JobNode node = new JobNode(job); |
|
282 |
node.mPrevJobs.add(jn); |
|
283 |
jn.mNextJobs.add(node); |
|
284 |
mJobs.add(node); |
|
285 |
return node; |
|
286 |
} |
|
287 |
|
|
288 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
289 |
|
|
290 |
static JobNode mergeTex(MeshBase target) |
|
291 |
{ |
|
292 |
JobNode jn = target.mJobNode[0]; |
|
293 |
Job job = new Job(JOB_TYPE_MERGE_TEX,target,null,null,null,null,0,0,0,0,0,0,null); |
|
294 |
JobNode node = new JobNode(job); |
|
295 |
node.mPrevJobs.add(jn); |
|
296 |
jn.mNextJobs.add(node); |
|
297 |
mJobs.add(node); |
|
298 |
return node; |
|
299 |
} |
|
300 |
|
|
301 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
302 |
|
|
303 |
static JobNode addEmptyTex(MeshBase target) |
|
304 |
{ |
|
305 |
JobNode jn = target.mJobNode[0]; |
|
306 |
Job job = new Job(JOB_TYPE_ADD_EMPTY_TEX,target,null,null,null,null,0,0,0,0,0,0,null); |
|
307 |
JobNode node = new JobNode(job); |
|
308 |
node.mPrevJobs.add(jn); |
|
309 |
jn.mNextJobs.add(node); |
|
310 |
mJobs.add(node); |
|
311 |
return node; |
|
312 |
} |
|
313 |
|
|
314 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
315 |
|
|
316 |
static JobNode mergeEff(MeshBase target) |
|
317 |
{ |
|
318 |
JobNode jn = target.mJobNode[0]; |
|
319 |
Job job = new Job(JOB_TYPE_MERGE_EFF,target,null,null,null,null,0,0,0,0,0,0,null); |
|
320 |
JobNode node = new JobNode(job); |
|
321 |
node.mPrevJobs.add(jn); |
|
322 |
jn.mNextJobs.add(node); |
|
323 |
mJobs.add(node); |
|
324 |
return node; |
|
325 |
} |
|
326 |
|
|
327 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
328 |
|
|
329 |
static JobNode join(MeshBase target, MeshBase[] meshes) |
|
330 |
{ |
|
331 |
JobNode jn; |
|
332 |
|
|
333 |
Job job = new Job(JOB_TYPE_JOIN,target,meshes,null,null,null,0,0,0,0,0,0,null); |
|
334 |
JobNode node = new JobNode(job); |
|
335 |
|
|
336 |
for (MeshBase mesh : meshes) |
|
337 |
{ |
|
338 |
jn = mesh.mJobNode[0]; |
|
339 |
|
|
340 |
if( jn!=null ) |
|
341 |
{ |
|
342 |
node.mPrevJobs.add(jn); |
|
343 |
jn.mNextJobs.add(node); |
|
344 |
} |
|
345 |
} |
|
346 |
|
|
347 |
mJobs.add(node); |
|
348 |
return node; |
|
349 |
} |
|
350 |
|
|
351 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
352 |
|
|
353 |
static JobNode copy(MeshBase target, MeshBase mesh) |
|
354 |
{ |
|
355 |
JobNode jn = mesh.mJobNode[0]; |
|
356 |
MeshBase[] meshes = new MeshBase[1]; |
|
357 |
meshes[0] = mesh; |
|
358 |
Job job = new Job(JOB_TYPE_COPY,target,meshes,null,null,null,0,0,0,0,0,0,null); |
|
359 |
JobNode node = new JobNode(job); |
|
360 |
node.mPrevJobs.add(jn); |
|
361 |
jn.mNextJobs.add(node); |
|
362 |
mJobs.add(node); |
|
363 |
return node; |
|
364 |
} |
|
365 |
|
|
366 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
367 |
|
|
368 |
static JobNode textureMap(MeshBase target, Static4D[] maps, int comp) |
|
369 |
{ |
|
370 |
JobNode jn = target.mJobNode[0]; |
|
371 |
Job job = new Job(JOB_TYPE_TEXTURE,target,null,null,null,maps,comp,0,0,0,0,0,null); |
|
372 |
JobNode node = new JobNode(job); |
|
373 |
node.mPrevJobs.add(jn); |
|
374 |
jn.mNextJobs.add(node); |
|
375 |
mJobs.add(node); |
|
376 |
return node; |
|
377 |
} |
|
378 |
|
|
379 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
380 |
|
|
381 |
static JobNode effectAssoc(MeshBase target, int comp, int andAssoc, int equAssoc) |
|
382 |
{ |
|
383 |
JobNode jn = target.mJobNode[0]; |
|
384 |
Job job = new Job(JOB_TYPE_ASSOC,target,null,null,null,null,comp,andAssoc,equAssoc,0,0,0,null); |
|
385 |
JobNode node = new JobNode(job); |
|
386 |
node.mPrevJobs.add(jn); |
|
387 |
jn.mNextJobs.add(node); |
|
388 |
mJobs.add(node); |
|
389 |
return node; |
|
390 |
} |
|
391 |
|
|
392 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
393 |
|
|
394 |
static JobNode componentCenter(MeshBase target, int comp, float x, float y, float z) |
|
395 |
{ |
|
396 |
JobNode jn = target.mJobNode[0]; |
|
397 |
Job job = new Job(JOB_TYPE_CENTER,target,null,null,null,null,comp,0,0,x,y,z,null); |
|
398 |
JobNode node = new JobNode(job); |
|
399 |
node.mPrevJobs.add(jn); |
|
400 |
jn.mNextJobs.add(node); |
|
401 |
mJobs.add(node); |
|
402 |
return node; |
|
403 |
} |
|
404 |
|
|
405 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
406 |
|
|
407 |
static JobNode setNotAffected(MeshBase target, int[] comps) |
|
408 |
{ |
|
409 |
JobNode jn = target.mJobNode[0]; |
|
410 |
Job job = new Job(JOB_TYPE_NOT_AFFECTED,target,null,null,null,null,0,0,0,0,0,0,comps); |
|
411 |
JobNode node = new JobNode(job); |
|
412 |
node.mPrevJobs.add(jn); |
|
413 |
jn.mNextJobs.add(node); |
|
414 |
mJobs.add(node); |
|
415 |
return node; |
|
416 |
} |
|
417 |
|
|
418 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
419 |
/** |
|
420 |
* Only for use by the library itself. |
|
421 |
* |
|
422 |
* @y.exclude |
|
423 |
*/ |
|
424 |
public static void onPause() |
|
425 |
{ |
|
426 |
int num = mJobs.size(); |
|
427 |
|
|
428 |
for(int i=0; i<num; i++) |
|
429 |
{ |
|
430 |
mJobs.get(i).clear(); |
|
431 |
} |
|
432 |
|
|
433 |
mJobs.clear(); |
|
434 |
} |
|
435 |
} |
src/main/java/org/distorted/library/mesh/DeferredJobs.kt | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2020 Leszek Koltunski leszek@koltunski.pl // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// This library is free software; you can redistribute it and/or // |
|
7 |
// modify it under the terms of the GNU Lesser General Public // |
|
8 |
// License as published by the Free Software Foundation; either // |
|
9 |
// version 2.1 of the License, or (at your option) any later version. // |
|
10 |
// // |
|
11 |
// This library is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // |
|
14 |
// Lesser General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU Lesser General Public // |
|
17 |
// License along with this library; if not, write to the Free Software // |
|
18 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // |
|
19 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
20 |
|
|
21 |
package org.distorted.library.mesh; |
|
22 |
|
|
23 |
import org.distorted.library.effect.MatrixEffect; |
|
24 |
import org.distorted.library.effect.VertexEffect; |
|
25 |
import org.distorted.library.effectqueue.EffectQueueVertex; |
|
26 |
import org.distorted.library.main.DistortedLibrary; |
|
27 |
import org.distorted.library.type.Static4D; |
|
28 |
|
|
29 |
import java.util.ArrayList; |
|
30 |
|
|
31 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
32 |
/** |
|
33 |
* Not part of public API, do not document (public only because has to be cleaned from the main package) |
|
34 |
* |
|
35 |
* @y.exclude |
|
36 |
*/ |
|
37 |
public class DeferredJobs |
|
38 |
{ |
|
39 |
private static final int JOB_TYPE_VERTEX = 0; |
|
40 |
private static final int JOB_TYPE_MATRIX = 1; |
|
41 |
private static final int JOB_TYPE_MERGE_TEX = 2; |
|
42 |
private static final int JOB_TYPE_MERGE_EFF = 3; |
|
43 |
private static final int JOB_TYPE_JOIN = 4; |
|
44 |
private static final int JOB_TYPE_COPY = 5; |
|
45 |
private static final int JOB_TYPE_TEXTURE = 6; |
|
46 |
private static final int JOB_TYPE_ASSOC = 7; |
|
47 |
private static final int JOB_TYPE_CENTER = 8; |
|
48 |
private static final int JOB_TYPE_ADD_EMPTY_TEX= 9; |
|
49 |
private static final int JOB_TYPE_NOT_AFFECTED = 10; |
|
50 |
|
|
51 |
private static final ArrayList<JobNode> mJobs = new ArrayList<>(); |
|
52 |
|
|
53 |
////////////////////////////////////////////////////////////////////////// |
|
54 |
|
|
55 |
private static class Job |
|
56 |
{ |
|
57 |
private final int mType; |
|
58 |
private final MeshBase mTarget; |
|
59 |
private final MeshBase[] mSource; |
|
60 |
private final MatrixEffect mMatrixEffect; |
|
61 |
private final Static4D[] mMaps; |
|
62 |
private final int mComp, mAndAssoc, mEquAssoc; |
|
63 |
private final float mX,mY,mZ; |
|
64 |
private final int[] mComps; |
|
65 |
|
|
66 |
private EffectQueueVertex mVertexEffects; |
|
67 |
|
|
68 |
Job(int type, MeshBase target, MeshBase[] source, VertexEffect vEff, MatrixEffect mEff, |
|
69 |
Static4D[] maps, int comp, int and, int equ, float x, float y, float z, int[] comps) |
|
70 |
{ |
|
71 |
mType = type; |
|
72 |
mTarget = target; |
|
73 |
mSource = source; |
|
74 |
mMaps = maps; |
|
75 |
mComp = comp; |
|
76 |
mAndAssoc = and; |
|
77 |
mEquAssoc = equ; |
|
78 |
mX = x; |
|
79 |
mY = y; |
|
80 |
mZ = z; |
|
81 |
mComps = comps; |
|
82 |
|
|
83 |
if( vEff!=null ) |
|
84 |
{ |
|
85 |
mVertexEffects= new EffectQueueVertex(); |
|
86 |
mVertexEffects.add(vEff); |
|
87 |
} |
|
88 |
|
|
89 |
mMatrixEffect = mEff; |
|
90 |
} |
|
91 |
|
|
92 |
void addEffect(VertexEffect effect) |
|
93 |
{ |
|
94 |
mVertexEffects.add(effect); |
|
95 |
} |
|
96 |
|
|
97 |
void execute() |
|
98 |
{ |
|
99 |
switch(mType) |
|
100 |
{ |
|
101 |
case JOB_TYPE_VERTEX : DistortedLibrary.adjustVertices(mTarget, mVertexEffects); |
|
102 |
break; |
|
103 |
case JOB_TYPE_MATRIX : mTarget.applyMatrix(mMatrixEffect,mAndAssoc,mEquAssoc); |
|
104 |
break; |
|
105 |
case JOB_TYPE_MERGE_TEX : mTarget.mergeTexComponentsNow(); |
|
106 |
break; |
|
107 |
case JOB_TYPE_MERGE_EFF : mTarget.mergeEffComponentsNow(); |
|
108 |
break; |
|
109 |
case JOB_TYPE_JOIN : mTarget.joinAttribs(mSource); |
|
110 |
break; |
|
111 |
case JOB_TYPE_COPY : mTarget.copy(mSource[0]); |
|
112 |
break; |
|
113 |
case JOB_TYPE_TEXTURE : mTarget.textureMap(mMaps,mComp); |
|
114 |
break; |
|
115 |
case JOB_TYPE_ASSOC : mTarget.setEffectAssociationNow(mComp,mAndAssoc,mEquAssoc); |
|
116 |
break; |
|
117 |
case JOB_TYPE_CENTER : mTarget.setComponentCenterNow(mComp,mX,mY,mZ); |
|
118 |
break; |
|
119 |
case JOB_TYPE_ADD_EMPTY_TEX: mTarget.addEmptyTexComponentNow(); |
|
120 |
break; |
|
121 |
case JOB_TYPE_NOT_AFFECTED: mTarget.setNotAffectedComponentsNow(mComps); |
|
122 |
} |
|
123 |
} |
|
124 |
|
|
125 |
void clear() |
|
126 |
{ |
|
127 |
if( mVertexEffects!=null ) mVertexEffects.removeAll(false); |
|
128 |
} |
|
129 |
|
|
130 |
String print() |
|
131 |
{ |
|
132 |
switch(mType) |
|
133 |
{ |
|
134 |
case JOB_TYPE_VERTEX : return "VERTEX"; |
|
135 |
case JOB_TYPE_MATRIX : return "MATRIX"; |
|
136 |
case JOB_TYPE_MERGE_TEX : return "MERGE_TEX"; |
|
137 |
case JOB_TYPE_MERGE_EFF : return "MERGE_EFF"; |
|
138 |
case JOB_TYPE_JOIN : return "JOIN"; |
|
139 |
case JOB_TYPE_COPY : return "COPY"; |
|
140 |
case JOB_TYPE_TEXTURE : return "TEXTURE"; |
|
141 |
case JOB_TYPE_ASSOC : return "ASSOC"; |
|
142 |
case JOB_TYPE_CENTER : return "CENTER"; |
|
143 |
case JOB_TYPE_ADD_EMPTY_TEX: return "ADD_EMPTY_TEX"; |
|
144 |
case JOB_TYPE_NOT_AFFECTED : return "POSTPROC COMPS"; |
|
145 |
} |
|
146 |
|
|
147 |
return null; |
|
148 |
} |
|
149 |
} |
|
150 |
|
|
151 |
////////////////////////////////////////////////////////////////////////// |
|
152 |
|
|
153 |
static class JobNode |
|
154 |
{ |
|
155 |
private ArrayList<JobNode> mPrevJobs; |
|
156 |
private ArrayList<JobNode> mNextJobs; |
|
157 |
private Job mJob; |
|
158 |
|
|
159 |
JobNode(Job job) |
|
160 |
{ |
|
161 |
mPrevJobs = new ArrayList<>(); |
|
162 |
mNextJobs = new ArrayList<>(); |
|
163 |
mJob = job; |
|
164 |
} |
|
165 |
|
|
166 |
synchronized void execute() |
|
167 |
{ |
|
168 |
if( mPrevJobs!=null ) |
|
169 |
{ |
|
170 |
JobNode node; |
|
171 |
int numPrev = mPrevJobs.size(); |
|
172 |
|
|
173 |
for(int i=0; i<numPrev; i++) |
|
174 |
{ |
|
175 |
node = mPrevJobs.get(0); // removeNode() rips the executed job out, thus the 0 |
|
176 |
node.execute(); |
|
177 |
} |
|
178 |
|
|
179 |
removeNode(this); |
|
180 |
mJob.execute(); |
|
181 |
} |
|
182 |
} |
|
183 |
|
|
184 |
synchronized void clear() |
|
185 |
{ |
|
186 |
mPrevJobs.clear(); |
|
187 |
mPrevJobs = null; |
|
188 |
mNextJobs.clear(); |
|
189 |
mNextJobs = null; |
|
190 |
|
|
191 |
mJob.clear(); |
|
192 |
mJob = null; |
|
193 |
} |
|
194 |
|
|
195 |
void print(int level) |
|
196 |
{ |
|
197 |
int numPrev = mPrevJobs.size(); |
|
198 |
int numNext = mNextJobs.size(); |
|
199 |
|
|
200 |
String str = ""; |
|
201 |
for(int i=0; i<level; i++) str+=" "; |
|
202 |
|
|
203 |
str += mJob.print(); |
|
204 |
|
|
205 |
str += (" next: "+numNext+" prev: "+numPrev); |
|
206 |
|
|
207 |
DistortedLibrary.logMessage("DeferredJobs: "+str); |
|
208 |
|
|
209 |
for(int i=0; i<numPrev; i++) |
|
210 |
{ |
|
211 |
JobNode node = mPrevJobs.get(i); |
|
212 |
node.print(level+1); |
|
213 |
} |
|
214 |
} |
|
215 |
} |
|
216 |
|
|
217 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
218 |
|
|
219 |
private static void removeNode(JobNode node) |
|
220 |
{ |
|
221 |
mJobs.remove(node); |
|
222 |
JobNode jn; |
|
223 |
|
|
224 |
int numPrev = node.mPrevJobs.size(); |
|
225 |
|
|
226 |
for(int i=0; i<numPrev; i++) |
|
227 |
{ |
|
228 |
jn = node.mPrevJobs.get(i); |
|
229 |
jn.mNextJobs.remove(node); |
|
230 |
} |
|
231 |
|
|
232 |
int numNext = node.mNextJobs.size(); |
|
233 |
|
|
234 |
for(int i=0; i<numNext; i++) |
|
235 |
{ |
|
236 |
jn = node.mNextJobs.get(i); |
|
237 |
jn.mPrevJobs.remove(node); |
|
238 |
} |
|
239 |
|
|
240 |
node.mJob.mTarget.mJobNode[0] = null; |
|
241 |
} |
|
242 |
|
|
243 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
244 |
|
|
245 |
static JobNode vertex(MeshBase target, VertexEffect effect) |
|
246 |
{ |
|
247 |
JobNode jn = target.mJobNode[0]; |
|
248 |
|
|
249 |
if( jn==null ) |
|
250 |
{ |
|
251 |
Job job = new Job(JOB_TYPE_VERTEX,target,null,effect,null,null,0,0,0,0,0,0,null); |
|
252 |
JobNode node = new JobNode(job); |
|
253 |
mJobs.add(node); |
|
254 |
return node; |
|
255 |
} |
|
256 |
else |
|
257 |
{ |
|
258 |
if( jn.mJob.mType==JOB_TYPE_VERTEX ) |
|
259 |
{ |
|
260 |
jn.mJob.addEffect(effect); |
|
261 |
return jn; |
|
262 |
} |
|
263 |
else |
|
264 |
{ |
|
265 |
Job job = new Job(JOB_TYPE_VERTEX,target,null,effect,null,null,0,0,0,0,0,0,null); |
|
266 |
JobNode node = new JobNode(job); |
|
267 |
node.mPrevJobs.add(jn); |
|
268 |
jn.mNextJobs.add(node); |
|
269 |
mJobs.add(node); |
|
270 |
return node; |
|
271 |
} |
|
272 |
} |
|
273 |
} |
|
274 |
|
|
275 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
276 |
|
|
277 |
static JobNode matrix(MeshBase target, MatrixEffect effect, int andAssoc, int ecuAssoc) |
|
278 |
{ |
|
279 |
JobNode jn = target.mJobNode[0]; |
|
280 |
Job job = new Job(JOB_TYPE_MATRIX,target,null,null,effect,null,0,andAssoc,ecuAssoc,0,0,0,null); |
|
281 |
JobNode node = new JobNode(job); |
|
282 |
node.mPrevJobs.add(jn); |
|
283 |
jn.mNextJobs.add(node); |
|
284 |
mJobs.add(node); |
|
285 |
return node; |
|
286 |
} |
|
287 |
|
|
288 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
289 |
|
|
290 |
static JobNode mergeTex(MeshBase target) |
|
291 |
{ |
|
292 |
JobNode jn = target.mJobNode[0]; |
|
293 |
Job job = new Job(JOB_TYPE_MERGE_TEX,target,null,null,null,null,0,0,0,0,0,0,null); |
|
294 |
JobNode node = new JobNode(job); |
|
295 |
node.mPrevJobs.add(jn); |
|
296 |
jn.mNextJobs.add(node); |
|
297 |
mJobs.add(node); |
|
298 |
return node; |
|
299 |
} |
|
300 |
|
|
301 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
302 |
|
|
303 |
static JobNode addEmptyTex(MeshBase target) |
|
304 |
{ |
|
305 |
JobNode jn = target.mJobNode[0]; |
|
306 |
Job job = new Job(JOB_TYPE_ADD_EMPTY_TEX,target,null,null,null,null,0,0,0,0,0,0,null); |
|
307 |
JobNode node = new JobNode(job); |
|
308 |
node.mPrevJobs.add(jn); |
|
309 |
jn.mNextJobs.add(node); |
|
310 |
mJobs.add(node); |
|
311 |
return node; |
|
312 |
} |
|
313 |
|
|
314 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
315 |
|
|
316 |
static JobNode mergeEff(MeshBase target) |
|
317 |
{ |
|
318 |
JobNode jn = target.mJobNode[0]; |
|
319 |
Job job = new Job(JOB_TYPE_MERGE_EFF,target,null,null,null,null,0,0,0,0,0,0,null); |
|
320 |
JobNode node = new JobNode(job); |
|
321 |
node.mPrevJobs.add(jn); |
|
322 |
jn.mNextJobs.add(node); |
|
323 |
mJobs.add(node); |
|
324 |
return node; |
|
325 |
} |
|
326 |
|
|
327 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
328 |
|
|
329 |
static JobNode join(MeshBase target, MeshBase[] meshes) |
|
330 |
{ |
|
331 |
JobNode jn; |
|
332 |
|
|
333 |
Job job = new Job(JOB_TYPE_JOIN,target,meshes,null,null,null,0,0,0,0,0,0,null); |
|
334 |
JobNode node = new JobNode(job); |
|
335 |
|
|
336 |
for (MeshBase mesh : meshes) |
|
337 |
{ |
|
338 |
jn = mesh.mJobNode[0]; |
|
339 |
|
|
340 |
if( jn!=null ) |
|
341 |
{ |
|
342 |
node.mPrevJobs.add(jn); |
|
343 |
jn.mNextJobs.add(node); |
|
344 |
} |
|
345 |
} |
|
346 |
|
|
347 |
mJobs.add(node); |
|
348 |
return node; |
|
349 |
} |
|
350 |
|
|
351 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
352 |
|
|
353 |
static JobNode copy(MeshBase target, MeshBase mesh) |
|
354 |
{ |
|
355 |
JobNode jn = mesh.mJobNode[0]; |
|
356 |
MeshBase[] meshes = new MeshBase[1]; |
|
357 |
meshes[0] = mesh; |
|
358 |
Job job = new Job(JOB_TYPE_COPY,target,meshes,null,null,null,0,0,0,0,0,0,null); |
|
359 |
JobNode node = new JobNode(job); |
|
360 |
node.mPrevJobs.add(jn); |
|
361 |
jn.mNextJobs.add(node); |
|
362 |
mJobs.add(node); |
|
363 |
return node; |
|
364 |
} |
|
365 |
|
|
366 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
367 |
|
|
368 |
static JobNode textureMap(MeshBase target, Static4D[] maps, int comp) |
|
369 |
{ |
|
370 |
JobNode jn = target.mJobNode[0]; |
|
371 |
Job job = new Job(JOB_TYPE_TEXTURE,target,null,null,null,maps,comp,0,0,0,0,0,null); |
|
372 |
JobNode node = new JobNode(job); |
|
373 |
node.mPrevJobs.add(jn); |
|
374 |
jn.mNextJobs.add(node); |
|
375 |
mJobs.add(node); |
|
376 |
return node; |
|
377 |
} |
|
378 |
|
|
379 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
380 |
|
|
381 |
static JobNode effectAssoc(MeshBase target, int comp, int andAssoc, int equAssoc) |
|
382 |
{ |
|
383 |
JobNode jn = target.mJobNode[0]; |
|
384 |
Job job = new Job(JOB_TYPE_ASSOC,target,null,null,null,null,comp,andAssoc,equAssoc,0,0,0,null); |
|
385 |
JobNode node = new JobNode(job); |
|
386 |
node.mPrevJobs.add(jn); |
|
387 |
jn.mNextJobs.add(node); |
|
388 |
mJobs.add(node); |
|
389 |
return node; |
|
390 |
} |
|
391 |
|
|
392 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
393 |
|
|
394 |
static JobNode componentCenter(MeshBase target, int comp, float x, float y, float z) |
|
395 |
{ |
|
396 |
JobNode jn = target.mJobNode[0]; |
|
397 |
Job job = new Job(JOB_TYPE_CENTER,target,null,null,null,null,comp,0,0,x,y,z,null); |
|
398 |
JobNode node = new JobNode(job); |
|
399 |
node.mPrevJobs.add(jn); |
|
400 |
jn.mNextJobs.add(node); |
|
401 |
mJobs.add(node); |
|
402 |
return node; |
|
403 |
} |
|
404 |
|
|
405 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
406 |
|
|
407 |
static JobNode setNotAffected(MeshBase target, int[] comps) |
|
408 |
{ |
|
409 |
JobNode jn = target.mJobNode[0]; |
|
410 |
Job job = new Job(JOB_TYPE_NOT_AFFECTED,target,null,null,null,null,0,0,0,0,0,0,comps); |
|
411 |
JobNode node = new JobNode(job); |
|
412 |
node.mPrevJobs.add(jn); |
|
413 |
jn.mNextJobs.add(node); |
|
414 |
mJobs.add(node); |
|
415 |
return node; |
|
416 |
} |
|
417 |
|
|
418 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
419 |
/** |
|
420 |
* Only for use by the library itself. |
|
421 |
* |
|
422 |
* @y.exclude |
|
423 |
*/ |
|
424 |
public static void onPause() |
|
425 |
{ |
|
426 |
int num = mJobs.size(); |
|
427 |
|
|
428 |
for(int i=0; i<num; i++) |
|
429 |
{ |
|
430 |
mJobs.get(i).clear(); |
|
431 |
} |
|
432 |
|
|
433 |
mJobs.clear(); |
|
434 |
} |
|
435 |
} |
src/main/java/org/distorted/library/mesh/MeshBandedTriangle.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2020 Leszek Koltunski leszek@koltunski.pl // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// This library is free software; you can redistribute it and/or // |
|
7 |
// modify it under the terms of the GNU Lesser General Public // |
|
8 |
// License as published by the Free Software Foundation; either // |
|
9 |
// version 2.1 of the License, or (at your option) any later version. // |
|
10 |
// // |
|
11 |
// This library is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // |
|
14 |
// Lesser General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU Lesser General Public // |
|
17 |
// License along with this library; if not, write to the Free Software // |
|
18 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // |
|
19 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
20 |
|
|
21 |
package org.distorted.library.mesh; |
|
22 |
|
|
23 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
24 |
|
|
25 |
import org.distorted.library.main.DistortedLibrary; |
|
26 |
|
|
27 |
/** |
|
28 |
* Creator a triangular mesh divided into 'bands' i.e. strips parallel to one of the sides and |
|
29 |
* and of different elevations. |
|
30 |
* <p> |
|
31 |
* This is a building block for MeshMultigon. |
|
32 |
*/ |
|
33 |
public class MeshBandedTriangle extends MeshBase |
|
34 |
{ |
|
35 |
public static final int MODE_NORMAL = 0; |
|
36 |
public static final int MODE_INVERTED= 1; |
|
37 |
public static final int MODE_FLAT = 2; |
|
38 |
|
|
39 |
private static final int NUM_CACHE = 20; |
|
40 |
|
|
41 |
private float mLeftX, mLeftY; |
|
42 |
private float mRightX, mRightY; |
|
43 |
private float mTopX, mTopY; |
|
44 |
|
|
45 |
private float[] mNormL, mNormR; |
|
46 |
private int mMode; |
|
47 |
|
|
48 |
private float[] mBands; |
|
49 |
private int mNumBands; |
|
50 |
|
|
51 |
private int remainingVert; |
|
52 |
private int numVertices; |
|
53 |
private int extraBands, extraVertices; |
|
54 |
|
|
55 |
private float[] mCurveCache; |
|
56 |
private float mVecX, mVecY; |
|
57 |
|
|
58 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
59 |
|
|
60 |
private void computeNumberOfVertices() |
|
61 |
{ |
|
62 |
if( mMode==MODE_FLAT ) |
|
63 |
{ |
|
64 |
numVertices = 3; |
|
65 |
} |
|
66 |
else if( mMode==MODE_NORMAL ) |
|
67 |
{ |
|
68 |
numVertices = mNumBands*(mNumBands+2) + 4*extraVertices*extraBands; |
|
69 |
} |
|
70 |
else |
|
71 |
{ |
|
72 |
numVertices = mNumBands*(mNumBands+2); |
|
73 |
} |
|
74 |
|
|
75 |
remainingVert = numVertices; |
|
76 |
} |
|
77 |
|
|
78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
79 |
|
|
80 |
private void computeCache() |
|
81 |
{ |
|
82 |
mCurveCache = new float[NUM_CACHE]; |
|
83 |
float[] tmpD = new float[mNumBands+1]; |
|
84 |
float[] tmpX = new float[mNumBands+1]; |
|
85 |
|
|
86 |
for(int i=1; i<mNumBands; i++) |
|
87 |
{ |
|
88 |
tmpD[i] = (mBands[2*i-1]-mBands[2*i+1]) / (mBands[2*i]-mBands[2*i-2]); |
|
89 |
tmpX[i] = 1.0f - (mBands[2*i]+mBands[2*i-2])/2; |
|
90 |
} |
|
91 |
|
|
92 |
tmpD[0] = tmpD[1]; |
|
93 |
tmpD[mNumBands] = tmpD[mNumBands-1]; |
|
94 |
tmpX[0] = 0.0f; |
|
95 |
tmpX[mNumBands] = 1.0f; |
|
96 |
|
|
97 |
int prev = 0; |
|
98 |
int next = 0; |
|
99 |
|
|
100 |
for(int i=0; i<NUM_CACHE-1; i++) |
|
101 |
{ |
|
102 |
float x = i/(NUM_CACHE-1.0f); |
|
103 |
|
|
104 |
if( x>=tmpX[next] ) |
|
105 |
{ |
|
106 |
prev = next; |
|
107 |
while( next<=mNumBands && x>=tmpX[next] ) next++; |
|
108 |
} |
|
109 |
|
|
110 |
if( next>prev ) |
|
111 |
{ |
|
112 |
float t = (x-tmpX[prev]) / (tmpX[next]-tmpX[prev]); |
|
113 |
mCurveCache[i] = t*(tmpD[next]-tmpD[prev]) + tmpD[prev]; |
|
114 |
} |
|
115 |
else |
|
116 |
{ |
|
117 |
mCurveCache[i] = tmpD[next]; |
|
118 |
} |
|
119 |
} |
|
120 |
|
|
121 |
mCurveCache[NUM_CACHE-1] = tmpD[mNumBands]; |
|
122 |
} |
|
123 |
|
|
124 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
125 |
|
|
126 |
private float derivative(float x) |
|
127 |
{ |
|
128 |
if( x>=1.0f ) |
|
129 |
{ |
|
130 |
return 0.0f; |
|
131 |
} |
|
132 |
else |
|
133 |
{ |
|
134 |
float tmp = x*(NUM_CACHE-1); |
|
135 |
int i1 = (int)tmp; |
|
136 |
int i2 = i1+1; |
|
137 |
|
|
138 |
// why 0.5? Arbitrarily; this way the cubit faces of Twisty Puzzles |
|
139 |
// [the main and only user of this class] look better. |
|
140 |
return 0.5f*((tmp-i1)*(mCurveCache[i2]-mCurveCache[i1]) + mCurveCache[i1]); |
|
141 |
} |
|
142 |
} |
|
143 |
|
|
144 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
145 |
|
|
146 |
private void figureOutNormalVector2D(float qx) |
|
147 |
{ |
|
148 |
mVecX = mNormL[0] + qx*(mNormR[0]-mNormL[0]); |
|
149 |
mVecY = mNormL[1] + qx*(mNormR[1]-mNormL[1]); |
|
150 |
} |
|
151 |
|
|
152 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
153 |
|
|
154 |
private float figureOutDerivative(float qy) |
|
155 |
{ |
|
156 |
switch(mMode) |
|
157 |
{ |
|
158 |
case MODE_NORMAL : return derivative(1-qy); |
|
159 |
case MODE_INVERTED: return -derivative(qy); |
|
160 |
default : return 0; |
|
161 |
} |
|
162 |
} |
|
163 |
|
|
164 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
165 |
|
|
166 |
private float computeElevation(int band) |
|
167 |
{ |
|
168 |
switch(mMode) |
|
169 |
{ |
|
170 |
case MODE_NORMAL : return mBands[2*band+1]; |
|
171 |
case MODE_INVERTED: return mBands[2*(mNumBands-band)+1]; |
|
172 |
default : return mBands[2*mNumBands+1]; |
|
173 |
} |
|
174 |
} |
|
175 |
|
|
176 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
177 |
|
|
178 |
private int addStripVertex(int vertex, float qx, float qy, int band, float[] attribs1, float[] attribs2) |
|
179 |
{ |
|
180 |
remainingVert--; |
|
181 |
|
|
182 |
float bx = mLeftX + qx*(mRightX-mLeftX); |
|
183 |
float by = mLeftY + qx*(mRightY-mLeftY); |
|
184 |
|
|
185 |
float q = 1-qy; |
|
186 |
float x = bx + q*(mTopX-bx); |
|
187 |
float y = by + q*(mTopY-by); |
|
188 |
float z = computeElevation(band); |
|
189 |
|
|
190 |
figureOutNormalVector2D(band<mNumBands ? qx : 0.5f); |
|
191 |
float d = figureOutDerivative(qy); |
|
192 |
|
|
193 |
attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB ] = x; |
|
194 |
attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y; |
|
195 |
attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = z; |
|
196 |
|
|
197 |
float vx = d*mVecX; |
|
198 |
float vy = d*mVecY; |
|
199 |
float vz = mVecX*mVecX + mVecY*mVecY; |
|
200 |
float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz); |
|
201 |
|
|
202 |
int index = VERT1_ATTRIBS*vertex + NOR_ATTRIB; |
|
203 |
attribs1[index ] = vx/len; |
|
204 |
attribs1[index+1] = vy/len; |
|
205 |
attribs1[index+2] = vz/len; |
|
206 |
|
|
207 |
attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB ] = x+0.5f; |
|
208 |
attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f; |
|
209 |
|
|
210 |
return vertex+1; |
|
211 |
} |
|
212 |
|
|
213 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
214 |
|
|
215 |
private int createBand(int vertex, int band, float[] attribs1, float[] attribs2) |
|
216 |
{ |
|
217 |
boolean fromLeft = (band%2 == 0); |
|
218 |
int extra = ((band<extraBands && mMode==MODE_NORMAL) ? extraVertices : 0); |
|
219 |
int n = mNumBands-band-1; |
|
220 |
|
|
221 |
float b = 1.0f/(mNumBands-band); |
|
222 |
float dxb = fromLeft ? b : -b; |
|
223 |
float sdx = dxb/(extra+1); |
|
224 |
|
|
225 |
float qx = fromLeft ? 0.0f : 1.0f; |
|
226 |
|
|
227 |
int bb = mMode==MODE_NORMAL ? band : mNumBands-band; |
|
228 |
int bt = mMode==MODE_NORMAL ? band+1 : mNumBands-(band+1); |
|
229 |
|
|
230 |
float qyb = mBands[2*bb]; |
|
231 |
float qyt = mBands[2*bt]; |
|
232 |
|
|
233 |
if( mMode!=MODE_NORMAL ) |
|
234 |
{ |
|
235 |
qyb = 1-qyb; |
|
236 |
qyt = 1-qyt; |
|
237 |
} |
|
238 |
|
|
239 |
vertex = addStripVertex(vertex, qx, qyb, band, attribs1,attribs2); |
|
240 |
|
|
241 |
for(int v=0; v<extra; v++) |
|
242 |
{ |
|
243 |
vertex = addStripVertex(vertex, qx , qyt, band+1, attribs1,attribs2); |
|
244 |
vertex = addStripVertex(vertex, qx+(v+1)*sdx, qyb, band , attribs1,attribs2); |
|
245 |
} |
|
246 |
|
|
247 |
if( n>0 ) |
|
248 |
{ |
|
249 |
float t = 1.0f/n; |
|
250 |
float dxt = fromLeft ? t : -t; |
|
251 |
|
|
252 |
for(int v=0; v<n; v++) |
|
253 |
{ |
|
254 |
vertex=addStripVertex(vertex, qx+ v *dxt, qyt, band+1, attribs1, attribs2); |
|
255 |
vertex=addStripVertex(vertex, qx+(v+1)*dxb, qyb, band , attribs1, attribs2); |
|
256 |
} |
|
257 |
} |
|
258 |
|
|
259 |
qx = 1-qx; |
|
260 |
|
|
261 |
for(int v=0; v<=extra; v++) |
|
262 |
{ |
|
263 |
vertex = addStripVertex(vertex, qx , qyt, band+1, attribs1,attribs2); |
|
264 |
vertex = addStripVertex(vertex, qx-dxb+(v+1)*sdx, qyb, band , attribs1,attribs2); |
|
265 |
} |
|
266 |
|
|
267 |
return vertex; |
|
268 |
} |
|
269 |
|
|
270 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
271 |
|
|
272 |
private void buildGrid(float[] attribs1, float[] attribs2) |
|
273 |
{ |
|
274 |
if( mMode==MODE_FLAT ) |
|
275 |
{ |
|
276 |
addStripVertex(0, 0, 1, 0, attribs1,attribs2); |
|
277 |
addStripVertex(1, 0, 0, 0, attribs1,attribs2); |
|
278 |
addStripVertex(2, 1, 1, 0, attribs1,attribs2); |
|
279 |
} |
|
280 |
else |
|
281 |
{ |
|
282 |
int vertex=0; |
|
283 |
for(int b=0; b<mNumBands; b++) vertex=createBand(vertex, b, attribs1, attribs2); |
|
284 |
} |
|
285 |
} |
|
286 |
|
|
287 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
288 |
// PUBLIC API |
|
289 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
290 |
/** |
|
291 |
* Create a triangular mesh split into 'bands' - i.e. strips of triangles - which are parallel to |
|
292 |
* a given edge. |
|
293 |
* |
|
294 |
* @param vL A pair of floats (x,y) which defines the 'left' vertex of the triangle. |
|
295 |
* @param vR A pair of floats (x,y) which defines the 'right' vertex of the triangle. |
|
296 |
* @param vT A pair of floats (x,y) which defines the 'top' vertex of the triangle. |
|
297 |
* @param bands 2K floats; K pairs of two floats each describing a single band. |
|
298 |
* From (1.0,Z[0]) (the 'left-right' edge, its Z elevation) to (0.0,Z[K]) |
|
299 |
* (the 'top' vertex, its elevation). The polygon is split into such strips. |
|
300 |
* Must be band[2*i] > band[2*(i+1)] ! |
|
301 |
* The way the bands get interpreted also depends on the 'mode' param. |
|
302 |
* @param normL A pair of floats which define a 2D vector - which is the normal vector of each |
|
303 |
* mesh vertex which lies on the 'left-top' edge casted to the XY plane. |
|
304 |
* @param normR Same as above but about the vertices which belong to the 'right-top' triangle |
|
305 |
* edge. This and the previous param define the vector field of normals, as seen |
|
306 |
* from above, of the whole mesh. |
|
307 |
* @param mode MODE_UP, MODE_DOWN or MODE_FLAT. |
|
308 |
* This defines how we interpret the bands. |
|
309 |
* If UP, we interpret them the same as in MeshPolygon - i.e. the first band is |
|
310 |
* about the 'left-right' edge, then progressively towards the 'top'. |
|
311 |
* If DOWN, we turn the interpretation of the bands upside-down: it is the last |
|
312 |
* band which defines the strip aong the 'left-right' edge. |
|
313 |
* If FLAT, everything is flat anyway, so we disregard the bands and return a mesh |
|
314 |
* with 3 vertices. |
|
315 |
* @param exBands This and the next parameter describe how to make the mesh denser at the |
|
316 |
* 'left' and 'right' vertices. If e.g. exBands=3 and exVertices=2, then 3 triangles |
|
317 |
* of the outermost band (and 2 triangles of the next band, and 1 triangle of the |
|
318 |
* third band) get denser - the 3 triangles become 3+2 = 5. |
|
319 |
* @param exVertices See above. |
|
320 |
*/ |
|
321 |
public MeshBandedTriangle(float[] vL, float[] vR, float[] vT, float[] bands, float[] normL, float[] normR, int mode, int exBands, int exVertices) |
|
322 |
{ |
|
323 |
super(); |
|
324 |
|
|
325 |
mLeftX = vL[0]; |
|
326 |
mLeftY = vL[1]; |
|
327 |
mRightX = vR[0]; |
|
328 |
mRightY = vR[1]; |
|
329 |
mTopX = vT[0]; |
|
330 |
mTopY = vT[1]; |
|
331 |
|
|
332 |
mMode = mode; |
|
333 |
mNormL= new float[] { normL[0],normL[1] }; |
|
334 |
mNormR= new float[] { normR[0],normR[1] }; |
|
335 |
|
|
336 |
mBands = bands; |
|
337 |
mNumBands = mBands.length/2 -1; |
|
338 |
extraBands = exBands; |
|
339 |
extraVertices = exVertices; |
|
340 |
|
|
341 |
computeNumberOfVertices(); |
|
342 |
computeCache(); |
|
343 |
|
|
344 |
float[] attribs1= new float[VERT1_ATTRIBS*numVertices]; |
|
345 |
float[] attribs2= new float[VERT2_ATTRIBS*numVertices]; |
|
346 |
|
|
347 |
buildGrid(attribs1,attribs2); |
|
348 |
|
|
349 |
if( remainingVert!=0 ) |
|
350 |
DistortedLibrary.logMessage("MeshBandedTriangle: remainingVert " +remainingVert ); |
|
351 |
|
|
352 |
setAttribs(attribs1,attribs2); |
|
353 |
} |
|
354 |
|
|
355 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
356 |
/** |
|
357 |
* Copy constructor. |
|
358 |
*/ |
|
359 |
public MeshBandedTriangle(MeshBandedTriangle mesh, boolean deep) |
|
360 |
{ |
|
361 |
super(mesh,deep); |
|
362 |
} |
|
363 |
|
|
364 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
365 |
/** |
|
366 |
* Copy the Mesh. |
|
367 |
* |
|
368 |
* @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices, |
|
369 |
* normals and inflates (the rest, in particular the mVertAttribs2 containing texture |
|
370 |
* coordinates and effect associations, is always deep copied) |
|
371 |
*/ |
|
372 |
public MeshBandedTriangle copy(boolean deep) |
|
373 |
{ |
|
374 |
return new MeshBandedTriangle(this,deep); |
|
375 |
} |
|
376 |
} |
src/main/java/org/distorted/library/mesh/MeshBandedTriangle.kt | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2020 Leszek Koltunski leszek@koltunski.pl // |
|
3 |
// // |
|
4 |
// This file is part of Distorted. // |
|
5 |
// // |
|
6 |
// This library is free software; you can redistribute it and/or // |
|
7 |
// modify it under the terms of the GNU Lesser General Public // |
|
8 |
// License as published by the Free Software Foundation; either // |
|
9 |
// version 2.1 of the License, or (at your option) any later version. // |
|
10 |
// // |
|
11 |
// This library is distributed in the hope that it will be useful, // |
|
12 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of // |
|
13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // |
|
14 |
// Lesser General Public License for more details. // |
|
15 |
// // |
|
16 |
// You should have received a copy of the GNU Lesser General Public // |
|
17 |
// License along with this library; if not, write to the Free Software // |
|
18 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // |
|
19 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
20 |
|
|
21 |
package org.distorted.library.mesh; |
|
22 |
|
|
23 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
24 |
|
|
25 |
import org.distorted.library.main.DistortedLibrary; |
|
26 |
|
|
27 |
/** |
|
28 |
* Creator a triangular mesh divided into 'bands' i.e. strips parallel to one of the sides and |
|
29 |
* and of different elevations. |
|
30 |
* <p> |
|
31 |
* This is a building block for MeshMultigon. |
|
32 |
*/ |
|
33 |
public class MeshBandedTriangle extends MeshBase |
|
34 |
{ |
|
35 |
public static final int MODE_NORMAL = 0; |
|
36 |
public static final int MODE_INVERTED= 1; |
|
37 |
public static final int MODE_FLAT = 2; |
|
38 |
|
|
39 |
private static final int NUM_CACHE = 20; |
|
40 |
|
|
41 |
private float mLeftX, mLeftY; |
|
42 |
private float mRightX, mRightY; |
|
43 |
private float mTopX, mTopY; |
|
44 |
|
|
45 |
private float[] mNormL, mNormR; |
|
46 |
private int mMode; |
|
47 |
|
|
48 |
private float[] mBands; |
|
49 |
private int mNumBands; |
|
50 |
|
|
51 |
private int remainingVert; |
|
52 |
private int numVertices; |
|
53 |
private int extraBands, extraVertices; |
|
54 |
|
|
55 |
private float[] mCurveCache; |
|
56 |
private float mVecX, mVecY; |
|
57 |
|
|
58 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
59 |
|
|
60 |
private void computeNumberOfVertices() |
|
61 |
{ |
|
62 |
if( mMode==MODE_FLAT ) |
|
63 |
{ |
|
64 |
numVertices = 3; |
|
65 |
} |
|
66 |
else if( mMode==MODE_NORMAL ) |
|
67 |
{ |
|
68 |
numVertices = mNumBands*(mNumBands+2) + 4*extraVertices*extraBands; |
|
69 |
} |
|
70 |
else |
|
71 |
{ |
|
72 |
numVertices = mNumBands*(mNumBands+2); |
|
73 |
} |
|
74 |
|
|
75 |
remainingVert = numVertices; |
|
76 |
} |
|
77 |
|
|
78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
79 |
|
|
80 |
private void computeCache() |
|
81 |
{ |
|
82 |
mCurveCache = new float[NUM_CACHE]; |
|
83 |
float[] tmpD = new float[mNumBands+1]; |
|
84 |
float[] tmpX = new float[mNumBands+1]; |
|
85 |
|
|
86 |
for(int i=1; i<mNumBands; i++) |
|
87 |
{ |
|
88 |
tmpD[i] = (mBands[2*i-1]-mBands[2*i+1]) / (mBands[2*i]-mBands[2*i-2]); |
|
89 |
tmpX[i] = 1.0f - (mBands[2*i]+mBands[2*i-2])/2; |
|
90 |
} |
|
91 |
|
|
92 |
tmpD[0] = tmpD[1]; |
|
93 |
tmpD[mNumBands] = tmpD[mNumBands-1]; |
|
94 |
tmpX[0] = 0.0f; |
|
95 |
tmpX[mNumBands] = 1.0f; |
|
96 |
|
|
97 |
int prev = 0; |
|
98 |
int next = 0; |
|
99 |
|
|
100 |
for(int i=0; i<NUM_CACHE-1; i++) |
|
101 |
{ |
|
102 |
float x = i/(NUM_CACHE-1.0f); |
|
103 |
|
|
104 |
if( x>=tmpX[next] ) |
|
105 |
{ |
|
106 |
prev = next; |
|
107 |
while( next<=mNumBands && x>=tmpX[next] ) next++; |
|
108 |
} |
|
109 |
|
|
110 |
if( next>prev ) |
|
111 |
{ |
|
112 |
float t = (x-tmpX[prev]) / (tmpX[next]-tmpX[prev]); |
|
113 |
mCurveCache[i] = t*(tmpD[next]-tmpD[prev]) + tmpD[prev]; |
|
114 |
} |
|
115 |
else |
|
116 |
{ |
|
117 |
mCurveCache[i] = tmpD[next]; |
|
118 |
} |
|
119 |
} |
|
120 |
|
|
121 |
mCurveCache[NUM_CACHE-1] = tmpD[mNumBands]; |
|
122 |
} |
|
123 |
|
|
124 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
125 |
|
|
126 |
private float derivative(float x) |
|
127 |
{ |
|
128 |
if( x>=1.0f ) |
|
129 |
{ |
|
130 |
return 0.0f; |
|
131 |
} |
|
132 |
else |
|
133 |
{ |
|
134 |
float tmp = x*(NUM_CACHE-1); |
|
135 |
int i1 = (int)tmp; |
|
136 |
int i2 = i1+1; |
|
137 |
|
|
138 |
// why 0.5? Arbitrarily; this way the cubit faces of Twisty Puzzles |
|
139 |
// [the main and only user of this class] look better. |
|
140 |
return 0.5f*((tmp-i1)*(mCurveCache[i2]-mCurveCache[i1]) + mCurveCache[i1]); |
|
141 |
} |
|
142 |
} |
|
143 |
|
|
144 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
145 |
|
|
146 |
private void figureOutNormalVector2D(float qx) |
|
147 |
{ |
|
148 |
mVecX = mNormL[0] + qx*(mNormR[0]-mNormL[0]); |
|
149 |
mVecY = mNormL[1] + qx*(mNormR[1]-mNormL[1]); |
|
150 |
} |
|
151 |
|
|
152 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
153 |
|
|
154 |
private float figureOutDerivative(float qy) |
|
155 |
{ |
|
156 |
switch(mMode) |
|
157 |
{ |
|
158 |
case MODE_NORMAL : return derivative(1-qy); |
|
159 |
case MODE_INVERTED: return -derivative(qy); |
|
160 |
default : return 0; |
|
161 |
} |
|
162 |
} |
|
163 |
|
|
164 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
165 |
|
|
166 |
private float computeElevation(int band) |
|
167 |
{ |
|
168 |
switch(mMode) |
|
169 |
{ |
|
170 |
case MODE_NORMAL : return mBands[2*band+1]; |
|
171 |
case MODE_INVERTED: return mBands[2*(mNumBands-band)+1]; |
|
172 |
default : return mBands[2*mNumBands+1]; |
|
173 |
} |
|
174 |
} |
|
175 |
|
|
176 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
177 |
|
|
178 |
private int addStripVertex(int vertex, float qx, float qy, int band, float[] attribs1, float[] attribs2) |
|
179 |
{ |
|
180 |
remainingVert--; |
|
181 |
|
|
182 |
float bx = mLeftX + qx*(mRightX-mLeftX); |
|
183 |
float by = mLeftY + qx*(mRightY-mLeftY); |
|
184 |
|
|
185 |
float q = 1-qy; |
|
186 |
float x = bx + q*(mTopX-bx); |
|
187 |
float y = by + q*(mTopY-by); |
|
188 |
float z = computeElevation(band); |
|
189 |
|
|
190 |
figureOutNormalVector2D(band<mNumBands ? qx : 0.5f); |
|
191 |
float d = figureOutDerivative(qy); |
|
192 |
|
|
193 |
attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB ] = x; |
|
194 |
attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y; |
|
195 |
attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = z; |
|
196 |
|
|
197 |
float vx = d*mVecX; |
|
198 |
float vy = d*mVecY; |
|
199 |
float vz = mVecX*mVecX + mVecY*mVecY; |
|
200 |
float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz); |
|
201 |
|
|
202 |
int index = VERT1_ATTRIBS*vertex + NOR_ATTRIB; |
|
203 |
attribs1[index ] = vx/len; |
|
204 |
attribs1[index+1] = vy/len; |
|
205 |
attribs1[index+2] = vz/len; |
|
206 |
|
|
207 |
attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB ] = x+0.5f; |
|
208 |
attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f; |
|
209 |
|
|
210 |
return vertex+1; |
|
211 |
} |
|
212 |
|
|
213 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
214 |
|
|
215 |
private int createBand(int vertex, int band, float[] attribs1, float[] attribs2) |
|
216 |
{ |
|
217 |
boolean fromLeft = (band%2 == 0); |
|
218 |
int extra = ((band<extraBands && mMode==MODE_NORMAL) ? extraVertices : 0); |
|
219 |
int n = mNumBands-band-1; |
|
220 |
|
|
221 |
float b = 1.0f/(mNumBands-band); |
|
222 |
float dxb = fromLeft ? b : -b; |
|
223 |
float sdx = dxb/(extra+1); |
|
224 |
|
Also available in: Unified diff
Rename .java to .kt