From 54adfcbf93eb477bedeec45409f36cf7e102b790 Mon Sep 17 00:00:00 2001
From: Normand Briere <nbriere@noware.ca>
Date: Mon, 16 Sep 2019 21:54:55 -0400
Subject: [PATCH] Navigation with intersection.

---
 Object3D.java |  284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 271 insertions(+), 13 deletions(-)

diff --git a/Object3D.java b/Object3D.java
index f36024d..71d96f3 100644
--- a/Object3D.java
+++ b/Object3D.java
@@ -662,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);
@@ -686,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);
@@ -4048,6 +4048,7 @@
     
     void RevertMeshes()
     {
+        // BLOCKLOOP
         if (this instanceof cMesh)
         {
             ((cMesh)this).Revert();
@@ -4078,11 +4079,6 @@
             Touch();
         }
         
-        ResetRecur();
-    }
-    
-    void ResetRecur()
-    {
         for (int i = 0; i < size(); i++)
         {
             Object3D child = (Object3D) get(i); // reserve(i);
@@ -4296,8 +4292,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)
     {
@@ -4313,7 +4309,7 @@
         if (blockloop)
             return;
         
-        if (min == null) // ???
+        if (min == null)
         {
             min = new cVector();
             max = new cVector();
@@ -4354,7 +4350,7 @@
         
         if (bRep != null)
         {
-            bRep.getBounds(minima,maxima,this);
+            bRep.getBounds(minima, maxima, xform?this:null);
         }
 
         if (false) // xform)
@@ -8571,8 +8567,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;
@@ -8770,7 +8766,269 @@
 
         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)
+        {
+            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)
+        {
+            if (bbox == null)
+            {
+                bbox = new BBox();
+                
+                cVector min = new cVector();
+                cVector max = new cVector();
+                
+                this.getBounds(min, max, false);
+                
+                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 (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)
+    {
+        /*
+        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