Browse Source

Create world submodel game objects and link them to entities, allowing doors and buttons and such to work properly. Also don't bother linking the view entity to a model.

console
Nico de Poel 5 years ago
parent
commit
0dc5c1a14b
  1. 12
      Assets/Scripts/Game/Entity.cs
  2. 12
      Assets/Scripts/Game/GameAssets.cs
  3. 80
      Assets/Scripts/Game/GameState.cs
  4. 8
      Assets/Scripts/Support/BrushModel.cs
  5. 2
      engine/Quake/cl_main.c
  6. 3
      engine/Quake/cl_parse.c

12
Assets/Scripts/Game/Entity.cs

@ -9,6 +9,7 @@ public class Entity
private SkinnedMeshRenderer meshRenderer;
private AliasModel aliasModel;
private GameObject worldModel;
public Entity(int entityNum)
{
@ -48,6 +49,12 @@ public class Entity
UpdateAnimation(0);
}
public void SetWorldModel(GameObject worldModelGO)
{
worldModel = worldModelGO;
worldModel.transform.SetParent(gameObject.transform);
}
public void UpdateAnimation(float frameNum)
{
if (aliasModel != null)
@ -58,6 +65,11 @@ public class Entity
if (mesh != null && mesh.blendShapeCount > 0)
meshRenderer.SetBlendShapeWeight(0, blendWeight);
}
if (worldModel != null)
{
// TODO: update texture animation
}
}
public void SetTransform(Vector3 position, Quaternion rotation)

12
Assets/Scripts/Game/GameAssets.cs

@ -71,6 +71,18 @@ public class GameAssets
worldModel = brushModel;
}
public bool TryGetWorldSubModel(int subModelIndex, out BrushModel.SubModel subModel)
{
if (worldModel == null || subModelIndex < 0 || subModelIndex >= worldModel.SubModelCount)
{
subModel = null;
return false;
}
subModel = worldModel.GetSubModel(subModelIndex);
return true;
}
public void Destroy()
{
if (worldModel != null)

80
Assets/Scripts/Game/GameState.cs

@ -26,38 +26,43 @@ public class GameState
{
Destroy();
// DEBUG - we'll want to instantiate prefabs for each submodel and assign materials from a preset collection
worldGameObject = new GameObject(worldModel.Name);
//for (int i = 0; i < worldModel.SubModelCount; ++i)
for (int i = 0; i < 1; ++i)
// The first sub-model contains all of the static geometry
var subModel = worldModel.GetSubModel(0);
var subModelGO = CreateWorldGameObject(subModel);
subModelGO.transform.SetParent(worldGameObject.transform);
}
private GameObject CreateWorldGameObject(BrushModel.SubModel subModel)
{
var subModelGO = new GameObject(subModel.Name);
// DEBUG - we'll want to instantiate prefabs for each sub-model and assign materials from a preset collection
foreach (var surfaceMesh in subModel.SurfaceMeshes)
{
var subModel = worldModel.GetSubModel(i);
var subModelGO = new GameObject($"SubModel_{i}");
subModelGO.transform.SetParent(worldGameObject.transform);
var meshGO = new GameObject(surfaceMesh.Mesh.name);
meshGO.transform.SetParent(subModelGO.transform);
foreach (var surfaceMesh in subModel.SurfaceMeshes)
var mf = meshGO.AddComponent<MeshFilter>();
mf.sharedMesh = surfaceMesh.Mesh;
var material = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
uint texNum = surfaceMesh.Texture.TextureNum;
if (uq.GameAssets.TryGetTexture(texNum, out var texture))
{
var meshGO = new GameObject(surfaceMesh.Mesh.name);
meshGO.transform.SetParent(subModelGO.transform);
var mf = meshGO.AddComponent<MeshFilter>();
mf.sharedMesh = surfaceMesh.Mesh;
var material = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
uint texNum = surfaceMesh.Texture.TextureNum;
if (uq.GameAssets.TryGetTexture(texNum, out var texture))
{
material.mainTexture = texture;
}
var mr = meshGO.AddComponent<MeshRenderer>();
mr.sharedMaterial = material;
mr.shadowCastingMode = ShadowCastingMode.Off;
mr.receiveShadows = false;
mr.lightProbeUsage = LightProbeUsage.Off;
mr.reflectionProbeUsage = ReflectionProbeUsage.Off;
material.mainTexture = texture;
}
var mr = meshGO.AddComponent<MeshRenderer>();
mr.sharedMaterial = material;
mr.shadowCastingMode = ShadowCastingMode.Off;
mr.receiveShadows = false;
mr.lightProbeUsage = LightProbeUsage.Off;
mr.reflectionProbeUsage = ReflectionProbeUsage.Off;
}
return subModelGO;
}
private void DestroyWorld()
@ -75,7 +80,7 @@ public class GameState
return entity;
}
public void SetEntityAliasModel(int entityNum, string modelName)
private Entity GetOrCreateEntity(int entityNum)
{
if (!entities.TryGetValue(entityNum, out var entity))
{
@ -83,6 +88,13 @@ public class GameState
entities.Add(entityNum, entity);
}
return entity;
}
public void SetEntityAliasModel(int entityNum, string modelName)
{
var entity = GetOrCreateEntity(entityNum);
if (!uq.GameAssets.TryGetAliasModel(modelName, out var aliasModel))
{
Debug.LogWarning($"Unknown alias model name: {modelName}");
@ -94,7 +106,19 @@ public class GameState
public void SetEntityWorldModel(int entityNum, int subModelNum)
{
// TODO: obtain Mesh from brush submodel and assign it to MeshRenderer
var entity = GetOrCreateEntity(entityNum);
if (!uq.GameAssets.TryGetWorldSubModel(subModelNum, out var subModel))
{
Debug.LogWarning($"Invalid world sub-model number: {subModelNum}");
return;
}
// TODO: these relatively complex world game objects are going to get destroyed and re-created all the time
// as the player moves through the map and moves in and out of range of these entities. This can and should
// be done more efficiently by creating the game objects only once and enabling/disabling them on demand.
var worldModelGO = CreateWorldGameObject(subModel);
entity.SetWorldModel(worldModelGO);
}
public void RemoveEntity(int entityNum)

8
Assets/Scripts/Support/BrushModel.cs

@ -35,7 +35,7 @@ public class BrushModel
for (int modelIdx = 0; modelIdx < inSubModels.Length; ++modelIdx)
{
var subModel = new SubModel();
var subModel = new SubModel($"SubModel_{modelIdx}");
subModels.Add(subModel);
// Traverse the BSP tree and group the surfaces based on their material properties
@ -134,8 +134,14 @@ public class BrushModel
public class SubModel
{
public string Name { get; private set; }
public List<SurfaceMesh> SurfaceMeshes { get; } = new List<SurfaceMesh>();
public SubModel(string name)
{
Name = name;
}
public void AddSurfaceMesh(SurfaceMesh surfaceMesh)
{
SurfaceMeshes.Add(surfaceMesh);

2
engine/Quake/cl_main.c

@ -588,7 +588,7 @@ void CL_RelinkEntities (void)
cl_numvisedicts++;
}
//UQ_Game_SetEntityTransform(i, ent->origin, ent->angles);
UQ_Game_SetEntityTransform(i, ent->origin, ent->angles);
}
}

3
engine/Quake/cl_parse.c

@ -618,7 +618,8 @@ void CL_ParseUpdate (int bits)
ent->lerpflags |= LERP_RESETANIM; //johnfitz -- don't lerp animation across model changes
UQ_Game_SetEntityModel(num, model ? model->name : NULL);
if (num != cl.viewentity)
UQ_Game_SetEntityModel(num, model ? model->name : NULL);
}
//johnfitz

Loading…
Cancel
Save