public void CreateLine3D() { CreateLookAtCamera(Vector3D.One * 4.0f, Vector3D.Zero); var entity = new Line3D(Vector3D.Zero, Vector3D.One, Color.Red); Assert.AreEqual(Vector3D.Zero, entity.StartPoint); Assert.AreEqual(Vector3D.One, entity.EndPoint); }
private bool IntersectsInner(Line3D other, out double f1, out double f2) { f2 = (-(P.X * V.Y - P.Y * V.X - other.P.X * V.Y + other.P.Y * V.X)) / (V.X * other.V.Y - V.Y * other.V.X); f1 = ((other.P.X + f2 * other.V.X) - P.X) / V.X; return P.Z + f1 * V.Z == other.P.Z + f2 * other.V.Z; }
public void Length(string p1s, string p2s, double expected) { var p1 = Point3D.Parse(p1s); var p2 = Point3D.Parse(p2s); var l = new Line3D(p1, p2); Assert.AreEqual(expected, l.Length, 1e-6); }
/// <summary> /// Bestimmt, ob diese Gerade parallel zu einer anderen ist. /// </summary> /// <returns></returns> public bool ParallelTo(Line3D other) { var factorX = System.Math.Abs(V.X / other.V.X); var factorY = System.Math.Abs(V.Y / other.V.Y); var factorZ = System.Math.Abs(V.Z / other.V.Z); return (factorX == factorY) && (factorX == factorZ); }
public void Equals(string p1s, string p2s, string p3s, string p4s, bool expected) { var line1 = new Line3D(Point3D.Parse(p1s), Point3D.Parse(p2s)); var line2 = new Line3D(Point3D.Parse(p3s), Point3D.Parse(p4s)); Assert.AreEqual(expected, line1.Equals(line2)); Assert.AreEqual(expected, line1 == line2); Assert.AreEqual(!expected, line1 != line2); }
public static Line3D[] Generate(Mesh mesh) { Vector3D boundsSize = mesh.Bounds.Size; float size = Math.Max(boundsSize.X, Math.Max(boundsSize.Y, boundsSize.Z)) / 50.0f; Line3D[] result = new Line3D[mesh.Normals.Count]; for (int i = 0; i < mesh.Normals.Count; ++i) result[i] = new Line3D(mesh.Positions[i], mesh.Positions[i] + (mesh.Normals[i] * size)); return result; }
public void SetLine3DPointList() { CreateLookAtCamera(Vector3D.One * 4.0f, Vector3D.Zero); var entity = new Line3D(Vector3D.Zero, Vector3D.Zero, Color.Red) { Points = new List<Vector3D> { Vector3D.UnitZ, Vector3D.UnitY } }; Assert.AreEqual(Vector3D.UnitZ, entity.StartPoint); Assert.AreEqual(Vector3D.UnitY, entity.EndPoint); }
public void LineToTest(string p1s, string p2s, string ps, bool mustStartFromLine, string sps) { var p1 = Point3D.Parse(p1s); var p2 = Point3D.Parse(p2s); Line3D l = new Line3D(p1, p2); var p = Point3D.Parse(ps); var actual = l.LineTo(p, mustStartFromLine); AssertGeometry.AreEqual(Point3D.Parse(sps), actual.StartPoint, 1e-6); AssertGeometry.AreEqual(p, actual.EndPoint, 1e-6); }
/// <summary> /// Bestimmt, ob eine andere Line3D-Instanz die selbe Gerade beschreibt. /// </summary> /// <returns></returns> public bool IsSame(Line3D other) { if (!ParallelTo(other)) return false; var factor = (other.P.X - P.X) / V.X; var y = other.P.Y + (factor * other.V.Y); var z = other.P.Z + (factor * other.V.Z); return (y == P.Y) && (z == P.Z); }
internal void LimitThirdPersonCameraToWalls(Game game, Vector3Ref eye, Vector3Ref target, FloatRef curtppcameradistance) { float one = 1; Vector3Ref ray_start_point = target; Vector3Ref raytarget = eye; Line3D pick = new Line3D(); float raydirX = (raytarget.X - ray_start_point.X); float raydirY = (raytarget.Y - ray_start_point.Y); float raydirZ = (raytarget.Z - ray_start_point.Z); float raydirLength1 = game.Length(raydirX, raydirY, raydirZ); raydirX /= raydirLength1; raydirY /= raydirLength1; raydirZ /= raydirLength1; raydirX = raydirX * (game.tppcameradistance + 1); raydirY = raydirY * (game.tppcameradistance + 1); raydirZ = raydirZ * (game.tppcameradistance + 1); pick.Start = Vec3.FromValues(ray_start_point.X, ray_start_point.Y, ray_start_point.Z); pick.End = new float[3]; pick.End[0] = ray_start_point.X + raydirX; pick.End[1] = ray_start_point.Y + raydirY; pick.End[2] = ray_start_point.Z + raydirZ; //pick terrain IntRef pick2Count = new IntRef(); BlockPosSide[] pick2 = game.Pick(game.s, pick, pick2Count); if (pick2Count.value > 0) { BlockPosSide pick2nearest = game.Nearest(pick2, pick2Count.value, ray_start_point.X, ray_start_point.Y, ray_start_point.Z); //pick2.Sort((a, b) => { return (FloatArrayToVector3(a.blockPos) - ray_start_point).Length.CompareTo((FloatArrayToVector3(b.blockPos) - ray_start_point).Length); }); float pickX = pick2nearest.blockPos[0] - target.X; float pickY = pick2nearest.blockPos[1] - target.Y; float pickZ = pick2nearest.blockPos[2] - target.Z; float pickdistance = game.Length(pickX, pickY, pickZ); curtppcameradistance.value = MathCi.MinFloat(pickdistance - 1, curtppcameradistance.value); if (curtppcameradistance.value < one * 3 / 10) { curtppcameradistance.value = one * 3 / 10; } } float cameraDirectionX = target.X - eye.X; float cameraDirectionY = target.Y - eye.Y; float cameraDirectionZ = target.Z - eye.Z; float raydirLength = game.Length(raydirX, raydirY, raydirZ); raydirX /= raydirLength; raydirY /= raydirLength; raydirZ /= raydirLength; eye.X = target.X + raydirX * curtppcameradistance.value; eye.Y = target.Y + raydirY * curtppcameradistance.value; eye.Z = target.Z + raydirZ * curtppcameradistance.value; }
public void BinaryRountrip() { var line = new Line3D(new Point3D(1, 2, 3), new Point3D(4, 5, 6)); using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, line); ms.Flush(); ms.Position = 0; var roundTrip = (Line3D)formatter.Deserialize(ms); AssertGeometry.AreEqual(line, roundTrip); } }
public void GetPickingLine(Game game, Line3D retPick, bool ispistolshoot) { int mouseX; int mouseY; if (game.cameratype == CameraType.Fpp || game.cameratype == CameraType.Tpp) { mouseX = game.Width() / 2; mouseY = game.Height() / 2; } else { mouseX = game.mouseCurrentX; mouseY = game.mouseCurrentY; } PointFloatRef aim = GetAim(game); if (ispistolshoot && (aim.X != 0 || aim.Y != 0)) { mouseX += game.platform.FloatToInt(aim.X); mouseY += game.platform.FloatToInt(aim.Y); } tempViewport[0] = 0; tempViewport[1] = 0; tempViewport[2] = game.Width(); tempViewport[3] = game.Height(); unproject.UnProject(mouseX, game.Height() - mouseY, 1, game.mvMatrix.Peek(), game.pMatrix.Peek(), tempViewport, tempRay); unproject.UnProject(mouseX, game.Height() - mouseY, 0, game.mvMatrix.Peek(), game.pMatrix.Peek(), tempViewport, tempRayStartPoint); float raydirX = (tempRay[0] - tempRayStartPoint[0]); float raydirY = (tempRay[1] - tempRayStartPoint[1]); float raydirZ = (tempRay[2] - tempRayStartPoint[2]); float raydirLength = game.Length(raydirX, raydirY, raydirZ); raydirX /= raydirLength; raydirY /= raydirLength; raydirZ /= raydirLength; retPick.Start = new float[3]; retPick.Start[0] = tempRayStartPoint[0];// +raydirX; //do not pick behind retPick.Start[1] = tempRayStartPoint[1];// +raydirY; retPick.Start[2] = tempRayStartPoint[2];// +raydirZ; float pickDistance1 = CurrentPickDistance(game) * ((ispistolshoot) ? 100 : 1); pickDistance1 += 1; retPick.End = new float[3]; retPick.End[0] = tempRayStartPoint[0] + raydirX * pickDistance1; retPick.End[1] = tempRayStartPoint[1] + raydirY * pickDistance1; retPick.End[2] = tempRayStartPoint[2] + raydirZ * pickDistance1; }
public BlockPosSide[] LineIntersection(DelegateIsBlockEmpty isEmpty, DelegateGetBlockHeight getBlockHeight, Line3D line, IntRef retCount) { lCount = 0; currentLine = line; currentHit[0] = 0; currentHit[1] = 0; currentHit[2] = 0; ListBox3d l1 = Search(PredicateBox3DHit.Create(this)); for (int i = 0; i < l1.count; i++) { Box3D node = l1.arr[i]; float[] hit = currentHit; float x = node.MinEdge[0]; float y = node.MinEdge[2]; float z = node.MinEdge[1]; if (!isEmpty.IsBlockEmpty(platform.FloatToInt(x),platform.FloatToInt(y),platform.FloatToInt( z))) { Box3D node2 = new Box3D(); node2.MinEdge = Vec3.CloneIt(node.MinEdge); node2.MaxEdge = Vec3.CloneIt(node.MaxEdge); node2.MaxEdge[1] = node2.MinEdge[1] + getBlockHeight.GetBlockHeight(platform.FloatToInt(x),platform.FloatToInt(y),platform.FloatToInt(z)); BlockPosSide b = new BlockPosSide(); float[] hit2 = new float[3]; float[] dir = new float[3]; dir[0] = line.End[0] - line.Start[0]; dir[1] = line.End[1] - line.Start[1]; dir[2] = line.End[2] - line.Start[2]; bool ishit = Intersection.HitBoundingBox(node2.MinEdge, node2.MaxEdge, line.Start, dir, hit2); if (ishit) { //hit2.pos = Vec3.FromValues(x, z, y); b.blockPos = Vec3.FromValues(platform.FloatToInt(x), platform.FloatToInt(z), platform.FloatToInt(y)); b.collisionPos = hit2; l[lCount++] = b; } } } BlockPosSide[] ll = new BlockPosSide[lCount]; for (int i = 0; i < lCount; i++) { ll[i] = l[i]; } retCount.value = lCount; return ll; }
/// <summary> /// Find intersection between Line3D and Plane /// http://geomalgorithms.com/a05-_intersect-1.html /// </summary> /// <param name="line"></param> /// <param name="tolerance"></param> /// <returns>Intersection Point or null</returns> public static Point3D IntersectionWith(Plane plane, Line3D line, double tolerance = float.Epsilon) { if (line.Direction.IsPerpendicularTo(plane.Normal)) { //either parallel or lies in the plane Point3D projectedPoint = plane.Project(line.StartPoint, line.Direction); if (projectedPoint == line.StartPoint) { //Line lies in the plane throw new InvalidOperationException("Line lies in the plane"); //Not sure what should be done here } else { // Line and plane are parallel throw new InvalidOperationException("NULLLLLLL"); } } var d = plane.SignedDistanceTo(line.StartPoint); var u = line.StartPoint.VectorTo(line.EndPoint); var t = -1 * d / u.DotProduct(plane.Normal); if (t > 1 || t < 0) { // They are not intersected throw new InvalidOperationException("NULLLLLLL"); } return line.StartPoint + (t * u); }
public void runIndoorTest() { device = new IrrlichtDevice(SelectedDriverType, new Dimension2D(800,600), 16, false, true, false); device.EventReceiver = this; device.ResizeAble = true; device.WindowCaption = "Irrlicht.NET indoor test"; // load some textures and meshes ITexture texSydney = device.VideoDriver.GetTexture(@"..\..\media\sydney.bmp"); ITexture texWall = device.VideoDriver.GetTexture(@"..\..\media\wall.jpg"); ITexture texLogo = device.VideoDriver.GetTexture(@"..\..\media\irrlichtlogoaligned.jpg"); Irrlicht.Scene.IAnimatedMesh mesh = device.SceneManager.GetMesh(@"..\..\media\sydney.md2"); if (mesh == null) { System.Windows.Forms.MessageBox.Show( @"Could not load mesh ..\..\media\sydney.md2, exiting.", "Problem starting program"); return; } // add a cube to the scene ISceneNode node = device.SceneManager.AddCubeSceneNode(15, null, -1, new Vector3D(30,-15,0)); node.SetMaterialTexture(0, texWall); node.SetMaterialFlag(Irrlicht.Video.MaterialFlag.LIGHTING, false); // add an animator to the cube to make it rotate ISceneNodeAnimator anim = device.SceneManager.CreateRotationAnimator(new Vector3D(0.2f, 0.2f, 0)); node.AddAnimator(anim); // add animated mesh IAnimatedMeshSceneNode anode = device.SceneManager.AddAnimatedMeshSceneNode(mesh, null, -1); anode.SetMaterialTexture(0, texSydney); anode.SetMaterialFlag(MaterialFlag.LIGHTING, false); anode.Scale = new Vector3D(2,2,2); anode.Position = new Vector3D(0, -20, 0); // add a shadow Shadow = anode.AddShadowVolumeSceneNode(); if (Shadow != null) Shadow.Visible = false; // where no light there no shadow device.SceneManager.AddLightSceneNode(null, new Vector3D(20,100,-50), new Colorf(255,0,0), 200, -1); // add quake 3 level device.FileSystem.AddZipFileArchive("../../media/map-20kdm2.pk3"); IAnimatedMesh q3levelmesh = device.SceneManager.GetMesh("20kdm2.bsp"); ISceneNode q3node = device.SceneManager.AddOctTreeSceneNode(q3levelmesh, null, -1); q3node.Position = new Vector3D(-1370,-130,-1400); // create octtree triangle selector for q3 mesh ITriangleSelector selector = device.SceneManager.CreateOctTreeTriangleSelector( q3levelmesh.GetMesh(0), q3node, 128); // add billboard IBillboardSceneNode bill = device.SceneManager.AddBillboardSceneNode(null, new Dimension2Df(20,20), new Vector3D(0,0,0), -1); bill.SetMaterialType(MaterialType.TRANSPARENT_ADD_COLOR); bill.SetMaterialTexture(0, device.VideoDriver.GetTexture("../../media/particle.bmp")); bill.SetMaterialFlag(MaterialFlag.LIGHTING, false); bill.SetMaterialFlag(MaterialFlag.ZBUFFER, false); // create camera ICameraSceneNode cam = device.SceneManager.AddCameraSceneNodeFPS(null, 100, 300, -1); cam.Position = new Vector3D(20,300,-50); // make cursor invisible device.CursorControl.Visible = false; // create collision animator and add it to the camera ISceneNodeAnimator collAnim = device.SceneManager.CreateCollisionResponseAnimator( selector, cam, new Vector3D(30,50,30), // size of ellipsoid around camera new Vector3D(0, -3, 0), // gravity new Vector3D(0, 50, 0), // translation 0.0005f); // sliding value cam.AddAnimator(collAnim); // load some font and set it into the skin IGUIFont font = device.GUIEnvironment.GetFont("../../media/fonthaettenschweiler.bmp"); device.GUIEnvironment.Skin.Font = font; // add some gui stuff device.GUIEnvironment.AddMessageBox("Hello World", "I'm a Irrlicht.NET MessageBox. Please press SPACE to close me.", true, MessageBoxFlag.OK | MessageBoxFlag.CANCEL, null, -1); // start drawing loop int fps = 0; device.Run(); // fix for a temporary bug where quit messages are not be removed in the queue while(device.Run()) if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(255,0,0,50)); // draw scene device.SceneManager.DrawAll(); device.GUIEnvironment.DrawAll(); // do some collision testing Line3D line = new Line3D(); line.start = cam.Position; line.end = ((cam.Target - line.start).Normalize() * 1000.0f ) + line.start; Vector3D intersection = new Vector3D(); Triangle3D tri = new Triangle3D(); if (device.SceneManager.SceneCollisionManager.GetCollisionPoint( line, selector, out intersection, out tri)) { bill.Position = intersection; Material mat = new Material(); mat.Lighting = false; device.VideoDriver.SetTransform(TransformationState.WORLD, new Matrix4()); device.VideoDriver.SetMaterial(mat); device.VideoDriver.Draw3DTriangle(tri, new Color(0,255,0,0)); } // draw 2d logo device.VideoDriver.Draw2DImage( texLogo, new Position2D(10,10), new Rect(0,0,88,31), new Rect(new Position2D(0,0),device.VideoDriver.ScreenSize), new Color(0xffffff), false); // draw some text font.Draw("Press 'S' to toggle the visibility of the realtime shadow.", new Position2D(120,20), new Color(100,150,200,200)); device.VideoDriver.EndScene(); if (fps != device.VideoDriver.FPS) { fps = device.VideoDriver.FPS; device.WindowCaption = "Irrlicht.NET test (primitives:" + device.VideoDriver.PrimitiveCountDrawn + ") fps:" + fps; } } }
/// <summary> /// Prüft, ob sich diese Gerade mit einer anderen schneidet. /// </summary> /// <returns></returns> public bool IntersectsWith(Line3D other) { double f1, f2; return IntersectsInner(other, out f1, out f2); }
/// <summary> /// 构造函数,此方法之能处理同一个平面的所有线段 /// </summary> /// <param name="searchLines"></param> /// <param name="isLargeRegion"></param> public ClosedLinesAlgorithm(List <Line3D> searchLines, bool isLargeRegion, bool isDecompose = true, Line3D orginLine = null) { //要选择的选段 this.SearchLines = searchLines; this.IsLargeRegion = isLargeRegion; this.IsDecompose = isDecompose; if (orginLine != null) { //起点位置 this.OrginLine = orginLine; //起点高度 this.Elevation = OrginLine.Start.Z; } }
public static bool IsOnLineBetween(this Point3D p, Point3D start, Point3D end) { var l = new Line3D(start, end); return(l.IsOnLine(p)); }
public bool IntersectLine(Line3D line, out double intersectDistance) { intersectDistance = this.Intersect(line.ToRay()); return(intersectDistance >= 0.0 && intersectDistance <= 1.0); }
public void ProjectLineOnTest() { var unitVector = UnitVector3D.ZAxis; var rootPoint = new Point3D(0, 0, 1); var plane = new Plane(unitVector, rootPoint); var line = new Line3D(new Point3D(0, 0, 0), new Point3D(1, 0, 0)); var projectOn = plane.Project(line); AssertGeometry.AreEqual(new Line3D(new Point3D(0, 0, 1), new Point3D(1, 0, 1)), projectOn, float.Epsilon); }
private void intersectToolStripMenuItem_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count != 2) { return; } var i0 = listView1.SelectedItems[0].Tag as HelperItem; var i1 = listView1.SelectedItems[1].Tag as HelperItem; var objs = new[] { i0, i1 }; if (i0 is LineHelper lh0 && i1 is LineHelper lh1) { var inter = Geometry.Intersect3dCrossedLines(new Line3D() { Start = lh0.Start, End = lh0.End }, new Line3D() { Start = lh1.Start, End = lh1.End }); if (inter != null && !double.IsNaN(inter.Value.X) && !double.IsInfinity(inter.Value.X)) { Helpers.Add(new PointHelper() { Position = inter.Value }); updateHelpersList(); } else { SetStatus("no intersection", StatusTypeEnum.Warning); } } if (objs.Any(z => z is LineHelper) && objs.Any(z => z is PointHelper)) { var pl = objs.First(z => z is PointHelper) as PointHelper; var th = objs.First(z => z is LineHelper) as LineHelper; var l = new Line3D() { Start = th.Start, End = th.End }; if (l.IsPointOnLine(pl.Position)) { SetStatus($"point is on line ({(l.IsPointInsideSegment(pl.Position) ? "inside" : "not inside")})", StatusTypeEnum.Information); } else { SetStatus("point is not on line", StatusTypeEnum.Warning); } } if (objs.Any(z => z is TriangleHelper) && objs.Any(z => z is PlaneHelper)) { var pl = objs.First(z => z is PlaneHelper) as PlaneHelper; var th = objs.First(z => z is TriangleHelper) as TriangleHelper; var n0 = th.V2 - th.V0; var n1 = th.V1 - th.V0; var normal = Vector3d.Cross(n0, n1); var pln = new PlaneHelper() { Position = th.V0, Normal = normal }; var ln = pln.Intersect(pl); if (ln != null) { Helpers.Add(new LineHelper() { Start = ln.Start, End = ln.End }); updateHelpersList(); } } if (objs.All(z => z is PlaneHelper)) { var pl = objs[0] as PlaneHelper; var pl2 = objs[1] as PlaneHelper; var ln = pl2.Intersect(pl); if (ln != null) { Helpers.Add(new LineHelper() { Start = ln.Start, End = ln.End }); updateHelpersList(); } } }
void PickEntity(Game game, Line3D pick, BlockPosSide[] pick2, IntRef pick2count) { game.SelectedEntityId = -1; game.currentlyAttackedEntity = -1; float one = 1; for (int i = 0; i < game.entitiesCount; i++) { if (game.entities[i] == null) { continue; } if (i == game.LocalPlayerId) { continue; } if (game.entities[i].drawModel == null) { continue; } Entity p_ = game.entities[i]; if (p_.networkPosition == null) { continue; } if (!p_.networkPosition.PositionLoaded) { continue; } if (!p_.usable) { continue; } float feetposX = p_.position.x; float feetposY = p_.position.y; float feetposZ = p_.position.z; float dist = game.Dist(feetposX, feetposY, feetposZ, game.player.position.x, game.player.position.y, game.player.position.z); if (dist > 5) { continue; } //var p = PlayerPositionSpawn; Box3D bodybox = new Box3D(); float h = p_.drawModel.ModelHeight; float r = one * 35 / 100; bodybox.AddPoint(feetposX - r, feetposY + 0, feetposZ - r); bodybox.AddPoint(feetposX - r, feetposY + 0, feetposZ + r); bodybox.AddPoint(feetposX + r, feetposY + 0, feetposZ - r); bodybox.AddPoint(feetposX + r, feetposY + 0, feetposZ + r); bodybox.AddPoint(feetposX - r, feetposY + h, feetposZ - r); bodybox.AddPoint(feetposX - r, feetposY + h, feetposZ + r); bodybox.AddPoint(feetposX + r, feetposY + h, feetposZ - r); bodybox.AddPoint(feetposX + r, feetposY + h, feetposZ + r); float[] p; float localeyeposX = game.EyesPosX(); float localeyeposY = game.EyesPosY(); float localeyeposZ = game.EyesPosZ(); p = Intersection.CheckLineBoxExact(pick, bodybox); if (p != null) { //do not allow to shoot through terrain if (pick2count.value == 0 || (game.Dist(pick2[0].blockPos[0], pick2[0].blockPos[1], pick2[0].blockPos[2], localeyeposX, localeyeposY, localeyeposZ) > game.Dist(p[0], p[1], p[2], localeyeposX, localeyeposY, localeyeposZ))) { game.SelectedEntityId = i; if (game.cameratype == CameraType.Fpp || game.cameratype == CameraType.Tpp) { game.currentlyAttackedEntity = i; } } } } }
internal void NextBullet(Game game, int bulletsshot) { float one = 1; bool left = game.mouseLeft; bool middle = game.mouseMiddle; bool right = game.mouseRight; bool IsNextShot = bulletsshot != 0; if (!game.leftpressedpicking) { if (game.mouseleftclick) { game.leftpressedpicking = true; } else { left = false; } } else { if (game.mouseleftdeclick) { game.leftpressedpicking = false; left = false; } } if (!left) { game.currentAttackedBlock = null; } Packet_Item item = game.d_Inventory.RightHand[game.ActiveMaterial]; bool ispistol = (item != null && game.blocktypes[item.BlockId].IsPistol); bool ispistolshoot = ispistol && left; bool isgrenade = ispistol && game.blocktypes[item.BlockId].PistolType == Packet_PistolTypeEnum.Grenade; if (ispistol && isgrenade) { ispistolshoot = game.mouseleftdeclick; } //grenade cooking - TODO: fix instant explosion when closing ESC menu if (game.mouseleftclick) { game.grenadecookingstartMilliseconds = game.platform.TimeMillisecondsFromStart(); if (ispistol && isgrenade) { if (game.blocktypes[item.BlockId].Sounds.ShootCount > 0) { game.AudioPlay(game.platform.StringFormat("{0}.ogg", game.blocktypes[item.BlockId].Sounds.Shoot[0])); } } } float wait = ((one * (game.platform.TimeMillisecondsFromStart() - game.grenadecookingstartMilliseconds)) / 1000); if (isgrenade && left) { if (wait >= game.grenadetime && isgrenade && game.grenadecookingstartMilliseconds != 0) { ispistolshoot = true; game.mouseleftdeclick = true; } else { return; } } else { game.grenadecookingstartMilliseconds = 0; } if (ispistol && game.mouserightclick && (game.platform.TimeMillisecondsFromStart() - game.lastironsightschangeMilliseconds) >= 500) { game.IronSights = !game.IronSights; game.lastironsightschangeMilliseconds = game.platform.TimeMillisecondsFromStart(); } IntRef pick2count = new IntRef(); Line3D pick = new Line3D(); GetPickingLine(game, pick, ispistolshoot); BlockPosSide[] pick2 = game.Pick(game.s, pick, pick2count); if (left) { game.handSetAttackDestroy = true; } else if (right) { game.handSetAttackBuild = true; } if (game.overheadcamera && pick2count.value > 0 && left) { //if not picked any object, and mouse button is pressed, then walk to destination. if (game.Follow == null) { //Only walk to destination when not following someone game.playerdestination = Vector3Ref.Create(pick2[0].blockPos[0], pick2[0].blockPos[1] + 1, pick2[0].blockPos[2]); } } bool pickdistanceok = (pick2count.value > 0); //&& (!ispistol); if (pickdistanceok) { if (game.Dist(pick2[0].blockPos[0] + one / 2, pick2[0].blockPos[1] + one / 2, pick2[0].blockPos[2] + one / 2, pick.Start[0], pick.Start[1], pick.Start[2]) > CurrentPickDistance(game)) { pickdistanceok = false; } } bool playertileempty = game.IsTileEmptyForPhysics( game.platform.FloatToInt(game.player.position.x), game.platform.FloatToInt(game.player.position.z), game.platform.FloatToInt(game.player.position.y + (one / 2))); bool playertileemptyclose = game.IsTileEmptyForPhysicsClose( game.platform.FloatToInt(game.player.position.x), game.platform.FloatToInt(game.player.position.z), game.platform.FloatToInt(game.player.position.y + (one / 2))); BlockPosSide pick0 = new BlockPosSide(); if (pick2count.value > 0 && ((pickdistanceok && (playertileempty || (playertileemptyclose))) || game.overheadcamera) ) { game.SelectedBlockPositionX = game.platform.FloatToInt(pick2[0].Current()[0]); game.SelectedBlockPositionY = game.platform.FloatToInt(pick2[0].Current()[1]); game.SelectedBlockPositionZ = game.platform.FloatToInt(pick2[0].Current()[2]); pick0 = pick2[0]; } else { game.SelectedBlockPositionX = -1; game.SelectedBlockPositionY = -1; game.SelectedBlockPositionZ = -1; pick0.blockPos = new float[3]; pick0.blockPos[0] = -1; pick0.blockPos[1] = -1; pick0.blockPos[2] = -1; } PickEntity(game, pick, pick2, pick2count); if (game.cameratype == CameraType.Fpp || game.cameratype == CameraType.Tpp) { int ntileX = game.platform.FloatToInt(pick0.Current()[0]); int ntileY = game.platform.FloatToInt(pick0.Current()[1]); int ntileZ = game.platform.FloatToInt(pick0.Current()[2]); if (game.IsUsableBlock(game.map.GetBlock(ntileX, ntileZ, ntileY))) { game.currentAttackedBlock = Vector3IntRef.Create(ntileX, ntileZ, ntileY); } } if (game.GetFreeMouse()) { if (pick2count.value > 0) { OnPick_(pick0); } return; } if ((one * (game.platform.TimeMillisecondsFromStart() - lastbuildMilliseconds) / 1000) >= BuildDelay(game) || IsNextShot) { if (left && game.d_Inventory.RightHand[game.ActiveMaterial] == null) { game.SendPacketClient(ClientPackets.MonsterHit(game.platform.FloatToInt(2 + game.rnd.NextFloat() * 4))); } if (left && !fastclicking) { //todo animation fastclicking = false; } if ((left || right || middle) && (!isgrenade)) { lastbuildMilliseconds = game.platform.TimeMillisecondsFromStart(); } if (isgrenade && game.mouseleftdeclick) { lastbuildMilliseconds = game.platform.TimeMillisecondsFromStart(); } if (game.reloadstartMilliseconds != 0) { PickingEnd(left, right, middle, ispistol); return; } if (ispistolshoot) { if ((!(game.LoadedAmmo[item.BlockId] > 0)) || (!(game.TotalAmmo[item.BlockId] > 0))) { game.AudioPlay("Dry Fire Gun-SoundBible.com-2053652037.ogg"); PickingEnd(left, right, middle, ispistol); return; } } if (ispistolshoot) { float toX = pick.End[0]; float toY = pick.End[1]; float toZ = pick.End[2]; if (pick2count.value > 0) { toX = pick2[0].blockPos[0]; toY = pick2[0].blockPos[1]; toZ = pick2[0].blockPos[2]; } Packet_ClientShot shot = new Packet_ClientShot(); shot.FromX = game.SerializeFloat(pick.Start[0]); shot.FromY = game.SerializeFloat(pick.Start[1]); shot.FromZ = game.SerializeFloat(pick.Start[2]); shot.ToX = game.SerializeFloat(toX); shot.ToY = game.SerializeFloat(toY); shot.ToZ = game.SerializeFloat(toZ); shot.HitPlayer = -1; for (int i = 0; i < game.entitiesCount; i++) { if (game.entities[i] == null) { continue; } if (game.entities[i].drawModel == null) { continue; } Entity p_ = game.entities[i]; if (p_.networkPosition == null) { continue; } if (!p_.networkPosition.PositionLoaded) { continue; } float feetposX = p_.position.x; float feetposY = p_.position.y; float feetposZ = p_.position.z; //var p = PlayerPositionSpawn; Box3D bodybox = new Box3D(); float headsize = (p_.drawModel.ModelHeight - p_.drawModel.eyeHeight) * 2; //0.4f; float h = p_.drawModel.ModelHeight - headsize; float r = one * 35 / 100; bodybox.AddPoint(feetposX - r, feetposY + 0, feetposZ - r); bodybox.AddPoint(feetposX - r, feetposY + 0, feetposZ + r); bodybox.AddPoint(feetposX + r, feetposY + 0, feetposZ - r); bodybox.AddPoint(feetposX + r, feetposY + 0, feetposZ + r); bodybox.AddPoint(feetposX - r, feetposY + h, feetposZ - r); bodybox.AddPoint(feetposX - r, feetposY + h, feetposZ + r); bodybox.AddPoint(feetposX + r, feetposY + h, feetposZ - r); bodybox.AddPoint(feetposX + r, feetposY + h, feetposZ + r); Box3D headbox = new Box3D(); headbox.AddPoint(feetposX - r, feetposY + h, feetposZ - r); headbox.AddPoint(feetposX - r, feetposY + h, feetposZ + r); headbox.AddPoint(feetposX + r, feetposY + h, feetposZ - r); headbox.AddPoint(feetposX + r, feetposY + h, feetposZ + r); headbox.AddPoint(feetposX - r, feetposY + h + headsize, feetposZ - r); headbox.AddPoint(feetposX - r, feetposY + h + headsize, feetposZ + r); headbox.AddPoint(feetposX + r, feetposY + h + headsize, feetposZ - r); headbox.AddPoint(feetposX + r, feetposY + h + headsize, feetposZ + r); float[] p; float localeyeposX = game.EyesPosX(); float localeyeposY = game.EyesPosY(); float localeyeposZ = game.EyesPosZ(); p = Intersection.CheckLineBoxExact(pick, headbox); if (p != null) { //do not allow to shoot through terrain if (pick2count.value == 0 || (game.Dist(pick2[0].blockPos[0], pick2[0].blockPos[1], pick2[0].blockPos[2], localeyeposX, localeyeposY, localeyeposZ) > game.Dist(p[0], p[1], p[2], localeyeposX, localeyeposY, localeyeposZ))) { if (!isgrenade) { Entity entity = new Entity(); Sprite sprite = new Sprite(); sprite.positionX = p[0]; sprite.positionY = p[1]; sprite.positionZ = p[2]; sprite.image = "blood.png"; entity.sprite = sprite; entity.expires = Expires.Create(one * 2 / 10); game.EntityAddLocal(entity); } shot.HitPlayer = i; shot.IsHitHead = 1; } } else { p = Intersection.CheckLineBoxExact(pick, bodybox); if (p != null) { //do not allow to shoot through terrain if (pick2count.value == 0 || (game.Dist(pick2[0].blockPos[0], pick2[0].blockPos[1], pick2[0].blockPos[2], localeyeposX, localeyeposY, localeyeposZ) > game.Dist(p[0], p[1], p[2], localeyeposX, localeyeposY, localeyeposZ))) { if (!isgrenade) { Entity entity = new Entity(); Sprite sprite = new Sprite(); sprite.positionX = p[0]; sprite.positionY = p[1]; sprite.positionZ = p[2]; sprite.image = "blood.png"; entity.sprite = sprite; entity.expires = Expires.Create(one * 2 / 10); game.EntityAddLocal(entity); } shot.HitPlayer = i; shot.IsHitHead = 0; } } } } shot.WeaponBlock = item.BlockId; game.LoadedAmmo[item.BlockId] = game.LoadedAmmo[item.BlockId] - 1; game.TotalAmmo[item.BlockId] = game.TotalAmmo[item.BlockId] - 1; float projectilespeed = game.DeserializeFloat(game.blocktypes[item.BlockId].ProjectileSpeedFloat); if (projectilespeed == 0) { { Entity entity = game.CreateBulletEntity( pick.Start[0], pick.Start[1], pick.Start[2], toX, toY, toZ, 150); game.EntityAddLocal(entity); } } else { float vX = toX - pick.Start[0]; float vY = toY - pick.Start[1]; float vZ = toZ - pick.Start[2]; float vLength = game.Length(vX, vY, vZ); vX /= vLength; vY /= vLength; vZ /= vLength; vX *= projectilespeed; vY *= projectilespeed; vZ *= projectilespeed; shot.ExplodesAfter = game.SerializeFloat(game.grenadetime - wait); { Entity grenadeEntity = new Entity(); Sprite sprite = new Sprite(); sprite.image = "ChemicalGreen.png"; sprite.size = 14; sprite.animationcount = 0; sprite.positionX = pick.Start[0]; sprite.positionY = pick.Start[1]; sprite.positionZ = pick.Start[2]; grenadeEntity.sprite = sprite; Grenade_ projectile = new Grenade_(); projectile.velocityX = vX; projectile.velocityY = vY; projectile.velocityZ = vZ; projectile.block = item.BlockId; projectile.sourcePlayer = game.LocalPlayerId; grenadeEntity.expires = Expires.Create(game.grenadetime - wait); grenadeEntity.grenade = projectile; game.EntityAddLocal(grenadeEntity); } } Packet_Client packet = new Packet_Client(); packet.Id = Packet_ClientIdEnum.Shot; packet.Shot = shot; game.SendPacketClient(packet); if (game.blocktypes[item.BlockId].Sounds.ShootEndCount > 0) { game.pistolcycle = game.rnd.Next() % game.blocktypes[item.BlockId].Sounds.ShootEndCount; game.AudioPlay(game.platform.StringFormat("{0}.ogg", game.blocktypes[item.BlockId].Sounds.ShootEnd[game.pistolcycle])); } bulletsshot++; if (bulletsshot < game.DeserializeFloat(game.blocktypes[item.BlockId].BulletsPerShotFloat)) { NextBullet(game, bulletsshot); } //recoil game.player.position.rotx -= game.rnd.NextFloat() * game.CurrentRecoil(); game.player.position.roty += game.rnd.NextFloat() * game.CurrentRecoil() * 2 - game.CurrentRecoil(); PickingEnd(left, right, middle, ispistol); return; } if (ispistol && right) { PickingEnd(left, right, middle, ispistol); return; } if (pick2count.value > 0) { if (middle) { int newtileX = game.platform.FloatToInt(pick0.Current()[0]); int newtileY = game.platform.FloatToInt(pick0.Current()[1]); int newtileZ = game.platform.FloatToInt(pick0.Current()[2]); if (game.map.IsValidPos(newtileX, newtileZ, newtileY)) { int clonesource = game.map.GetBlock(newtileX, newtileZ, newtileY); int clonesource2 = game.d_Data.WhenPlayerPlacesGetsConvertedTo()[clonesource]; bool gotoDone = false; //find this block in another right hand. for (int i = 0; i < 10; i++) { if (game.d_Inventory.RightHand[i] != null && game.d_Inventory.RightHand[i].ItemClass == Packet_ItemClassEnum.Block && game.d_Inventory.RightHand[i].BlockId == clonesource2) { game.ActiveMaterial = i; gotoDone = true; } } if (!gotoDone) { IntRef freehand = game.d_InventoryUtil.FreeHand(game.ActiveMaterial); //find this block in inventory. for (int i = 0; i < game.d_Inventory.ItemsCount; i++) { Packet_PositionItem k = game.d_Inventory.Items[i]; if (k == null) { continue; } if (k.Value_.ItemClass == Packet_ItemClassEnum.Block && k.Value_.BlockId == clonesource2) { //free hand if (freehand != null) { game.WearItem( game.InventoryPositionMainArea(k.X, k.Y), game.InventoryPositionMaterialSelector(freehand.value)); break; } //try to replace current slot if (game.d_Inventory.RightHand[game.ActiveMaterial] != null && game.d_Inventory.RightHand[game.ActiveMaterial].ItemClass == Packet_ItemClassEnum.Block) { game.MoveToInventory( game.InventoryPositionMaterialSelector(game.ActiveMaterial)); game.WearItem( game.InventoryPositionMainArea(k.X, k.Y), game.InventoryPositionMaterialSelector(game.ActiveMaterial)); } } } } string[] sound = game.d_Data.CloneSound()[clonesource]; if (sound != null) // && sound.Length > 0) { game.AudioPlay(sound[0]); //todo sound cycle } } } if (left || right) { BlockPosSide tile = pick0; int newtileX; int newtileY; int newtileZ; if (right) { newtileX = game.platform.FloatToInt(tile.Translated()[0]); newtileY = game.platform.FloatToInt(tile.Translated()[1]); newtileZ = game.platform.FloatToInt(tile.Translated()[2]); } else { newtileX = game.platform.FloatToInt(tile.Current()[0]); newtileY = game.platform.FloatToInt(tile.Current()[1]); newtileZ = game.platform.FloatToInt(tile.Current()[2]); } if (game.map.IsValidPos(newtileX, newtileZ, newtileY)) { //Console.WriteLine(". newtile:" + newtile + " type: " + d_Map.GetBlock(newtileX, newtileZ, newtileY)); if (!(pick0.blockPos[0] == -1 && pick0.blockPos[1] == -1 && pick0.blockPos[2] == -1)) { int blocktype; if (left) { blocktype = game.map.GetBlock(newtileX, newtileZ, newtileY); } else { blocktype = ((game.BlockInHand() == null) ? 1 : game.BlockInHand().value); } if (left && blocktype == game.d_Data.BlockIdAdminium()) { PickingEnd(left, right, middle, ispistol); return; } string[] sound = left ? game.d_Data.BreakSound()[blocktype] : game.d_Data.BuildSound()[blocktype]; if (sound != null) // && sound.Length > 0) { game.AudioPlay(sound[0]); //todo sound cycle } } //normal attack if (!right) { //attack int posx = newtileX; int posy = newtileZ; int posz = newtileY; game.currentAttackedBlock = Vector3IntRef.Create(posx, posy, posz); if (!game.blockHealth.ContainsKey(posx, posy, posz)) { game.blockHealth.Set(posx, posy, posz, game.GetCurrentBlockHealth(posx, posy, posz)); } game.blockHealth.Set(posx, posy, posz, game.blockHealth.Get(posx, posy, posz) - game.WeaponAttackStrength()); float health = game.GetCurrentBlockHealth(posx, posy, posz); if (health <= 0) { if (game.currentAttackedBlock != null) { game.blockHealth.Remove(posx, posy, posz); } game.currentAttackedBlock = null; OnPick(game, game.platform.FloatToInt(newtileX), game.platform.FloatToInt(newtileZ), game.platform.FloatToInt(newtileY), game.platform.FloatToInt(tile.Current()[0]), game.platform.FloatToInt(tile.Current()[2]), game.platform.FloatToInt(tile.Current()[1]), tile.collisionPos, right); } PickingEnd(left, right, middle, ispistol); return; } if (!right) { game.particleEffectBlockBreak.StartParticleEffect(newtileX, newtileY, newtileZ);//must be before deletion - gets ground type. } if (!game.map.IsValidPos(newtileX, newtileZ, newtileY)) { game.platform.ThrowException("Error in picking - NextBullet()"); } OnPick(game, game.platform.FloatToInt(newtileX), game.platform.FloatToInt(newtileZ), game.platform.FloatToInt(newtileY), game.platform.FloatToInt(tile.Current()[0]), game.platform.FloatToInt(tile.Current()[2]), game.platform.FloatToInt(tile.Current()[1]), tile.collisionPos, right); //network.SendSetBlock(new Vector3((int)newtile.X, (int)newtile.Z, (int)newtile.Y), // right ? BlockSetMode.Create : BlockSetMode.Destroy, (byte)MaterialSlots[activematerial]); } } } } PickingEnd(left, right, middle, ispistol); }
/// <summary> /// Performs a ray/mesh intersection with the depth map /// </summary> /// <param name="kinectCalibration">Defines the calibration (extrinsics and intrinsics) for the Kinect</param> /// <param name="line">Ray to intersect against depth map</param> /// <param name="depthImage">Depth map to ray cast against</param> /// <param name="skipFactor">Distance to march on each step along ray</param> /// <param name="undistort">Should undistortion be applied to the point?</param> /// <returns>Returns point of intersection</returns> internal static Point3D?IntersectLineWithDepthMesh(IKinectCalibration kinectCalibration, Line3D line, Image depthImage, double skipFactor, bool undistort = true) { // max distance to check for intersection with the scene double totalDistance = 5; var delta = skipFactor * (line.EndPoint - line.StartPoint).Normalize(); // size of increment along the ray int maxSteps = (int)(totalDistance / delta.Length); var hypothesisPoint = line.StartPoint; for (int i = 0; i < maxSteps; i++) { hypothesisPoint += delta; // get the mesh distance at the extended point float meshDistance = DepthExtensions.GetMeshDepthAtPoint(kinectCalibration, depthImage, hypothesisPoint, undistort); // if the mesh distance is less than the distance to the point we've hit the mesh if (!float.IsNaN(meshDistance) && (meshDistance < hypothesisPoint.Z)) { return(hypothesisPoint); } } return(null); }
//mxd protected void RenderGuidelines(Vector2D start, Vector2D end, PixelColor c, double angle) { start = start.GetRotated(angle); end = end.GetRotated(angle); if (end.x != start.x && end.y != start.y) { Vector2D tr = new Vector2D(Math.Max(end.x, start.x), Math.Max(end.y, start.y)); Vector2D bl = new Vector2D(Math.Min(end.x, start.x), Math.Min(end.y, start.y)); // Create guidelines Line3D[] lines = new Line3D[5]; lines[0] = new Line3D(new Vector2D(tr.x, General.Map.Config.TopBoundary).GetRotated(-angle), new Vector2D(tr.x, General.Map.Config.BottomBoundary).GetRotated(-angle), c, false); lines[1] = new Line3D(new Vector2D(bl.x, General.Map.Config.TopBoundary).GetRotated(-angle), new Vector2D(bl.x, General.Map.Config.BottomBoundary).GetRotated(-angle), c, false); lines[2] = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, tr.y).GetRotated(-angle), new Vector2D(General.Map.Config.RightBoundary, tr.y).GetRotated(-angle), c, false); lines[3] = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, bl.y).GetRotated(-angle), new Vector2D(General.Map.Config.RightBoundary, bl.y).GetRotated(-angle), c, false); // Create current line extent. Make sure v1 is to the left of v2 Line2D current = (end.x < start.x ? new Line2D(end, start) : new Line2D(start, end)); Vector2D extentstart, extentend; if (current.v1.y < current.v2.y) // Start is lower { // Start point can hit left or bottom boundaries extentstart = Line2D.GetIntersectionPoint(left, current, false); if (extentstart.y < General.Map.Config.BottomBoundary) { extentstart = Line2D.GetIntersectionPoint(bottom, current, false); } // End point can hit right or top boundaries extentend = Line2D.GetIntersectionPoint(right, current, false); if (extentend.y > General.Map.Config.TopBoundary) { extentend = Line2D.GetIntersectionPoint(top, current, false); } } else // Start is higher { // Start point can hit left or top boundaries extentstart = Line2D.GetIntersectionPoint(left, current, false); if (extentstart.y > General.Map.Config.TopBoundary) { extentstart = Line2D.GetIntersectionPoint(top, current, false); } // End point can hit right or bottom boundaries extentend = Line2D.GetIntersectionPoint(right, current, false); if (extentend.y < General.Map.Config.BottomBoundary) { extentend = Line2D.GetIntersectionPoint(bottom, current, false); } } lines[4] = new Line3D(extentstart.GetRotated(-angle), extentend.GetRotated(-angle), c, false); // Render them renderer.RenderArrows(lines); // Update horiz/vert length labels if (guidelabels != null) { guidelabels[0].Move(tr.GetRotated(-angle), new Vector2D(tr.x, bl.y).GetRotated(-angle)); guidelabels[1].Move(new Vector2D(bl.x, tr.y).GetRotated(-angle), tr.GetRotated(-angle)); guidelabels[2].Move(new Vector2D(tr.x, bl.y).GetRotated(-angle), bl.GetRotated(-angle)); guidelabels[3].Move(bl.GetRotated(-angle), new Vector2D(bl.x, tr.y).GetRotated(-angle)); } } // Render horizontal line + 2 vertical guidelines else if (end.x != start.x) { Line3D l = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, end.y).GetRotated(-angle), new Vector2D(General.Map.Config.RightBoundary, end.y).GetRotated(-angle), c, false); Line3D gs = new Line3D(new Vector2D(start.x, General.Map.Config.TopBoundary).GetRotated(-angle), new Vector2D(start.x, General.Map.Config.BottomBoundary).GetRotated(-angle), c, false); Line3D ge = new Line3D(new Vector2D(end.x, General.Map.Config.TopBoundary).GetRotated(-angle), new Vector2D(end.x, General.Map.Config.BottomBoundary).GetRotated(-angle), c, false); renderer.RenderArrows(new List <Line3D> { l, gs, ge }); } // Render vertical line + 2 horizontal guidelines else if (end.y != start.y) { Line3D l = new Line3D(new Vector2D(end.x, General.Map.Config.TopBoundary).GetRotated(-angle), new Vector2D(end.x, General.Map.Config.BottomBoundary).GetRotated(-angle), c, false); Line3D gs = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, start.y).GetRotated(-angle), new Vector2D(General.Map.Config.RightBoundary, start.y).GetRotated(-angle), c, false); Line3D ge = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, end.y).GetRotated(-angle), new Vector2D(General.Map.Config.RightBoundary, end.y).GetRotated(-angle), c, false); renderer.RenderArrows(new List <Line3D> { l, gs, ge }); } // Start and end match. Render a cross else { Line3D gs = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, start.y).GetRotated(-angle), new Vector2D(General.Map.Config.RightBoundary, start.y).GetRotated(-angle), c, false); Line3D ge = new Line3D(new Vector2D(start.x, General.Map.Config.TopBoundary).GetRotated(-angle), new Vector2D(start.x, General.Map.Config.BottomBoundary).GetRotated(-angle), c, false); renderer.RenderArrows(new List <Line3D> { gs, ge }); } }
/// <summary> /// Aligns the solution using the specified planets /// </summary> /// <remarks>WARNING!!! 3D MATH!!!</remarks> /// <param name="alignment">The planets to align using.</param> /// <param name="planetLocations">The planet location data.</param> private void FlattenAlignment(string[] alignment, Dictionary <string, PlanetInfo> planetLocations) { // ** STEP ONE ** // Translate everything such that the first alignment planet is at { 0, 0, 0 } Vector3D offset = planetLocations[alignment[0]].Location; if (offset.Length > 0) { foreach (PlanetInfo curInfo in planetLocations.Values) { curInfo.Location -= offset; } } // ** STEP TWO ** // Rotate everything such that the second alignment planet is on the x-axis (without translating the previous alignment planets) Vector3D xAxis = new Vector3D(1, 0, 0); Angle angle = planetLocations[alignment[1]].Location.AngleTo(xAxis); Vector3D rotationAxis = xAxis.CrossProduct(planetLocations[alignment[1]].Location); if (rotationAxis.Length > 0) { rotationAxis = rotationAxis.Normalize().ToVector3D(); foreach (PlanetInfo curInfo in planetLocations.Values) { curInfo.Location = curInfo.Location.Rotate(rotationAxis, -angle); } } // ** STEP THREE ** // Rotate everything such that the third alignment planet is on the x/y-plane (without translating the previous alignment planets) Point3D planetOne = planetLocations[alignment[0]].Location.ToPoint3D(); Point3D planetTwo = planetLocations[alignment[1]].Location.ToPoint3D(); Point3D planetThree = planetLocations[alignment[2]].Location.ToPoint3D(); Line3D oneTwoLine = new Line3D(planetOne, planetTwo); Line3D lineToThird = oneTwoLine.LineTo(planetThree, false); Vector3D vectorToThird = (lineToThird.EndPoint - lineToThird.StartPoint); Vector3D destLine = new Vector3D(vectorToThird.Y < 0 ? -vectorToThird.X : vectorToThird.X, vectorToThird.Y < 0 ? -vectorToThird.Y : vectorToThird.Y, 0); angle = destLine.AngleTo(vectorToThird); rotationAxis = destLine.CrossProduct(vectorToThird); if (rotationAxis.Length > 0) { rotationAxis = rotationAxis.Normalize().ToVector3D(); foreach (PlanetInfo curInfo in planetLocations.Values) { curInfo.Location = curInfo.Location.Rotate(rotationAxis, -angle); } } // ** STEP FOUR ** // Invert the Z coordinates of all planets to ensure the first non-aligned planet has a positive Z location if (planetLocations.Values.First(cur => !alignment.Contains(cur.Name)).Location.Z < 0) { foreach (PlanetInfo curInfo in planetLocations.Values) { curInfo.Location = new Vector3D(curInfo.Location.X, curInfo.Location.Y, -curInfo.Location.Z); } } // Just double check the alignment worked... foreach (string curAlignment in alignment) { if (Math.Round(planetLocations[curAlignment].Location.Z, 4) != 0) { throw new Exception("Alignment Failed!!!"); } } }
public void CanGetPoint() { var line = new Line3D(new Point3D(2, 3, 1), new Vector3(2, 1, 2)); Assert.AreEqual(new Point3D(6, 5, 5), line.GetPoint(2)); }
//mxd protected void AlignTextureToClosestLine(bool alignx, bool aligny) { if (!(mode.HighlightedObject is BaseVisualSector)) { return; } // Do we need to align this? (and also grab texture scale while we are at it) float scaleX, scaleY; bool isFloor = (geometrytype == VisualGeometryType.FLOOR); if (mode.HighlightedTarget is VisualFloor) { Sector target; VisualFloor vf = (VisualFloor)mode.HighlightedTarget; // Use the control sector if the floor belongs to a 3D floor if (vf.ExtraFloor == null) { target = vf.Sector.Sector; } else { target = vf.GetControlSector(); } // Check texture if (target.FloorTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Fields.GetValue("xscalefloor", 1.0f); scaleY = target.Fields.GetValue("yscalefloor", 1.0f); } else { Sector target; VisualCeiling vc = (VisualCeiling)mode.HighlightedTarget; // Use the control sector if the ceiling belongs to a 3D floor if (vc.ExtraFloor == null) { target = vc.Sector.Sector; } else { target = vc.GetControlSector(); } // Check texture if (target.CeilTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture)) { return; } scaleX = target.Fields.GetValue("xscaleceiling", 1.0f); scaleY = target.Fields.GetValue("yscaleceiling", 1.0f); } //find a linedef to align to Vector2D hitpos = mode.GetHitPosition(); if (!hitpos.IsFinite()) { return; } //align to line of highlighted sector, which is closest to hitpos Sector highlightedSector = ((BaseVisualSector)mode.HighlightedObject).Sector; List <Linedef> lines = new List <Linedef>(); foreach (Sidedef side in highlightedSector.Sidedefs) { lines.Add(side.Line); } Linedef targetLine = MapSet.NearestLinedef(lines, hitpos); if (targetLine == null) { return; } bool isFront = targetLine.SideOfLine(hitpos) > 0; Sector.Sector.Fields.BeforeFieldsChange(); //find an angle to rotate texture float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(targetLine.Angle) + 90 : -Angle2D.RadToDeg(targetLine.Angle) - 90), 1); if (!isFront) { sourceAngle = General.ClampAngle(sourceAngle + 180); } //update angle UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "rotationfloor" : "rotationceiling"), sourceAngle, 0f); // Scale texture if it's a slope and the appropriate option is set if (level.plane.Normal.z != 1.0f && BuilderPlug.Me.ScaleTexturesOnSlopes != 2) { Vector2D basescale = new Vector2D(1.0f, 1.0f); // User wants to use the current scale as a base? if (BuilderPlug.Me.ScaleTexturesOnSlopes == 1) { basescale.x = scaleX; basescale.y = scaleY; } // Create a unit vector of the direction of the target line in 3D space Vector3D targetlinevector = new Line3D(new Vector3D(targetLine.Start.Position, level.plane.GetZ(targetLine.Start.Position)), new Vector3D(targetLine.End.Position, level.plane.GetZ(targetLine.End.Position))).GetDelta().GetNormal(); // Get a perpendicular vector of the target line in 3D space. This is used to get the slope angle relative to the target line Vector3D targetlineperpendicular = Vector3D.CrossProduct(targetlinevector, level.plane.Normal); if (alignx) { scaleX = Math.Abs(basescale.x * (1.0f / (float)Math.Cos(targetlinevector.GetAngleZ()))); } if (aligny) { scaleY = Math.Abs(basescale.y * (1.0f / (float)Math.Cos(targetlineperpendicular.GetAngleZ()))); } } //set scale UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xscalefloor" : "xscaleceiling"), scaleX, 1.0f); UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "yscalefloor" : "yscaleceiling"), scaleY, 1.0f); //update offset float distToStart = Vector2D.Distance(hitpos, targetLine.Start.Position); float distToEnd = Vector2D.Distance(hitpos, targetLine.End.Position); Vector2D offset = (distToStart < distToEnd ? targetLine.Start.Position : targetLine.End.Position).GetRotated(Angle2D.DegToRad(sourceAngle)); if (alignx) { if (Texture != null && Texture.IsImageLoaded) { offset.x %= Texture.Width / scaleX; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xpanningfloor" : "xpanningceiling"), (float)Math.Round(-offset.x), 0f); } if (aligny) { if (Texture != null && Texture.IsImageLoaded) { offset.y %= Texture.Height / scaleY; } UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "ypanningfloor" : "ypanningceiling"), (float)Math.Round(offset.y), 0f); } //update geometry Sector.UpdateSectorGeometry(false); }
/// <summary> /// states if given wcs segment is contained in this plane /// </summary> public bool Contains(double tol, Line3D line) { return(Contains(tol, line.From) && Contains(tol, line.To)); }
/// <summary> /// Returns an intersection with a 3d line. /// </summary> /// <param name="line">Line to intersect with.</param> /// <param name="outIntersection">Place to store the intersection point, if there is one.</param> /// <returns>Returns true if there was an intersection, false if there was not.</returns> public bool GetIntersectionWithLimitedLine(Line3D line, out Vector3D outIntersection) { return GetIntersectionWithLine(line.Start, line.Vector, out outIntersection) && outIntersection.IsBetweenPoints(line.Start, line.End); }
/// <summary> /// states if the given polygon contains the test point ( z not considered ) /// https://en.wikipedia.org/wiki/Point_in_polygon /// By default check the point contained in the polygon perimeter. /// Optionally duplicate points are zapped in comparing. /// </summary> public static bool ContainsPoint(this IReadOnlyList <Vector3D> _pts, double tol, Vector3D _pt, bool zapDuplicates = false) { var pt = _pt.Set(OrdIdx.Z, 0); var pts = _pts.Select(w => w.Set(OrdIdx.Z, 0)); var ptHs = new HashSet <Vector3D>(new Vector3DEqualityComparer(tol)); var ptsFiltered = pts; var pts_bbox = _pts.BBox(); if (!pts_bbox.Contains2D(tol, _pt)) { return(false); } if (zapDuplicates) { var tmp = new List <Vector3D>(); foreach (var p in pts) { if (!ptHs.Contains(p)) { ptHs.Add(p); tmp.Add(p); } } ptsFiltered = tmp; } var segs = ptsFiltered.PolygonSegments(tol); if (_pts.Any(w => _pt.EqualsTol(tol, w))) { return(true); } var ray = new Line3D(pt, Vector3D.XAxis, Line3DConstructMode.PointAndVector); var conflictVertex = false; do { conflictVertex = false; foreach (var pp in ptsFiltered) { if (ray.LineContainsPoint(tol, pp)) { conflictVertex = true; // ray intersect vertex, change it ray = new Line3D(pt, pp + Vector3D.YAxis * tol * 1.1); break; } } }while (conflictVertex); var intCnt = 0; foreach (var seg in segs) { if (seg.SegmentContainsPoint(tol, pt)) { return(true); } Vector3D ip = null; ip = ray.Intersect(tol, seg); if (ip != null && seg.SegmentContainsPoint(tol, ip)) { if (pt.X.GreatThanOrEqualsTol(tol, ip.X)) { ++intCnt; } } } return(intCnt % 2 != 0); }
public Vector<double> Solve(List<double[]> Vertices, List<int[]> Triangles, List<int> IndiceOfFixedPoints, Point3D oRoot, UnitVector3D vDir1, UnitVector3D vDir2) { Vector<double> Solution = Vector<double>.Build.Dense(Triangles.Count * 3); List<List<int[]>> Wheels = new List<List<int[]>>(); for (int i = 0; i < Vertices.Count; i++) { List<int> TrianglesWithThisVertice = new List<int>(); for (int t = 0; t < Triangles.Count; t++) { if (Triangles[t][0] == i || Triangles[t][1] == i || Triangles[t][2] == i) TrianglesWithThisVertice.Add(t); } int[] SheredEdge = new int[] { 0, 0 }; int Last = 0; int Firt = 0; if (Triangles[TrianglesWithThisVertice[0]][0] == i) { SheredEdge = new int[] {i, Triangles[TrianglesWithThisVertice[0]][1] }; } else if( Triangles[TrianglesWithThisVertice[0]][1] == i) { SheredEdge = new int[] {i, Triangles[TrianglesWithThisVertice[0]][2] }; } else if (Triangles[TrianglesWithThisVertice[0]][2] == i) { SheredEdge = new int[] { i, Triangles[TrianglesWithThisVertice[0]][0] }; } List<int[]> WheelEdges = new List<int[]>(); WheelEdges.Add(SheredEdge); do { int found=-1 ; for (int t = 0; t < TrianglesWithThisVertice.Count; t++) { if (t != Last) { if (SheredEdge.Contains(Triangles[TrianglesWithThisVertice[t]][0]) && SheredEdge.Contains(Triangles[TrianglesWithThisVertice[t]][1])) { SheredEdge = new int[] { i, Triangles[TrianglesWithThisVertice[t]][2] }; found = t; } else if (SheredEdge.Contains(Triangles[TrianglesWithThisVertice[t]][1]) && SheredEdge.Contains(Triangles[TrianglesWithThisVertice[t]][2])) { SheredEdge = new int[] { i, Triangles[TrianglesWithThisVertice[t]][0] }; found = t; } else if (SheredEdge.Contains(Triangles[TrianglesWithThisVertice[t]][0]) && SheredEdge.Contains(Triangles[TrianglesWithThisVertice[t]][2])) { SheredEdge = new int[] { i, Triangles[TrianglesWithThisVertice[t]][1] }; found = t; } } } if (found != -1) { Last = found; if (Last == Firt) goto ClosedWeel; WheelEdges.Add(SheredEdge); } else goto Continue; } while (true); ClosedWeel: Wheels.Add(WheelEdges); Continue: continue; } Matrix <double> StiffMatrix = Matrix<double>.Build.Dense(Vertices.Count+ Triangles.Count+ Wheels.Count, Triangles.Count * 3); //Vertex consistency ∑ei = 2π −∑αi Vector<double> VertexConsistency = Vector<double>.Build.Dense(Vertices.Count + Triangles.Count + Wheels.Count); for (int i = 0; i < Vertices.Count; i++) { Point3D CurrentVertex = new Point3D(Vertices[i]); List<double> Angles = new List<double>(); foreach (int[] t in Triangles) { int i1 = -1, i2 = 0, i0 = 0; if (t[0] == i) { i1 = 0; } else if (t[1] == i) { i1 = 1; } else if (t[2] == i) { i1 = 2; } if (i1 != -1) { i2 = i1 + 1; if (i2 == 3) i2 = 0; i0 = i1 - 1; if (i0 == -1) i0 = 2; Point3D vd0, vd1, vd2; vd0 = new Point3D(Vertices[t[i0]]); vd1 = new Point3D(Vertices[t[i1]]); vd2 = new Point3D(Vertices[t[i2]]); Line3D lU, lD; lU = new Line3D(vd1, vd0); lD = new Line3D(vd1, vd2); Angles.Add(lD.Direction.AngleTo(lU.Direction).Radians); } } VertexConsistency[i] = 2 * Math.PI - Angles.Sum(); } //Triangle Consistency eα +eβ +eγ = π − (α + β + γ) Vector<double> TriangleConsistency = Vector<double>.Build.Dense(Vertices.Count + Triangles.Count + Wheels.Count); for (int t = 0; t < Triangles.Count; t++) { double[] Angles = new double[] { 0, 0, 0 }; for (int i = 0; i < 3; i++) { int i1 = i, i2 = 0, i0 = 0; i2 = i1 + 1; if (i2 == 3) i2 = 0; i0 = i1 - 1; if (i0 == -1) i0 = 2; Point3D vd0, vd1, vd2; vd0 = new Point3D(Vertices[Triangles[t][i0]]); vd1 = new Point3D(Vertices[Triangles[t][i1]]); vd2 = new Point3D(Vertices[Triangles[t][i2]]); Line3D lU, lD; lU = new Line3D(vd1, vd0); lD = new Line3D(vd1, vd2); Angles[i] = lD.Direction.AngleTo(lU.Direction).Radians; StiffMatrix[Vertices.Count + t, t * 3 + i] = 1; } TriangleConsistency[Vertices.Count + t] = Math.PI - Angles.Sum(); } //Wheel Consistency ∑cot(βi) eβi − cot(γi) eγi =∑log(sinγi) − log(sinβi) Vector<double> WheelConsistency = Vector<double>.Build.Dense(Vertices.Count + Triangles.Count + Wheels.Count); for (int t = 0; t < Wheels.Count; t++) { double cotβi = 0; double cotγi = 0; double logSinβi = 0; double logSinγi = 0; double[] Angles = new double[] { 0, 0, 0 }; for (int i = 0; i < Wheels[t].Count; i++) { Point3D vd0, vd1, vd2; vd0 = new Point3D(Vertices[Wheels[t][i][0]]); vd1 = new Point3D(Vertices[Wheels[t][i][1]]); int other = i + 1; if (other == Wheels[t].Count) other = 0; vd2 = new Point3D(Vertices[Wheels[t][other][1]]); Line3D lV1, lV2, lOp; lV1 = new Line3D(vd0, vd1); lV2 = new Line3D(vd0, vd2); lOp = new Line3D(vd1, vd2); cotβi += Acot(Math.Abs(lV2.Direction.AngleTo(lOp.Direction).Radians)); cotγi += Acot(Math.Abs(lV1.Direction.AngleTo(lOp.Direction).Radians)); logSinβi += Math.Log(Math.Sin(Math.Abs(lV2.Direction.AngleTo(lOp.Direction).Radians))); logSinγi += Math.Log(Math.Sin(Math.Abs(lV1.Direction.AngleTo(lOp.Direction).Radians))); StiffMatrix[Vertices.Count + t, t * 3 + i] = 1; } TriangleConsistency[Vertices.Count + t] = Math.PI - Angles.Sum(); } double[,] MatrixA = new double[Vertices.Count * 2, Vertices.Count * 2]; for (int i = 0; i < Vertices.Count; i++) { int[] CurTri = new int[] { 0, 0, 0 }; int indexDown0 = -1; foreach (int[] t in Triangles) { for (int j = 0; j < 3; j++) { if (t[j] == i) { indexDown0 = j; break; } } if (indexDown0 != -1) { CurTri = t; break; } } int indexDown1 = indexDown0 - 1; if (indexDown1 < 0) indexDown1 = 2; int indexDown2 = indexDown1 - 1; if (indexDown2 < 0) indexDown2 = 2; Point3D vd0, vd1, vd2; vd0 = new Point3D(Vertices[CurTri[indexDown0]]); vd1 = new Point3D(Vertices[CurTri[indexDown1]]); vd2 = new Point3D(Vertices[CurTri[indexDown2]]); Line3D lU, lD; lU = new Line3D(vd1, vd0); lD = new Line3D(vd1, vd2); double Ang = -lU.Direction.AngleTo(lD.Direction).Radians; double Len = lD.Length / lU.Length; MatrixA[CurTri[indexDown0] * 2, CurTri[indexDown0] * 2] = 1; MatrixA[CurTri[indexDown0] * 2, CurTri[indexDown0] * 2 + 1] = 0; MatrixA[CurTri[indexDown0] * 2, CurTri[indexDown1] * 2] = -Len * Math.Cos(Ang); MatrixA[CurTri[indexDown0] * 2, CurTri[indexDown1] * 2 + 1] = Len * Math.Sin(Ang); MatrixA[CurTri[indexDown0] * 2, CurTri[indexDown2] * 2] = Len * Math.Cos(Ang) - 1; MatrixA[CurTri[indexDown0] * 2, CurTri[indexDown2] * 2 + 1] = -Len * Math.Sin(Ang); MatrixA[CurTri[indexDown0] * 2 + 1, CurTri[indexDown0] * 2] = 0; MatrixA[CurTri[indexDown0] * 2 + 1, CurTri[indexDown0] * 2 + 1] = 1; MatrixA[CurTri[indexDown0] * 2 + 1, CurTri[indexDown1] * 2] = -Len * Math.Sin(Ang); MatrixA[CurTri[indexDown0] * 2 + 1, CurTri[indexDown1] * 2 + 1] = -Len * Math.Cos(Ang); MatrixA[CurTri[indexDown0] * 2 + 1, CurTri[indexDown2] * 2] = Len * Math.Sin(Ang); MatrixA[CurTri[indexDown0] * 2 + 1, CurTri[indexDown2] * 2 + 1] = Len * Math.Cos(Ang) - 1; } double[,] MatrixCa = new double[IndiceOfFixedPoints.Count * 2, Vertices.Count * 2]; double[] VectorR = new double[IndiceOfFixedPoints.Count * 2]; Plane oPlane = new Plane(vDir1.CrossProduct(vDir2), oRoot); for (int i = 0; i < IndiceOfFixedPoints.Count; i++) { MatrixCa[i * 2, IndiceOfFixedPoints[i] * 2] = 1; VectorR[i * 2] = new Point3D(Vertices[IndiceOfFixedPoints[i]]).ProjectOn(oPlane).X; MatrixCa[i * 2 + 1, IndiceOfFixedPoints[i] * 2 + 1] = 1; VectorR[i * 2 + 1] = new Point3D(Vertices[IndiceOfFixedPoints[i]]).ProjectOn(oPlane).Y; } Matrix<double> Ca = Matrix<double>.Build.DenseOfArray(MatrixCa); Console.WriteLine(Ca); Vector<double> R = Vector<double>.Build.DenseOfArray(VectorR); Console.WriteLine(R); Matrix<double> A = Matrix<double>.Build.DenseOfArray(MatrixA); Console.WriteLine(A); double Penalty = 1000; Matrix<double> Ak = A.Transpose() * A + Penalty * Ca.Transpose() * Ca; Console.WriteLine(Ak); Vector<double> X = Ak.Solve(Penalty * Ca.Transpose() * R); Console.WriteLine(X); return X; }
public void ProjectOn(string p1s, string p2s, string pls, string ep1s, string ep2s) { var p1 = Point3D.Parse(p1s); var p2 = Point3D.Parse(p2s); var line = new Line3D(p1, p2); var plane = Plane.Parse(pls); var expected = new Line3D(Point3D.Parse(ep1s), Point3D.Parse(ep2s)); AssertGeometry.AreEqual(expected, line.ProjectOn(plane)); }
public static float DistanceSquaredToLine(vec3 p, vec3 e0, vec3 e1) { return(Line3D.DistanceSquared(p, e0, e1)); }
public static Line3D LongestLineBetweenCoords(vector_Coord3D tab, ref int startIndex, ref int endIndex) { Line3D ret = new Line3D(VisionLabPINVOKE.LongestLineBetweenCoords__SWIG_2(vector_Coord3D.getCPtr(tab), ref startIndex, ref endIndex), true); if (VisionLabPINVOKE.SWIGPendingException.Pending) throw VisionLabPINVOKE.SWIGPendingException.Retrieve(); return ret; }
public static vec3 ClosestPointOnLine(vec3 p, vec3 e0, vec3 e1) { return(Line3D.ClosestPoint(p, e0, e1)); }
/// <summary> /// 开始查找 /// </summary> /// <returns></returns> public List <Line3D> Find() { List <Line3D> result = new List <Line3D>(); //将所有的线段投影到XYZ平面 List <Line2D> line2ds = new List <Line2D>(); //获取线段的标高信息 this.Elevation = SearchLines.First().Start.Z; //首先投影所有线段 SearchLines.ForEach(x => { if (!x.Start.Z.AreEqual(this.Elevation) || !x.End.Z.AreEqual(this.Elevation)) { result = null; } Vector2D start = new Vector2D(x.Start.X, x.Start.Y); Vector2D end = new Vector2D(x.End.X, x.End.Y); Line2D line2d = Line2D.Create(start, end); line2ds.Add(line2d); }); if (result == null) { //说明直线高度不一致 throw new Exception("给的线段高度不一致"); } List <Line2D> remainingLines = null; if (IsDecompose) { //对当前的线段进行打断 remainingLines = line2ds.Decompose(); } else { remainingLines = new List <Line2D>(line2ds); } //首先要移除独立的线,不和其他线供端点,或者只公用一个端点 //获取最近点坐标 Vector2D origin = null; //返回所有最靠近原点的店 List <Line2D> huntLines = this.GetHuntWithOrigin(out origin, remainingLines); //所有的外框线 List <Line2D> outerLines = new List <Line2D>(); //获取起点的墙体 this.FindOuterLinessWithAngle(remainingLines, huntLines, outerLines, origin); if (outerLines != null) { outerLines.ForEach(x => { Line3D line3d = new Line3D(Vector3D.Create(x.Start.X, x.Start.Y, Elevation), Vector3D.Create(x.End.X, x.End.Y, Elevation)); result.Add(line3d); }); } return(result); }
public static float DistanceToLine(vec3 p, vec3 e0, vec3 e1, out float t) { return(Line3D.Distance(p, e0, e1, out t)); }
public BlockPosSide[] Pick(BlockOctreeSearcher s_, Line3D line, IntRef retCount) { //pick terrain int minX = platform.FloatToInt(MathCi.MinFloat(line.Start[0], line.End[0])); int minY = platform.FloatToInt(MathCi.MinFloat(line.Start[1], line.End[1])); int minZ = platform.FloatToInt(MathCi.MinFloat(line.Start[2], line.End[2])); if (minX < 0) { minX = 0; } if (minY < 0) { minY = 0; } if (minZ < 0) { minZ = 0; } int maxX = platform.FloatToInt(MathCi.MaxFloat(line.Start[0], line.End[0])); int maxY = platform.FloatToInt(MathCi.MaxFloat(line.Start[1], line.End[1])); int maxZ = platform.FloatToInt(MathCi.MaxFloat(line.Start[2], line.End[2])); if (maxX > map.MapSizeX) { maxX = map.MapSizeX; } if (maxY > map.MapSizeZ) { maxY = map.MapSizeZ; } if (maxZ > map.MapSizeY) { maxZ = map.MapSizeY; } int sizex = maxX - minX + 1; int sizey = maxY - minY + 1; int sizez = maxZ - minZ + 1; int size = BitTools.NextPowerOfTwo(MathCi.MaxInt(sizex, MathCi.MaxInt(sizey, sizez))); s_.StartBox = Box3D.Create(minX, minY, minZ, size); //s_.StartBox = Box3D.Create(0, 0, 0, BitTools.NextPowerOfTwo(MaxInt(MapSizeX, MaxInt(MapSizeY, MapSizeZ)))); BlockPosSide[] pick2 = s_.LineIntersection(IsBlockEmpty_.Create(this), GetBlockHeight_.Create(this), line, retCount); PickSort(pick2, retCount.value, line.Start[0], line.Start[1], line.Start[2]); return pick2; }
public FaceIntersectionLineResult(Geom_Curve curve, Line3D intersectionLine) { Curve = curve; IntersectionLine = intersectionLine; }
/// <summary> /// Berechnet den Schnittpunkt zweier Geraden. /// </summary> /// <returns></returns> public Point3D IntersectionWith(Line3D other) { double f1, f2; if (IntersectsInner(other, out f1, out f2)) return GetPoint(f1); else throw new InvalidOperationException("Diese beiden Geraden schneiden sich nicht."); }
public static TopoDS_Face FromEdges(Line3D line1, Line3D line2) { return(BRepFill.Face( new BRepBuilderAPI_MakeEdge(line1.From.gp_Pnt(), line1.To.gp_Pnt()).Edge(), new BRepBuilderAPI_MakeEdge(line2.From.gp_Pnt(), line2.To.gp_Pnt()).Edge())); }
public void run() { /* At first, we let the user select the driver type, * then start up the engine, set a caption, and get a * pointer to the video driver. */ // ask user for driver DriverType driverType; // Ask user to select driver: StringBuilder sb = new StringBuilder(); sb.Append("Please select the driver you want for this example:\n"); sb.Append("\n(a) Direct3D 9.0c\n(b) Direct3D 8.1\n(c) OpenGL 1.5"); sb.Append("\n(d) Software Renderer\n(e) Apfelbaum Software Renderer"); sb.Append("\n(f) Null Device\n(otherKey) exit\n\n"); // Get the user's input: TextReader tIn = Console.In; TextWriter tOut = Console.Out; tOut.Write(sb.ToString()); string input = tIn.ReadLine(); // Select device based on user's input: switch (input) { case "a": driverType = DriverType.DIRECT3D9; break; case "b": driverType = DriverType.DIRECT3D8; break; case "c": driverType = DriverType.OPENGL; break; case "d": driverType = DriverType.SOFTWARE; break; case "e": driverType = DriverType.SOFTWARE2; break; case "f": driverType = DriverType.NULL_DRIVER; break; default: return; } // Create device and exit if creation fails: device = new IrrlichtDevice(driverType, new Dimension2D(1024, 768), 32, false, true, true); if (device == null) { tOut.Write("Device creation failed."); return; } /* * Get a pointer to the video driver and the SceneManager so that * we do not always have to write device->getVideoDriver() and * device->getSceneManager(). */ ISceneManager smgr = device.SceneManager; IVideoDriver driver = device.VideoDriver; device.FileSystem.AddZipFileArchive(path + "map-20kdm2.pk3"); IAnimatedMesh q3levelmesh = smgr.GetMesh("20kdm2.bsp"); ISceneNode q3node = null; if (q3levelmesh != null) { q3node = smgr.AddOctTreeSceneNode(q3levelmesh.GetMesh(0), null, 0); } /*So far so good, we've loaded the quake 3 level like in tutorial 2. * Now, here comes something different: We create a triangle selector. A * triangle selector is a class which can fetch the triangles from scene * nodes for doing different things with them, for example collision * detection. There are different triangle selectors, and all can be * created with the ISceneManager. In this example, we create an * OctTreeTriangleSelector, which optimizes the triangle output a little * bit by reducing it like an octree. This is very useful for huge meshes * like quake 3 levels. * After we created the triangle selector, we attach it to the q3node. * This is not necessary, but in this way, we do not need to care for the * selector, for example dropping it after we do not need it anymore.*/ ITriangleSelector selector = null; if (q3node != null) { q3node.Position = new Vector3D(-1370, -130, -1400); selector = smgr.CreateOctTreeTriangleSelector( q3levelmesh.GetMesh(0), q3node, 128); // not implemented but not necessary //q3node.TriangleSelector=selector; } /*We add a first person shooter camera to the scene for being able to move in * the quake 3 level like in tutorial 2. But this, time, we add a special * animator to the camera: A Collision Response animator. This thing modifies * the scene node to which it is attached to in that way, that it may no * more move through walls and is affected by gravity. The only thing we have * to tell the animator is how the world looks like, how big the scene node is, * how gravity and so on. After the collision response animator is attached to * the camera, we do not have to do anything more for collision detection, * anything is done automaticly, all other collision detection code below is * for picking. And please note another cool feature: The collsion response * animator can be attached also to all other scene nodes, not only to cameras. * And it can be mixed with other scene node animators. In this way, collision * detection and response in the Irrlicht engine is really, really easy. * Now we'll take a closer look on the parameters of * createCollisionResponseAnimator(). The first parameter is the TriangleSelector, * which specifies how the world, against collision detection is done looks like. * The second parameter is the scene node, which is the object, which is affected * by collision detection, in our case it is the camera. The third defines how big * the object is, it is the radius of an ellipsoid. Try it out and change the radius * to smaller values, the camera will be able to move closer to walls after this. * The next parameter is the direction and speed of gravity. You could set it to * (0,0,0) to disable gravity. And the last value is just a translation: Without * this, the ellipsoid with which collision detection is done would be around * the camera, and the camera would be in the middle of the ellipsoid. But as * human beings, we are used to have our eyes on top of the body, with which * we collide with our world, not in the middle of it. So we place the scene * node 50 units over the center of the ellipsoid with this parameter. And * that's it, collision detection works now. */ ICameraSceneNode camera = smgr.AddCameraSceneNodeFPS(null, 100, 300, 0); camera.Position = new Vector3D(-100, 50, -150); ISceneNodeAnimator anim = smgr.CreateCollisionResponseAnimator( selector, camera, new Vector3D(30, 50, 30), new Vector3D(0, -3, 0), new Vector3D(0, 50, 0), 0); camera.AddAnimator(anim); /*Because collision detection is no big deal in irrlicht, I'll describe how * to do two different types of picking in the next section. But before this, * I'll prepare the scene a little. I need three animated characters which we * could pick later, a dynamic light for lighting them, a billboard for drawing * where we found an intersection, and, yes, I need to get rid of this mouse * cursor. :)*/ //disable mouse cursor device.CursorControl.Visible = false; // add billboard IBillboardSceneNode bill = smgr.AddBillboardSceneNode( null, new Dimension2Df(20, 20), new Vector3D(), 0); bill.SetMaterialType(MaterialType.TRANSPARENT_ADD_COLOR); bill.SetMaterialTexture(0, driver.GetTexture( path + "particle.bmp")); bill.SetMaterialFlag(MaterialFlag.LIGHTING, false); bill.SetMaterialFlag(MaterialFlag.ZBUFFER, false); Material material = new Material(); material.Texture1 = driver.GetTexture( path + "faerie2.bmp"); material.Lighting = true; IAnimatedMeshSceneNode node = null; IAnimatedMesh faerie = smgr.GetMesh( path + "faerie.md2"); if (faerie != null) { node = smgr.AddAnimatedMeshSceneNode(faerie, null, 0); node.Position = new Vector3D(-70, 0, -90); node.SetMD2Animation(MD2AnimationType.RUN); node.SetMaterial(0, material); node = smgr.AddAnimatedMeshSceneNode(faerie, null, 0); node.Position = new Vector3D(-70, 0, -30); node.SetMD2Animation(MD2AnimationType.SALUTE); node.SetMaterial(0, material); node = smgr.AddAnimatedMeshSceneNode(faerie, null, 0); node.Position = new Vector3D(-70, 0, -60); node.SetMD2Animation(MD2AnimationType.JUMP); node.SetMaterial(0, material); } material.Texture1 = null; material.Lighting = false; //Add a light smgr.AddLightSceneNode(null, new Vector3D(-60, 100, 400), new Colorf(1.0f, 1.0f, 1.0f, 1.0f), 600, 0); /*For not making it too complicated, I'm doing picking inside the drawing * loop. We take two pointers for storing the current and the last selected * scene node and start the loop.*/ ISceneNode selectedSceneNode = null; ISceneNode lastSelectedSceneNode = null; int lastFPS = -1; while (device.Run()) { if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(0, 200, 200, 200)); device.SceneManager.DrawAll(); /*After we've drawn the whole scene whit smgr->drawAll(), we'll do the * first picking: We want to know which triangle of the world we are * looking at. In addition, we want the exact point of the quake 3 * level we are looking at. For this, we create a 3d line starting at * the position of the camera and going through the lookAt-target of it. * Then we ask the collision manager if this line collides with a * triangle of the world stored in the triangle selector. If yes, we draw * the 3d triangle and set the position of the billboard to the intersection * point.*/ Line3D line = new Line3D(); line.start = camera.Position; line.end = line.start + (camera.Target - line.start).Normalize() * 1000; Vector3D intersection; Triangle3D tri; if (smgr.SceneCollisionManager.GetCollisionPoint( line, selector, out intersection, out tri)) { bill.Position = intersection; driver.SetTransform(TransformationState.WORLD, new Matrix4()); driver.SetMaterial(material); driver.Draw3DTriangle(tri, new Color(0, 255, 0, 0)); } /*Another type of picking supported by the Irrlicht Engine is scene node * picking based on bouding boxes. Every scene node has got a bounding box, * and because of that, it's very fast for example to get the scene node * which the camera looks at. Again, we ask the collision manager for this, * and if we've got a scene node, we highlight it by disabling Lighting in * its material, if it is not the billboard or the quake 3 level.*/ selectedSceneNode = smgr.SceneCollisionManager. GetSceneNodeFromCameraBB(camera, 0); if (lastSelectedSceneNode != null) { lastSelectedSceneNode.SetMaterialFlag( MaterialFlag.LIGHTING, true); } if (selectedSceneNode == q3node || selectedSceneNode == bill) { selectedSceneNode = null; } if (selectedSceneNode != null) { selectedSceneNode.SetMaterialFlag( MaterialFlag.LIGHTING, false); } lastSelectedSceneNode = selectedSceneNode; /*That's it, we just have to finish drawing.*/ driver.EndScene(); int fps = device.VideoDriver.FPS; if (lastFPS != fps) { device.WindowCaption = "Irrlicht Engine - Quake 3 Map example [" + device.VideoDriver.Name + "] FPS:" + fps.ToString(); lastFPS = fps; } } } /* * In the end, delete the Irrlicht device. */ // Instead of device->drop, we'll use: GC.Collect(); }
// This checks if the view offset/zoom changed and updates the check (never used. mxd) /*protected bool CheckViewChanged() * { * // View changed? * bool viewchanged = (renderer.OffsetX != lastoffsetx || renderer.OffsetY != lastoffsety || renderer.Scale != lastscale); * * // Keep view information * lastoffsetx = renderer.OffsetX; * lastoffsety = renderer.OffsetY; * lastscale = renderer.Scale; * * // Return result * return viewchanged; * }*/ // This updates the dragging protected virtual void Update() { PixelColor stitchcolor = General.Colors.Highlight; PixelColor losecolor = General.Colors.Selection; snaptocardinaldirection = General.Interface.ShiftState && General.Interface.AltState; //mxd snaptogrid = (snaptocardinaldirection || General.Interface.ShiftState ^ General.Interface.SnapToGrid); snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge; DrawnVertex curp = GetCurrentPosition(); float vsize = (renderer.VertexSize + 1.0f) / renderer.Scale; // Update label positions (mxd) if (labels.Count > 0) { // Update labels for already drawn lines for (int i = 0; i < labels.Count - 1; i++) { labels[i].ShowAngle = showguidelines; labels[i].Move(points[i].pos, points[i + 1].pos); } // Update label for active line labels[labels.Count - 1].ShowAngle = showguidelines; labels[labels.Count - 1].Move(points[points.Count - 1].pos, curp.pos); } // Render drawing lines if (renderer.StartOverlay(true)) { // Go for all points to draw lines PixelColor color; if (points.Count > 0) { //mxd bool renderguidelabels = false; if (showguidelines) { Vector2D prevp = points[points.Count - 1].pos; PixelColor c = General.Colors.InfoLine.WithAlpha(80); if (curp.pos.x != prevp.x && curp.pos.y != prevp.y) { renderguidelabels = true; Vector2D tr = new Vector2D(Math.Max(curp.pos.x, prevp.x), Math.Max(curp.pos.y, prevp.y)); Vector2D bl = new Vector2D(Math.Min(curp.pos.x, prevp.x), Math.Min(curp.pos.y, prevp.y)); // Create guidelines Line3D[] lines = new Line3D[5]; lines[0] = new Line3D(new Vector2D(tr.x, General.Map.Config.TopBoundary), new Vector2D(tr.x, General.Map.Config.BottomBoundary), c, false); lines[1] = new Line3D(new Vector2D(bl.x, General.Map.Config.TopBoundary), new Vector2D(bl.x, General.Map.Config.BottomBoundary), c, false); lines[2] = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, tr.y), new Vector2D(General.Map.Config.RightBoundary, tr.y), c, false); lines[3] = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, bl.y), new Vector2D(General.Map.Config.RightBoundary, bl.y), c, false); // Create current line extent. Make sure v1 is to the left of v2 Line2D current = (curp.pos.x < prevp.x ? new Line2D(curp.pos, prevp) : new Line2D(prevp, curp.pos)); Vector2D extentstart, extentend; if (current.v1.y < current.v2.y) // Start is lower { // Start point can hit left or bottom boundaries extentstart = Line2D.GetIntersectionPoint(left, current, false); if (extentstart.y < General.Map.Config.BottomBoundary) { extentstart = Line2D.GetIntersectionPoint(bottom, current, false); } // End point can hit right or top boundaries extentend = Line2D.GetIntersectionPoint(right, current, false); if (extentend.y > General.Map.Config.TopBoundary) { extentend = Line2D.GetIntersectionPoint(top, current, false); } } else // Start is higher { // Start point can hit left or top boundaries extentstart = Line2D.GetIntersectionPoint(left, current, false); if (extentstart.y > General.Map.Config.TopBoundary) { extentstart = Line2D.GetIntersectionPoint(top, current, false); } // End point can hit right or bottom boundaries extentend = Line2D.GetIntersectionPoint(right, current, false); if (extentend.y < General.Map.Config.BottomBoundary) { extentend = Line2D.GetIntersectionPoint(bottom, current, false); } } lines[4] = new Line3D(extentstart, extentend, c, false); // Render them renderer.RenderArrows(lines); // Update horiz/vert length labels guidelabels[0].Move(tr, new Vector2D(tr.x, bl.y)); guidelabels[1].Move(new Vector2D(bl.x, tr.y), tr); guidelabels[2].Move(new Vector2D(tr.x, bl.y), bl); guidelabels[3].Move(bl, new Vector2D(bl.x, tr.y)); } // Render horizontal line else if (curp.pos.x != prevp.x) { Line3D l = new Line3D(new Vector2D(General.Map.Config.LeftBoundary, curp.pos.y), new Vector2D(General.Map.Config.RightBoundary, curp.pos.y), c, false); renderer.RenderArrows(new List <Line3D> { l }); } // Render vertical line else if (curp.pos.y != prevp.y) { Line3D l = new Line3D(new Vector2D(curp.pos.x, General.Map.Config.TopBoundary), new Vector2D(curp.pos.x, General.Map.Config.BottomBoundary), c, false); renderer.RenderArrows(new List <Line3D> { l }); } } // Render lines DrawnVertex lastp = points[0]; for (int i = 1; i < points.Count; i++) { // Determine line color if (lastp.stitchline && points[i].stitchline) { color = stitchcolor; } else { color = losecolor; } // Render line renderer.RenderLine(lastp.pos, points[i].pos, LINE_THICKNESS, color, true); RenderLinedefDirectionIndicator(lastp.pos, points[i].pos, color); //mxd lastp = points[i]; } // Determine line color color = (lastp.stitchline && snaptonearest ? stitchcolor : losecolor); // Render line to cursor renderer.RenderLine(lastp.pos, curp.pos, LINE_THICKNESS, color, true); RenderLinedefDirectionIndicator(lastp.pos, curp.pos, color); //mxd // Render vertices for (int i = 0; i < points.Count; i++) { // Determine vertex color color = points[i].stitch ? stitchcolor : losecolor; // Render vertex renderer.RenderRectangleFilled(new RectangleF(points[i].pos.x - vsize, points[i].pos.y - vsize, vsize * 2.0f, vsize * 2.0f), color, true); } //mxd. Render guide labels? if (renderguidelabels) { renderer.RenderText(guidelabels); } // Render labels renderer.RenderText(labels.ToArray()); } // Determine point color color = snaptonearest ? stitchcolor : losecolor; // Render vertex at cursor renderer.RenderRectangleFilled(new RectangleF(curp.pos.x - vsize, curp.pos.y - vsize, vsize * 2.0f, vsize * 2.0f), color, true); // Done renderer.Finish(); } // Done renderer.Present(); }
public void CanNavigateRings() { var multilinestring = new MultiPolycurve( new[] { new Linestring(new[] { new Pnt3D(0, 0, 9), new Pnt3D(0, 100, 9), new Pnt3D(100, 100, 9), new Pnt3D(100, 0, 9), new Pnt3D(0, 0, 9) }), new Linestring(new[] { // interior ring new Pnt3D(40, 40, 123), new Pnt3D(60, 40, 123), new Pnt3D(60, 60, 12), new Pnt3D(40, 60, 12), new Pnt3D(40, 40, 123) }) }); Assert.True(multilinestring.IsClosed); int partIdx; int localSegmentIdx = multilinestring.GetLocalSegmentIndex(5, out partIdx); Assert.AreEqual(6, multilinestring.GetSegmentStartPointIndex(5)); Assert.AreEqual(1, partIdx); Assert.AreEqual(1, localSegmentIdx); Line3D previousSegment = multilinestring.PreviousSegment(5); Assert.AreEqual(multilinestring.GetSegment(4), previousSegment); Assert.AreEqual(multilinestring.GetSegment(1, 0), previousSegment); int?previousSegmentIdx = multilinestring.PreviousSegmentIndex(5); Assert.NotNull(previousSegmentIdx); Assert.AreEqual(4, previousSegmentIdx); previousSegmentIdx = multilinestring.PreviousSegmentIndex(previousSegmentIdx.Value); Assert.NotNull(previousSegmentIdx); Assert.AreEqual(7, previousSegmentIdx); int?nextSegmentIndex = multilinestring.NextSegmentIndex(previousSegmentIdx.Value); Assert.NotNull(nextSegmentIndex); Assert.AreEqual(4, nextSegmentIndex); Line3D nextSegment = multilinestring.NextSegment(previousSegmentIdx.Value); Assert.AreEqual(multilinestring.GetSegment(4), nextSegment); Assert.AreEqual(multilinestring.GetSegment(1, 0), nextSegment); Assert.AreEqual(5, multilinestring.GetSegmentStartPointIndex(4)); // With the exterior ring: localSegmentIdx = multilinestring.GetLocalSegmentIndex(1, out partIdx); Assert.AreEqual(0, partIdx); Assert.AreEqual(1, localSegmentIdx); previousSegment = multilinestring.PreviousSegment(1); Assert.AreEqual(multilinestring.GetSegment(0), previousSegment); Assert.AreEqual(multilinestring.GetSegment(0, 0), previousSegment); previousSegmentIdx = multilinestring.PreviousSegmentIndex(1); Assert.NotNull(previousSegmentIdx); Assert.AreEqual(0, previousSegmentIdx); previousSegmentIdx = multilinestring.PreviousSegmentIndex(previousSegmentIdx.Value); Assert.NotNull(previousSegmentIdx); Assert.AreEqual(3, previousSegmentIdx); nextSegmentIndex = multilinestring.NextSegmentIndex(previousSegmentIdx.Value); Assert.NotNull(nextSegmentIndex); Assert.AreEqual(0, nextSegmentIndex); nextSegment = multilinestring.NextSegment(previousSegmentIdx.Value); Assert.AreEqual(multilinestring.GetSegment(0), nextSegment); Assert.AreEqual(multilinestring.GetSegment(0, 0), nextSegment); }
public static Line ToLine(this Line3D line) { return(new Line(line.From, line.To)); }
/// <summary> /// Warning: randomly returns incorrect hit position (back side of box). /// </summary> /// <param name="box"></param> /// <param name="line"></param> /// <param name="hit"></param> /// <returns></returns> public static bool CheckLineBox(Box3D box, Line3D line, float[] hit) { return CheckLineBox1(box.MinEdge, box.MaxEdge, line.Start, line.End, hit); }
/// <summary> /// 将三维线段打断成最小的单元 /// </summary> /// <param name="lines"></param> /// <returns></returns> public List <Line3D> Decompose(List <Line3D> lines) { //获取原始的线集合 List <Line3D> newLines = new List <Line3D>(lines); //获取线和分割点的字典表 Dictionary <Line3D, List <Vector3D> > lineDIC = new Dictionary <Line3D, List <Vector3D> >(); //循环所有的线的相交关系,得到字典表 for (int i = 0; i < newLines.Count; i++) { for (int j = i; j < newLines.Count; j++) { Vector3D IntersectP = newLines[i].Intersect(newLines[j]); if (IntersectP != null) { if (!IntersectP.IsEndPoint(newLines[i])) { if (lineDIC[newLines[i]] == null) { lineDIC.Add(newLines[i], new List <Vector3D>() { IntersectP }); } else { lineDIC[newLines[i]].Add(IntersectP); } } if (!IntersectP.IsEndPoint(newLines[j])) { if (lineDIC[newLines[j]] == null) { lineDIC.Add(newLines[j], new List <Vector3D>() { IntersectP }); } else { lineDIC[newLines[j]].Add(IntersectP); } } } } } //变化所有线 foreach (KeyValuePair <Line3D, List <Vector3D> > vetsInLine in lineDIC) { //移除原来线段 newLines.Remove(vetsInLine.Key); vetsInLine.Value.Add(vetsInLine.Key.Start); vetsInLine.Value.Add(vetsInLine.Key.End); ///去掉重复的点 var vets = vetsInLine.Value.Distinct <Vector3D>(new Vector3DEqualityComparer()); //通过比较距离 var orderVets = vets.OrderBy(x => x.Distance(vetsInLine.Key.Start)); var count = orderVets.Count(); for (int i = 0; i < count - 1; i++) { newLines.Add(Line3D.Create(orderVets.ElementAt(i), orderVets.ElementAt(i + 1))); } } return(newLines); }
public void Draw(Line3D line, Color color) { DrawLine(line.P1, line.P2, color); }
/// <summary> /// build polygons from given list of segments /// if want to represent arcs, add them as dummy lines to segs /// polys returned are ordered anticlockwise /// </summary> public static IEnumerable <IReadOnlyList <Vector3D> > ClosedPolys2D(this IEnumerable <Line3D> segs, double tolLen, int polyMaxPoints = 0) { var minCoord = new BBox3D(segs.SelectMany(r => new[] { r.From, r.To })).Min; var vcmp = new Vector3DEqualityComparer(tolLen); var lcmp = new Line3DEqualityComparer(tolLen); var segsDict = segs.ToDictionary(k => k.ToString(tolLen), v => v); var segsFromDict = segs.GroupBy(g => g.From, v => v, vcmp).ToDictionary(k => k.Key, v => v.ToList(), vcmp); var segsToDict = segs.GroupBy(g => g.To, v => v, vcmp).ToDictionary(k => k.Key, v => v.ToList(), vcmp); var segsLeft = segs.OrderBy(w => w.MidPoint.Distance(minCoord)).ToList(); var polys = new List <List <Vector3D> >(); var polyCentroidDone = new HashSet <Vector3D>(vcmp); while (segsLeft.Count > 0) { //Console.WriteLine($"segsLeft: {segsLeft.Count} polys:{polys.Count}"); var seg = segsLeft.First(); segsLeft.Remove(seg); var poly = new List <Vector3D>() { seg.From, seg.To }; var rotDir = 1.0; // 1=+Z, -1=-Z while (true) { List <Line3D> segsNext = null; { var hs = new HashSet <Line3D>(lcmp); { List <Line3D> tmp = null; if (segsFromDict.TryGetValue(seg.To, out tmp)) { foreach (var x in tmp.Where(r => !r.EqualsTol(tolLen, seg))) { hs.Add(x); } } if (segsToDict.TryGetValue(seg.To, out tmp)) { foreach (var x in tmp.Where(r => !r.EqualsTol(tolLen, seg))) { hs.Add(x); } } } segsNext = hs.Select(w => w.EnsureFrom(tolLen, seg.To)).ToList(); } Line3D segNext = null; var force_close_poly = false; if (polyMaxPoints > 0 && poly.Count > polyMaxPoints) { throw new Exception($"polygon [{poly.PolygonSegments(tolLen).ToCadScript()}] max point exceeded"); } //#if DEBUG // if (//poly.Count >= 2 && // poly.Any(r => r.EqualsTol(1e-2, 31.0626,-0.0018)) // //&& // //poly.Any(r => r.EqualsTol(tolLen, -42.9561, 0)) // ) // ; //#endif if (poly.Count == 2) { if (segsNext.Count == 0) { throw new Exception($"check singular segment [{seg}] cadscript [{seg.CadScript}]"); } segNext = segsNext .OrderBy(w => (-seg.V).AngleRad(tolLen, w.V)) .First(); rotDir = seg.V.CrossProduct(segNext.V).Z > 0 ? 1 : -1; } else { var qSegsNext = segsNext .Select(w => new { arad = (seg.V).AngleToward(tolLen, w.V, Vector3D.ZAxis * rotDir), seg = w }) .Where(r => r.arad <= PI).ToList(); if (qSegsNext.Count == 0) { force_close_poly = true; } else { // retrieve next segment with current rotation direction w/acutest angle segNext = qSegsNext .OrderByDescending(r => r.arad) .First().seg; } } if (force_close_poly) { break; } segsLeft.Remove(segNext); if (segNext.To.EqualsTol(tolLen, poly[0])) { break; } poly.Add(segNext.To); seg = segNext; } if (poly.Count > 2) { poly = poly.SortPoly(tolLen, Vector3D.ZAxis).ToList(); var polyCentroid = poly.Centroid(tolLen); if (!polyCentroidDone.Contains(polyCentroid)) { polys.Add(poly); polyCentroidDone.Add(polyCentroid); } } else { // todo warning } } return(polys.OrderByDescending(w => w.Count)); }
/// <summary> /// retrieve perpendicular distance of this point from the given line /// </summary> public double Distance(double tol, Line3D other) { return(other.Perpendicular(tol, this).Length); }
/// <summary> /// project this vector to the given line /// </summary> public Vector3D Project(Line3D line) { return((this - line.From).Project(line.V) + line.From); }
public void XmlTests(string p1s, string p2s, string xml) { Point3D p1 = Point3D.Parse(p1s); Point3D p2 = Point3D.Parse(p2s); var l = new Line3D(p1, p2); AssertXml.XmlRoundTrips(l, xml, (e, a) => AssertGeometry.AreEqual(e, a)); }
/// <summary> /// mirror this point about given axis /// </summary> public Vector3D Mirror(Line3D axis) { return(this + 2 * (Project(axis) - this)); }
/// <summary> /// build 3d circle that tangent to lines t1,t2 and that intersects point p /// note: point p must contained in one of t1,t2 /// circle will be inside region t1.V toward t2.V /// they are 4 circles /// </summary> public static IEnumerable <Circle3D> CirclesTan12P(double tol_len, Line3D t1, Line3D t2, Vector3D p) { foreach (var da in new double[] { 0, PI / 2 }) { var ip = t1.Intersect(tol_len, t2); var angle = t1.V.AngleRad(tol_len, t2.V); var t3 = new Line3D(ip, t1.V.RotateAs(tol_len, t1.V, t2.V, .5, da), Line3DConstructMode.PointAndVector); Line3D lp = null; Line3D lNp = null; if (t1.LineContainsPoint(tol_len, p)) { lp = t1; lNp = t2; } else if (t2.LineContainsPoint(tol_len, p)) { lp = t2; lNp = t1; } else { throw new Exception($"circle 2 tan 1 point : pt must contained in one of given tan"); } var lpp = new Line3D(p, lp.V.RotateAboutAxis(t1.V.CrossProduct(t2.V), PI / 2), Line3DConstructMode.PointAndVector); var c = lpp.Intersect(tol_len, t3); var Radius = p.Distance(c); var CS = new CoordinateSystem3D(c, lpp.V, t2.V); yield return(new Circle3D(tol_len, CS, Radius)); // mirrored addictional circle var mc = c.Mirror(new Line3D(p, p.Project(lNp) - p, Line3DConstructMode.PointAndVector)); yield return(new Circle3D(tol_len, new CoordinateSystem3D(mc, lpp.V, t2.V), Radius)); } }
/// <summary> /// Berechnet die Entfernung von dieser Geraden zu einer anderen. /// </summary> /// <returns></returns> public double DistanceTo(Line3D other) { return Vector.DotProduct(P - other.P, Vector3.GetCrossProduct(V, other.V).Normalize()); }
public void run() { /* At first, we let the user select the driver type, then start up the engine, set a caption, and get a pointer to the video driver. */ // ask user for driver DriverType driverType; // Ask user to select driver: StringBuilder sb = new StringBuilder(); sb.Append("Please select the driver you want for this example:\n"); sb.Append("\n(a) Direct3D 9.0c\n(b) Direct3D 8.1\n(c) OpenGL 1.5"); sb.Append("\n(d) Software Renderer\n(e) Apfelbaum Software Renderer"); sb.Append("\n(f) Null Device\n(otherKey) exit\n\n"); // Get the user's input: TextReader tIn = Console.In; TextWriter tOut = Console.Out; tOut.Write(sb.ToString()); string input = tIn.ReadLine(); // Select device based on user's input: switch (input) { case "a": driverType = DriverType.DIRECT3D9; break; case "b": driverType = DriverType.DIRECT3D8; break; case "c": driverType = DriverType.OPENGL; break; case "d": driverType = DriverType.SOFTWARE; break; case "e": driverType = DriverType.SOFTWARE2; break; case "f": driverType = DriverType.NULL_DRIVER; break; default: return; } // Create device and exit if creation fails: device = new IrrlichtDevice(driverType, new Dimension2D(1024, 768), 32, false, true, true); if (device == null) { tOut.Write("Device creation failed."); return; } /* Get a pointer to the video driver and the SceneManager so that we do not always have to write device->getVideoDriver() and device->getSceneManager(). */ ISceneManager smgr=device.SceneManager; IVideoDriver driver=device.VideoDriver; device.FileSystem.AddZipFileArchive(path+"map-20kdm2.pk3"); IAnimatedMesh q3levelmesh = smgr.GetMesh("20kdm2.bsp"); ISceneNode q3node = null; if (q3levelmesh!=null) q3node=smgr.AddOctTreeSceneNode(q3levelmesh.GetMesh(0),null,0); /*So far so good, we've loaded the quake 3 level like in tutorial 2. Now, here comes something different: We create a triangle selector. A triangle selector is a class which can fetch the triangles from scene nodes for doing different things with them, for example collision detection. There are different triangle selectors, and all can be created with the ISceneManager. In this example, we create an OctTreeTriangleSelector, which optimizes the triangle output a little bit by reducing it like an octree. This is very useful for huge meshes like quake 3 levels. After we created the triangle selector, we attach it to the q3node. This is not necessary, but in this way, we do not need to care for the selector, for example dropping it after we do not need it anymore.*/ ITriangleSelector selector = null; if (q3node!=null) { q3node.Position= new Vector3D(-1370,-130,-1400); selector=smgr.CreateOctTreeTriangleSelector( q3levelmesh.GetMesh(0),q3node,128); // not implemented but not necessary //q3node.TriangleSelector=selector; } /*We add a first person shooter camera to the scene for being able to move in the quake 3 level like in tutorial 2. But this, time, we add a special animator to the camera: A Collision Response animator. This thing modifies the scene node to which it is attached to in that way, that it may no more move through walls and is affected by gravity. The only thing we have to tell the animator is how the world looks like, how big the scene node is, how gravity and so on. After the collision response animator is attached to the camera, we do not have to do anything more for collision detection, anything is done automaticly, all other collision detection code below is for picking. And please note another cool feature: The collsion response animator can be attached also to all other scene nodes, not only to cameras. And it can be mixed with other scene node animators. In this way, collision detection and response in the Irrlicht engine is really, really easy. Now we'll take a closer look on the parameters of createCollisionResponseAnimator(). The first parameter is the TriangleSelector, which specifies how the world, against collision detection is done looks like. The second parameter is the scene node, which is the object, which is affected by collision detection, in our case it is the camera. The third defines how big the object is, it is the radius of an ellipsoid. Try it out and change the radius to smaller values, the camera will be able to move closer to walls after this. The next parameter is the direction and speed of gravity. You could set it to (0,0,0) to disable gravity. And the last value is just a translation: Without this, the ellipsoid with which collision detection is done would be around the camera, and the camera would be in the middle of the ellipsoid. But as human beings, we are used to have our eyes on top of the body, with which we collide with our world, not in the middle of it. So we place the scene node 50 units over the center of the ellipsoid with this parameter. And that's it, collision detection works now. */ ICameraSceneNode camera = smgr.AddCameraSceneNodeFPS(null,100,300,0); camera.Position=new Vector3D(-100,50,-150); ISceneNodeAnimator anim = smgr.CreateCollisionResponseAnimator( selector,camera,new Vector3D(30,50,30), new Vector3D(0,-3,0),new Vector3D(0,50,0),0); camera.AddAnimator(anim); /*Because collision detection is no big deal in irrlicht, I'll describe how to do two different types of picking in the next section. But before this, I'll prepare the scene a little. I need three animated characters which we could pick later, a dynamic light for lighting them, a billboard for drawing where we found an intersection, and, yes, I need to get rid of this mouse cursor. :)*/ //disable mouse cursor device.CursorControl.Visible=false; // add billboard IBillboardSceneNode bill = smgr.AddBillboardSceneNode( null,new Dimension2Df(20,20),new Vector3D(),0); bill.SetMaterialType(MaterialType.TRANSPARENT_ADD_COLOR); bill.SetMaterialTexture(0,driver.GetTexture( path+"particle.bmp")); bill.SetMaterialFlag(MaterialFlag.LIGHTING,false); bill.SetMaterialFlag(MaterialFlag.ZBUFFER,false); Material material = new Material(); material.Texture1= driver.GetTexture( path+"faerie2.bmp"); material.Lighting=true; IAnimatedMeshSceneNode node = null; IAnimatedMesh faerie = smgr.GetMesh( path+"faerie.md2"); if (faerie!=null) { node=smgr.AddAnimatedMeshSceneNode(faerie,null,0); node.Position=new Vector3D(-70,0,-90); node.SetMD2Animation(MD2AnimationType.RUN); node.SetMaterial(0,material); node=smgr.AddAnimatedMeshSceneNode(faerie,null,0); node.Position=new Vector3D(-70,0,-30); node.SetMD2Animation(MD2AnimationType.SALUTE); node.SetMaterial(0,material); node=smgr.AddAnimatedMeshSceneNode(faerie,null,0); node.Position=new Vector3D(-70,0,-60); node.SetMD2Animation(MD2AnimationType.JUMP); node.SetMaterial(0,material); } material.Texture1=null; material.Lighting=false; //Add a light smgr.AddLightSceneNode(null,new Vector3D(-60,100,400), new Colorf(1.0f,1.0f,1.0f,1.0f),600,0); /*For not making it too complicated, I'm doing picking inside the drawing loop. We take two pointers for storing the current and the last selected scene node and start the loop.*/ ISceneNode selectedSceneNode =null; ISceneNode lastSelectedSceneNode =null; int lastFPS=-1; while (device.Run()) { if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(0, 200, 200, 200)); device.SceneManager.DrawAll(); /*After we've drawn the whole scene whit smgr->drawAll(), we'll do the first picking: We want to know which triangle of the world we are looking at. In addition, we want the exact point of the quake 3 level we are looking at. For this, we create a 3d line starting at the position of the camera and going through the lookAt-target of it. Then we ask the collision manager if this line collides with a triangle of the world stored in the triangle selector. If yes, we draw the 3d triangle and set the position of the billboard to the intersection point.*/ Line3D line = new Line3D(); line.start=camera.Position; line.end=line.start+ (camera.Target - line.start).Normalize() * 1000; Vector3D intersection; Triangle3D tri; if (smgr.SceneCollisionManager.GetCollisionPoint( line,selector,out intersection, out tri)) { bill.Position=intersection; driver.SetTransform(TransformationState.WORLD, new Matrix4()); driver.SetMaterial(material); driver.Draw3DTriangle(tri,new Color(0,255,0,0)); } /*Another type of picking supported by the Irrlicht Engine is scene node picking based on bouding boxes. Every scene node has got a bounding box, and because of that, it's very fast for example to get the scene node which the camera looks at. Again, we ask the collision manager for this, and if we've got a scene node, we highlight it by disabling Lighting in its material, if it is not the billboard or the quake 3 level.*/ selectedSceneNode=smgr.SceneCollisionManager. GetSceneNodeFromCameraBB(camera,0); if (lastSelectedSceneNode!=null) lastSelectedSceneNode.SetMaterialFlag( MaterialFlag.LIGHTING, true); if (selectedSceneNode==q3node|| selectedSceneNode==bill) selectedSceneNode=null; if(selectedSceneNode!=null) selectedSceneNode.SetMaterialFlag( MaterialFlag.LIGHTING,false); lastSelectedSceneNode=selectedSceneNode; /*That's it, we just have to finish drawing.*/ driver.EndScene(); int fps = device.VideoDriver.FPS; if (lastFPS != fps) { device.WindowCaption = "Irrlicht Engine - Quake 3 Map example [" + device.VideoDriver.Name + "] FPS:" + fps.ToString(); lastFPS = fps; } } } /* In the end, delete the Irrlicht device. */ // Instead of device->drop, we'll use: GC.Collect(); }
public static float[] CheckLineBoxExact(Line3D line, Box3D box) { float[] dir_ = new float[3]; dir_[0] = line.End[0] - line.Start[0]; dir_[1] = line.End[1] - line.Start[1]; dir_[2] = line.End[2] - line.Start[2]; float[] hit = new float[3]; if (!Intersection.HitBoundingBox(box.MinEdge, box.MaxEdge, line.Start, dir_, hit)) { return null; } return hit; }