diff --git a/CodeWalker.Core/GameFiles/Resources/Bounds.cs b/CodeWalker.Core/GameFiles/Resources/Bounds.cs index 2ad2aca..e551a19 100644 --- a/CodeWalker.Core/GameFiles/Resources/Bounds.cs +++ b/CodeWalker.Core/GameFiles/Resources/Bounds.cs @@ -727,6 +727,8 @@ namespace CodeWalker.GameFiles } if (p != null) { + p.Owner = this; + p.Index = i; p.Read(polygonData, offset); } Polygons[i] = p; @@ -737,6 +739,19 @@ namespace CodeWalker.GameFiles { return ((index < 0) || (index >= Vertices.Length)) ? Vector3.Zero : Vertices[index]; } + public Vector3 GetVertexPos(int index) + { + var v = GetVertex(index) + CenterGeom; + return Vector3.Transform(v, Transform).XYZ(); + } + public void SetVertexPos(int index, Vector3 v) + { + if ((index >= 0) && (index < Vertices.Length)) + { + var t = Vector3.Transform(v, TransformInv).XYZ() - CenterGeom; + Vertices[index] = t; + } + } /// @@ -934,7 +949,6 @@ namespace CodeWalker.GameFiles var spht = new BoundingSphere(); var sp = sph.Center; var sr = sph.Radius; - var cg = CenterGeom; Vector3 p1, p2, p3, p4, a1, a2, a3; Vector3 n1 = Vector3.Zero; @@ -946,15 +960,15 @@ namespace CodeWalker.GameFiles { case BoundPolygonType.Triangle: var ptri = polygon as BoundPolygonTriangle; - p1 = GetVertex(ptri.vertIndex1) + cg; - p2 = GetVertex(ptri.vertIndex2) + cg; - p3 = GetVertex(ptri.vertIndex3) + cg; + p1 = GetVertexPos(ptri.vertIndex1); + p2 = GetVertexPos(ptri.vertIndex2); + p3 = GetVertexPos(ptri.vertIndex3); polyhit = sph.Intersects(ref p1, ref p2, ref p3); if (polyhit) n1 = Vector3.Normalize(Vector3.Cross(p2 - p1, p3 - p1)); break; case BoundPolygonType.Sphere: var psph = polygon as BoundPolygonSphere; - tsph.Center = GetVertex(psph.sphereIndex) + cg; + tsph.Center = GetVertexPos(psph.sphereIndex); tsph.Radius = psph.sphereRadius; polyhit = sph.Intersects(ref tsph); if (polyhit) n1 = Vector3.Normalize(sph.Center - tsph.Center); @@ -962,17 +976,17 @@ namespace CodeWalker.GameFiles case BoundPolygonType.Capsule: var pcap = polygon as BoundPolygonCapsule; var tcap = new BoundingCapsule(); - tcap.PointA = GetVertex(pcap.capsuleIndex1) + cg; - tcap.PointB = GetVertex(pcap.capsuleIndex2) + cg; + tcap.PointA = GetVertexPos(pcap.capsuleIndex1); + tcap.PointB = GetVertexPos(pcap.capsuleIndex2); tcap.Radius = pcap.capsuleRadius; polyhit = sph.Intersects(ref tcap, out n1); break; case BoundPolygonType.Box: var pbox = polygon as BoundPolygonBox; - p1 = GetVertex(pbox.boxIndex1);// + cg; //corner - p2 = GetVertex(pbox.boxIndex2);// + cg; - p3 = GetVertex(pbox.boxIndex3);// + cg; - p4 = GetVertex(pbox.boxIndex4);// + cg; + p1 = GetVertexPos(pbox.boxIndex1);//corner + p2 = GetVertexPos(pbox.boxIndex2); + p3 = GetVertexPos(pbox.boxIndex3); + p4 = GetVertexPos(pbox.boxIndex4); a1 = ((p3 + p4) - (p1 + p2)) * 0.5f; a2 = p3 - (p1 + a1); a3 = p4 - (p1 + a1); @@ -983,7 +997,7 @@ namespace CodeWalker.GameFiles if ((bs.X < bs.Y) && (bs.X < bs.Z)) m1 = Vector3.Cross(m2, m3); else if (bs.Y < bs.Z) m2 = Vector3.Cross(m3, m1); else m3 = Vector3.Cross(m1, m2); - Vector3 tp = sp - (p1 + cg); + Vector3 tp = sp - (p1);//+cg spht.Center = new Vector3(Vector3.Dot(tp, m1), Vector3.Dot(tp, m2), Vector3.Dot(tp, m3)); spht.Radius = sph.Radius; box.Minimum = Vector3.Zero; @@ -1009,14 +1023,14 @@ namespace CodeWalker.GameFiles case BoundPolygonType.Cylinder: var pcyl = polygon as BoundPolygonCylinder; //var tcyl = new BoundingCylinder(); - //tcyl.PointA = GetVertex(pcyl.cylinderIndex1) + cg; - //tcyl.PointB = GetVertex(pcyl.cylinderIndex2) + cg; + //tcyl.PointA = GetVertexPos(pcyl.cylinderIndex1); + //tcyl.PointB = GetVertexPos(pcyl.cylinderIndex2); //tcyl.Radius = pcyl.cylinderRadius; - //////polyhit = ray.Intersects(ref tcyl, out polyhittestdist, out n1); + //////polyhit = sph.Intersects(ref tcyl, out polyhittestdist, out n1); ////////TODO var ttcap = new BoundingCapsule();//just use the capsule intersection for now... - ttcap.PointA = GetVertex(pcyl.cylinderIndex1) + cg; - ttcap.PointB = GetVertex(pcyl.cylinderIndex2) + cg; + ttcap.PointA = GetVertexPos(pcyl.cylinderIndex1); + ttcap.PointB = GetVertexPos(pcyl.cylinderIndex2); ttcap.Radius = pcyl.cylinderRadius; polyhit = sph.Intersects(ref ttcap, out n1); break; @@ -1041,7 +1055,6 @@ namespace CodeWalker.GameFiles var rayt = new Ray(); var rp = ray.Position; var rd = ray.Direction; - var cg = CenterGeom; Vector3 p1, p2, p3, p4, a1, a2, a3; Vector3 n1 = Vector3.Zero; @@ -1054,15 +1067,15 @@ namespace CodeWalker.GameFiles { case BoundPolygonType.Triangle: var ptri = polygon as BoundPolygonTriangle; - p1 = GetVertex(ptri.vertIndex1) + cg; - p2 = GetVertex(ptri.vertIndex2) + cg; - p3 = GetVertex(ptri.vertIndex3) + cg; + p1 = GetVertexPos(ptri.vertIndex1); + p2 = GetVertexPos(ptri.vertIndex2); + p3 = GetVertexPos(ptri.vertIndex3); polyhit = ray.Intersects(ref p1, ref p2, ref p3, out polyhittestdist); if (polyhit) n1 = Vector3.Normalize(Vector3.Cross(p2 - p1, p3 - p1)); break; case BoundPolygonType.Sphere: var psph = polygon as BoundPolygonSphere; - tsph.Center = GetVertex(psph.sphereIndex) + cg; + tsph.Center = GetVertexPos(psph.sphereIndex); tsph.Radius = psph.sphereRadius; polyhit = ray.Intersects(ref tsph, out polyhittestdist); if (polyhit) n1 = Vector3.Normalize((ray.Position + ray.Direction * polyhittestdist) - tsph.Center); @@ -1070,8 +1083,8 @@ namespace CodeWalker.GameFiles case BoundPolygonType.Capsule: var pcap = polygon as BoundPolygonCapsule; var tcap = new BoundingCapsule(); - tcap.PointA = GetVertex(pcap.capsuleIndex1) + cg; - tcap.PointB = GetVertex(pcap.capsuleIndex2) + cg; + tcap.PointA = GetVertexPos(pcap.capsuleIndex1); + tcap.PointB = GetVertexPos(pcap.capsuleIndex2); tcap.Radius = pcap.capsuleRadius; polyhit = ray.Intersects(ref tcap, out polyhittestdist); res.Position = (ray.Position + ray.Direction * polyhittestdist); @@ -1079,10 +1092,10 @@ namespace CodeWalker.GameFiles break; case BoundPolygonType.Box: var pbox = polygon as BoundPolygonBox; - p1 = GetVertex(pbox.boxIndex1);// + cg; //corner - p2 = GetVertex(pbox.boxIndex2);// + cg; - p3 = GetVertex(pbox.boxIndex3);// + cg; - p4 = GetVertex(pbox.boxIndex4);// + cg; + p1 = GetVertexPos(pbox.boxIndex1);//corner + p2 = GetVertexPos(pbox.boxIndex2); + p3 = GetVertexPos(pbox.boxIndex3); + p4 = GetVertexPos(pbox.boxIndex4); a1 = ((p3 + p4) - (p1 + p2)) * 0.5f; a2 = p3 - (p1 + a1); a3 = p4 - (p1 + a1); @@ -1093,7 +1106,7 @@ namespace CodeWalker.GameFiles if ((bs.X < bs.Y) && (bs.X < bs.Z)) m1 = Vector3.Cross(m2, m3); else if (bs.Y < bs.Z) m2 = Vector3.Cross(m3, m1); else m3 = Vector3.Cross(m1, m2); - Vector3 tp = rp - (p1 + cg); + Vector3 tp = rp - (p1);//+cg rayt.Position = new Vector3(Vector3.Dot(tp, m1), Vector3.Dot(tp, m2), Vector3.Dot(tp, m3)); rayt.Direction = new Vector3(Vector3.Dot(rd, m1), Vector3.Dot(rd, m2), Vector3.Dot(rd, m3)); box.Minimum = Vector3.Zero; @@ -1116,8 +1129,8 @@ namespace CodeWalker.GameFiles case BoundPolygonType.Cylinder: var pcyl = polygon as BoundPolygonCylinder; var tcyl = new BoundingCylinder(); - tcyl.PointA = GetVertex(pcyl.cylinderIndex1) + cg; - tcyl.PointB = GetVertex(pcyl.cylinderIndex2) + cg; + tcyl.PointA = GetVertexPos(pcyl.cylinderIndex1); + tcyl.PointB = GetVertexPos(pcyl.cylinderIndex2); tcyl.Radius = pcyl.cylinderRadius; polyhit = ray.Intersects(ref tcyl, out polyhittestdist, out n1); break; @@ -1350,6 +1363,8 @@ namespace CodeWalker.GameFiles [TC(typeof(EXP))] public abstract class BoundPolygon { public BoundPolygonType Type { get; set; } + public BoundGeometry Owner { get; set; } //for browsing/editing convenience + public int Index { get; set; } //for editing convenience, not stored public abstract void Read(byte[] bytes, int offset); public abstract void Write(BinaryWriter bw); public override string ToString() @@ -1374,6 +1389,21 @@ namespace CodeWalker.GameFiles public bool vertFlag2 { get { return (triIndex2 & 0x8000) > 0; } } public bool vertFlag3 { get { return (triIndex3 & 0x8000) > 0; } } + public Vector3 Vertex1 + { + get { return (Owner != null) ? Owner.GetVertexPos(vertIndex1) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(vertIndex1, value); } + } + public Vector3 Vertex2 + { + get { return (Owner != null) ? Owner.GetVertexPos(vertIndex2) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(vertIndex2, value); } + } + public Vector3 Vertex3 + { + get { return (Owner != null) ? Owner.GetVertexPos(vertIndex3) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(vertIndex3, value); } + } public BoundPolygonTriangle() { @@ -1412,6 +1442,12 @@ namespace CodeWalker.GameFiles public uint unused0 { get; set; } public uint unused1 { get; set; } + public Vector3 Position + { + get { return (Owner != null) ? Owner.GetVertexPos(sphereIndex) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(sphereIndex, value); } + } + public BoundPolygonSphere() { Type = BoundPolygonType.Sphere; @@ -1446,6 +1482,17 @@ namespace CodeWalker.GameFiles public ushort unused0 { get; set; } public uint unused1 { get; set; } + public Vector3 Vertex1 + { + get { return (Owner != null) ? Owner.GetVertexPos(capsuleIndex1) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(capsuleIndex1, value); } + } + public Vector3 Vertex2 + { + get { return (Owner != null) ? Owner.GetVertexPos(capsuleIndex2) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(capsuleIndex2, value); } + } + public BoundPolygonCapsule() { Type = BoundPolygonType.Capsule; @@ -1482,6 +1529,27 @@ namespace CodeWalker.GameFiles public short boxIndex4 { get; set; } public uint unused0 { get; set; } + public Vector3 Vertex1 + { + get { return (Owner != null) ? Owner.GetVertexPos(boxIndex1) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(boxIndex1, value); } + } + public Vector3 Vertex2 + { + get { return (Owner != null) ? Owner.GetVertexPos(boxIndex2) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(boxIndex2, value); } + } + public Vector3 Vertex3 + { + get { return (Owner != null) ? Owner.GetVertexPos(boxIndex3) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(boxIndex3, value); } + } + public Vector3 Vertex4 + { + get { return (Owner != null) ? Owner.GetVertexPos(boxIndex4) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(boxIndex4, value); } + } + public BoundPolygonBox() { Type = BoundPolygonType.Box; @@ -1518,6 +1586,17 @@ namespace CodeWalker.GameFiles public ushort unused0 { get; set; } public uint unused1 { get; set; } + public Vector3 Vertex1 + { + get { return (Owner != null) ? Owner.GetVertexPos(cylinderIndex1) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(cylinderIndex1, value); } + } + public Vector3 Vertex2 + { + get { return (Owner != null) ? Owner.GetVertexPos(cylinderIndex2) : Vector3.Zero; } + set { if (Owner != null) Owner.SetVertexPos(cylinderIndex2, value); } + } + public BoundPolygonCylinder() { Type = BoundPolygonType.Cylinder; diff --git a/Rendering/Renderer.cs b/Rendering/Renderer.cs index 05d014f..fef6f33 100644 --- a/Rendering/Renderer.cs +++ b/Rendering/Renderer.cs @@ -715,14 +715,14 @@ namespace CodeWalker.Rendering const int Reso = 36; const float MaxDeg = 360f; const float DegToRad = 0.0174533f; - const float Ang = MaxDeg / Reso; + const float Ang = DegToRad * MaxDeg / Reso; var axis = Vector3.Cross(dir, up); var c = new VertexTypePC[Reso]; for (var i = 0; i < Reso; i++) { - var rDir = Quaternion.RotationAxis(dir, (i * Ang) * DegToRad).Multiply(axis); + var rDir = Quaternion.RotationAxis(dir, i * Ang).Multiply(axis); c[i].Position = position + (rDir * radius); c[i].Colour = col; } @@ -737,6 +737,27 @@ namespace CodeWalker.Rendering SelectionLineVerts.Add(new VertexTypePC { Colour = col, Position = position + dir * 2f}); } + public void RenderMouseHit(BoundsShaderMode mode, ref Vector3 camrel, ref Vector3 bbmin, ref Vector3 bbmax, ref Vector3 scale, ref Quaternion ori, float bsphrad) + { + if (mode == BoundsShaderMode.Box) + { + var wbox = new MapBox(); + wbox.CamRelPos = camrel; + wbox.BBMin = bbmin; + wbox.BBMax = bbmax; + wbox.Scale = scale; + wbox.Orientation = ori; + WhiteBoxes.Add(wbox); + } + else if (mode == BoundsShaderMode.Sphere) + { + var wsph = new MapSphere(); + wsph.CamRelPos = camrel; + wsph.Radius = bsphrad; + WhiteSpheres.Add(wsph); + } + } + public void RenderSelectionArrowOutline(Vector3 pos, Vector3 dir, Vector3 up, Quaternion ori, float len, float rad, uint colour) { Vector3 ax = Vector3.Cross(dir, up); @@ -812,6 +833,63 @@ namespace CodeWalker.Rendering } + public void RenderSelectionCircle(Vector3 position, float radius, uint col) + { + const int Reso = 36; + const float MaxDeg = 360f; + const float DegToRad = 0.0174533f; + const float Ang = DegToRad * MaxDeg / Reso; + + var dir = Vector3.Normalize(position - camera.Position); + var up = Vector3.Normalize(dir.GetPerpVec()); + var axis = Vector3.Cross(dir, up); + var c = new VertexTypePC[Reso]; + + for (var i = 0; i < Reso; i++) + { + var rDir = Quaternion.RotationAxis(dir, i * Ang).Multiply(axis); + c[i].Position = position + (rDir * radius); + c[i].Colour = col; + } + + for (var i = 0; i < c.Length; i++) + { + SelectionLineVerts.Add(c[i]); + SelectionLineVerts.Add(c[(i + 1) % c.Length]); + } + } + + public void RenderSelectionBox(Vector3 p1, Vector3 p2, Vector3 a2, Vector3 a3, uint col) + { + VertexTypePC v = new VertexTypePC(); + v.Colour = col; + var c1 = p1 - a2 - a3; + var c2 = p1 - a2 + a3; + var c3 = p1 + a2 + a3; + var c4 = p1 + a2 - a3; + var c5 = p2 - a2 - a3; + var c6 = p2 - a2 + a3; + var c7 = p2 + a2 + a3; + var c8 = p2 + a2 - a3; + v.Position = c1; SelectionLineVerts.Add(v); + v.Position = c2; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = c3; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = c4; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = c1; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = c5; SelectionLineVerts.Add(v); + v.Position = c2; SelectionLineVerts.Add(v); + v.Position = c6; SelectionLineVerts.Add(v); + v.Position = c3; SelectionLineVerts.Add(v); + v.Position = c7; SelectionLineVerts.Add(v); + v.Position = c4; SelectionLineVerts.Add(v); + v.Position = c8; SelectionLineVerts.Add(v); + v.Position = c5; SelectionLineVerts.Add(v); + v.Position = c6; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = c7; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = c8; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = c5; SelectionLineVerts.Add(v); + } + public void RenderSelectionNavPoly(YnvPoly poly) { ////draw poly triangles @@ -915,6 +993,78 @@ namespace CodeWalker.Rendering //} } + public void RenderSelectionCollisionPolyOutline(BoundPolygon poly, uint colourval, YmapEntityDef entity) + { + var bgeom = poly?.Owner; + if (bgeom == null) return; + + VertexTypePC v = new VertexTypePC(); + v.Colour = colourval; + + var ori = Quaternion.Identity; + var pos = Vector3.Zero; + var sca = Vector3.One; + if (entity != null) + { + ori = entity.Orientation; + pos = entity.Position; + sca = entity.Scale; + } + + if (poly is BoundPolygonTriangle ptri) + { + var p1 = pos + (ori.Multiply(ptri.Vertex1) * sca); + var p2 = pos + (ori.Multiply(ptri.Vertex2) * sca); + var p3 = pos + (ori.Multiply(ptri.Vertex3) * sca); + v.Position = p1; SelectionLineVerts.Add(v); + v.Position = p2; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = p3; SelectionLineVerts.Add(v); SelectionLineVerts.Add(v); + v.Position = p1; SelectionLineVerts.Add(v); + } + else if (poly is BoundPolygonSphere psph) + { + var p1 = pos + (ori.Multiply(psph.Position) * sca); + RenderSelectionCircle(p1, psph.sphereRadius * 1.03f, colourval);//enlarge the circle to make it more visible.. + } + else if (poly is BoundPolygonCapsule pcap) + { + var p1 = pos + (ori.Multiply(pcap.Vertex1) * sca); + var p2 = pos + (ori.Multiply(pcap.Vertex2) * sca); + var a1 = Vector3.Normalize(p2 - p1); + var a2 = Vector3.Normalize(a1.GetPerpVec()); + var a3 = Vector3.Normalize(Vector3.Cross(a1, a2)); + a1 *= pcap.capsuleRadius; + a2 *= pcap.capsuleRadius; + a3 *= pcap.capsuleRadius; + RenderSelectionBox(p1 - a1, p2 + a1, a2, a3, colourval); + } + else if (poly is BoundPolygonBox pbox) + { + var p1 = pos + (ori.Multiply(pbox.Vertex1) * sca); + var p2 = pos + (ori.Multiply(pbox.Vertex2) * sca); + var p3 = pos + (ori.Multiply(pbox.Vertex3) * sca); + var p4 = pos + (ori.Multiply(pbox.Vertex4) * sca); + var p5 = (p1 + p2) * 0.5f; + var p6 = (p3 + p4) * 0.5f; + var a1 = (p6 - p5); + var a2 = (p3 - (p1 + a1)) * 0.5f; + var a3 = (p4 - (p1 + a1)) * 0.5f; + RenderSelectionBox(p5, p6, a2, a3, colourval); + } + else if (poly is BoundPolygonCylinder pcyl) + { + var p1 = pos + (ori.Multiply(pcyl.Vertex1) * sca); + var p2 = pos + (ori.Multiply(pcyl.Vertex2) * sca); + var a1 = Vector3.Normalize(p2 - p1); + var a2 = Vector3.Normalize(a1.GetPerpVec()); + var a3 = Vector3.Normalize(Vector3.Cross(a1, a2)); + a2 *= pcyl.cylinderRadius; + a3 *= pcyl.cylinderRadius; + RenderSelectionBox(p1, p2, a2, a3, colourval); + } + + } + public void RenderSelectionGeometry(MapSelectionMode mode) { @@ -954,13 +1104,6 @@ namespace CodeWalker.Rendering shader.SetShader(context); shader.SetInputLayout(context, VertexType.Default); shader.SetSceneVars(context, camera, null, globalLights); - shader.SetColourVars(context, new Vector4(colourwht, 1)); - for (int i = 0; i < WhiteBoxes.Count; i++) - { - MapBox mb = WhiteBoxes[i]; - shader.SetBoxVars(context, mb.CamRelPos, mb.BBMin, mb.BBMax, mb.Orientation, mb.Scale); - shader.DrawBox(context); - } shader.SetColourVars(context, new Vector4(coloursel, 1)); for (int i = 0; i < SelectionBoxes.Count; i++) { @@ -968,6 +1111,13 @@ namespace CodeWalker.Rendering shader.SetBoxVars(context, mb.CamRelPos, mb.BBMin, mb.BBMax, mb.Orientation, mb.Scale); shader.DrawBox(context); } + shader.SetColourVars(context, new Vector4(colourwht, 1)); + for (int i = 0; i < WhiteBoxes.Count; i++) + { + MapBox mb = WhiteBoxes[i]; + shader.SetBoxVars(context, mb.CamRelPos, mb.BBMin, mb.BBMax, mb.Orientation, mb.Scale); + shader.DrawBox(context); + } shader.UnbindResources(context); } @@ -977,13 +1127,6 @@ namespace CodeWalker.Rendering shader.SetShader(context); shader.SetInputLayout(context, VertexType.Default); shader.SetSceneVars(context, camera, null, globalLights); - shader.SetColourVars(context, new Vector4(colourwht, 1)); - for (int i = 0; i < WhiteSpheres.Count; i++) - { - MapSphere ms = WhiteSpheres[i]; - shader.SetSphereVars(context, ms.CamRelPos, ms.Radius); - shader.DrawSphere(context); - } shader.SetColourVars(context, new Vector4(coloursel, 1)); for (int i = 0; i < SelectionSpheres.Count; i++) { @@ -991,41 +1134,19 @@ namespace CodeWalker.Rendering shader.SetSphereVars(context, ms.CamRelPos, ms.Radius); shader.DrawSphere(context); } + shader.SetColourVars(context, new Vector4(colourwht, 1)); + for (int i = 0; i < WhiteSpheres.Count; i++) + { + MapSphere ms = WhiteSpheres[i]; + shader.SetSphereVars(context, ms.CamRelPos, ms.Radius); + shader.DrawSphere(context); + } shader.UnbindResources(context); } } - public void RenderMouseHit(BoundsShaderMode mode, bool clip, ref Vector3 camrel, ref Vector3 bbmin, ref Vector3 bbmax, ref Vector3 scale, ref Quaternion ori, float bsphrad) - { - Vector3 colour = new Vector3(1, 1, 1); - colour *= globalLights.HdrIntensity * 5.0f; - - shaders.SetDepthStencilMode(context, clip ? DepthStencilMode.Enabled : DepthStencilMode.DisableAll); - - //render moused object box. - var shader = shaders.Bounds; - shader.SetMode(mode); - shader.SetShader(context); - shader.SetInputLayout(context, VertexType.Default); - shader.SetSceneVars(context, camera, null, globalLights); - shader.SetColourVars(context, new Vector4(colour, 1)); //white box - - if (mode == BoundsShaderMode.Box) - { - shader.SetBoxVars(context, camrel, bbmin, bbmax, ori, scale); - shader.DrawBox(context); - } - else if (mode == BoundsShaderMode.Sphere) - { - shader.SetSphereVars(context, camrel, bsphrad); - shader.DrawSphere(context); - } - - shader.UnbindResources(context); - } - public void RenderBounds(MapSelectionMode mode) { diff --git a/Utils/MapUtils.cs b/Utils/MapUtils.cs index d62cf01..28eec70 100644 --- a/Utils/MapUtils.cs +++ b/Utils/MapUtils.cs @@ -187,6 +187,7 @@ namespace CodeWalker public MCMloRoomDef MloRoomDef { get; set; } public WaterQuad WaterQuad { get; set; } public Bounds CollisionBounds { get; set; } + public BoundPolygon CollisionPoly { get; set; } public YnvPoly NavPoly { get; set; } public YnvPoint NavPoint { get; set; } public YnvPortal NavPortal { get; set; } @@ -224,6 +225,7 @@ namespace CodeWalker (GrassBatch != null) || (WaterQuad != null) || (CollisionBounds != null) || + (CollisionPoly != null) || (NavPoly != null) || (NavPoint != null) || (NavPortal != null) || @@ -261,6 +263,7 @@ namespace CodeWalker || (OccludeModel != mhit.OccludeModel) || (WaterQuad != mhit.WaterQuad) || (CollisionBounds != mhit.CollisionBounds) + || (CollisionPoly != mhit.CollisionPoly) || (NavPoly != mhit.NavPoly) || (NavPoint != mhit.NavPoint) || (NavPortal != mhit.NavPortal) @@ -286,6 +289,7 @@ namespace CodeWalker || (OccludeModel != null) || (WaterQuad != null) || (CollisionBounds != null) + || (CollisionPoly != null) || (NavPoly != null) || (NavPoint != null) || (NavPortal != null) @@ -313,6 +317,7 @@ namespace CodeWalker OccludeModel = null; WaterQuad = null; CollisionBounds = null; + CollisionPoly = null; NavPoly = null; NavPoint = null; NavPortal = null; @@ -366,6 +371,10 @@ namespace CodeWalker { name = "OccludeModel " + (OccludeModel.Ymap?.Name ?? "") + ": " + OccludeModel.Index.ToString(); } + else if (CollisionPoly != null) + { + name = "Poly " + CollisionPoly.Index.ToString() + ((CollisionBounds != null) ? (": " + CollisionBounds.GetName()) : string.Empty); + } else if (CollisionBounds != null) { name = CollisionBounds.GetName(); @@ -432,6 +441,10 @@ namespace CodeWalker { name = Archetype.Hash.ToString(); } + else if (CollisionPoly != null) + { + name = "Poly " + CollisionPoly.Index.ToString() + ((CollisionBounds != null) ? (": " + CollisionBounds.GetName()) : string.Empty); + } else if (CollisionBounds != null) { name = CollisionBounds.GetName(); diff --git a/World/WorldInfoForm.cs b/World/WorldInfoForm.cs index 706137b..4ddc3cd 100644 --- a/World/WorldInfoForm.cs +++ b/World/WorldInfoForm.cs @@ -181,6 +181,11 @@ namespace CodeWalker SelectionExtensionTabPage.Text = "Archetype Extension"; SelExtensionPropertyGrid.SelectedObject = item.ArchetypeExtension; } + else if (item.CollisionPoly != null) + { + SelectionExtensionTabPage.Text = "Collision Polygon"; + SelExtensionPropertyGrid.SelectedObject = item.CollisionPoly; + } else if (item.CollisionBounds != null) { SelectionExtensionTabPage.Text = "Collision Bounds"; diff --git a/WorldForm.cs b/WorldForm.cs index 134df1f..0eb17f2 100644 --- a/WorldForm.cs +++ b/WorldForm.cs @@ -446,14 +446,14 @@ namespace CodeWalker RenderSelection(); + RenderMoused(); + Renderer.RenderQueued(); Renderer.RenderBounds(SelectionMode); Renderer.RenderSelectionGeometry(SelectionMode); - RenderMoused(); - Renderer.RenderFinalPass(); RenderMarkers(); @@ -1137,7 +1137,8 @@ namespace CodeWalker change = change || (LastMouseHit.WaterQuad != PrevMouseHit.WaterQuad); break; case MapSelectionMode.Collision: - change = change || (LastMouseHit.CollisionBounds != PrevMouseHit.CollisionBounds); + change = change || (LastMouseHit.CollisionBounds != PrevMouseHit.CollisionBounds) + || (LastMouseHit.CollisionPoly != PrevMouseHit.CollisionPoly); break; case MapSelectionMode.NavMesh: change = change || (LastMouseHit.NavPoly != PrevMouseHit.NavPoly) @@ -1169,14 +1170,6 @@ namespace CodeWalker { return; } - if ((SelectionMode == MapSelectionMode.NavMesh) && (CurMouseHit.NavPoly != null)) - { - return;//navmesh poly isn't needing a selection box.. - } - - - bool clip = Renderer.renderboundsclip; - BoundsShaderMode mode = BoundsShaderMode.Box; float bsphrad = CurMouseHit.BSphere.Radius; Vector3 bbmin = CurMouseHit.AABB.Minimum; @@ -1215,11 +1208,9 @@ namespace CodeWalker if (CurMouseHit.MloEntityDef != null) { scale = Vector3.One; - clip = false; } if (CurMouseHit.WaterQuad != null) { - clip = false; } if (CurMouseHit.ScenarioNode != null) { @@ -1238,6 +1229,11 @@ namespace CodeWalker { ori = CurMouseHit.NavPortal.Orientation; } + if (CurMouseHit.NavPoly != null) + { + Renderer.RenderSelectionNavPolyOutline(CurMouseHit.NavPoly, 0xFFFFFFFF); + return; + } if (CurMouseHit.Audio != null) { ori = CurMouseHit.Audio.Orientation; @@ -1246,13 +1242,17 @@ namespace CodeWalker mode = BoundsShaderMode.Sphere; } } + if (CurMouseHit.CollisionPoly != null) + { + Renderer.RenderSelectionCollisionPolyOutline(CurMouseHit.CollisionPoly, 0xFFFFFFFF, CurMouseHit.EntityDef); + } if (CurMouseHit.CollisionBounds != null) { ori = ori * CurMouseHit.BBOrientation; } - Renderer.RenderMouseHit(mode, clip, ref camrel, ref bbmin, ref bbmax, ref scale, ref ori, bsphrad); + Renderer.RenderMouseHit(mode, ref camrel, ref bbmin, ref bbmax, ref scale, ref ori, bsphrad); } private void RenderSelection() @@ -1282,12 +1282,12 @@ namespace CodeWalker if (ControlBrushEnabled && MouseRayCollision.Hit) { - var arup = GetPerpVec(MouseRayCollision.Normal); + var arup = MouseRayCollision.Normal.GetPerpVec(); Renderer.RenderBrushRadiusOutline(MouseRayCollision.Position, MouseRayCollision.Normal, arup, ProjectForm.GetInstanceBrushRadius(), cgrn); } if (MouseRayCollisionVisible && MouseRayCollision.Hit) { - var arup = GetPerpVec(MouseRayCollision.Normal); + var arup = MouseRayCollision.Normal.GetPerpVec(); Renderer.RenderSelectionArrowOutline(MouseRayCollision.Position, MouseRayCollision.Normal, arup, Quaternion.Identity, 1.0f, 0.05f, cgrn); } @@ -1544,6 +1544,10 @@ namespace CodeWalker Renderer.WhiteBoxes.Add(wbox); } } + if (selectionItem.CollisionPoly != null) + { + Renderer.RenderSelectionCollisionPolyOutline(selectionItem.CollisionPoly, cgrn, selectionItem.EntityDef); + } if (selectionItem.CollisionBounds != null) { camrel += ori.Multiply(selectionItem.BBOffset); @@ -2060,27 +2064,6 @@ namespace CodeWalker } - public static Vector3 GetPerpVec(Vector3 n) - { - //make a vector perpendicular to the given one - float nx = Math.Abs(n.X); - float ny = Math.Abs(n.Y); - float nz = Math.Abs(n.Z); - if ((nx < ny) && (nx < nz)) - { - return Vector3.Cross(n, Vector3.Right); - } - else if (ny < nz) - { - return Vector3.Cross(n, Vector3.Up); - } - else - { - return Vector3.Cross(n, Vector3.ForwardLH); - } - } - - private void SpawnTestEntity(bool cameraCenter = false) { if (!space.Inited) return; @@ -2264,10 +2247,6 @@ namespace CodeWalker { UpdateMouseHits(rd.Drawable, rd.Archetype, rd.Entity); } - //foreach (var rb in Renderer.RenderedBoundComps) - //{ - // UpdateMouseHits(rb.BoundComp, rb.Entity); - //} } private void UpdateMouseHitsFromSpace() { @@ -2286,6 +2265,7 @@ namespace CodeWalker var camrel = position - camera.Position; var trans = MouseRayCollision.HitBounds?.Transform.TranslationVector ?? Vector3.Zero; + CurMouseHit.CollisionPoly = MouseRayCollision.HitPolygon; CurMouseHit.CollisionBounds = MouseRayCollision.HitBounds; CurMouseHit.EntityDef = MouseRayCollision.HitEntity; CurMouseHit.Archetype = MouseRayCollision.HitEntity?.Archetype; @@ -2294,21 +2274,8 @@ namespace CodeWalker CurMouseHit.BBOffset = trans; CurMouseHit.BBOrientation = Quaternion.RotationMatrix(rmat); CurMouseHit.AABB = new BoundingBox(MouseRayCollision.HitBounds?.BoundingBoxMin ?? Vector3.Zero, MouseRayCollision.HitBounds?.BoundingBoxMax ?? Vector3.Zero); - - - MapBox mb = new MapBox(); - mb.CamRelPos = MouseRayCollision.Position - camera.Position; - mb.Orientation = Quaternion.Identity; - mb.Scale = Vector3.One; - mb.BBMin = new Vector3(-0.01f); - mb.BBMax = new Vector3(+0.01f); - Renderer.BoundingBoxes.Add(mb); - - } - } - } private void UpdateMouseHits(DrawableBase drawable, Archetype arche, YmapEntityDef entity) { @@ -2614,65 +2581,6 @@ namespace CodeWalker //{ } - } - private void UpdateMouseHits(RenderableBoundComposite rndbc, YmapEntityDef entity) - { - if (SelectionMode != MapSelectionMode.Collision) return; - - var position = entity?.Position ?? Vector3.Zero; - var orientation = entity?.Orientation ?? Quaternion.Identity; - var scale = entity?.Scale ?? Vector3.One; - - var camrel = position - camera.Position; - - - - BoundingBox bbox = new BoundingBox(); - Ray mray = new Ray(); - mray.Position = camera.MouseRay.Position + camera.Position; - mray.Direction = camera.MouseRay.Direction; - float hitdist = float.MaxValue; - - Ray mraytrn = new Ray(); - - MapBox mb = new MapBox(); - mb.CamRelPos = camrel;// rbginst.Inst.CamRel; - mb.Orientation = orientation; - mb.Scale = scale; - - foreach (var geom in rndbc.Geometries) - { - if (geom == null) continue; - - mb.BBMin = geom.BBMin; - mb.BBMax = geom.BBMax; - mb.CamRelPos = camrel + orientation.Multiply(geom.BBOffset); - mb.Orientation = orientation * geom.BBOrientation; - - var cent = mb.CamRelPos + (mb.BBMin + mb.BBMax) * 0.5f; - if (cent.Length() > Renderer.renderboundsmaxdist) continue; - - Renderer.BoundingBoxes.Add(mb); - - Quaternion orinv = Quaternion.Invert(mb.Orientation); - mraytrn.Position = orinv.Multiply(camera.MouseRay.Position - mb.CamRelPos); - mraytrn.Direction = orinv.Multiply(mray.Direction); - - bbox.Minimum = mb.BBMin * scale; - bbox.Maximum = mb.BBMax * scale; - if (mraytrn.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) - { - CurMouseHit.CollisionBounds = geom.Bound; - CurMouseHit.EntityDef = entity; - CurMouseHit.Archetype = entity?.Archetype; - CurMouseHit.HitDist = hitdist; - CurMouseHit.CamRel = mb.CamRelPos; - CurMouseHit.BBOffset = geom.BBOffset; - CurMouseHit.BBOrientation = geom.BBOrientation; - CurMouseHit.AABB = bbox; - } - } - } private void UpdateMouseHits(YmapFile ymap) { @@ -2954,11 +2862,6 @@ namespace CodeWalker } } - if ((CurMouseHit.NavPoly != null) && MouseSelectEnabled) - { - Renderer.RenderSelectionNavPolyOutline(CurMouseHit.NavPoly, 0xFFFFFFFF); - } - } private void UpdateMouseHits(YnvFile ynv, NavMeshSector navsector, NavMeshSector rootsec, ref Ray mray) { @@ -3955,6 +3858,11 @@ namespace CodeWalker SelExtensionPropertyGrid.SelectedObject = item.ArchetypeExtension; ShowSelectedExtensionTab(true); } + else if (item.CollisionPoly != null) + { + SelExtensionPropertyGrid.SelectedObject = item.CollisionPoly; + ShowSelectedExtensionTab(true, "Coll"); + } else if (item.CollisionBounds != null) { SelExtensionPropertyGrid.SelectedObject = item.CollisionBounds;