From 767be784dc7fe293bf5c5ee6507df242526be3ed Mon Sep 17 00:00:00 2001 From: Normand Briere <nbriere@noware.ca> Date: Tue, 24 Sep 2019 02:10:06 -0400 Subject: [PATCH] Rag doll is back. --- Object3D.java | 695 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 557 insertions(+), 138 deletions(-) diff --git a/Object3D.java b/Object3D.java index b8c4bc0..b4eaccb 100644 --- a/Object3D.java +++ b/Object3D.java @@ -25,30 +25,106 @@ // Use GetUUID for backward compatibility with null. private UUID uuid = UUID.randomUUID(); - // TEMPORARY for mocap undo. No need to be transient. + // TEMPORARY for versions. No need to be transient. mocap.reader.BVHReader.BVHResult savebvh; Object3D saveskeleton; + + // FileObject + Object3D savefilecontent; // String skyboxname; String skyboxext; - Object3D versionlist[]; + Object3D[] versionlist; int versionindex = -1; java.util.Hashtable<java.util.UUID, Object3D> versiontable; // = new java.util.Hashtable<java.util.UUID, Object3D>(); ScriptNode scriptnode; + void deepCopyNode(Object3D other) + { + other.skyboxname = skyboxname; + other.skyboxext = skyboxext; + + if (toParent != null) + { + other.toParent = LA.newMatrix(); + other.fromParent = LA.newMatrix(); + LA.matCopy(toParent, other.toParent); + LA.matCopy(fromParent, other.fromParent); + if (toParentMarked != null) + { + other.toParentMarked = LA.newMatrix(); + other.fromParentMarked = LA.newMatrix(); + LA.matCopy(toParentMarked, other.toParentMarked); + LA.matCopy(fromParentMarked, other.fromParentMarked); + } + } + else + { + if (other.toParent == null) +// assert(other.toParent == null); +// new Exception().printStackTrace(); + System.err.println("null parent: " + other); + } + + /* + double ident[][] = LA.newMatrix(); + if (bRep == null) + other.bRep = null; + else + other.bRep = new BoundaryRep(bRep, ident); + */ + // Really new... + //other.editWindow = null; + if (name == null) + other.name = null; + else + other.name = new String(name); + + if (material != null) + { + other.material = new cMaterial(material); + } else + { + other.material = null; + } + + other.GetTextures().name = GetTextures().name; + + CopyExtraMaterial(other); + + other.touched = touched; + other.softtouched = softtouched; + + other.random = random; + other.link2master = link2master; + other.transformcount = transformcount; + other.marked = marked; + other.skip = skip; + other.count = count; + other.flipV = flipV; + other.live = live; + other.rewind = rewind; + other.hide = hide; + other.texres = texres; + other.speedup = speedup; + other.height = height; + other.depth = depth; + } + int VersionCount() { int count = 0; - for (int i = versionlist.length; --i >= 0;) - { - if (versionlist[i] != null) - count++; - } + if (versionlist != null) + for (int i = versionlist.length; --i >= 0;) + { + if (versionlist[i] != null) + count++; + } return count; } @@ -64,6 +140,7 @@ projectedVertices[i] = new cVector2(); // Others } projectedVertices[0].x = 100; // bump + projectedVertices[1].y = 1000; // punchthrough. only for png } void MinMax(cVector minima, cVector maxima) @@ -190,8 +267,39 @@ } } + boolean HasBigData() + { + if (blockloop) + return false; + + if (bRep != null) + { + return true; + } + + blockloop = true; + + for (int i = 0; i < Size(); i++) + { + Object3D child = (Object3D) get(i); + if (child == null) + continue; + if (child.HasBigData()) + { + blockloop = false; + return true; + } + } + + blockloop = false; + return false; + } + void ExtractBigData(java.util.Hashtable<java.util.UUID, Object3D> hashtable) { + if (blockloop) + return; + Object3D o; boolean isnew = false; @@ -215,7 +323,7 @@ hashtable.put(GetUUID(), o); } - if (!blockloop) + //if (!blockloop) { blockloop = true; @@ -227,7 +335,7 @@ blockloop = false; } - if (isnew) + //if (isnew) ExtractBigData(o); } @@ -338,15 +446,15 @@ void RestoreBigData(java.util.Hashtable<java.util.UUID, Object3D> hashtable) { + if (blockloop) + return; + if (!hashtable.containsKey(GetUUID())) return; Object3D o = hashtable.get(GetUUID()); RestoreBigData(o); - - if (blockloop) - return; blockloop = true; @@ -363,6 +471,7 @@ void RestoreBigData(Object3D o) { //System.err.println("RestoreBigData : " + this + " <-- " + o); + Grafreed.Assert(this.bRep == null); this.bRep = o.bRep; if (this.support != null && o.transientrep != null) @@ -524,7 +633,7 @@ transient boolean keepdontselect; boolean dontselect = false; boolean hide = false; - boolean link2master = false; // performs reset support/master at each frame + boolean link2master = false; // performs reset support/master at each frame (cannot rename due to serialization) boolean marked = false; // animation node boolean skip = false; // centroid issue boolean skipmocap = false; // mocap data @@ -532,6 +641,9 @@ boolean random = false; boolean speedup = false; boolean rewind = false; + + // Option to sort triangles, e.g. for transparency. + boolean sort = false; float NORMALPUSH = 0; @@ -550,7 +662,7 @@ { sorted = true; - for (int i=0; i<size()-1; i++) + for (int i=0; i<Size()-1; i++) { Object3D obji = get(i); Object3D objj = get(i+1); @@ -574,7 +686,7 @@ { sorted = true; - for (int i=0; i<size()-1; i++) + for (int i=0; i<Size()-1; i++) { Object3D obji = get(i); Object3D objj = get(i+1); @@ -911,7 +1023,7 @@ void Step() { - // marde pour serialization de Texture + // patch pour serialization de Texture resetmaxcount(); resettransformcount(); resetstep(); @@ -1104,24 +1216,28 @@ { // return true; - if (material == null || material.multiply) - return true; +// if (material == null || material.multiply) +// return true; +// +// if (projectedVertices != null && projectedVertices.length > 2 && projectedVertices[2].y >= 10000) +// return false; +// +// // Transparent objects are dynamic because we have to sort the triangles. +// return material.opacity > 0.99; - if (projectedVertices != null && projectedVertices.length > 2 && projectedVertices[2].y >= 10000) - return false; - - // Transparent objects are dynamic because we have to sort the triangles. - return material.opacity > 0.99; + return !sort; } boolean IsOpaque() { // return true; - if (material == null || material.multiply) - return true; +// if (material == null || material.multiply) +// return true; +// +// return material.opacity > 0.99; - return material.opacity > 0.99; + return !sort; } Object3D() @@ -1199,8 +1315,10 @@ // will share the geometry assert (!(this instanceof Composite)); - return deepCopy(); // Never called for Composite - + + Object3D obj = deepCopy(); // Never called for Composite + obj.count = 2; + return obj; } boolean HasLoops() @@ -1208,6 +1326,30 @@ return false; } + void ResetUUIDs() + { + if (blockloop) + { + return; + } + + this.uuid = null; + + blockloop = true; + + for (int i = 0; i < Size(); i++) + { + Object3D obj = (Object3D) Children().get(i); + + if (obj != null) + { + obj.ResetUUIDs(); + } + } + + blockloop = false; + } + boolean IsInfinite() { if (blockloop) @@ -1278,78 +1420,16 @@ return; blockloop = true; + + other.parent = parent; + //System.out.println("COPY " + this + " to " + other); //new Exception().printStackTrace(); + deepCopyNode(other); - other.parent = parent; - if (toParent != null) - { - other.toParent = LA.newMatrix(); - other.fromParent = LA.newMatrix(); - LA.matCopy(toParent, other.toParent); - LA.matCopy(fromParent, other.fromParent); - if (toParentMarked != null) - { - other.toParentMarked = LA.newMatrix(); - other.fromParentMarked = LA.newMatrix(); - LA.matCopy(toParentMarked, other.toParentMarked); - LA.matCopy(fromParentMarked, other.fromParentMarked); - } - } - else - { - if (other.toParent == null) -// assert(other.toParent == null); -// new Exception().printStackTrace(); - System.err.println("null parent: " + other); - } - /* - double ident[][] = LA.newMatrix(); - if (bRep == null) - other.bRep = null; - else - other.bRep = new BoundaryRep(bRep, ident); - */ - // Really new... other.bRep = bRep; // Share the geometry other.support = support; // Share the support - - //other.editWindow = null; - if (name == null) - other.name = null; - else - other.name = new String(name); - - if (material != null) - { - other.material = new cMaterial(material); - } else - { - other.material = null; - } - - other.GetTextures().name = GetTextures().name; - - CopyExtraMaterial(other); - - other.touched = touched; - other.softtouched = softtouched; - - other.random = random; - other.link2master = link2master; - other.transformcount = transformcount; - other.marked = marked; - other.skip = skip; - other.count = count; - other.flipV = flipV; - other.live = live; - other.rewind = rewind; - other.hide = hide; - other.texres = texres; - other.speedup = speedup; - other.height = height; - other.depth = depth; // aout 2013 if (/*displaylist != -1 &&*/other.displaylist != displaylist) // { @@ -1405,17 +1485,24 @@ if ((mask & GEOMETRY) != 0) { if (bRep != null) - bRep.overwriteThis(other.bRep==null?other.transientrep:other.bRep); - else - assert(other.bRep == null); - - if (bRep != null) { + bRep.overwriteThis(other.bRep==null?other.transientrep:other.bRep); CameraPane.RemoveList(bRep.displaylist); bRep.displaylist = 0; // june 2013 -1; } else - bRep = bRep; + { + //assert(other.bRep == null); + bRep = other.bRep; + } + +// if (bRep != null) +// { +// CameraPane.RemoveList(bRep.displaylist); +// bRep.displaylist = 0; // june 2013 -1; +// } +// else +// bRep = bRep; } /* Use a MASK = GEO/MAT @@ -3211,7 +3298,10 @@ { if (bRep != null) { + //bRep.GenerateNormals2(crease); // in-place doesn't work. it gives wrong normals (diamond artifact). bRep.GenerateNormals(crease); + if (!bRep.trimmed) + bRep.MergeNormals(); Touch(); } } @@ -3322,6 +3412,18 @@ obj.fromParent[3][0] = obj.fromParent[3][1] = obj.fromParent[3][2] = 0; } } + } + + public void Scale(int scale) + { + Object3D obj = this; + + obj.toParent[0][0] = obj.toParent[1][1] = obj.toParent[2][2] = scale; + obj.toParent[0][1] = obj.toParent[1][0] = obj.toParent[2][0] = 0; + obj.toParent[0][2] = obj.toParent[1][2] = obj.toParent[2][1] = 0; + obj.fromParent[0][0] = obj.fromParent[1][1] = obj.fromParent[2][2] = 1/scale; + obj.fromParent[0][1] = obj.fromParent[1][0] = obj.fromParent[2][0] = 0; + obj.fromParent[0][2] = obj.fromParent[1][2] = obj.fromParent[2][1] = 0; } public void TextureRatioTransform(int axis) @@ -3615,6 +3717,7 @@ if (bRep != null) { //bRep.RemoveOneTriangle(); + System.out.println(); System.out.println("Reducing " + this); if (name != null && name.contains("lockpickstraps")) name = name; @@ -3945,6 +4048,7 @@ void RevertMeshes() { + // BLOCKLOOP if (this instanceof cMesh) { ((cMesh)this).Revert(); @@ -3975,11 +4079,6 @@ Touch(); } - ResetRecur(); - } - - void ResetRecur() - { for (int i = 0; i < size(); i++) { Object3D child = (Object3D) get(i); // reserve(i); @@ -4002,11 +4101,6 @@ Step(); Touch(); - StepRecur(); - } - - void StepRecur() - { for (int i = 0; i < size(); i++) { Object3D child = (Object3D) get(i); // reserve(i); @@ -4193,8 +4287,8 @@ Touch(); } - transient cVector min = new cVector(); - transient cVector max = new cVector(); + transient cVector min; + transient cVector max; void getBounds(cVector minima, cVector maxima, boolean xform) { @@ -4210,15 +4304,15 @@ if (blockloop) return; - if (min == null) // ??? + if (min == null) { min = new cVector(); max = new cVector(); } - for (int i = 0; i<size(); i++) + for (int i = 0; i<Size(); i++) { - Object3D child = (Object3D) reserve(i); + Object3D child = (Object3D) get(i); //reserve(i); if (child == null) continue; @@ -4237,21 +4331,21 @@ if (child.hide && !(child instanceof Merge) || child.skip) //if (child.hide) { - release(i); + //release(i); continue; } blockloop = true; child.getBounds(min, max, true); // xform); blockloop = false; - release(i); + //release(i); MinMax(minima, maxima); } if (bRep != null) { - bRep.getBounds(minima,maxima,this); + bRep.getBounds(minima, maxima, xform?this:null); } if (false) // xform) @@ -6083,6 +6177,10 @@ return live && bRep != null; } + static cVector minima = new cVector(); + static cVector maxima = new cVector(); + static javax.vecmath.Point3d center = new javax.vecmath.Point3d(); + void Draw(iCameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked) { Invariants(); // june 2013 @@ -6090,6 +6188,29 @@ if (support != null) { // System.err.println("Draw " + this + " Frame # " + ((Mocap)((Merge)support).object).frame); + } + + if (live && link2master && support == null && !this.marked) // project on ground + { + getBounds(minima, maxima, true); + center.x = (minima.x + maxima.x) / 2; + center.y = 10000; // (minima.y + maxima.y) / 2; + center.z = (minima.z + maxima.z) / 2; + + Ray ray = new Ray(center, new Vector3d(0,-1,0)); + + IntersectResult res = new IntersectResult(); + res.t = Double.POSITIVE_INFINITY; + + if (Grafreed.grafreed.universe.intersect(ray, res)) + { + double resx = ray.eyePoint.x + ray.viewDirection.x * res.t; + double resy = ray.eyePoint.y + ray.viewDirection.y * res.t; + double resz = ray.eyePoint.z + ray.viewDirection.z * res.t; + + LA.matTranslate(toParent, 0, resy - minima.y, 0); + LA.matInvert(toParent, fromParent); + } } if (display.DrawMode() == iCameraPane.SELECTION && @@ -6211,8 +6332,8 @@ Globals.lighttouched = true; // all panes... } - touched = GetBRep() == null; // this instanceof Composite || this instanceof FileObject; // false; - //touched = false; + //touched = GetBRep() == null; // this instanceof Composite || this instanceof FileObject; // false; + touched = false; if (this instanceof Texture || this instanceof TextureNode) { @@ -6313,6 +6434,20 @@ { drawSelf(display, root, selected, blocked); } + +// if (!(this instanceof Composite)) +// { +// for (int i = 0; i < size(); i++) +// { +// Object3D child = (Object3D) reserve(i); +// if (child == null) +// continue; +// +// child.draw(display, root, selected, blocked); +// +// release(i); +// } +// } } else { /* @@ -6345,13 +6480,14 @@ boolean failedPigment = false; boolean failedBump = false; + CameraPane.lastObject = this; try { display.BindPigmentTexture(tex, texres); } catch (Exception e) { - System.err.println("FAILED: " + this); + // System.err.println("FAILED: " + this); failedPigment = true; } @@ -6382,6 +6518,20 @@ display.CallList(bRep.displaylist); // june 2013 drawSelf(display, root, selected); } + } + + assert (!(this instanceof Composite)); + { +// CRASH MOCAP!! for (int i = 0; i < size(); i++) +// { +// Object3D child = (Object3D) reserve(i); +// if (child == null) +// continue; +// +// child.draw(display, root, selected, blocked); +// +// release(i); +// } } } @@ -6435,16 +6585,17 @@ void CallList(iCameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked) { - if (GetBRep() == null) - { - drawSelf(display, root, selected, blocked); - } else + if (GetBRep() != null) { DrawNode(display, root, selected); if (this instanceof BezierPatch) { //drawSelf(display, root, selected); } + } + else + { + drawSelf(display, root, selected, blocked); } } @@ -6856,7 +7007,7 @@ facescompare[k] = new FaceCompare(k); } - center = new cVector(); + centertriangle = new cVector(); } else { @@ -6979,7 +7130,7 @@ */ } - transient cVector center; + transient cVector centertriangle; class FaceCompare implements Comparable { @@ -7008,14 +7159,14 @@ Vertex q = bRep.GetVertex(face.q); Vertex r = bRep.GetVertex(face.r); - center.set(p); - center.add(q); - center.add(r); - center.mul(1.0/3); + centertriangle.set(p); + centertriangle.add(q); + centertriangle.add(r); + centertriangle.mul(1.0/3); - center.sub(Globals.theRenderer.EyeCamera().location); + centertriangle.sub(Globals.theRenderer.EyeCamera().location); - distance = center.dot(center); + distance = centertriangle.dot(centertriangle); } return distance; @@ -8190,10 +8341,10 @@ } // + super.toString(); //return name + " (" + (SizeOf.deepSizeOf(this)/1024) + "K) " + this.getClass().getName(); -// if (!Globals.ADVANCED) -// return objname; + if (!Globals.ADVANCED) + return objname; - return objname + " " + System.identityHashCode(this); // + GetUUID() + return objname + " " + System.identityHashCode(this) + " " + GetUUID(); } public int hashCode() @@ -8438,8 +8589,8 @@ private static cVector2 qq2 = new cVector2(); private static cVector2 rr2 = new cVector2(); private static cVector2 ss2 = new cVector2(); - private static cVector edge1 = new cVector(); - private static cVector edge2 = new cVector(); +// private static cVector edge1 = new cVector(); +// private static cVector edge2 = new cVector(); //private static cVector norm = new cVector(); /*transient private*/ int hitSomething; static final int hitCenter = 1; @@ -8637,7 +8788,275 @@ Touch(); } + + static Vertex s1 = new Vertex(); + static Vertex s2 = new Vertex(); + static Vertex s3 = new Vertex(); + boolean intersectMesh(Ray ray, IntersectResult result) + { + boolean success = false; + + if (bRep.stripified) + { + int[] strips = bRep.getRawIndices(); + + // TRIANGLE STRIP ARRAY + if (bRep.trimmed) + { + float[] v = bRep.getRawVertices(); + + int count3 = 0; + + if (v.length > 0) + { + for (int i = 0; i < strips.length; i++) + { + s1.set(v[count3], v[count3 + 1], v[count3 + 2]); + count3 += 3; + + s2.set(v[count3], v[count3 + 1], v[count3 + 2]); + count3 += 3; + + for (int j = 0; j < strips[i] - 2; j++) + { + s3.set(v[count3], v[count3 + 1], v[count3 + 2]); + count3 += 3; + + if (j%2 == 0) + success |= intersectTriangle(ray, result, s1, s2, s3); + else + success |= intersectTriangle(ray, result, s1, s3, s2); + + s1.set(s2); + s2.set(s3); + } + } + } + + assert count3 == v.length; + } + else // !trimmed + { + int count = 0; + for (int i = 0; i < strips.length; i++) + { + Vertex p = bRep.GetVertex(bRep.indices[count++]); + Vertex q = bRep.GetVertex(bRep.indices[count++]); + + for (int j = 0; j < strips[i] - 2; j++) + { + Vertex r = bRep.GetVertex(bRep.indices[count++]); + + if (j%2 == 0) + success |= intersectTriangle(ray, result, p, q, r); + else + success |= intersectTriangle(ray, result, p, r, q); + + p = q; + q = r; + } + } + } + } else // catch (Error e) + { + int facecount = bRep.FaceCount(); + for (int i = 0; i < facecount; i++) + { + Face face = bRep.GetFace(i); + + Vertex p = bRep.GetVertex(face.p); + Vertex q = bRep.GetVertex(face.q); + Vertex r = bRep.GetVertex(face.r); + + success |= intersectTriangle(ray, result, p, q, r); + } + } + + return success; + } + + static cVector eye = new cVector(); + static cVector dir = new cVector(); + + transient BBox bbox = null; + + boolean intersect(Ray ray, IntersectResult result) + { + double eyex = ray.eyePoint.x; + double eyey = ray.eyePoint.y; + double eyez = ray.eyePoint.z; + + double dirx = ray.viewDirection.x; + double diry = ray.viewDirection.y; + double dirz = ray.viewDirection.z; + + if (this.fromParent != null && !(this instanceof TextureNode)) + { + eye.x = eyex; + eye.y = eyey; + eye.z = eyez; + dir.x = dirx; + dir.y = diry; + dir.z = dirz; + + LA.xformPos(eye, this.fromParent, eye); + LA.xformDir(dir, this.fromParent, dir); + + ray.eyePoint.x = eye.x; + ray.eyePoint.y = eye.y; + ray.eyePoint.z = eye.z; + + ray.viewDirection.x = dir.x; + ray.viewDirection.y = dir.y; + ray.viewDirection.z = dir.z; + } + + boolean success = false; + + boolean touch = false; + + if (bRep != null && link2master) + { + if (bbox == null) + { + bbox = new BBox(); + + cVector min = new cVector(); + cVector max = new cVector(); + + this.getBounds(min, max, true); + + bbox.min.x = min.x; + bbox.min.y = min.y; + bbox.min.z = min.z; + + bbox.max.x = max.x; + bbox.max.y = max.y; + bbox.max.z = max.z; + } + + if (true) // NOT WORKING bbox.intersect(ray, result)) + { + success |= intersectMesh(ray, result); + } + else + { + //this.hide = true; + touch = true; + } + } + + for (int i=0; i<size(); i++) + { + Object3D child = (Object3D) reserve(i); + + if (child == null) + continue; + + success |= child.intersect(ray, result); + release(i); + } + + ray.eyePoint.x = eyex; + ray.eyePoint.y = eyey; + ray.eyePoint.z = eyez; + + ray.viewDirection.x = dirx; + ray.viewDirection.y = diry; + ray.viewDirection.z = dirz; + +// if (touch) +// this.Touch(); // refresh display list + + return success; + } + + static Vector3d edge1 = new Vector3d(); + static Vector3d edge2 = new Vector3d(); + static Vector3d P = new Vector3d(); + static Vector3d T = new Vector3d(); + static Vector3d Q = new Vector3d(); + + private boolean intersectTriangle(Ray ray, IntersectResult result, Vertex v1, Vertex v2, Vertex v3) + { + if (false) + { + result.t = 0; + return true; + } + + /* + Fast, Minimum Storage Ray/Triangle Intersection, Moller et al. + + Reference: http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf + */ + + // Calculate edges of the triangle + edge1.set(v2.x - v1.x, v2.y - v1.y, v2.z - v1.z); + edge2.set(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z); + + // Calculate the determinant (U parameter) + P.cross(ray.viewDirection, edge2); + double det = edge1.dot(P); + + if (det > -1e-9 && det < 1e-9) + { + return false; + } // Ray lies in plane of triangle + + double invDet = 1 / det; + + // Calculate distance from vertex1 to ray origin + T.set(ray.eyePoint.x - v1.x, ray.eyePoint.y - v1.y, ray.eyePoint.z - v1.z); + + double U = (T.dot(P)) * invDet; // Calculate U parameter + + if (U < 0.f || U > 1.f) + { + return false; + } // Intersection lies outside of the triangle + + // Calculate V parameter + Q.cross(T, edge1); + + double V = ray.viewDirection.dot(Q) * invDet; + + if (V < 0.f || (U + V) > 1.f) + { + return false; + } // Intersection lies outside of the triangle + + double t = edge2.dot(Q) * invDet; + + if (t > 1e-9) // Triangle and ray intersects + { + //result.isIntersected = true; + //result.id = id; + + if (false) // isShadow) + { + result.t = t; + return true; + } else if (t < result.t) + { + result.object = this; + + result.t = t; + + //result.p.x = ray.eyePoint.x + ray.viewDirection.x * t; + //result.p.y = ray.eyePoint.y + ray.viewDirection.y * t; + //result.p.z = ray.eyePoint.z + ray.viewDirection.z * t; + + result.n.cross(edge1, edge2); + result.n.normalize(); + } + + return true; + } + + return false; + } public int Size() { -- Gitblit v1.6.2