import java.util.Hashtable;
|
|
//import javax.media.opengl.GL;
|
|
public class cMesh extends cSpring
|
{
|
static final long serialVersionUID = 8827868377169642153L; // 868525893588650813L;
|
|
Object3D ref;
|
transient Hashtable springs = new Hashtable(); // not used...
|
transient Hashtable folds = new Hashtable(); //
|
transient BoundaryRep refcopy = null;
|
|
static class cSpring
|
{
|
Vertex u,v;
|
|
cSpring(Vertex a, Vertex b)
|
{
|
u = a;
|
v = b;
|
}
|
|
public int hashCode()
|
{
|
return u.hashCode() ^ v.hashCode();
|
}
|
|
public boolean equals(Object o)
|
{
|
cSpring s = (cSpring) o;
|
|
// return u.equals(s.u) && v.equals(s.v) ||
|
// u.equals(s.v) && v.equals(s.u);
|
return u.x == s.u.x && u.y == s.u.y && u.z == s.u.z &&
|
v.x == s.v.x && v.y == s.v.y && v.z == s.v.z &&
|
v.s == s.v.s && v.t == s.v.t ||
|
u.x == s.v.x && u.y == s.v.y && u.z == s.v.z &&
|
v.x == s.u.x && v.y == s.u.y && v.z == s.u.z &&
|
v.s == s.u.s && v.t == s.u.t
|
;
|
}
|
}
|
|
cMesh()
|
{
|
this(null);
|
}
|
|
cMesh(Object3D bRep)
|
{
|
this("Mesh:" + bRep.name, bRep);
|
}
|
|
cMesh(String name, Object3D bRep)
|
{
|
super(name);
|
|
timeout = 100000000;
|
|
/*
|
assert(bRep.bRep != null);
|
if (bRep.bRep.trimmed)
|
{
|
System.out.print("TRIMMED MESH : " + bRep);
|
System.out.println("; BREP = " + bRep.bRep);
|
}
|
else
|
*/
|
ref = bRep;
|
|
material = //ref.material.Clone(); //
|
new cMaterial(ref.material);
|
ref.CopyExtraMaterial(this);
|
GetTextures().name = ref.GetTextures().name;
|
flipV = ref.flipV;
|
texres = ref.texres;
|
|
live = true;
|
}
|
|
Object3D deepCopy()
|
{
|
/*
|
cMesh e = new cMesh(ref);
|
deepCopySelf(e);
|
|
e.setup();
|
*/
|
assert(bRep == null);
|
Object3D e = new Object3D(ref.name);
|
bRep = transientrep;
|
deepCopySelf(e);
|
bRep = null;
|
|
// unshare the geometry
|
// double ident[][] = LA.newMatrix();
|
// bRep = new BoundaryRep(bRep, ident);
|
// displaylist = -1;
|
|
return e;
|
}
|
|
void merge(Object3D obj)
|
{
|
if (obj.bRep != null /*&& !obj.bRep.trimmed*/ && obj.bRep.VertexCount() >= 3 &&
|
!(obj instanceof Sphere && ((Sphere)obj).handle))
|
{
|
if (obj.bRep.stripified)
|
{
|
try
|
{
|
obj.bRep.Untrim();
|
obj.bRep.Trim(false,false,false);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
double gti[][] = LA.newMatrix(); // june 2013 obj.GlobalTransform();
|
double gt[][] = new double[4][4];
|
|
LA.matInvert(gti, gt);
|
LA.matTranspose(gti, gti);
|
|
System.out.println("----> MERGE " + this + "; #vertices = " + bRep.VertexCount() + "; #faces = " + bRep.FaceCount());
|
System.out.println(" OBJECT " + obj + "; #vertices = " + obj.bRep.VertexCount() + "; #faces = " + obj.bRep.FaceCount());
|
int base = bRep.VertexCount();
|
int linkoffset = 0;
|
int[] index = new int[obj.bRep.VertexCount()];
|
|
for (int i=0; i<obj.bRep.VertexCount(); i++)
|
{
|
Vertex v = obj.bRep.GetVertex(i);
|
|
Vertex v2 = new Vertex(v);
|
|
LA.xformPos(v2,gt, v2);
|
if (v2.norm != null)
|
{
|
LA.xformDir(v2.norm,gti, v2.norm);
|
v2.norm.normalize();
|
}
|
|
//v2.index = -1;
|
//bRep.AddVertex(v2);
|
Vertex in = bRep.GetCache(v2);
|
if (in == null)
|
{
|
v2.index = -1;
|
bRep.Remember(v2);
|
index[i] = i - linkoffset + base;
|
}
|
else
|
{
|
//bRep.AddVertex(in);
|
index[i] = in.index;
|
linkoffset += 1;
|
}
|
}
|
|
//assert bRep.VertexCount() == base + obj.bRep.VertexCount();
|
|
for (int j=0; j<obj.bRep.FaceCount(); j++)
|
{
|
Face f = obj.bRep.GetFace(j);
|
|
bRep.AddFace(index[f.p], index[f.q], index[f.r]);
|
}
|
|
//bRep.Trim(false, false,false,false);
|
}
|
|
if (obj instanceof Composite && !(obj instanceof CSG))
|
{
|
Composite group = (Composite) obj;
|
for (int i=group.children.size(); --i>=0;)
|
{
|
Object3D child = (Object3D) group.children.reserve(i);
|
|
if (child == null)
|
continue;
|
|
merge(child);
|
|
group.children.release(i);
|
}
|
}
|
}
|
|
void RefreshPositions()
|
{
|
if (transientrep == null)
|
Revert();
|
|
if (refcopy == null)
|
FreezeCopy();
|
|
for (int i=0; i<transientrep.VertexCount(); i++)
|
{
|
Vertex v = transientrep.GetVertex(i);
|
|
v.set(refcopy.GetVertex(i));
|
v.norm.set(refcopy.GetVertex(i).norm);
|
}
|
}
|
|
void RefreshNormals()
|
{
|
for (int i=0; i<transientrep.VertexCount(); i++)
|
{
|
Vertex v = transientrep.GetVertex(i);
|
|
Phys.allNodes.get(i).normal.set(v.norm);
|
}
|
}
|
|
void TransformToWorld(cVector out) //, cVector out)
|
{
|
// if (!live)
|
super.TransformToWorld(out);
|
}
|
|
void InitPhysics()
|
{
|
Phys = new PhysicsController3D();
|
|
C = new Collision(THEFLOOR);
|
|
// Point3D center = new Point3D();
|
|
// center.mul(0);
|
|
for (int i=0; i<transientrep.VertexCount(); i++)
|
{
|
Vertex v = transientrep.GetVertex(i);
|
|
// center.add(v);
|
|
DynamicNode n = new DynamicNode(v);
|
|
if (v.norm != null)
|
n.normal.set(v.norm);
|
|
n.addForce(G);
|
n.addForce(W);
|
Phys.addNode(n);
|
}
|
|
// center.mul(1.0/bRep.VertexCount());
|
|
Phys.addForce(C);
|
|
//if (folds == null)
|
// folds = new Hashtable();
|
|
|
//if (IsSoft() || IsFold() || IsUnfold())
|
{
|
Hashtable<cSpring,cSpring> springs = new Hashtable<cSpring,cSpring>();
|
|
for (int i=0; i<transientrep.FaceCount(); i++)
|
{
|
Face f = transientrep.GetFace(i);
|
Vertex p = transientrep.GetVertex(f.p);
|
Vertex q = transientrep.GetVertex(f.q);
|
Vertex r = transientrep.GetVertex(f.r);
|
|
if (p == q || q == r || r == p)
|
continue;
|
|
// new Fold(Phys.allNodes.get(f.p), Phys.allNodes.get(f.q), Phys.allNodes.get(f.q), K, 1);
|
|
DynamicNode dp = Phys.allNodes.get(f.p);
|
DynamicNode dq = Phys.allNodes.get(f.q);
|
DynamicNode dr = Phys.allNodes.get(f.r);
|
|
float deform = 0;
|
cSpring s = new cSpring(p,q);
|
//if (springs.get(s) == null)
|
if (springs.put(s,s) == null)
|
{
|
//System.out.println("New spring");
|
new Spring(dp, dq, 1/*K*/, 1,deform,false);
|
//springs.put(s, s);
|
}
|
s = new cSpring(p,r);
|
if (springs.put(s,s) == null)
|
{
|
//System.out.println("New spring");
|
new Spring(dp, dr, 1/*K*/, 1,deform,false);
|
//springs.put(s, s);
|
}
|
s = new cSpring(r,q);
|
if (springs.put(s,s) == null)
|
{
|
//System.out.println("New spring");
|
new Spring(dr, dq, 1/*K*/, 1,deform,false);
|
//springs.put(s, s);
|
}
|
}
|
|
for (int k=0; k<Phys.allSprings.size(); k++)
|
{
|
Spring s = Phys.allSprings.get(k);
|
|
s.nbcopies = 1;
|
|
if (IsNormalize())
|
//s.nbcopies = Math.abs(s.a.myForces.size() - s.b.myForces.size()) + 1;
|
s.nbcopies = (100/s.a.mySprings.size() + 100/s.b.mySprings.size())/2;
|
}
|
|
springs.clear();
|
|
Phys.InitNormals();
|
|
if (IsFold())
|
{
|
Phys.InitFolds(IsUnfold()); //, !IsSoft());
|
}
|
|
if (IsUnfold())
|
{
|
// Phys.InitUnfolds(!IsSoft());
|
}
|
}
|
|
if (!IsSoft() && !IsFold())
|
Phys.ClearSprings();
|
|
if (IsSolid())
|
{
|
/*
|
java.util.Vector<DynamicNode> handles = new java.util.Vector<DynamicNode>();
|
|
for (int k=0; k<Phys.allNodes.size(); k++)
|
{
|
DynamicNode n = Phys.allNodes.get(k);
|
|
//if (n.normal.y > 0.5)
|
// if (n.myForces.size() > 8)
|
// n.count = 1;
|
// else
|
// {
|
// }
|
//else
|
// n.mass = 0;
|
|
handles.add(n);
|
}
|
*/
|
|
// test
|
// DynamicNode handle = new DynamicNode(center.x, center.y, center.z, 0 /*0 , 1 or Float.MAX_VALUE*/, 0);
|
// Phys.addHandle(handle);
|
|
int size = Phys.allNodes.size();
|
|
for (int k=0; k < size; k++) // warning: "add handle" adds a node
|
{
|
DynamicNode dn = Phys.allNodes.get(k);
|
DynamicNode handle = new DynamicNode(dn.position.x, dn.position.y, dn.position.z, 0 /*0 , 1 or Float.MAX_VALUE*/, 0);
|
// DynamicNode handle = new DynamicNode(dn.position.x, dn.position.y, center.z, 0 /*0 , 1 or Float.MAX_VALUE*/, 0);
|
Phys.addHandle(handle);
|
|
double stiff = 1;
|
|
/*
|
// if (dn.normal.z > -0.75)
|
double cut = 1; // 0.5;
|
if (false) // -dn.normal.z < cut)
|
{
|
stiff = 1000*(1 + (-dn.normal.z-cut)/3); // ((-dn.normal.y-0.5)*(-dn.normal.y-0.5)*4) + 1;
|
//for (int i=0; i<stiff; i++)
|
// new Spring(handle, dn, K, 1);
|
}
|
else
|
stiff = 1000;
|
*/
|
|
double restlength = 1;
|
|
new Spring(handle, dn, stiff*1/*K*/, restlength,0,true);
|
|
// handle = new DynamicNode(dn.position.x, center.y, dn.position.z, 0 /*0 , 1 or Float.MAX_VALUE*/, 0);
|
// Phys.addHandle(handle);
|
// new Spring(handle, dn, stiff*K, restlength,0,true);
|
|
// handle = new DynamicNode(center.x, dn.position.y, dn.position.z, 0 /*0 , 1 or Float.MAX_VALUE*/, 0);
|
// Phys.addHandle(handle);
|
// new Spring(handle, dn, stiff*K, restlength,0,true);
|
}
|
}
|
|
System.out.println("#nodes = " + Phys.allNodes.size());
|
System.out.println("#springs = " + Phys.allSprings.size());
|
System.out.println("#forces = " + Phys.allForces.size());
|
System.out.println("#handles = " + Phys.allHandles.size());
|
}
|
|
void setup()
|
{
|
if (ref == null)
|
return;
|
|
Grafreed.epsequal = IsEpsEqual();
|
Grafreed.linkUV = IsLinkUV();
|
|
// BoundaryRep oldrep = transientrep;
|
|
bRep = new BoundaryRep();
|
//(BoundaryRep) Applet3D.clone(ref.bRep);
|
|
int keepcount = ref.count;
|
if (ref.count == 0 || ref.count == -1000)
|
ref.count = 1;
|
|
Object3D obj = ref.GetObject();
|
Object3D par = obj.parent;
|
obj.parent = null;
|
|
// may 2014: side-effect with UVs!!
|
merge((Object3D) Grafreed.clone(obj));
|
|
obj.parent = par;
|
|
ref.count = keepcount;
|
|
System.out.println("RESULT " + ref + "; #vertices = " + bRep.VertexCount() + "; #faces = " + bRep.FaceCount());
|
bRep.Trim(false, false,false,false,false);
|
System.out.println("------> TRIM " + ref + "; #vertices = " + bRep.VertexCount() + "; #faces = " + bRep.FaceCount());
|
|
Grafreed.epsequal = false;
|
|
if (transientrep != null && bRep.VertexCount() == transientrep.VertexCount())
|
{
|
// suppose same mesh
|
for (int i=transientrep.VertexCount(); --i>=0;)
|
{
|
Vertex v = bRep.GetVertex(i);
|
|
transientrep.SetVertex(v, i);
|
}
|
|
bRep = transientrep; // goodbye...
|
}
|
|
// FreezeCopy();
|
/*
|
mesh = new DynamicNode[numX][numY];
|
|
if(thick)
|
mesh2 = new DynamicNode[numX][numY];
|
else
|
mesh2 = null;
|
|
//centers = new DynamicNode[numX-1][numY-1];
|
handles = new DynamicNode[numX];
|
|
time = 0;
|
*/
|
}
|
|
void FreezeCopy()
|
{
|
if (ref instanceof cMesh)
|
{
|
if (ref.transientrep == null)
|
ref.Revert();
|
refcopy = ref.transientrep;
|
}
|
else
|
// geometry is merged...
|
refcopy = (BoundaryRep) Grafreed.clone(transientrep);
|
}
|
|
transient cVector minima = new cVector();
|
transient cVector maxima = new cVector();
|
|
void ClearReferences()
|
{
|
ref = null;
|
|
super.ClearReferences();
|
}
|
|
|
void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) // ??
|
{
|
// ?????? if (size() > 0)
|
// {
|
// super.drawSelf(display, root, selected);
|
// return;
|
// }
|
// if (live && display.LIVE && display.drawMode == CameraPane.DEFAULT)
|
// {
|
// //System.out.println("UPDATE");
|
// if (Phys == null)
|
// InitPhysics();
|
//
|
// if (minima == null)
|
// {
|
// minima = new cVector();
|
// maxima = new cVector();
|
// }
|
//
|
//// ref.getBounds(minima, maxima, true);
|
//// Phys.reference.set((maxima.x+minima.x)/2,(maxima.y+minima.y)/2,(maxima.z+minima.z)/2);
|
// //ref.
|
// // CameraPane.selectedpoint.
|
// getAverage(minima, true);
|
// // minima.y += 0.1;
|
// // minima.z -= 0.075;
|
//
|
// // getAverage(minima, true, 0.1);
|
//
|
// if (Phys.reference.dot(Phys.reference) == 0)
|
// Phys.reference.set(minima);
|
// //Phys.reference.add(minima);
|
// //Phys.reference.mul(0.5);
|
//
|
// Phys.update();
|
//
|
// // if (IsAutoFreeze())
|
// // InitPhysics();
|
// // bRep.GenerateNormals();
|
// // Phys.update();
|
// // Phys.update();
|
// // Phys.update();
|
// }
|
|
if (transientrep == null)
|
{
|
setup();
|
transientrep = bRep;
|
FreezeCopy();
|
}
|
|
bRep = transientrep; // TEMPO!
|
|
//System.out.println("TRIMMED : " + bRep.trimmed);
|
// System.out.println("111 node : " + Phys.allNodes.get(0) + "; " + System.identityHashCode(Phys.allNodes.get(0)));
|
//System.out.println("222 node : " + Phys.allNodes.get(0) + "; " + System.identityHashCode(Phys.allNodes.get(0)));
|
|
DrawNode0(display);
|
|
if(/*showsprings &&*/ Phys != null)
|
{
|
display.DrawDynamicMesh(this);
|
}
|
|
if (live && Globals.isLIVE() && display.DrawMode() == CameraPane.DEFAULT)
|
{
|
//System.out.println("UPDATE");
|
if (Phys == null)
|
InitPhysics();
|
|
if (minima == null)
|
{
|
minima = new cVector();
|
maxima = new cVector();
|
}
|
|
CameraPane.CreateSelectedPoint();
|
|
// ref.getBounds(minima, maxima, true);
|
// Phys.reference.set((maxima.x+minima.x)/2,(maxima.y+minima.y)/2,(maxima.z+minima.z)/2);
|
//ref.
|
CameraPane.selectedpoint.
|
getAverage(minima, true);
|
// minima.y += 0.1;
|
// minima.z -= 0.075;
|
|
getAverage(minima, true, 0.1);
|
|
Phys.reference.set(minima);
|
//Phys.reference.add(minima);
|
//Phys.reference.mul(0.5);
|
|
Phys.update();
|
|
// if (IsAutoFreeze())
|
// InitPhysics();
|
// bRep.GenerateNormals();
|
// Phys.update();
|
// Phys.update();
|
// Phys.update();
|
}
|
|
bRep = null;
|
}
|
}
|