Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial implementation of zCVobAnimate #329

Merged
merged 8 commits into from
Mar 30, 2024
10 changes: 9 additions & 1 deletion Assets/GothicVR/Scripts/Caches/AssetCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,15 @@ public static IMorphMesh TryGetMmb(string key)
if (MmbCache.TryGetValue(preparedKey, out var data))
return data;

var newData = new MorphMesh(GameData.Vfs, $"{preparedKey}.mmb").Cache();
IMorphMesh newData = null;
try
JaXt0r marked this conversation as resolved.
Show resolved Hide resolved
{
newData = new MorphMesh(GameData.Vfs, $"{preparedKey}.mmb").Cache();
}
catch (Exception)
{
// ignored
}
MmbCache[preparedKey] = newData;

return newData;
Expand Down
8 changes: 6 additions & 2 deletions Assets/GothicVR/Scripts/Caches/MorphMeshCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,16 @@ public static void AddVertexMapping(string morphMeshName, int arraySize)

public static void AddVertexMappingEntry(string preparedMorphMeshName, int originalVertexIndex, int additionalUnityVertexIndex)
{
HeadVertexMapping[preparedMorphMeshName][originalVertexIndex].Add(additionalUnityVertexIndex);
var preparedKey = GetPreparedKey(preparedMorphMeshName);

HeadVertexMapping[preparedKey][originalVertexIndex].Add(additionalUnityVertexIndex);
}

public static void SetUnityVerticesForVertexMapping(string preparedMorphMeshName, Vector3[] unityVertices)
{
UnityVertices.Add(preparedMorphMeshName, unityVertices);
var preparedKey = GetPreparedKey(preparedMorphMeshName);

UnityVertices.Add(preparedKey, unityVertices);
}

public static Vector3[] GetOriginalUnityVertices(string morphMeshName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public abstract class AbstractMeshBuilder

protected Vector3 RootPosition;
protected Quaternion RootRotation;

protected bool isMorphMeshMappingAlreadyCached;


public abstract GameObject Build();
Expand Down Expand Up @@ -102,6 +104,11 @@ public void SetMrm(IMultiResolutionMesh mrm)
this.Mrm = mrm;
}

public void SetMmb(IMorphMesh mmb)
{
this.Mmb = mmb;
}

public void SetMrm(string mrmName)
{
Mrm = AssetCache.TryGetMrm(mrmName);
Expand Down Expand Up @@ -268,6 +275,19 @@ protected GameObject BuildViaMdmAndMdh()
return RootGo;
}

protected GameObject BuildViaMmb()
{
var meshFilter = RootGo.AddComponent<MeshFilter>();
var meshRenderer = RootGo.AddComponent<MeshRenderer>();

PrepareMeshFilter(meshFilter, Mmb.Mesh, meshRenderer, true, Mmb.Name);
PrepareMeshRenderer(meshRenderer, Mmb.Mesh);

SetPosAndRot(RootGo, RootPosition, RootRotation);

return RootGo;
}

protected void PrepareMeshRenderer(Renderer rend, IMultiResolutionMesh mrmData)
{
if (null == mrmData)
Expand Down Expand Up @@ -328,7 +348,7 @@ protected void PrepareMeshFilter(MeshFilter meshFilter, IMultiResolutionMesh mrm
return;
}

CreateMorphMeshBegin(mrmData, mesh);
CreateMorphMeshBegin(mrmData, mesh, morphMeshName);

int triangleCount = mrmData.SubMeshes.Sum(i => i.Triangles.Count);
int vertexCount = triangleCount * 3;
Expand Down Expand Up @@ -379,7 +399,7 @@ protected void PrepareMeshFilter(MeshFilter meshFilter, IMultiResolutionMesh mrm
Vector2 uv = Vector2.Scale(textureScale, wedges[w].Texture.ToUnityVector());
preparedUVs.Add(new Vector4(uv.x, uv.y, textureArrayIndex, maxMipLevel));

CreateMorphMeshEntry(wedges[w].Index, preparedVertices.Count);
CreateMorphMeshEntry(wedges[w].Index, preparedVertices.Count, morphMeshName);
}
}
}
Expand All @@ -397,7 +417,7 @@ protected void PrepareMeshFilter(MeshFilter meshFilter, IMultiResolutionMesh mrm
mesh.SetTriangles(preparedTriangles[i], i);
}

CreateMorphMeshEnd(preparedVertices);
CreateMorphMeshEnd(preparedVertices, morphMeshName);

if (UseTextureArray)
{
Expand Down Expand Up @@ -558,19 +578,39 @@ protected void PrepareMeshCollider(GameObject obj, Mesh mesh, List<IMaterial> ma
}
}

protected virtual void CreateMorphMeshBegin(IMultiResolutionMesh mrm, Mesh mesh)
protected void CreateMorphMeshBegin(IMultiResolutionMesh mrm, Mesh mesh, string morphMeshName)
{
// NOP
// MorphMeshes will change the vertices. This call optimizes performance.
mesh.MarkDynamic();

isMorphMeshMappingAlreadyCached = MorphMeshCache.IsMappingAlreadyCached(morphMeshName);
if (isMorphMeshMappingAlreadyCached)
{
return;
}

MorphMeshCache.AddVertexMapping(morphMeshName, mrm.PositionCount);
}

protected virtual void CreateMorphMeshEntry(int index1, int preparedVerticesCount)
protected void CreateMorphMeshEntry(int index1, int preparedVerticesCount, string morphMeshName)
{
// NOP
// We add mapping data to later reuse for IMorphAnimation samples
if (isMorphMeshMappingAlreadyCached)
{
return;
}

MorphMeshCache.AddVertexMappingEntry(morphMeshName, index1, preparedVerticesCount - 1);
}

protected virtual void CreateMorphMeshEnd(List<Vector3> preparedVertices)
protected void CreateMorphMeshEnd(List<Vector3> preparedVertices, string morphMeshName)
{
// NOP
if (isMorphMeshMappingAlreadyCached)
{
return;
}

MorphMeshCache.SetUnityVerticesForVertexMapping(morphMeshName, preparedVertices.ToArray());
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ namespace GVR.Creator.Meshes.V2.Builder
{
public class NpcHeadMeshBuilder : NpcMeshBuilder
{
private bool isMorphMeshMappingAlreadyCached;
private string headName;

public override void SetBodyData(VmGothicExternals.ExtSetVisualBodyData body)
Expand Down Expand Up @@ -55,7 +54,7 @@ private void BuildHead()

var headMeshFilter = headGo.AddComponent<MeshFilter>();
var headMeshRenderer = headGo.AddComponent<MeshRenderer>();
PrepareMeshFilter(headMeshFilter, morphMesh.Mesh, headMeshRenderer);
PrepareMeshFilter(headMeshFilter, morphMesh.Mesh, headMeshRenderer, true, headName);
PrepareMeshRenderer(headMeshRenderer, morphMesh.Mesh);
}

Expand Down Expand Up @@ -84,40 +83,5 @@ protected override Texture2D GetTexture(string name)

return base.GetTexture(finalTextureName);
}

protected override void CreateMorphMeshBegin(IMultiResolutionMesh mrm, Mesh mesh)
{
// MorphMeshes will change the vertices. This call optimizes performance.
mesh.MarkDynamic();

isMorphMeshMappingAlreadyCached = MorphMeshCache.IsMappingAlreadyCached(headName);
if (isMorphMeshMappingAlreadyCached)
{
return;
}

MorphMeshCache.AddVertexMapping(headName, mrm.PositionCount);
}

protected override void CreateMorphMeshEntry(int index1, int preparedVerticesCount)
{
// We add mapping data to later reuse for IMorphAnimation samples
if (isMorphMeshMappingAlreadyCached)
{
return;
}

MorphMeshCache.AddVertexMappingEntry(headName, index1, preparedVerticesCount - 1);
}

protected override void CreateMorphMeshEnd(List<Vector3> preparedVertices)
{
if (isMorphMeshMappingAlreadyCached)
{
return;
}

MorphMeshCache.SetUnityVerticesForVertexMapping(headName, preparedVertices.ToArray());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public override GameObject Build()
BuildViaMdmAndMdh();
}
}
else if (Mmb != null)
{
BuildViaMmb();
}
else
{
Debug.LogError($"No suitable data for Vob to be created found >{RootGo.name}<");
Expand Down
13 changes: 13 additions & 0 deletions Assets/GothicVR/Scripts/Creator/Meshes/V2/MeshFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ public static GameObject CreateVob(string objectName, IModel mdl, Vector3 positi

return vobBuilder.Build();
}

public static GameObject CreateVob(string objectName, IMorphMesh mmb, Vector3 position, Quaternion rotation,
GameObject parent = null, GameObject rootGo = null)
{
var vobBuilder = new VobMeshBuilder();
vobBuilder.SetRootPosAndRot(position, rotation);
vobBuilder.SetGameObject(rootGo, objectName);
vobBuilder.SetParent(parent);
vobBuilder.SetMmb(mmb);
vobBuilder.SetUseTextureArray(true);

return vobBuilder.Build();
}

public static GameObject CreateVob(string objectName, IModelMesh mdm, IModelHierarchy mdh,
Vector3 position, Quaternion rotation, GameObject parent = null, GameObject rootGo = null)
Expand Down
35 changes: 33 additions & 2 deletions Assets/GothicVR/Scripts/Creator/VobCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using GVR.GothicVR.Scripts.Manager;
using GVR.Manager;
using GVR.Manager.Culling;
using GVR.Npc;
using GVR.Properties;
using GVR.Vob;
using GVR.Vob.WayNet;
Expand Down Expand Up @@ -41,7 +42,8 @@ public static class VobCreator
VirtualObjectType.oCZoneMusic,
VirtualObjectType.oCZoneMusicDefault,
VirtualObjectType.zCVobSound,
VirtualObjectType.zCVobSoundDaytime
VirtualObjectType.zCVobSoundDaytime,
VirtualObjectType.zCVobAnimate
};

private static int _totalVObs;
Expand Down Expand Up @@ -233,8 +235,13 @@ private static GameObject LoadVob(IVirtualObject vob, GameObject parent = null)
_cullingVobObjects.Add(go);
break;
}
case VirtualObjectType.zCVobScreenFX:
case VirtualObjectType.zCVobAnimate:
{
go = CreateAnimatedVob((Animate)vob, parent);
_cullingVobObjects.Add(go);
break;
}
case VirtualObjectType.zCVobScreenFX:
case VirtualObjectType.zCTriggerWorldStart:
case VirtualObjectType.zCTriggerList:
case VirtualObjectType.oCCSTrigger:
Expand Down Expand Up @@ -958,6 +965,14 @@ private static GameObject CreatePfx(IVirtualObject vob, GameObject parent = null

return pfxGo;
}

private static GameObject CreateAnimatedVob(Animate vob, GameObject parent = null)
{
var go = CreateDefaultMesh(vob, parent, true);
var headmorph = go.AddComponent<HeadMorph>();
headmorph.StartAnimation(vob.Visual.Name);
return go;
}

private static GameObject CreateDefaultMesh(IVirtualObject vob, GameObject parent = null, bool nonTeleport = false)
{
Expand Down Expand Up @@ -996,6 +1011,22 @@ private static GameObject CreateDefaultMesh(IVirtualObject vob, GameObject paren

return ret;
}

// MMB
var mmb = AssetCache.TryGetMmb(meshName);
if (mmb != null)
{
var ret = MeshFactory.CreateVob(meshName, mmb, vob.Position.ToUnityVector(),
vob.Rotation.ToUnityQuaternion(), parent ?? parentGo, go);

// this is a dynamic object

// A few objects are broken and have no meshes. We need to destroy them immediately again.
if (ret == null)
GameObject.Destroy(go);

return ret;
}

// MRM
var mrm = AssetCache.TryGetMrm(meshName);
Expand Down
8 changes: 8 additions & 0 deletions Assets/GothicVR/Scripts/Npc/HeadMorph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ public void StartAnimation(string headName, HeadMorphType type)
morphAnimationMetadata = morphMetadata.Animations.First(anim => anim.Name.EqualsIgnoreCase(animationName));
morphFrameData = MorphMeshCache.TryGetHeadMorphData(headName, animationName);

isAnimationRunning = true;
}
public void StartAnimation(string headName)
{
morphMetadata = AssetCache.TryGetMmb(headName);
morphAnimationMetadata = morphMetadata.Animations.First();
morphFrameData = MorphMeshCache.TryGetHeadMorphData(headName, morphAnimationMetadata.Name);

isAnimationRunning = true;
}

Expand Down