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. --- ObjEditor.java | 4 cMesh.java | 8 BBox.java | 166 ++++++++++++ CameraPane.java | 142 +++++++++- Camera.java | 2 Globals.java | 2 GroupEditor.java | 22 Ray.java | 55 ++++ Object3D.java | 284 ++++++++++++++++++++- IntersectResult.java | 48 +++ 10 files changed, 681 insertions(+), 52 deletions(-) diff --git a/BBox.java b/BBox.java new file mode 100755 index 0000000..4a28409 --- /dev/null +++ b/BBox.java @@ -0,0 +1,166 @@ +//package comp557.a5; + +import javax.vecmath.Point3d; + +public class BBox +{ + + public Point3d max; + public Point3d min; + + public BBox() + { + this.max = new Point3d(1, 1, 1); + this.min = new Point3d(-1, -1, -1); + } + + public boolean intersect0(Ray ray, IntersectResult result) + { + // Reference: http://people.csail.mit.edu/amy/papers/box-jgt.pdf + + double tmin, tmax, tymin, tymax, tzmin, tzmax; + + double invDirX = 1 / ray.viewDirection.x; + double invDirY = 1 / ray.viewDirection.y; + double invDirZ = 1 / ray.viewDirection.z; + + if (ray.viewDirection.x >= 1e-9) + { + tmin = (min.x - ray.eyePoint.x) * invDirX; + tmax = (max.x - ray.eyePoint.x) * invDirX; + } else + { + tmax = (min.x - ray.eyePoint.x) * invDirX; + tmin = (max.x - ray.eyePoint.x) * invDirX; + } + + if (ray.viewDirection.y >= 1e-9) + { + tymin = (min.y - ray.eyePoint.y) * invDirY; + tymax = (max.y - ray.eyePoint.y) * invDirY; + } else + { + tymax = (min.y - ray.eyePoint.y) * invDirY; + tymin = (max.y - ray.eyePoint.y) * invDirY; + } + + if ((tmin > tymax) || (tymin > tmax)) + { + return false; + } + + if (tymin > tmin) + { + tmin = tymin; + } + + if (tymax < tmax) + { + tmax = tymax; + } + + if (ray.viewDirection.z >= 1e-9) + { + tzmin = (min.z - ray.eyePoint.z) * invDirZ; + tzmax = (max.z - ray.eyePoint.z) * invDirZ; + } else + { + tzmax = (min.z - ray.eyePoint.z) * invDirZ; + tzmin = (max.z - ray.eyePoint.z) * invDirZ; + } + + if ((tmin > tzmax) || (tzmin > tmax)) + { + return false; + } + +// result.isIntersected = true; +// +// if (tzmin > tmin) +// { +// tmin = tzmin; +// } +// +// if (tzmax < tmax) +// { +// tmax = tzmax; +// } +// +// if (tmin > 1e-9) +// { +// result.t = tmin; +// } else +// { +// result.t = tmax; +// } + + return true; + } + + public boolean intersect(Ray ray, IntersectResult result) + { + double tmin = Double.NEGATIVE_INFINITY, tmax = Double.POSITIVE_INFINITY; + + double t1 = (min.x - ray.eyePoint.x) / ray.viewDirection.x; + double t2 = (max.x - ray.eyePoint.x) / ray.viewDirection.x; + + double mint = t1; + if (mint > t2) mint = t2; + + double maxt = t1; + if (maxt < t2) maxt = t2; + + if (ray.viewDirection.x == 0) + { + if (ray.eyePoint.x <= min.x || ray.eyePoint.x >= max.x) + return false; + } + else + { + if (tmin > mint) tmin = mint; + if (tmax < maxt) tmax = maxt; + } + + t1 = (min.y - ray.eyePoint.y) / ray.viewDirection.y; + t2 = (max.y - ray.eyePoint.y) / ray.viewDirection.y; + + mint = t1; + if (mint > t2) mint = t2; + + maxt = t1; + if (maxt < t2) maxt = t2; + + if (ray.viewDirection.y == 0) + { + if (ray.eyePoint.y <= min.y || ray.eyePoint.y >= max.y) + return false; + } + else + { + if (tmin > mint) tmin = mint; + if (tmax < maxt) tmax = maxt; + } + + t1 = (min.z - ray.eyePoint.z) / ray.viewDirection.z; + t2 = (max.z - ray.eyePoint.z) / ray.viewDirection.z; + + mint = t1; + if (mint > t2) mint = t2; + + maxt = t1; + if (maxt < t2) maxt = t2; + + if (ray.viewDirection.z == 0) + { + if (ray.eyePoint.z <= min.z || ray.eyePoint.z >= max.z) + return false; + } + else + { + if (tmin > mint) tmin = mint; + if (tmax < maxt) tmax = maxt; + } + + return tmax > tmin && tmax > 0.0; + } +} diff --git a/Camera.java b/Camera.java index e2f05a8..e9360b7 100644 --- a/Camera.java +++ b/Camera.java @@ -302,7 +302,7 @@ } else if (//shaper_fovy < 180 && factor > 1 || - shaper_fovy * factor < 180) + shaper_fovy * factor < 150) { shaper_fovy *= factor; //System.out.println("fovy = " + shaper_fovy); diff --git a/CameraPane.java b/CameraPane.java index 90689ce..6e4b50c 100644 --- a/CameraPane.java +++ b/CameraPane.java @@ -134,7 +134,7 @@ static boolean ZOOMBOXMODE = false; static boolean BOXMODE = false; static boolean IMAGEFLIP = false; -static boolean SMOOTHFOCUS = false; +static boolean SMOOTHFOCUS = true; // false; static boolean SPEAKERMOCAP = true; // jan 2014 false; static boolean SPEAKERCAMERA = false; static boolean SPEAKERFOCUS = false; @@ -2109,7 +2109,7 @@ // Start with free camera SwitchCameras(true); - pingthread.jump = true; // optional? +// pingthread.jump = true; // optional? if (TRACKONCE) { @@ -2296,18 +2296,6 @@ public void ToggleTrack() { TRACK ^= true; - if (TRACK) - { - if (object.selection != null && - object.selection.size() > 0 && - object.selection.elementAt(0) != null && - !(object.selection.elementAt(0) instanceof Camera) && - !(object.selection.elementAt(0) instanceof ScriptNode)) - { - trackedobject = object.selection.elementAt(0); - repaint(); - } - } repaint(); } @@ -10916,6 +10904,12 @@ else speedkey[RIGHT_ARROW] = 0; + if (Globals.WALK && capsLocked) + { + Walk(); + keyon = true; + } + if (keyon) { repaint(); @@ -11870,7 +11864,7 @@ repaint(); } - if (Globals.isLIVE() && DrawMode() == DEFAULT) // may 2013 + if (Globals.isLIVE() && DrawMode() == DEFAULT || pingthread.live) // may 2013 repaint(); displaydone = true; @@ -11946,9 +11940,23 @@ //GL gl = getGL(); if ((TRACK || SHADOWTRACK) || zoomonce) { + if (TRACK) + { + if (object.selection != null && + object.selection.size() > 0 && + object.selection.elementAt(0) != null && + !(object.selection.elementAt(0) instanceof Camera) && + !(object.selection.elementAt(0) instanceof ScriptNode)) + { + trackedobject = object.selection.elementAt(0); + //repaint(); + } + else + trackedobject = null; + } if ((TRACK || SHADOWTRACK) && trackedobject != null && DrawMode() == SHADOW) // && !lightMode) object.GetWindow().ScreenFit(trackedobject, SHADOWTRACK && !TRACK); - pingthread.StepToTarget(true); // true); + pingthread.StepToTarget(); // true); // zoomonce = false; } @@ -14508,8 +14516,9 @@ // fev 2014??? if ((TRACK || SHADOWTRACK) && trackedobject != null) // && DrawMode() == SHADOW) // && !lightMode) object.GetWindow().ScreenFit(trackedobject, SHADOWTRACK && !TRACK); - pingthread.StepToTarget(true); // true); + pingthread.StepToTarget(); // true); } + // if (!LIVE) super.repaint(); } @@ -14629,9 +14638,15 @@ return targetLookAt; } + javax.vecmath.Point3d eye = new javax.vecmath.Point3d(); + javax.vecmath.Point3d eye2 = new javax.vecmath.Point3d(); + javax.vecmath.Vector3d dir = new javax.vecmath.Vector3d(); + + class PingThread extends Thread { boolean jump; + boolean live; boolean mute; @@ -14651,6 +14666,70 @@ { if (mute) return; + + if (capsLocked) + { + eye.x = manipCamera.location.x; + eye.y = manipCamera.location.y + 0.25; + eye.z = manipCamera.location.z; + + dir.y = -1; + + Ray ray = new Ray(eye, dir); + + IntersectResult res = new IntersectResult(); + res.t = Double.POSITIVE_INFINITY; + + tmp.set(targetLookAt); + tmp.sub(manipCamera.location); + + double dist = tmp.length(); + + tmp.normalize(); + + eye2.x = manipCamera.location.x + tmp.x * 0.25; + eye2.y = manipCamera.location.y + 0.25; + eye2.z = manipCamera.location.z + tmp.z * 0.25; + + Ray ray2 = new Ray(eye2, dir); + + IntersectResult res2 = new IntersectResult(); + res2.t = Double.POSITIVE_INFINITY; + + if (object.intersect(ray, res) && object.intersect(ray2, res2) && Math.abs(res.t - res2.t) < 0.25) + { + //tmp.set(manipCamera.location); + + manipCamera.location.x = ray.eyePoint.x + ray.viewDirection.x * res.t; + manipCamera.location.y = ray.eyePoint.y + ray.viewDirection.y * res.t + 0.5; + manipCamera.location.z = ray.eyePoint.z + ray.viewDirection.z * res.t; + + //tmp.sub(manipCamera.location); + + targetLookAt.x = ray2.eyePoint.x + ray2.viewDirection.x * res2.t; + targetLookAt.y = ray2.eyePoint.y + ray2.viewDirection.y * res2.t + 0.5; + targetLookAt.z = ray2.eyePoint.z + ray2.viewDirection.z * res2.t; + + targetLookAt.sub(manipCamera.location); + targetLookAt.normalize(); + targetLookAt.mul(dist); + targetLookAt.add(manipCamera.location); + + //if (tmp.dot(tmp) > 0.000001) + // System.out.println("INTERSECTION " + manipCamera.location); + + manipCamera.lookAt.set(targetLookAt); + + tmp.x = res.n.x; + tmp.y = res.n.y; + tmp.z = res.n.z; + tmp.x += res2.n.x; + tmp.y += res2.n.y; + tmp.z += res2.n.z; + tmp.normalize(); + manipCamera.UP.set(tmp); + } + } tmp.set(targetLookAt); tmp.sub(manipCamera.lookAt); // june 2014 @@ -14689,7 +14768,7 @@ if (tmp.dot(tmp) > 1) // may 2014. far away: jump to target { - jump = true; // step = 1; + // sep 2019 jump = true; // step = 1; } if (OEILONCE && OEIL) @@ -14724,7 +14803,10 @@ if (tmp.dot(tmp) < 0.00001) { zoomonce = false; + live = false; } + else + live = true; tmp.mul(step > step2 ? step : step2); } @@ -14866,8 +14948,16 @@ PingThread pingthread = new PingThread(); int delta = 1; int speed = 1; + int walk = 8; boolean autorepeat = false; + void Walk() + { + manipCamera.BackForth(0, walk, 1000); + + targetLookAt.set(manipCamera.lookAt); + } + void GoDown(int mod) { MODIFIERS |= COMMAND; @@ -15869,17 +15959,23 @@ object.GetWindow().refreshContents(true); break; case '{': - manipCamera.shaper_fovy /= 1.1; + double factor = 1.1; + if (manipCamera.shaper_fovy / factor > 0.1) + manipCamera.shaper_fovy /= factor; System.out.println("FOV = " + manipCamera.shaper_fovy); repaint(); break; case '}': - manipCamera.shaper_fovy *= 1.1; + factor = 1.1; + if (manipCamera.shaper_fovy * factor < 150) + manipCamera.shaper_fovy *= factor; System.out.println("FOV = " + manipCamera.shaper_fovy); repaint(); break; case '[': - manipCamera.shaper_fovy /= 1.01; + factor = 1.01; + if (manipCamera.shaper_fovy / factor > 0.1) + manipCamera.shaper_fovy /= factor; if (false) //manipCamera.hAspect == 0) { double x = Math.tan(manipCamera.shaper_fovy * Math.PI / 180 / 2); @@ -15895,7 +15991,9 @@ break; case ']': //manipCamera.shaper_fovy += (180 - manipCamera.shaper_fovy)*0.1; - manipCamera.shaper_fovy *= 1.01; + factor = 1.01; + if (manipCamera.shaper_fovy * factor < 150) + manipCamera.shaper_fovy *= factor; if (false) //manipCamera.hAspect == 0) { double x = Math.tan(manipCamera.shaper_fovy * Math.PI / 180 / 2); diff --git a/Globals.java b/Globals.java index fe225bd..e47b66e 100644 --- a/Globals.java +++ b/Globals.java @@ -1,6 +1,8 @@ public class Globals { + static boolean WALK = false; + static boolean SHOWINFO = true; static boolean ADVANCED = false; // false; diff --git a/GroupEditor.java b/GroupEditor.java index 513ea9a..d328971 100644 --- a/GroupEditor.java +++ b/GroupEditor.java @@ -1404,7 +1404,7 @@ // supportCB.setToolTipText("Enable rigging"); // supportCB.addItemListener(this); - panel.add(freezeCB = new cCheckBox("Freeze", Globals.FREEZEONMOVE)); //, constraints); + panel.add(freezeCB = new cCheckBox("Fast cam", Globals.FREEZEONMOVE)); //, constraints); freezeCB.setToolTipText("Fast moving camera"); freezeCB.addItemListener(this); @@ -1413,9 +1413,12 @@ panel.Return(); + if (Globals.ADVANCED) + { panel.add(crowdCB = new cCheckBox("Crowd", Globals.CROWD)); //, constraints); crowdCB.setToolTipText("Used for crowds"); crowdCB.addItemListener(this); + } panel.add(smoothCB = new cCheckBox("Inertia", CameraPane.INERTIA)); //, constraints); smoothCB.setToolTipText("Snapping delay"); @@ -1428,30 +1431,26 @@ minshaderCB.setToolTipText("Minimal fast shader"); minshaderCB.addItemListener(this); -// constraints.gridy += 1; // panel.add(speakerMocapCB = new cCheckBox("Mocap", CameraPane.SPEAKERMOCAP), constraints); // speakerMocapCB.addItemListener(this); - panel.Return(); - if (false) { // handled in scripts - //constraints.gridy += 1; panel.add(speakerCameraCB = new cCheckBox("Cam", CameraPane.SPEAKERCAMERA)); //, constraints); speakerCameraCB.addItemListener(this); - //constraints.gridy += 1; panel.add(speakerFocusCB = new cCheckBox("Focus", CameraPane.SPEAKERFOCUS)); //, constraints); speakerFocusCB.addItemListener(this); - //constraints.gridy += 1; - panel.add(smoothfocusCB = new cCheckBox("Smooth", CameraPane.SMOOTHFOCUS)); //, constraints); - smoothfocusCB.addItemListener(this); panel.Return(); } -//constraints.gridx += 1; + panel.add(smoothfocusCB = new cCheckBox("Smooth", CameraPane.SMOOTHFOCUS)); //, constraints); + smoothfocusCB.addItemListener(this); + + panel.Return(); + //panel.add(debugCB = new cCheckBox("Debug", CameraPane.DEBUG), constraints); // debugCB.addItemListener(this); @@ -2090,7 +2089,7 @@ Object3D obj = (Object3D)group.selection.elementAt(0); objEditor.ScreenFit(obj, false); - cameraView.pingthread.StepToTarget(true); + cameraView.pingthread.StepToTarget(); //true); refreshContents(); } @@ -4874,6 +4873,7 @@ LA.matTranslateInv(obj.fromParent, -i * scale, 0, 0); } + Globals.lighttouched = true; refreshContents(); } diff --git a/IntersectResult.java b/IntersectResult.java new file mode 100755 index 0000000..be2c1d2 --- /dev/null +++ b/IntersectResult.java @@ -0,0 +1,48 @@ +//package comp557.a5; + +import javax.vecmath.Point3d; +import javax.vecmath.Vector3d; + +/** + * Use this class to store the result of an intersection. + */ +public class IntersectResult +{ + + /** The normal at the intersection */ + public Vector3d n = new Vector3d(); + + /** Intersection position */ + //public Point3d p = new Point3d(); + + /** The object of the intersection */ + public Object3D object = null; + + /** Parameter on the ray giving the position of the intersection */ + public double t = Double.POSITIVE_INFINITY; + + //public boolean isIntersected = false; + //public int id = -1; + + // UV Coordinates of the object + public double u = Double.NaN; + public double v = Double.NaN; + + /** + * Default constructor. + */ + IntersectResult() + { + // do nothing + } + + /** + * Copy constructor. + */ + IntersectResult(IntersectResult other) + { + n.set(other.n); + //p.set(other.p); + t = other.t; + } +} diff --git a/ObjEditor.java b/ObjEditor.java index 00afea7..d5be27b 100644 --- a/ObjEditor.java +++ b/ObjEditor.java @@ -5715,7 +5715,7 @@ interest.y = k * interest.y + (1 - k) * height; } - CameraPane.zoomonce = true; + // CameraPane.zoomonce = true; // june 2014 Camera parentcam = cameraView.manipCamera; @@ -5789,7 +5789,7 @@ objEditor.ScreenFit(obj, false); - cameraView.pingthread.StepToTarget(true); // aout 2013 + cameraView.pingthread.StepToTarget(); //true); // aout 2013 refreshContents(); } 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() { diff --git a/Ray.java b/Ray.java new file mode 100755 index 0000000..c7d4c33 --- /dev/null +++ b/Ray.java @@ -0,0 +1,55 @@ +//package comp557.a5; + +import javax.vecmath.Point3d; +import javax.vecmath.Vector3d; + +public class Ray +{ + + /** Originating point for the ray */ + public Point3d eyePoint = new Point3d(0, 0, 0); + /** The direction of the ray */ + public Vector3d viewDirection = new Vector3d(0, 0, -1); + + /** + * Default constructor. Be careful not to use the ray before + * setting the eye point and view direction! + */ + public Ray() + { + // do nothing + } + + /** + * Creates a new ray with the given eye point and view direction + * @param eyePoint + * @param viewDirection + */ + public Ray(Point3d eyePoint, Vector3d viewDirection) + { + this.eyePoint.set(eyePoint); + this.viewDirection.set(viewDirection); + } + + /** + * Setup the ray. + * @param eyePoint + * @param viewDirection + */ + public void set(Point3d eyePoint, Vector3d viewDirection) + { + this.eyePoint.set(eyePoint); + this.viewDirection.set(viewDirection); + } + + /** + * Computes the location of a point along the ray using parameter t. + * @param t + * @param p + */ + public void getPoint(double t, Point3d p) // After the intersection, you will call this method to get the intersection point + { + p.scale(t, viewDirection); + p.add(eyePoint); + } +} diff --git a/cMesh.java b/cMesh.java index 51a76c3..e79623b 100644 --- a/cMesh.java +++ b/cMesh.java @@ -417,12 +417,14 @@ ref.count = 1; Object3D obj = ref.GetObject(); + Object3D par = obj.parent; + obj.parent = null; // may 2014: side-effect with UVs!! - obj = (Object3D) Grafreed.clone(obj); - - merge(obj); + merge((Object3D) Grafreed.clone(obj)); + obj.parent = par; + ref.count = keepcount; System.out.println("RESULT " + ref + "; #vertices = " + bRep.VertexCount() + "; #faces = " + bRep.FaceCount()); -- Gitblit v1.6.2