19 |
19 |
|
20 |
20 |
package org.distorted.examples.meshfile;
|
21 |
21 |
|
|
22 |
import org.distorted.library.effect.MatrixEffect;
|
|
23 |
import org.distorted.library.effect.MatrixEffectMove;
|
|
24 |
import org.distorted.library.effect.MatrixEffectQuaternion;
|
|
25 |
import org.distorted.library.effect.MatrixEffectScale;
|
22 |
26 |
import org.distorted.library.effect.VertexEffect;
|
23 |
27 |
import org.distorted.library.effect.VertexEffectDeform;
|
24 |
|
import org.distorted.library.effect.VertexEffectMove;
|
25 |
|
import org.distorted.library.effect.VertexEffectQuaternion;
|
26 |
|
import org.distorted.library.effect.VertexEffectScale;
|
27 |
28 |
import org.distorted.library.mesh.MeshBase;
|
28 |
29 |
import org.distorted.library.mesh.MeshJoined;
|
29 |
30 |
import org.distorted.library.mesh.MeshPolygon;
|
... | ... | |
37 |
38 |
|
38 |
39 |
class FactoryCubit
|
39 |
40 |
{
|
40 |
|
static final float SQ5 = (float)Math.sqrt(5);
|
41 |
|
static final float SIN18 = (SQ5-1)/4;
|
42 |
|
static final float COS18 = (float)(0.25f*Math.sqrt(10.0f+2.0f*SQ5));
|
43 |
|
|
44 |
41 |
private static final float[] mBuffer = new float[3];
|
45 |
42 |
private static final float[] mQuat1 = new float[4];
|
46 |
43 |
private static final float[] mQuat2 = new float[4];
|
... | ... | |
50 |
47 |
|
51 |
48 |
private static FactoryCubit mThis;
|
52 |
49 |
|
53 |
|
private static class FaceInfo
|
|
50 |
private static class StickerInfo
|
54 |
51 |
{
|
55 |
52 |
float[] vertices;
|
|
53 |
}
|
|
54 |
|
|
55 |
private static class FaceInfo
|
|
56 |
{
|
|
57 |
int sticker;
|
56 |
58 |
float vx,vy,vz;
|
57 |
59 |
float scale;
|
58 |
60 |
float qx,qy,qz,qw;
|
59 |
61 |
boolean flip;
|
60 |
62 |
}
|
61 |
63 |
|
62 |
|
private static final ArrayList<FaceInfo> mFaceInfo = new ArrayList<>();
|
|
64 |
private static final ArrayList<FaceInfo> mFaceInfo = new ArrayList<>();
|
|
65 |
private static final ArrayList<StickerInfo> mStickerInfo = new ArrayList<>();
|
63 |
66 |
|
64 |
67 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
65 |
68 |
|
... | ... | |
189 |
192 |
|
190 |
193 |
private void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
|
191 |
194 |
{
|
192 |
|
Static4D reg= new Static4D(0,0,0,regionRadius);
|
|
195 |
Static4D region= new Static4D(0,0,0,regionRadius);
|
193 |
196 |
|
194 |
197 |
float centX = center.get0();
|
195 |
198 |
float centY = center.get1();
|
... | ... | |
201 |
204 |
float y = strength*(centY - vertex.get1());
|
202 |
205 |
float z = strength*(centZ - vertex.get2());
|
203 |
206 |
|
204 |
|
VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, reg);
|
|
207 |
VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, region);
|
205 |
208 |
mesh.apply(effect);
|
206 |
209 |
}
|
207 |
210 |
}
|
... | ... | |
229 |
232 |
|
230 |
233 |
float A = (float)Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) );
|
231 |
234 |
|
232 |
|
//android.util.Log.e("D", "("+x1+","+y1+","+z1+") , ("+x2+","+y2+","+z2+") , ("+x3+","+y3+","+z3+")" );
|
233 |
|
|
234 |
|
//boolean result = (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
|
235 |
|
|
236 |
|
//android.util.Log.e("D", "are those colinear? : "+result);
|
237 |
|
|
238 |
235 |
return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
|
239 |
236 |
}
|
240 |
237 |
|
... | ... | |
268 |
265 |
mBuffer[0] /= len;
|
269 |
266 |
mBuffer[1] /= len;
|
270 |
267 |
mBuffer[2] /= len;
|
271 |
|
|
272 |
|
//android.util.Log.e("D", " normal: "+mBuffer[0]+" "+mBuffer[1]+" "+mBuffer[2]);
|
273 |
268 |
}
|
274 |
269 |
|
275 |
270 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
... | ... | |
316 |
311 |
info.scale = Math.max(maxX-minX,maxY-minY);
|
317 |
312 |
|
318 |
313 |
int len = vert3D.length;
|
319 |
|
info.vertices = new float[2*len];
|
|
314 |
StickerInfo sInfo = new StickerInfo();
|
|
315 |
sInfo.vertices = new float[2*len];
|
|
316 |
mStickerInfo.add(sInfo);
|
320 |
317 |
|
321 |
318 |
for( int vertex=0; vertex<len; vertex++ )
|
322 |
319 |
{
|
323 |
|
info.vertices[2*vertex ] = vert3D[vertex][0] / info.scale;
|
324 |
|
info.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
|
|
320 |
sInfo.vertices[2*vertex ] = vert3D[vertex][0] / info.scale;
|
|
321 |
sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
|
325 |
322 |
}
|
326 |
323 |
|
327 |
324 |
info.flip = false;
|
... | ... | |
399 |
396 |
}
|
400 |
397 |
|
401 |
398 |
float cosTheta = mBuffer[2];
|
402 |
|
//float sinTheta = axiLen / vecLen;
|
403 |
|
|
404 |
399 |
float sinHalfTheta = (float)Math.sqrt(0.5f*(1-cosTheta));
|
405 |
400 |
float cosHalfTheta = (float)Math.sqrt(0.5f*(1+cosTheta));
|
406 |
401 |
|
... | ... | |
486 |
481 |
|
487 |
482 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
488 |
483 |
|
489 |
|
private void correctInfo(FaceInfo info, float[] rotatedVertices, int len, float[] originalVertices, float sin, float cos, boolean flip)
|
|
484 |
private void correctInfo(FaceInfo info, float scale, float sin, float cos, int oldSticker, boolean flip)
|
490 |
485 |
{
|
491 |
|
info.flip = flip;
|
|
486 |
mStickerInfo.remove(info.sticker);
|
492 |
487 |
|
493 |
|
System.arraycopy(originalVertices, 0, info.vertices, 0, 2*len);
|
494 |
|
|
495 |
|
float scale = rotatedVertices[0]!=0.0f ? originalVertices[0]/rotatedVertices[0] :
|
496 |
|
originalVertices[1]/rotatedVertices[1];
|
|
488 |
info.flip = flip;
|
|
489 |
info.sticker = oldSticker;
|
497 |
490 |
info.scale *= scale;
|
498 |
491 |
|
499 |
492 |
mQuat1[0] = 0.0f;
|
... | ... | |
516 |
509 |
|
517 |
510 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
518 |
511 |
|
519 |
|
private boolean foundVertex(FaceInfo info, float[] buffer, int len, boolean inverted, float[] vertices, float[] vert2D, float lenVert)
|
|
512 |
private boolean foundVertex(FaceInfo info, float[] buffer, int len, float[] preVert,
|
|
513 |
float[] newVert, float lenVert, int oldSticker, boolean inverted)
|
520 |
514 |
{
|
521 |
515 |
for(int vertex=0; vertex<len; vertex++)
|
522 |
516 |
{
|
523 |
|
float xR = vertices[2*vertex ];
|
524 |
|
float yR = vertices[2*vertex+1];
|
|
517 |
float xR = newVert[2*vertex ];
|
|
518 |
float yR = newVert[2*vertex+1];
|
525 |
519 |
float lenRotV = (float)Math.sqrt(xR*xR+yR*yR);
|
526 |
|
float cos = computeCos(xR,yR,vert2D[0],vert2D[1], lenRotV, lenVert);
|
527 |
|
float sin = computeSin(xR,yR,vert2D[0],vert2D[1], lenRotV, lenVert);
|
|
520 |
float cos = computeCos(xR,yR,preVert[0],preVert[1], lenRotV, lenVert);
|
|
521 |
float sin = computeSin(xR,yR,preVert[0],preVert[1], lenRotV, lenVert);
|
528 |
522 |
|
529 |
|
rotateAllVertices(buffer,len,vertices,sin,cos);
|
|
523 |
rotateAllVertices(buffer,len,newVert,sin,cos);
|
530 |
524 |
|
531 |
|
if( isScaledVersionOf(buffer,vert2D,len) )
|
|
525 |
if( isScaledVersionOf(buffer,preVert,len) )
|
532 |
526 |
{
|
533 |
|
correctInfo(info,buffer,len,vert2D,sin,cos,inverted);
|
|
527 |
float scale = preVert[0]!=0.0f ? buffer[0]/preVert[0] : buffer[1]/preVert[1];
|
|
528 |
correctInfo(info,scale,sin,cos,oldSticker,inverted);
|
534 |
529 |
return true;
|
535 |
530 |
}
|
536 |
531 |
}
|
... | ... | |
540 |
535 |
|
541 |
536 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
542 |
537 |
|
543 |
|
private boolean tryFindingRotation(final FaceInfo info, final float[] vert2D)
|
|
538 |
private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo preInfo)
|
544 |
539 |
{
|
545 |
|
int len = vert2D.length/2;
|
|
540 |
StickerInfo sNewInfo = mStickerInfo.get(newInfo.sticker);
|
|
541 |
StickerInfo sPreInfo = mStickerInfo.get(preInfo.sticker);
|
|
542 |
int len = sPreInfo.vertices.length;
|
|
543 |
float[] newVert = sNewInfo.vertices;
|
546 |
544 |
|
547 |
|
if( len == info.vertices.length/2 )
|
|
545 |
if( len == newVert.length )
|
548 |
546 |
{
|
549 |
|
float[] tmp1 = new float[2*len];
|
550 |
|
float lenVert = (float)Math.sqrt(vert2D[0]*vert2D[0] + vert2D[1]*vert2D[1]);
|
551 |
|
if( foundVertex(info,tmp1,len,false,info.vertices,vert2D,lenVert) ) return true;
|
552 |
|
float[] tmp2 = new float[2*len];
|
553 |
|
mirrorAllVertices(tmp2,len,info.vertices);
|
554 |
|
if( foundVertex(info,tmp1,len,true ,tmp2 ,vert2D,lenVert) ) return true;
|
|
547 |
int oldSticker = preInfo.sticker;
|
|
548 |
float[] tmp1 = new float[len];
|
|
549 |
float lenVert = (float)Math.sqrt(newVert[0]*newVert[0] + newVert[1]*newVert[1]);
|
|
550 |
if( foundVertex(newInfo, tmp1, len/2, sPreInfo.vertices, newVert, lenVert, oldSticker, false) ) return true;
|
|
551 |
float[] tmp2 = new float[len];
|
|
552 |
mirrorAllVertices(tmp2,len/2,sPreInfo.vertices);
|
|
553 |
if( foundVertex(newInfo, tmp1, len/2, tmp2 , newVert, lenVert, oldSticker, true ) ) return true;
|
555 |
554 |
}
|
556 |
555 |
|
557 |
556 |
return false;
|
... | ... | |
580 |
579 |
private void prepareFaceInfo( final float[][] vertices, final int[][] indexes)
|
581 |
580 |
{
|
582 |
581 |
mFaceInfo.clear();
|
|
582 |
mStickerInfo.clear();
|
583 |
583 |
|
584 |
584 |
int numFaces = indexes.length;
|
585 |
|
FaceInfo info;
|
|
585 |
FaceInfo preInfo;
|
586 |
586 |
|
587 |
587 |
for(int face=0; face<numFaces; face++)
|
588 |
588 |
{
|
... | ... | |
593 |
593 |
|
594 |
594 |
for(int previous=0; previous<face; previous++)
|
595 |
595 |
{
|
596 |
|
info = mFaceInfo.get(previous);
|
597 |
|
if( tryFindingRotation(newInfo,info.vertices) )
|
598 |
|
{
|
599 |
|
android.util.Log.e("D", "comparing face "+face+" to "+previous+" SUCCESS!!");
|
600 |
|
break;
|
601 |
|
}
|
|
596 |
preInfo = mFaceInfo.get(previous);
|
|
597 |
if( successfullyCollapsedStickers(newInfo,preInfo) ) break;
|
602 |
598 |
}
|
603 |
599 |
|
604 |
600 |
mFaceInfo.add(newInfo);
|
... | ... | |
607 |
603 |
|
608 |
604 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
609 |
605 |
|
610 |
|
private void printInfo(FaceInfo info)
|
|
606 |
private void prepareAndRoundCorners(MeshBase mesh, float[][] vertices, int[][] vertIndexes,
|
|
607 |
float[][] corners, int[] cornerIndexes )
|
611 |
608 |
{
|
612 |
|
android.util.Log.e("D", "vx="+info.vx+" vy="+info.vy+" vz="+info.vz);
|
613 |
|
android.util.Log.e("D", "qx="+info.qx+" qy="+info.qy+" qz="+info.qz+" qw="+info.qw);
|
614 |
|
android.util.Log.e("D", "scale="+info.scale);
|
|
609 |
int numNeig, lenFV;
|
|
610 |
int lenV = vertices.length;
|
|
611 |
int[] verts = new int[2*(lenV-1)];
|
|
612 |
Static3D[] staticVert = new Static3D[1];
|
|
613 |
Static3D center = new Static3D(0,0,0);
|
|
614 |
float cx, cy, cz;
|
|
615 |
float[] singleV;
|
615 |
616 |
|
616 |
|
String ver="";
|
|
617 |
for(int v=0; v<lenV; v++)
|
|
618 |
{
|
|
619 |
// prepare verts[]
|
|
620 |
numNeig = 0;
|
617 |
621 |
|
618 |
|
int len = info.vertices.length/2;
|
|
622 |
for (int[] vertIndex : vertIndexes)
|
|
623 |
{
|
|
624 |
lenFV = vertIndex.length;
|
619 |
625 |
|
620 |
|
for(int i =0; i<len; i++)
|
|
626 |
for (int fv = 0; fv < lenFV; fv++)
|
|
627 |
if (vertIndex[fv] == v)
|
|
628 |
{
|
|
629 |
int prev = fv > 0 ? fv - 1 : lenFV - 1;
|
|
630 |
int next = fv < lenFV - 1 ? fv + 1 : 0;
|
|
631 |
|
|
632 |
verts[numNeig++] = vertIndex[prev];
|
|
633 |
verts[numNeig++] = vertIndex[next];
|
|
634 |
}
|
|
635 |
}
|
|
636 |
|
|
637 |
cx=cy=cz=0.0f;
|
|
638 |
|
|
639 |
// from verts[] prepare center
|
|
640 |
for(int n=0; n<numNeig; n++)
|
|
641 |
{
|
|
642 |
singleV = vertices[verts[n]];
|
|
643 |
|
|
644 |
cx += singleV[0];
|
|
645 |
cy += singleV[1];
|
|
646 |
cz += singleV[2];
|
|
647 |
}
|
|
648 |
center.set(cx/numNeig - vertices[v][0],cy/numNeig - vertices[v][1],cz/numNeig - vertices[v][2]);
|
|
649 |
|
|
650 |
// round Corners
|
|
651 |
staticVert[0] = new Static3D(vertices[v][0], vertices[v][1], vertices[v][2]);
|
|
652 |
|
|
653 |
int corn = cornerIndexes[v];
|
|
654 |
float strength = corners[corn][0];
|
|
655 |
float radius = corners[corn][1];
|
|
656 |
|
|
657 |
roundCorners(mesh, center, staticVert, strength, radius);
|
|
658 |
}
|
|
659 |
}
|
|
660 |
|
|
661 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
662 |
|
|
663 |
private void printStickerInfo()
|
|
664 |
{
|
|
665 |
String ver="";
|
|
666 |
int stickers = mStickerInfo.size();
|
|
667 |
|
|
668 |
for(int s=0; s<stickers; s++)
|
621 |
669 |
{
|
622 |
|
ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
|
|
670 |
ver = "";
|
|
671 |
StickerInfo info = mStickerInfo.get(s);
|
|
672 |
int len = info.vertices.length/2;
|
|
673 |
|
|
674 |
for(int i =0; i<len; i++)
|
|
675 |
{
|
|
676 |
ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
|
|
677 |
}
|
623 |
678 |
}
|
624 |
679 |
|
625 |
680 |
android.util.Log.e("D", "vertices= "+ver);
|
... | ... | |
627 |
682 |
|
628 |
683 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
629 |
684 |
|
630 |
|
MeshBase createRoundedSolid(final float[][] vertices, final int[][] vertIndexes, final float[][] bands, final int[] bandIndexes)
|
|
685 |
private void printFaceInfo(FaceInfo info)
|
|
686 |
{
|
|
687 |
android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
|
|
688 |
+info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
|
|
689 |
}
|
|
690 |
|
|
691 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
692 |
|
|
693 |
MeshBase createRoundedSolid(final float[][] vertices, final int[][] vertIndexes,
|
|
694 |
final float[][] bands , final int[] bandIndexes,
|
|
695 |
final float[][] corners , final int[] cornerIndexes)
|
631 |
696 |
{
|
632 |
697 |
int EFFECTS_PER_FACE = 3;
|
633 |
698 |
|
... | ... | |
636 |
701 |
int numFaces = vertIndexes.length;
|
637 |
702 |
float[] band, bandsComputed;
|
638 |
703 |
MeshBase[] meshes = new MeshBase[numFaces];
|
639 |
|
FaceInfo info;
|
|
704 |
FaceInfo fInfo;
|
|
705 |
StickerInfo sInfo;
|
|
706 |
|
|
707 |
//printStickerInfo();
|
640 |
708 |
|
641 |
709 |
for(int face=0; face<numFaces; face++)
|
642 |
710 |
{
|
643 |
|
info = mFaceInfo.get(face);
|
|
711 |
fInfo = mFaceInfo.get(face);
|
|
712 |
sInfo = mStickerInfo.get(fInfo.sticker);
|
644 |
713 |
|
645 |
|
android.util.Log.d("D", "--------------");
|
646 |
|
printInfo(info);
|
|
714 |
//printFaceInfo(fInfo);
|
647 |
715 |
|
648 |
716 |
band = bands[bandIndexes[face]];
|
649 |
717 |
bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
|
650 |
|
meshes[face] = new MeshPolygon(info.vertices,bandsComputed,(int)band[5],(int)band[6]);
|
|
718 |
meshes[face] = new MeshPolygon(sInfo.vertices,bandsComputed,(int)band[5],(int)band[6]);
|
651 |
719 |
meshes[face].setEffectAssociation(0,(1<<face),0);
|
652 |
720 |
}
|
653 |
721 |
|
654 |
722 |
MeshBase mesh = new MeshJoined(meshes);
|
655 |
|
VertexEffect[] effects = new VertexEffect[EFFECTS_PER_FACE*numFaces];
|
|
723 |
MatrixEffect[] effects = new MatrixEffect[EFFECTS_PER_FACE*numFaces];
|
656 |
724 |
Static3D center = new Static3D(0,0,0);
|
657 |
725 |
|
658 |
726 |
for(int face=0; face<numFaces; face++)
|
659 |
727 |
{
|
660 |
728 |
int assoc = (1<<face);
|
661 |
|
info = mFaceInfo.get(face);
|
|
729 |
fInfo = mFaceInfo.get(face);
|
662 |
730 |
|
663 |
|
Static3D move3D= new Static3D(info.vx,info.vy,info.vz);
|
664 |
|
Static3D scale = new Static3D(info.scale,info.scale, info.flip ? -info.scale : info.scale);
|
665 |
|
Static4D quat = new Static4D(info.qx,info.qy,info.qz,info.qw);
|
|
731 |
Static3D move3D= new Static3D(fInfo.vx,fInfo.vy,fInfo.vz);
|
|
732 |
Static3D scale = new Static3D(fInfo.scale,fInfo.scale, fInfo.flip ? -fInfo.scale : fInfo.scale);
|
|
733 |
Static4D quat = new Static4D(fInfo.qx,fInfo.qy,fInfo.qz,fInfo.qw);
|
666 |
734 |
|
667 |
|
effects[EFFECTS_PER_FACE*face ] = new VertexEffectScale(scale);
|
668 |
|
effects[EFFECTS_PER_FACE*face+1] = new VertexEffectQuaternion(quat,center);
|
669 |
|
effects[EFFECTS_PER_FACE*face+2] = new VertexEffectMove(move3D);
|
|
735 |
effects[EFFECTS_PER_FACE*face ] = new MatrixEffectScale(scale);
|
|
736 |
effects[EFFECTS_PER_FACE*face+1] = new MatrixEffectQuaternion(quat,center);
|
|
737 |
effects[EFFECTS_PER_FACE*face+2] = new MatrixEffectMove(move3D);
|
670 |
738 |
|
671 |
|
effects[EFFECTS_PER_FACE*face ].setMeshAssociation(assoc,-1);
|
672 |
|
effects[EFFECTS_PER_FACE*face+1].setMeshAssociation(assoc,-1);
|
673 |
|
effects[EFFECTS_PER_FACE*face+2].setMeshAssociation(assoc,-1);
|
|
739 |
mesh.apply(effects[EFFECTS_PER_FACE*face ],assoc,-1);
|
|
740 |
mesh.apply(effects[EFFECTS_PER_FACE*face+1],assoc,-1);
|
|
741 |
mesh.apply(effects[EFFECTS_PER_FACE*face+2],assoc,-1);
|
674 |
742 |
}
|
675 |
743 |
|
676 |
|
for( VertexEffect effect : effects ) mesh.apply(effect);
|
|
744 |
prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
|
677 |
745 |
|
678 |
746 |
return mesh;
|
679 |
747 |
}
|
Face cubit creation: progress: rounded corners