diff --git a/Mafia2Libs/Forms/MapEditor.cs b/Mafia2Libs/Forms/MapEditor.cs index 5aa7e2a4..922d95c4 100644 --- a/Mafia2Libs/Forms/MapEditor.cs +++ b/Mafia2Libs/Forms/MapEditor.cs @@ -1104,11 +1104,15 @@ private void BuildRenderObjects() if (groupRef != null && hasMesh) { - for (int i = 0; i < groupRef.Children.Count; i++) + for (int i = 0; i < groupRef.Children.Count; i++)//i dont think this for cycle is needed really if done right { InstanceTranslokatorPart(assets, groupRef.Children[i], Matrix4x4.Identity, instance); } } + else + { + Graphics.InstanceGizmo.InstanceTranslokator(instance); + } TreeNode instanceNode = new TreeNode(obj.Name + " " + x); instanceNode.Tag = instance; @@ -1431,6 +1435,10 @@ private void ApplyEntryChanges(object sender, EventArgs e) Graphics.UpdateInstanceBuffers(modelsToUpdate); } } + else + { + Graphics.InstanceGizmo.UpdateInstanceBuffer(instance, Graphics.GetId3D11Device()); + } } } } @@ -1598,7 +1606,7 @@ private void Pick(int sx, int sy) { dSceneTree.SelectedNode = nodes[0]; - if (dSceneTree.SelectedNode.Tag is FrameObjectBase obj)//dostat se na instance, ne na ref frame, od toho je jump, když na nějakej instance šáhnu, abych v tree viděl jakej to přesně je + if (dSceneTree.SelectedNode.Tag is FrameObjectBase obj) { int Parent1Index = obj.ParentIndex1.Index; int Parent2Index = obj.ParentIndex2.Index; @@ -1838,6 +1846,10 @@ private void OnPropertyValueChanged(object s, PropertyValueChangedEventArgs e) Graphics.UpdateInstanceBuffers(modelsToUpdate); } } + else + { + Graphics.InstanceGizmo.UpdateInstanceBuffer(instance, Graphics.GetId3D11Device()); + } } pGrid.Refresh(); @@ -2671,13 +2683,17 @@ private void TranslokatorNewInstance(TreeNode parentObj, Instance old) Object parent = parentObj.Tag as Object; FrameObjectBase frameref = SceneData.FrameResource.GetObjectByHash(parent.Name.Hash); - if (frameref != null && frameref.HasMeshObject())//todo nonframerefs solution once they are managed + if (frameref != null && frameref.HasMeshObject()) { for (int i = 0; i < frameref.Children.Count; i++) { InstanceTranslokatorPart(Graphics.Assets, frameref.Children[i], Matrix4x4.Identity, newInstance,true); } } + else + { + Graphics.InstanceGizmo.InstanceTranslokator(newInstance,Graphics.GetId3D11Device()); + } dSceneTree.AddToTree(newInstanceNode,parentObj); } @@ -2685,10 +2701,6 @@ private void TranslokatorNewInstance(TreeNode parentObj, Instance old) private void UpdateInstanceVisualisation(TreeNode instanceNode, Object trObject, bool visibility) { FrameObjectBase groupRef = SceneData.FrameResource.GetObjectByHash(trObject.Name.Hash); - if (groupRef == null)//todo: once placeholder is implemented, reword this to work with it - { - return; - } Instance instance = instanceNode.Tag as Instance; if (visibility) @@ -2700,10 +2712,21 @@ private void UpdateInstanceVisualisation(TreeNode instanceNode, Object trObject, InstanceTranslokatorPart(Graphics.Assets, groupRef.Children[i], Matrix4x4.Identity, instance,true); } } + else + { + Graphics.InstanceGizmo.InstanceTranslokator(instance,Graphics.GetId3D11Device()); + } } else { - Graphics.DeleteInstance(groupRef,instance.RefID); + if (groupRef != null && groupRef.HasMeshObject()) + { + Graphics.DeleteInstance(groupRef,instance.RefID); + } + else + { + Graphics.DeleteInstance(instance.RefID); + } } } @@ -2757,12 +2780,14 @@ private void DeleteTRInstance(TreeNode instanceNode) Instance instance = instanceNode.Tag as Instance; FrameObjectBase groupRef = SceneData.FrameResource.GetObjectByHash((instanceNode.Parent.Tag as Object).Name.Hash); dSceneTree.RemoveNode(instanceNode); - if (groupRef == null)//todo: once placeholder is implemented, reword this to work with it + if (groupRef != null) { - return; + Graphics.DeleteInstance(groupRef, instance.RefID); + } + else + { + Graphics.DeleteInstance(instance.RefID); } - - Graphics.DeleteInstance(groupRef, instance.RefID); } private void DeleteTRObject(TreeNode objectNode) diff --git a/Mafia2Libs/MafiaToolkit.csproj b/Mafia2Libs/MafiaToolkit.csproj index df960204..61cca918 100644 --- a/Mafia2Libs/MafiaToolkit.csproj +++ b/Mafia2Libs/MafiaToolkit.csproj @@ -85,6 +85,12 @@ + + Always + + + Always + diff --git a/Mafia2Libs/Rendering/Core/InstanceGizmo.cs b/Mafia2Libs/Rendering/Core/InstanceGizmo.cs new file mode 100644 index 00000000..24ee8317 --- /dev/null +++ b/Mafia2Libs/Rendering/Core/InstanceGizmo.cs @@ -0,0 +1,114 @@ +using Rendering.Graphics; +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using ResourceTypes.Translokator; +using Utils.Logging; +using Utils.VorticeUtils; +using Vortice.Direct3D; +using Vortice.Direct3D11; +using Vortice.Mathematics; + +namespace Rendering.Core +{ + public class InstanceGizmo + { + + // Variable for rendering + public RenderModel InstanceModel; + + public InstanceGizmo(RenderModel InModel) + { + InstanceModel = InModel; + } + + public void InitBuffers(ID3D11Device d3d, ID3D11DeviceContext d3dContext) + { + InstanceModel.InitBuffers(d3d, d3dContext);//texture should be loaded either differently or rendersingleton should precache it + InstanceModel.AOTexture = LoadTexture(d3d, d3dContext); + } + + public ID3D11ShaderResourceView LoadTexture(ID3D11Device d3d, ID3D11DeviceContext d3dContext) + { + try + { + ID3D11Resource ddsResource; + ID3D11ShaderResourceView _temp; + DDSTextureLoader.DDS_ALPHA_MODE mode; + DDSTextureLoader.CreateDDSTextureFromFile(d3d, d3dContext, "Resources/Translokator_Texture.dds", out ddsResource, out _temp, 4096, out mode); + return _temp; + } + catch + { + Log.WriteLine(string.Format("Failed to load file: {0}", "Resources/Translokator_Texture.dds"), LoggingTypes.FATAL, LogCategoryTypes.IO); + return null; + } + } + + public void UpdateInstanceBuffer(Instance instance, ID3D11Device d3d) + { + Matrix4x4 newtransform = MatrixUtils.SetMatrix(instance.Quaternion, new Vector3(0.015f,0.015f,0.015f), instance.Position); + + if (!InstanceModel.InstanceTransforms.ContainsKey(instance.RefID)) + { + InstanceModel.InstanceTransforms.Add(instance.RefID, Matrix4x4.Transpose(newtransform)); + } + else + { + InstanceModel.InstanceTransforms[instance.RefID] = Matrix4x4.Transpose(newtransform); + } + + InstanceModel.ReloadInstanceBuffer(d3d); + } + + public void UpdateBuffers(ID3D11Device d3d, ID3D11DeviceContext d3dContext) + { + InstanceModel.UpdateBuffers(d3d, d3dContext); + } + + public void Render(ID3D11Device d3d, ID3D11DeviceContext d3dContext, Camera camera)//render only instances + { + if (InstanceModel.InstanceTransforms.Count > 0) + { + VertexBufferView VertexBufferView = new VertexBufferView(InstanceModel.GetVB(), Unsafe.SizeOf(), 0);//polish so getib/vb doesnt have to be used + d3dContext.IASetVertexBuffers(0, VertexBufferView); + d3dContext.IASetIndexBuffer(InstanceModel.GetIB(), Vortice.DXGI.Format.R32_UInt, 0); + d3dContext.IASetPrimitiveTopology(PrimitiveTopology.TriangleList); + d3dContext.PSSetShaderResource(2, InstanceModel.AOTexture); + + InstanceModel.RenderInstances(d3dContext, camera, d3d); + } + } + + public void InstanceTranslokator(Instance instance,ID3D11Device device = null) + { + Matrix4x4 newtransform = new Matrix4x4(); + + newtransform = MatrixUtils.SetMatrix(instance.Quaternion, new Vector3(0.015f,0.015f,0.015f), instance.Position);//fbx to m2t enlarged the mesh so, beware gltf + + if (!InstanceModel.InstanceTransforms.ContainsKey(instance.RefID)) + { + InstanceModel.InstanceTransforms.Add(instance.RefID, Matrix4x4.Transpose(newtransform)); + if (device!=null) + { + InstanceModel.ReloadInstanceBuffer(device); + } + } + } + + public void Select(int InstanceId) + { + InstanceModel.SelectInstance(InstanceId); + } + + public void Unselect() + { + InstanceModel.UnselectInstance(); + } + + public void Shutdown() + { + InstanceModel.Shutdown(); + } + } +} diff --git a/Mafia2Libs/Rendering/Graphics/GraphicsClass.cs b/Mafia2Libs/Rendering/Graphics/GraphicsClass.cs index e00a75bf..88fd653c 100644 --- a/Mafia2Libs/Rendering/Graphics/GraphicsClass.cs +++ b/Mafia2Libs/Rendering/Graphics/GraphicsClass.cs @@ -46,6 +46,7 @@ public class GraphicsClass private RenderModel sky; private RenderModel clouds; private GizmoTool TranslationGizmo; + public InstanceGizmo InstanceGizmo; private DirectX11Class D3D; @@ -119,6 +120,13 @@ public bool PreInit(IntPtr WindowHandle) clouds.ConvertMTKToRenderModel(structure); clouds.InitBuffers(D3D.Device, D3D.DeviceContext); clouds.DoRender = false; + + RenderModel instancePlaceholder = new RenderModel(); + structure = new M2TStructure(); + structure.ReadFromM2T("Resources/Translokator.m2t"); + instancePlaceholder.ConvertMTKToRenderModel(structure); + instancePlaceholder.InitBuffers(D3D.Device,D3D.DeviceContext); + InstanceGizmo = new InstanceGizmo(instancePlaceholder); } selectionBox.SetColour(System.Drawing.Color.Red); @@ -140,6 +148,14 @@ public bool InitScene(int width, int height) sky.InitBuffers(D3D.Device, D3D.DeviceContext); sky.DoRender = WorldSettings.RenderSky; clouds.InitBuffers(D3D.Device, D3D.DeviceContext); + InstanceGizmo.InitBuffers(D3D.Device, D3D.DeviceContext); + var task = InstanceGizmo.InstanceModel.GetBVHBuildingTask(); // Maybe this function should be added to the IRenderer class instead? probably + + if (task != null) + { + BVHBuildingTasks.Add(task); + } + Input = new InputClass(); Input.Init(); return true; @@ -283,6 +299,31 @@ public PickOutParams Pick(int sx, int sy, int Width, int Height) index++; } + + foreach (var transform in InstanceGizmo.InstanceModel.InstanceTransforms) + { + var transposed = Matrix4x4.Transpose(transform.Value); + + Matrix4x4 tvWM = Matrix4x4.Identity; + Matrix4x4.Invert(transposed, out tvWM); + var localInstanceRay = new Ray( + Vector3Utils.TransformCoordinate(ray.Position, tvWM), + Vector3.TransformNormal(ray.Direction, tvWM) + ); + + if (localInstanceRay.Intersects(InstanceGizmo.InstanceModel.BoundingBox) == 0.0f) continue; + + var bvhInstanceIntersect = InstanceGizmo.InstanceModel.BVH.Intersect(localInstanceRay); + + if (bvhInstanceIntersect.distance < lowest) + { + lowest = bvhInstanceIntersect.distance; + lowestRefID = -2; + lowestInstanceID = transform.Key; + WorldPosIntersect = bvhInstanceIntersect.pos; + } + } + PickOutParams OutputParams = new PickOutParams(); OutputParams.LowestRefID = lowestRefID; @@ -398,6 +439,9 @@ public bool Render() sky.DoRender = WorldSettings.RenderSky; sky.UpdateBuffers(D3D.Device, D3D.DeviceContext); sky.Render(D3D.Device, D3D.DeviceContext, Camera); + InstanceGizmo.UpdateBuffers(D3D.Device, D3D.DeviceContext); + InstanceGizmo.Render(D3D.Device, D3D.DeviceContext, Camera); + D3D.EndScene(); return true; @@ -462,6 +506,7 @@ public void SelectEntry(int id) } selectedInstances.Clear(); } + InstanceGizmo.Unselect(); TranslationGizmo.OnSelectEntry(NewObject.Transform, true); NewObject.Select(); @@ -489,6 +534,7 @@ public void SelectInstance(int instanceId) } selectedInstances.Clear(); } + InstanceGizmo.Unselect(); selectedInstances = new Dictionary(); @@ -507,6 +553,11 @@ public void SelectInstance(int instanceId) RenderModel model = Assets[selectedInstances.First().Key] as RenderModel; TranslationGizmo.OnSelectEntry(Matrix4x4.Transpose(model.InstanceTransforms[selectedInstances.First().Value]) , true); } + else + { + InstanceGizmo.Select(instanceId); + TranslationGizmo.OnSelectEntry(Matrix4x4.Transpose(InstanceGizmo.InstanceModel.InstanceTransforms[instanceId]) , true); + } } public IRenderer GetAsset(int RefID) @@ -610,6 +661,7 @@ public void Shutdown() D3D?.Shutdown(); D3D = null; selectedInstances = null; + InstanceGizmo.Shutdown(); } @@ -668,5 +720,9 @@ public void DeleteInstance(FrameObjectBase frame,int InstanceRefID) } } } + public void DeleteInstance(int InstanceRefID) + { + InstanceGizmo.InstanceModel.RemoveInstance(InstanceRefID,D3D.Device); + } } } \ No newline at end of file diff --git a/Mafia2Libs/Rendering/Graphics/RenderTypes/RenderModel.cs b/Mafia2Libs/Rendering/Graphics/RenderTypes/RenderModel.cs index 3b6cee69..181bbf4a 100644 --- a/Mafia2Libs/Rendering/Graphics/RenderTypes/RenderModel.cs +++ b/Mafia2Libs/Rendering/Graphics/RenderTypes/RenderModel.cs @@ -407,7 +407,7 @@ public override void Render(ID3D11Device device, ID3D11DeviceContext deviceConte private float colorTransitionTime = 0.0f; // timer for distinguishing translokators - private void RenderInstances(ID3D11DeviceContext deviceContext, Camera camera, ID3D11Device device) + public void RenderInstances(ID3D11DeviceContext deviceContext, Camera camera, ID3D11Device device) { deviceContext.VSSetShaderResource(0, instanceBufferView); @@ -544,5 +544,14 @@ public void RemoveInstance(int instanceRefId,ID3D11Device d3d) ReloadInstanceBuffer(d3d); } } + + public ID3D11Buffer GetVB() + { + return vertexBuffer; + } + public ID3D11Buffer GetIB() + { + return indexBuffer; + } } } diff --git a/Mafia2Libs/Resources/Translokator.m2t b/Mafia2Libs/Resources/Translokator.m2t new file mode 100644 index 00000000..83b51c1d Binary files /dev/null and b/Mafia2Libs/Resources/Translokator.m2t differ diff --git a/Mafia2Libs/Resources/Translokator_Texture.dds b/Mafia2Libs/Resources/Translokator_Texture.dds new file mode 100644 index 00000000..dce83b8b Binary files /dev/null and b/Mafia2Libs/Resources/Translokator_Texture.dds differ