Object3d GetSupportParrent(float x, float y, float z) { //Object3d obj; List <Object3d> matchingObjects = new List <Object3d>(); foreach (Object3d obj in UVDLPApp.Instance().Engine3D.m_objects) { if (obj.tag != Object3d.OBJ_NORMAL) { continue; } if ((x > obj.m_min.x) && (x < obj.m_max.x) && (y > obj.m_min.y) && (y < obj.m_max.y)) { matchingObjects.Add(obj); } } if (matchingObjects.Count == 0) { return(null); // Should not happen! } if (matchingObjects.Count == 1) { return(matchingObjects[0]); // the easy case. } Point3d origin; origin = new Point3d(); // bottom point origin.Set(x, y, 0.0f); //intersected = false; // reset the intersected flag to be false Vector3d up = new Vector3d(); // the up vector up.x = 0.0f; up.y = 0.0f; up.z = 1.0f; List <ISectData> lstISects = RTUtils.IntersectObjects(up, origin, matchingObjects, false); Object3d objFound = null; float minzdiff = 99999999f; // find the intersection closest to z. foreach (ISectData htd in lstISects) { float zdiff = Math.Abs(htd.intersect.z - z); if (zdiff < minzdiff) { minzdiff = zdiff; objFound = htd.obj; } } return(objFound); }
private void glControl1_MouseMove(object sender, MouseEventArgs e) { double dx = 0, dy = 0; if (lmdown || rmdown || mmdown) { dx = e.X - mdx; dy = e.Y - mdy; mdx = e.X; mdy = e.Y; } dx /= 2; dy /= 2; if (lmdown) { m_camera.RotateRightFlat((float)dx); m_camera.RotateUp((float)dy); m_axisCam.RotateRightFlat((float)dx); m_axisCam.RotateUp((float)dy); UpdateView(); } else if (mmdown) { m_camera.MoveForward((float)dy); UpdateView(); } else if (rmdown) { m_camera.Move((float)dx, (float)dy); UpdateView(); } // if no object selected, bail if (UVDLPApp.Instance().SelectedObject == null) { return; } if (m_movingobjectmode) // if we're moving an object - shift key down { List <ISectData> hits = TestHitTest(e.X, e.Y); // hit-test all // examine the last isect data foreach (ISectData dat in hits) { //remember to break out of this foreach loop after executing a movement. // either we're moving a support if (UVDLPApp.Instance().SelectedObject.tag == Object3d.OBJ_SUPPORT) { // if it's the base we're moving, //allow the base to change types // see if it intersects with the ground, or an object //cast as a support object Support sup = (Support)UVDLPApp.Instance().SelectedObject; if (sup.SelectionType == Support.eSelType.eWhole) { // we're in modify mode, but we're still moving the whole support if (dat.obj.tag == Object3d.OBJ_SEL_PLANE) { //we should really try a top/ bottom intersection / scale to hieg // move the support sup.Translate( (float)(dat.intersect.x - UVDLPApp.Instance().SelectedObject.m_center.x), (float)(dat.intersect.y - UVDLPApp.Instance().SelectedObject.m_center.y), 0.0f); // now we've moved the object approximately to where it needs to be //turn it back into a base sup.SubType = Support.eSubType.eBase; //get the center location Point3d centroid = sup.Centroid(); Engine3D.Vector3d upvec = new Engine3D.Vector3d(); upvec.Set(0, 0, 1); Point3d origin = new Point3d(); origin.Set(centroid.x, centroid.y, .001f); // above the ground plane List <ISectData> isects = RTUtils.IntersectObjects(upvec, origin, UVDLPApp.Instance().Engine3D.m_objects, false); foreach (ISectData isd in isects) { if (isd.obj.tag == Object3d.OBJ_NORMAL) // if we've intersected a normal object upwards { sup.SelectionType = Support.eSelType.eTip; sup.MoveFromTip(isd); sup.SelectionType = Support.eSelType.eWhole; break; } } //starting at the x/y ground plane, hittest upward break; } } else if (sup.SelectionType == Support.eSelType.eBase) { //going to change this to test for intersection with object, or ground plane // if intersected with an object, change to intra type // and set the base on the object // if intersected with ground, change to base type and put on ground if (dat.obj.tag == Object3d.OBJ_GROUND) { // make sure we're a base tip sup.SubType = Support.eSubType.eBase; // position the bottom to the intersection point sup.PositionBottom(dat); break; } else if (dat.obj.tag == Object3d.OBJ_NORMAL) // intersected with an object { //should check with the normal of the object to see if it's facing upwards sup.SubType = Support.eSubType.eIntra; // position the bottom to the intersection point sup.PositionBottom(dat); break; } } else if (sup.SelectionType == Support.eSelType.eTip) { if (dat.obj.tag == Object3d.OBJ_NORMAL) // intersected with an object { sup.MoveFromTip(dat); UpdateView(); break; } } } else // or a normal object based on object selection plane { if (dat.obj.tag == Object3d.OBJ_SEL_PLANE) { UVDLPApp.Instance().SelectedObject.Translate( (float)(dat.intersect.x - UVDLPApp.Instance().SelectedObject.m_center.x), (float)(dat.intersect.y - UVDLPApp.Instance().SelectedObject.m_center.y), 0.0f); } break; } } UpdateView(); } }
private List <ISectData> TestHitTest(int X, int Y) { if (!loaded) { return(null); } // String mess = ""; // mess = "Screen X,Y = (" + X.ToString() + "," + Y.ToString() + ")\r\n"; /* * (Note that most window systems place the mouse coordinate origin in the upper left of the window instead of the lower left. * That's why window_y is calculated the way it is in the above code. When using a glViewport() that doesn't match the window height, * the viewport height and viewport Y are used to determine the values for window_y and norm_y.) * * The variables norm_x and norm_y are scaled between -1.0 and 1.0. Use them to find the mouse location on your zNear clipping plane like so: * * float y = near_height * norm_y; * float x = near_height * aspect * norm_x; * Now your pick ray vector is (x, y, -zNear). */ int w = glControl1.Width; int h = glControl1.Height; // mess += "Screen Width/Height = " + w.ToString() + "," + h.ToString() + "\r\n"; float aspect = ((float)glControl1.Width) / ((float)glControl1.Height); //mess += "Screen Aspect = " + aspect.ToString() + "\r\n"; int window_y = (h - Y) - h / 2; double norm_y = (double)(window_y) / (double)(h / 2); int window_x = X - w / 2; double norm_x = (double)(window_x) / (double)(w / 2); float near_height = .2825f; // no detectable error float y = (float)(near_height * norm_y); float x = (float)(near_height * aspect * norm_x); /* * To transform this eye coordinate pick ray into object coordinates, multiply it by the inverse of the ModelView matrix in use * when the scene was rendered. When performing this multiplication, remember that the pick ray is made up of a vector and a point, * and that vectors and points transform differently. You can translate and rotate points, but vectors only rotate. * The way to guarantee that this is working correctly is to define your point and vector as four-element arrays, * as the following pseudo-code shows: * * float ray_pnt[4] = {0.f, 0.f, 0.f, 1.f}; * float ray_vec[4] = {x, y, -near_distance, 0.f}; * The one and zero in the last element determines whether an array transforms as a point or a vector when multiplied by the * inverse of the ModelView matrix.*/ Vector4 ray_pnt = new Vector4(0.0f, 0.0f, 0.0f, 1.0f); //Vector4 ray_vec = new Vector4((float)norm_x, (float)norm_y, -1.0f, 0); Vector4 ray_vec = new Vector4((float)x, (float)y, -1f, 0); ray_vec.Normalize(); //mess += "Eye Pick Vec = (" + String.Format("{0:0.00}", ray_vec.X) + ", " + String.Format("{0:0.00}", ray_vec.Y) + "," + String.Format("{0:0.00}", ray_vec.Z) + ")\r\n"; Matrix4 modelViewMatrix; GL.GetFloat(GetPName.ModelviewMatrix, out modelViewMatrix); Matrix4 viewInv = Matrix4.Invert(modelViewMatrix); Vector4 t_ray_pnt = new Vector4(); Vector4 t_ray_vec = new Vector4(); Vector4.Transform(ref ray_vec, ref viewInv, out t_ray_vec); Vector4.Transform(ref ray_pnt, ref viewInv, out t_ray_pnt); //mess += "World Pick Vec = (" + String.Format("{0:0.00}", t_ray_vec.X) + ", " + String.Format("{0:0.00}", t_ray_vec.Y) + "," + String.Format("{0:0.00}", t_ray_vec.Z) + ")\r\n"; //mess += "World Pick Pnt = (" + String.Format("{0:0.00}", t_ray_pnt.X) + ", " + String.Format("{0:0.00}", t_ray_pnt.Y) + "," + String.Format("{0:0.00}", t_ray_pnt.Z) + ")\r\n"; Point3d origin = new Point3d(); Point3d intersect = new Point3d(); Engine3D.Vector3d dir = new Engine3D.Vector3d(); origin.Set(t_ray_pnt.X, t_ray_pnt.Y, t_ray_pnt.Z); dir.Set(t_ray_vec.X, t_ray_vec.Y, t_ray_vec.Z); // should this be scaled? List <ISectData> isects = RTUtils.IntersectObjects(dir, origin, UVDLPApp.Instance().Engine3D.m_objects, true); if (isects.Count > 0) { foreach (ISectData isect in isects) { if (!float.IsNaN(isect.intersect.x)) // check for NaN { /* * m_ix = (float)isect.intersect.x; // show the closest * m_iy = (float)isect.intersect.y; * m_iz = (float)isect.intersect.z; */ isect.poly.CalcNormal(); m_isectnormal.x = isect.poly.m_normal.x; m_isectnormal.y = isect.poly.m_normal.y; m_isectnormal.z = isect.poly.m_normal.z; break; } } //ISectData isect = (ISectData)isects[0]; // get the first // check for NaN } return(isects); }
private void glControl1_MouseMove(object sender, MouseEventArgs e) { List <ISectData> hits = TestHitTest(e.X, e.Y); double dx = 0, dy = 0; if (lmdown || rmdown || mmdown) { dx = e.X - mdx; dy = e.Y - mdy; mdx = e.X; mdy = e.Y; } dx /= 2; dy /= 2; if (lmdown) { m_camera.RotateRightFlat((float)dx); m_camera.RotateUp((float)dy); } else if (mmdown) { m_camera.MoveForward((float)dy); } else if (rmdown) { m_camera.Move((float)dx, (float)dy); } if (UVDLPApp.Instance().SelectedObject != null) { if (m_movingobjectmode) // if we're moving an object { // examine the last isect data foreach (ISectData dat in hits) { if (dat.obj.tag == Object3d.OBJ_GROUND) //found the ground plane { UVDLPApp.Instance().SelectedObject.Translate( (float)(dat.intersect.x - UVDLPApp.Instance().SelectedObject.m_center.x), (float)(dat.intersect.y - UVDLPApp.Instance().SelectedObject.m_center.y), 0.0f); } } if (UVDLPApp.Instance().SelectedObject.tag == Object3d.OBJ_SUPPORT) // if the current selected object is a support { Support tmpsup = (Support)UVDLPApp.Instance().SelectedObject; Point3d pnt = new Point3d(); pnt.Set(tmpsup.m_center.x, tmpsup.m_center.y, 0); Engine3D.Vector3d vec = new Engine3D.Vector3d(); vec.Set(0, 0, 1); // create a vector striaght up // hit test from the selected objects center x/y/0 position straight up //see if it hits any object in the scene, // if it does, scale the object from the ground plane to the closest intersection point List <ISectData> iss = RTUtils.IntersectObjects(vec, pnt, UVDLPApp.Instance().Engine3D.m_objects, false); foreach (ISectData htd in iss) { if (htd.obj.tag != Object3d.OBJ_SUPPORT) // if this is not another support or the ground { if (htd.obj.tag != Object3d.OBJ_GROUND) { // this should be it... tmpsup.ScaleToHeight(htd.intersect.z); break; } } } } } } //glControl1.Invalidate(); UpdateView(); }
public List <Object3d> GenerateSupportObjects() { // iterate over the platform size by indicated mm step; // projected resolution in x,y // generate a 3d x/y point on z=0, // generate another on the z=zmax // use this ray to intersect the scene // foreach intersection point, generate a support // we gott make sure supports don't collide // I also have to take into account the // interface between the support and the model List <Object3d> lstsupports = new List <Object3d>(); float ZVal = (float)UVDLPApp.Instance().m_printerinfo.m_PlatZSize; m_model.Update(); float MinX = m_model.m_min.x; float MaxX = m_model.m_max.x; float MinY = m_model.m_min.y; float MaxY = m_model.m_max.y; // bool intersected = false; int scnt = 0; // support count // iterate from -HX to HX step xtep; double dts = (MaxX - MinX) / m_sc.xspace; int its = (int)dts; int curstep = 0; for (float x = (float)(MinX + (m_sc.xspace / 2.0f)); x < MaxX; x += (float)m_sc.xspace) { // say we're doing stuff RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eProgress, "" + curstep + "/" + its, null); curstep++; for (float y = (float)(MinY + (m_sc.yspace / 2)); y < MaxY; y += (float)m_sc.yspace) { Point3d origin; origin = new Point3d(); // bottom point origin.Set(x, y, 0.0f); //intersected = false; // reset the intersected flag to be false Vector3d up = new Vector3d(); // the up vector up.x = 0.0f; up.y = 0.0f; up.z = 1.0f; List <ISectData> lstISects = RTUtils.IntersectObjects(up, origin, UVDLPApp.Instance().Engine3D.m_objects, false); //check for cancelling if (m_cancel) { RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCancel, "Support Generation Cancelled", null); return(lstsupports); } foreach (ISectData htd in lstISects) { if (htd.obj.tag != Object3d.OBJ_SUPPORT) // if this is not another support or the ground { if (htd.obj.tag != Object3d.OBJ_GROUND) // if it's not the ground { if (m_sc.m_onlydownward && htd.poly.tag != Polygon.TAG_MARKDOWN) { break; // not a downward facing and we're only doing downward } // this should be the closest intersected Support s = new Support(); float lz = (float)htd.intersect.z; s.Create((float)m_sc.fbrad, (float)m_sc.ftrad, (float)m_sc.hbrad, (float)m_sc.htrad, lz * .2f, lz * .6f, lz * .2f, 11); s.Translate((float)x, (float)y, 0); s.Name = "Support " + scnt; s.SetColor(Color.Yellow); scnt++; lstsupports.Add(s); RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eSupportGenerated, s.Name, s); break; // only need to make one support } } } } } // return objects; RaiseSupportEvent(UV_DLP_3D_Printer.SupportEvent.eCompleted, "Support Generation Completed", lstsupports); m_generating = false; return(lstsupports); }