From d85f5eddb2959766f2015cbe3baf8cfbf5f3c23a Mon Sep 17 00:00:00 2001 From: dexy Date: Thu, 2 Jan 2020 00:16:49 +1100 Subject: [PATCH] Collisions editing beginnings --- CodeWalker.Core/GameFiles/Resources/Bounds.cs | 248 ++++++++++++- CodeWalker.Core/Utils/Matrices.cs | 6 + Project/UndoStep.cs | 335 +++++++++++++++++- Rendering/RenderableCache.cs | 14 +- Rendering/Renderer.cs | 6 +- Utils/MapUtils.cs | 53 ++- WorldForm.cs | 84 ++++- 7 files changed, 704 insertions(+), 42 deletions(-) diff --git a/CodeWalker.Core/GameFiles/Resources/Bounds.cs b/CodeWalker.Core/GameFiles/Resources/Bounds.cs index e551a19..64f7138 100644 --- a/CodeWalker.Core/GameFiles/Resources/Bounds.cs +++ b/CodeWalker.Core/GameFiles/Resources/Bounds.cs @@ -130,7 +130,7 @@ namespace CodeWalker.GameFiles public float BoundingBoxVolume { get; set; } - public Bounds Parent { get; set; } + public BoundComposite Parent { get; set; } public string OwnerName { get; set; } public string GetName() { @@ -147,6 +147,49 @@ namespace CodeWalker.GameFiles public Matrix Transform { get; set; } = Matrix.Identity; //when it's the child of a bound composite public Matrix TransformInv { get; set; } = Matrix.Identity; + public virtual Vector3 Scale + { + get + { + return Transform.ScaleVector; + } + set + { + var m = Transform; + m.ScaleVector = value; + Transform = m; + TransformInv = Matrix.Invert(m); + } + } + public virtual Vector3 Position + { + get + { + return Transform.TranslationVector; + } + set + { + var m = Transform; + m.TranslationVector = value; + Transform = m; + TransformInv = Matrix.Invert(m); + } + } + public virtual Quaternion Orientation + { + get + { + return Transform.ToQuaternion(); + } + set + { + var m = value.ToMatrix(); + m.TranslationVector = Transform.TranslationVector; + m.ScaleVector = Transform.ScaleVector; + Transform = m; + TransformInv = Matrix.Invert(m); + } + } /// /// Reads the data-block from a stream. @@ -1365,6 +1408,9 @@ namespace CodeWalker.GameFiles 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 Vector3 Scale { get; set; } + public abstract Vector3 Position { get; set; } + public abstract Quaternion Orientation { get; set; } public abstract void Read(byte[] bytes, int offset); public abstract void Write(BinaryWriter bw); public override string ToString() @@ -1405,6 +1451,41 @@ namespace CodeWalker.GameFiles set { if (Owner != null) Owner.SetVertexPos(vertIndex3, value); } } + public override Vector3 Scale + { + get + { + return Vector3.One; + } + set + { + } + } + public override Vector3 Position + { + get + { + return (Vertex1 + Vertex2 + Vertex3) * (1.0f / 3.0f); + } + set + { + var offset = value - Position; + Vertex1 += offset; + Vertex2 += offset; + Vertex3 += offset; + } + } + public override Quaternion Orientation + { + get + { + return Quaternion.Identity; + } + set + { + } + } + public BoundPolygonTriangle() { Type = BoundPolygonType.Triangle; @@ -1442,11 +1523,31 @@ namespace CodeWalker.GameFiles public uint unused0 { get; set; } public uint unused1 { get; set; } - public Vector3 Position + public override Vector3 Scale + { + get + { + return Vector3.One; + } + set + { + } + } + public override Vector3 Position { get { return (Owner != null) ? Owner.GetVertexPos(sphereIndex) : Vector3.Zero; } set { if (Owner != null) Owner.SetVertexPos(sphereIndex, value); } } + public override Quaternion Orientation + { + get + { + return Quaternion.Identity; + } + set + { + } + } public BoundPolygonSphere() { @@ -1493,6 +1594,40 @@ namespace CodeWalker.GameFiles set { if (Owner != null) Owner.SetVertexPos(capsuleIndex2, value); } } + public override Vector3 Scale + { + get + { + return Vector3.One; + } + set + { + } + } + public override Vector3 Position + { + get + { + return (Vertex1 + Vertex2) * 0.5f; + } + set + { + var offset = value - Position; + Vertex1 += offset; + Vertex2 += offset; + } + } + public override Quaternion Orientation + { + get + { + return Quaternion.Identity; + } + set + { + } + } + public BoundPolygonCapsule() { Type = BoundPolygonType.Capsule; @@ -1550,6 +1685,42 @@ namespace CodeWalker.GameFiles set { if (Owner != null) Owner.SetVertexPos(boxIndex4, value); } } + public override Vector3 Scale + { + get + { + return Vector3.One; + } + set + { + } + } + public override Vector3 Position + { + get + { + return (Vertex1 + Vertex2 + Vertex3 + Vertex4) * 0.25f; + } + set + { + var offset = value - Position; + Vertex1 += offset; + Vertex2 += offset; + Vertex3 += offset; + Vertex4 += offset; + } + } + public override Quaternion Orientation + { + get + { + return Quaternion.Identity; + } + set + { + } + } + public BoundPolygonBox() { Type = BoundPolygonType.Box; @@ -1597,6 +1768,40 @@ namespace CodeWalker.GameFiles set { if (Owner != null) Owner.SetVertexPos(cylinderIndex2, value); } } + public override Vector3 Scale + { + get + { + return Vector3.One; + } + set + { + } + } + public override Vector3 Position + { + get + { + return (Vertex1 + Vertex2) * 0.5f; + } + set + { + var offset = value - Position; + Vertex1 += offset; + Vertex2 += offset; + } + } + public override Quaternion Orientation + { + get + { + return Quaternion.Identity; + } + set + { + } + } + public BoundPolygonCylinder() { Type = BoundPolygonType.Cylinder; @@ -1708,6 +1913,14 @@ namespace CodeWalker.GameFiles + + public void BuildBVH() + { + + } + + + public override SpaceSphereIntersectResult SphereIntersect(ref BoundingSphere sph) { var res = new SpaceSphereIntersectResult(); @@ -1742,11 +1955,11 @@ namespace CodeWalker.GameFiles box.Maximum = new Vector3(node.MaxX, node.MaxY, node.MaxZ) * q + c; bool nodehit = sph.Intersects(ref box); bool nodeskip = !nodehit; - if (node.PolyCount <= 0) //intermediate node with child nodes + if (node.ItemCount <= 0) //intermediate node with child nodes { if (nodeskip) { - nodeind += node.PolyId; //(child node count) + nodeind += node.ItemId; //(child node count) } else { @@ -1757,9 +1970,9 @@ namespace CodeWalker.GameFiles { if (!nodeskip) { - var lastp = Math.Min(node.PolyId + node.PolyCount, (int)PolygonsCount); + var lastp = Math.Min(node.ItemId + node.ItemCount, (int)PolygonsCount); - SphereIntersectPolygons(ref sph, ref res, node.PolyId, lastp); + SphereIntersectPolygons(ref sph, ref res, node.ItemId, lastp); } nodeind++; @@ -1812,11 +2025,11 @@ namespace CodeWalker.GameFiles box.Maximum = new Vector3(node.MaxX, node.MaxY, node.MaxZ) * q + c; bool nodehit = ray.Intersects(ref box, out bvhboxhittest); bool nodeskip = !nodehit || (bvhboxhittest > res.HitDist); - if (node.PolyCount <= 0) //intermediate node with child nodes + if (node.ItemCount <= 0) //intermediate node with child nodes { if (nodeskip) { - nodeind += node.PolyId; //(child node count) + nodeind += node.ItemId; //(child node count) } else { @@ -1827,9 +2040,9 @@ namespace CodeWalker.GameFiles { if (!nodeskip) { - var lastp = Math.Min(node.PolyId + node.PolyCount, (int)PolygonsCount); + var lastp = Math.Min(node.ItemId + node.ItemCount, (int)PolygonsCount); - RayIntersectPolygons(ref ray, ref res, node.PolyId, lastp); + RayIntersectPolygons(ref ray, ref res, node.ItemId, lastp); } nodeind++; @@ -2008,6 +2221,15 @@ namespace CodeWalker.GameFiles + + public void BuildBVH() + { + + } + + + + public override SpaceSphereIntersectResult SphereIntersect(ref BoundingSphere sph) { var res = new SpaceSphereIntersectResult(); @@ -2218,12 +2440,12 @@ namespace CodeWalker.GameFiles public short MaxX { get; set; } public short MaxY { get; set; } public short MaxZ { get; set; } - public short PolyId { get; set; } - public short PolyCount { get; set; } + public short ItemId { get; set; } + public short ItemCount { get; set; } public override string ToString() { - return PolyId.ToString() + ": " + PolyCount.ToString(); + return ItemId.ToString() + ": " + ItemCount.ToString(); } } diff --git a/CodeWalker.Core/Utils/Matrices.cs b/CodeWalker.Core/Utils/Matrices.cs index 580b553..15441c8 100644 --- a/CodeWalker.Core/Utils/Matrices.cs +++ b/CodeWalker.Core/Utils/Matrices.cs @@ -45,6 +45,12 @@ namespace CodeWalker return new Vector4(x, y, z, w); } + public static Quaternion ToQuaternion(this Matrix m) + { + var rmat = m; + rmat.TranslationVector = Vector3.Zero; + return Quaternion.RotationMatrix(rmat); + } } } diff --git a/Project/UndoStep.cs b/Project/UndoStep.cs index 2a05baa..fc2aee9 100644 --- a/Project/UndoStep.cs +++ b/Project/UndoStep.cs @@ -65,6 +65,7 @@ namespace CodeWalker.Project Dictionary navYnvs = new Dictionary(); Dictionary trainTracks = new Dictionary(); Dictionary scenarioYmts = new Dictionary(); + Dictionary bounds = new Dictionary(); if (Items != null) { @@ -94,9 +95,21 @@ namespace CodeWalker.Project { scenarioYmts[item.ScenarioNode.Ymt] = 1; } + if (item.CollisionBounds != null) + { + bounds[item.CollisionBounds] = 1; + } + if (item.CollisionPoly?.Owner != null) + { + bounds[item.CollisionPoly.Owner] = 1; + } } } + foreach (var kvp in bounds) + { + wf.UpdateCollisionBoundsGraphics(kvp.Key); + } foreach (var kvp in pathYnds) { wf.UpdatePathYndGraphics(kvp.Key, true); @@ -172,7 +185,6 @@ namespace CodeWalker.Project return (Entity?._CEntityDef.archetypeName.ToString() ?? "") + ": Position"; } } - public class EntityRotationUndoStep : UndoStep { public YmapEntityDef Entity { get; set; } @@ -211,7 +223,6 @@ namespace CodeWalker.Project return (Entity?._CEntityDef.archetypeName.ToString() ?? "") + ": Rotation"; } } - public class EntityScaleUndoStep : UndoStep { public YmapEntityDef Entity { get; set; } @@ -252,6 +263,7 @@ namespace CodeWalker.Project } + public class EntityPivotPositionUndoStep : UndoStep { public YmapEntityDef Entity { get; set; } @@ -288,7 +300,6 @@ namespace CodeWalker.Project return (Entity?._CEntityDef.archetypeName.ToString() ?? "") + ": Pivot Position"; } } - public class EntityPivotRotationUndoStep : UndoStep { public YmapEntityDef Entity { get; set; } @@ -366,7 +377,6 @@ namespace CodeWalker.Project return "CarGen " + (CarGen?._CCarGen.carModel.ToString() ?? "") + ": Position"; } } - public class CarGenRotationUndoStep : UndoStep { public YmapCarGen CarGen { get; set; } @@ -404,7 +414,6 @@ namespace CodeWalker.Project return "CarGen " + (CarGen?._CCarGen.carModel.ToString() ?? "") + ": Rotation"; } } - public class CarGenScaleUndoStep : UndoStep { public YmapCarGen CarGen { get; set; } @@ -445,6 +454,317 @@ namespace CodeWalker.Project + public class CollisionPositionUndoStep : UndoStep + { + public Bounds Bounds { get; set; } + public Vector3 StartPosition { get; set; } + public Vector3 EndPosition { get; set; } + + public CollisionPositionUndoStep(Bounds bounds, Vector3 startpos, WorldForm wf) + { + Bounds = bounds; + StartPosition = startpos; + EndPosition = bounds?.Position ?? Vector3.Zero; + + UpdateGraphics(wf); + } + + private void Update(WorldForm wf, ref MapSelection sel, Vector3 p) + { + if (Bounds != null) + { + Bounds.Position = p; + } + + if (Bounds != sel.CollisionBounds) wf.SelectCollisionBounds(Bounds); + wf.SetWidgetPosition(p); + + UpdateGraphics(wf); + } + + private void UpdateGraphics(WorldForm wf) + { + if (Bounds != null) + { + wf.UpdateCollisionBoundsGraphics(Bounds); + } + } + + public override void Undo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, StartPosition); + } + + public override void Redo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, EndPosition); + } + + public override string ToString() + { + return "Collision " + (Bounds?.GetName() ?? "") + ": Position"; + } + } + public class CollisionRotationUndoStep : UndoStep + { + public Bounds Bounds { get; set; } + public Quaternion StartRotation { get; set; } + public Quaternion EndRotation { get; set; } + + public CollisionRotationUndoStep(Bounds bounds, Quaternion startrot, WorldForm wf) + { + Bounds = bounds; + StartRotation = startrot; + EndRotation = bounds?.Orientation ?? Quaternion.Identity; + + UpdateGraphics(wf); + } + + + private void Update(WorldForm wf, ref MapSelection sel, Quaternion q) + { + if (Bounds != null) + { + Bounds.Orientation = q; + } + + if (Bounds != sel.CollisionBounds) wf.SelectCollisionBounds(Bounds); + wf.SetWidgetRotation(q); + + UpdateGraphics(wf); + } + + private void UpdateGraphics(WorldForm wf) + { + if (Bounds != null) + { + wf.UpdateCollisionBoundsGraphics(Bounds); + } + } + + public override void Undo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, StartRotation); + } + + public override void Redo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, EndRotation); + } + + public override string ToString() + { + return "Collision " + (Bounds?.GetName() ?? "") + ": Rotation"; + } + } + public class CollisionScaleUndoStep : UndoStep + { + public Bounds Bounds { get; set; } + public Vector3 StartScale { get; set; } + public Vector3 EndScale { get; set; } + + public CollisionScaleUndoStep(Bounds bounds, Vector3 startsca, WorldForm wf) + { + Bounds = bounds; + StartScale = startsca; + EndScale = bounds?.Scale ?? Vector3.One; + + UpdateGraphics(wf); + } + + private void Update(WorldForm wf, ref MapSelection sel, Vector3 s) + { + if (Bounds != null) + { + Bounds.Scale = s; + } + + if (Bounds != sel.CollisionBounds) wf.SelectCollisionBounds(Bounds); + wf.SetWidgetScale(s); + + UpdateGraphics(wf); + } + + private void UpdateGraphics(WorldForm wf) + { + if (Bounds != null) + { + wf.UpdateCollisionBoundsGraphics(Bounds); + } + } + + public override void Undo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, StartScale); + } + + public override void Redo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, EndScale); + } + + public override string ToString() + { + return "Collision " + (Bounds?.GetName() ?? "") + ": Scale"; + } + } + + public class CollisionPolyPositionUndoStep : UndoStep + { + public BoundPolygon Polygon { get; set; } + public Vector3 StartPosition { get; set; } + public Vector3 EndPosition { get; set; } + + public CollisionPolyPositionUndoStep(BoundPolygon poly, Vector3 startpos, WorldForm wf) + { + Polygon = poly; + StartPosition = startpos; + EndPosition = poly?.Position ?? Vector3.Zero; + + UpdateGraphics(wf); + } + + private void Update(WorldForm wf, ref MapSelection sel, Vector3 p) + { + if (Polygon != null) + { + Polygon.Position = p; + } + + if (Polygon != sel.CollisionPoly) wf.SelectCollisionPoly(Polygon); + wf.SetWidgetPosition(p); + + UpdateGraphics(wf); + } + + private void UpdateGraphics(WorldForm wf) + { + if (Polygon?.Owner != null) + { + wf.UpdateCollisionBoundsGraphics(Polygon.Owner); + } + } + + public override void Undo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, StartPosition); + } + + public override void Redo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, EndPosition); + } + + public override string ToString() + { + return "Collision Poly " + (Polygon?.Index.ToString() ?? "") + ": Position"; + } + } + public class CollisionPolyRotationUndoStep : UndoStep + { + public BoundPolygon Polygon { get; set; } + public Quaternion StartRotation { get; set; } + public Quaternion EndRotation { get; set; } + + public CollisionPolyRotationUndoStep(BoundPolygon poly, Quaternion startrot, WorldForm wf) + { + Polygon = poly; + StartRotation = startrot; + EndRotation = poly?.Orientation ?? Quaternion.Identity; + + UpdateGraphics(wf); + } + + private void Update(WorldForm wf, ref MapSelection sel, Quaternion q) + { + if (Polygon != null) + { + Polygon.Orientation = q; + } + + if (Polygon != sel.CollisionPoly) wf.SelectCollisionPoly(Polygon); + wf.SetWidgetRotation(q); + + UpdateGraphics(wf); + } + + private void UpdateGraphics(WorldForm wf) + { + if (Polygon?.Owner != null) + { + wf.UpdateCollisionBoundsGraphics(Polygon.Owner); + } + } + + public override void Undo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, StartRotation); + } + + public override void Redo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, EndRotation); + } + + public override string ToString() + { + return "Collision Poly " + (Polygon?.Index.ToString() ?? "") + ": Rotation"; + } + } + public class CollisionPolyScaleUndoStep : UndoStep + { + public BoundPolygon Polygon { get; set; } + public Vector3 StartScale { get; set; } + public Vector3 EndScale { get; set; } + + public CollisionPolyScaleUndoStep(BoundPolygon poly, Vector3 startsca, WorldForm wf) + { + Polygon = poly; + StartScale = startsca; + EndScale = poly?.Scale ?? Vector3.One; + + UpdateGraphics(wf); + } + + private void Update(WorldForm wf, ref MapSelection sel, Vector3 s) + { + if (Polygon != null) + { + Polygon.Scale = s; + } + + if (Polygon != sel.CollisionPoly) wf.SelectCollisionPoly(Polygon); + wf.SetWidgetScale(s); + + UpdateGraphics(wf); + } + + private void UpdateGraphics(WorldForm wf) + { + if (Polygon?.Owner != null) + { + wf.UpdateCollisionBoundsGraphics(Polygon.Owner); + } + } + + public override void Undo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, StartScale); + } + + public override void Redo(WorldForm wf, ref MapSelection sel) + { + Update(wf, ref sel, EndScale); + } + + public override string ToString() + { + return "Collision Poly " + (Polygon?.Index.ToString() ?? "") + ": Scale"; + } + } + + + public class PathNodePositionUndoStep : UndoStep { public YndNode PathNode { get; set; } @@ -563,7 +883,6 @@ namespace CodeWalker.Project return "NavPoint " + (Point?.ToString() ?? "") + ": Position"; } } - public class NavPointRotationUndoStep : UndoStep { public YnvPoint Point { get; set; } @@ -781,7 +1100,6 @@ namespace CodeWalker.Project - public class ScenarioNodePositionUndoStep : UndoStep { public ScenarioNode ScenarioNode { get; set; } @@ -831,7 +1149,6 @@ namespace CodeWalker.Project return ScenarioNode.ToString() + ": Position"; } } - public class ScenarioNodeRotationUndoStep : UndoStep { public ScenarioNode ScenarioNode { get; set; } @@ -886,7 +1203,6 @@ namespace CodeWalker.Project - public class AudioPositionUndoStep : UndoStep { public AudioPlacement Audio { get; set; } @@ -923,7 +1239,6 @@ namespace CodeWalker.Project return "Audio " + (Audio?.GetNameString() ?? "") + ": Position"; } } - public class AudioRotationUndoStep : UndoStep { public AudioPlacement Audio { get; set; } diff --git a/Rendering/RenderableCache.cs b/Rendering/RenderableCache.cs index ebe00c8..46a62e6 100644 --- a/Rendering/RenderableCache.cs +++ b/Rendering/RenderableCache.cs @@ -231,19 +231,17 @@ namespace CodeWalker.Rendering + public void Invalidate(Bounds bounds) + { + boundcomps.Invalidate(bounds); + } public void Invalidate(BasePathData path) { - //lock (updateSyncRoot) - { - pathbatches.Invalidate(path); - } + pathbatches.Invalidate(path); } public void Invalidate(YmapGrassInstanceBatch batch) { - //lock (updateSyncRoot) - { - instbatches.Invalidate(batch); - } + instbatches.Invalidate(batch); } diff --git a/Rendering/Renderer.cs b/Rendering/Renderer.cs index fef6f33..9f4c76e 100644 --- a/Rendering/Renderer.cs +++ b/Rendering/Renderer.cs @@ -395,12 +395,14 @@ namespace CodeWalker.Rendering + public void Invalidate(Bounds bounds) + { + renderableCache.Invalidate(bounds); + } public void Invalidate(BasePathData path) { - //used to update path graphics. renderableCache.Invalidate(path); } - public void Invalidate(YmapGrassInstanceBatch batch) { renderableCache.Invalidate(batch); diff --git a/Utils/MapUtils.cs b/Utils/MapUtils.cs index 28eec70..c89687c 100644 --- a/Utils/MapUtils.cs +++ b/Utils/MapUtils.cs @@ -540,6 +540,14 @@ namespace CodeWalker { res = true; } + else if (CollisionPoly != null) + { + res = true; + } + else if (CollisionBounds != null) + { + res = true; + } else if (NavPoint != null) { res = true; @@ -583,6 +591,14 @@ namespace CodeWalker { return CarGenerator.Position; } + else if (CollisionPoly != null) + { + return CollisionPoly.Position; + } + else if (CollisionBounds != null) + { + return CollisionBounds.Center; + } else if (NavPoly != null) { return NavPoly.Position; @@ -630,6 +646,14 @@ namespace CodeWalker { return CarGenerator.Orientation; } + else if (CollisionPoly != null) + { + return Quaternion.Identity; + } + else if (CollisionBounds != null) + { + return Quaternion.Identity; + } else if (NavPoly != null) { return Quaternion.Identity; @@ -677,6 +701,14 @@ namespace CodeWalker { return WidgetAxis.Z; } + else if (CollisionPoly != null) + { + return WidgetAxis.XYZ; + } + else if (CollisionBounds != null) + { + return WidgetAxis.XYZ; + } else if (NavPoly != null) { return WidgetAxis.XYZ; @@ -724,6 +756,14 @@ namespace CodeWalker { return new Vector3(CarGenerator.CCarGen.perpendicularLength); } + else if (CollisionPoly != null) + { + return Vector3.One; + } + else if (CollisionBounds != null) + { + return Vector3.One; + } else if (NavPoly != null) { return Vector3.One; @@ -784,14 +824,17 @@ namespace CodeWalker { PathNode.SetPosition(newpos); } + else if (CollisionPoly != null) + { + CollisionPoly.Position = newpos; + } + else if (CollisionBounds != null) + { + CollisionBounds.Center = newpos; + } else if (NavPoly != null) { NavPoly.SetPosition(newpos); - - //if (projectForm != null) - //{ - // projectForm.OnWorldNavPolyModified(NavPoly); - //} } else if (NavPoint != null) { diff --git a/WorldForm.cs b/WorldForm.cs index 0eb17f2..cf1ba5f 100644 --- a/WorldForm.cs +++ b/WorldForm.cs @@ -1821,6 +1821,29 @@ namespace CodeWalker return space.NodeGrid.GetYndNode(areaid, nodeid); } + public void UpdateCollisionBoundsGraphics(Bounds b) + { + if (b is BoundBVH bvh) + { + bvh.BuildBVH(); + } + else if (b is BoundComposite bc) + { + bc.BuildBVH(); + } + + var ib = b; + while (ib.Parent != null) + { + ib = ib.Parent; + } + + //lock (Renderer.RenderSyncRoot) + { + Renderer.Invalidate(ib); + } + } + public void UpdateNavYnvGraphics(YnvFile ynv, bool fullupdate) { ynv.UpdateAllNodePositions(); @@ -2256,9 +2279,6 @@ namespace CodeWalker if (MouseRayCollision.Hit) { - Matrix rmat = MouseRayCollision.HitBounds?.Transform ?? Matrix.Identity; - rmat.TranslationVector = Vector3.Zero; - var position = MouseRayCollision.HitEntity?.Position ?? Vector3.Zero; var orientation = MouseRayCollision.HitEntity?.Orientation ?? Quaternion.Identity; var scale = MouseRayCollision.HitEntity?.Scale ?? Vector3.One; @@ -2272,7 +2292,7 @@ namespace CodeWalker CurMouseHit.HitDist = MouseRayCollision.HitDist; CurMouseHit.CamRel = camrel + orientation.Multiply(trans); CurMouseHit.BBOffset = trans; - CurMouseHit.BBOrientation = Quaternion.RotationMatrix(rmat); + CurMouseHit.BBOrientation = MouseRayCollision.HitBounds?.Transform.ToQuaternion() ?? Quaternion.Identity; CurMouseHit.AABB = new BoundingBox(MouseRayCollision.HitBounds?.BoundingBoxMin ?? Vector3.Zero, MouseRayCollision.HitBounds?.BoundingBoxMax ?? Vector3.Zero); } } @@ -3511,6 +3531,40 @@ namespace CodeWalker SelectItem(ms); } } + public void SelectCollisionBounds(Bounds b) + { + if (b == null) + { + SelectItem(null); + } + else + { + + MapSelection ms = new MapSelection(); + ms.CollisionBounds = b; + + ms.AABB = new BoundingBox(b.BoundingBoxMin, b.BoundingBoxMax); + + SelectItem(ms); + } + } + public void SelectCollisionPoly(BoundPolygon p) + { + if (p == null) + { + SelectItem(null); + } + else + { + + MapSelection ms = new MapSelection(); + ms.CollisionPoly = p; + + //ms.AABB = new BoundingBox(p.BoundingBoxMin, p.BoundingBoxMax); + + SelectItem(ms); + } + } public void SelectNavPoly(YnvPoly poly) { if (poly == null) @@ -4744,6 +4798,8 @@ namespace CodeWalker if (SelectedItem.MultipleSelection) return true; if (SelectedItem.EntityDef != null) return true; if (SelectedItem.CarGenerator != null) return true; + if (SelectedItem.CollisionBounds != null) return true; + if (SelectedItem.CollisionPoly != null) return true; if (SelectedItem.PathNode != null) return true; //if (SelectedItem.NavPoly != null) return true; if (SelectedItem.NavPoint != null) return true; @@ -4768,6 +4824,8 @@ namespace CodeWalker if (!CanMarkUndo()) return; var ent = SelectedItem.EntityDef; var cargen = SelectedItem.CarGenerator; + var bounds = SelectedItem.CollisionBounds; + var boundpoly = SelectedItem.CollisionPoly; var pathnode = SelectedItem.PathNode; var navpoly = SelectedItem.NavPoly; var navpoint = SelectedItem.NavPoint; @@ -4815,6 +4873,24 @@ namespace CodeWalker case WidgetMode.Scale: s = new CarGenScaleUndoStep(cargen, UndoStartScale); break; } } + else if (boundpoly != null) + { + switch (tw.Mode) + { + case WidgetMode.Position: s = new CollisionPolyPositionUndoStep(boundpoly, UndoStartPosition, this); break; + case WidgetMode.Rotation: s = new CollisionPolyRotationUndoStep(boundpoly, UndoStartRotation, this); break; + case WidgetMode.Scale: s = new CollisionPolyScaleUndoStep(boundpoly, UndoStartScale, this); break; + } + } + else if (bounds != null) + { + switch (tw.Mode) + { + case WidgetMode.Position: s = new CollisionPositionUndoStep(bounds, UndoStartPosition, this); break; + case WidgetMode.Rotation: s = new CollisionRotationUndoStep(bounds, UndoStartRotation, this); break; + case WidgetMode.Scale: s = new CollisionScaleUndoStep(bounds, UndoStartScale, this); break; + } + } else if (pathnode != null) { switch (tw.Mode)