Skip to content

Commit

Permalink
Support first version of Hatch model format
Browse files Browse the repository at this point in the history
  • Loading branch information
Lactozilla committed Mar 13, 2024
1 parent 44d092a commit 20e562d
Show file tree
Hide file tree
Showing 15 changed files with 1,215 additions and 121 deletions.
3 changes: 3 additions & 0 deletions VisualC/HatchGameEngine.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,10 @@ CD ..</Command>
<ClCompile Include="..\source\engine\resourcetypes\IModel.cpp" />
<ClCompile Include="..\source\engine\resourcetypes\ISound.cpp" />
<ClCompile Include="..\source\engine\resourcetypes\ISprite.cpp" />
<ClCompile Include="..\source\engine\resourcetypes\modelformats\HatchModel.cpp" />
<ClCompile Include="..\source\engine\resourcetypes\modelformats\Importer.cpp" />
<ClCompile Include="..\source\engine\resourcetypes\modelformats\MD3Model.cpp" />
<ClCompile Include="..\source\engine\resourcetypes\modelformats\RSDKModel.cpp" />
<ClCompile Include="..\source\engine\resourcetypes\ResourceManager.cpp" />
<ClCompile Include="..\source\Engine\ResourceTypes\SceneFormats\HatchSceneReader.cpp" />
<ClCompile Include="..\source\engine\resourcetypes\sceneformats\RSDKSceneReader.cpp" />
Expand Down
9 changes: 9 additions & 0 deletions VisualC/HatchGameEngine.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,18 @@
<ClCompile Include="..\source\engine\resourcetypes\ISprite.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\source\engine\resourcetypes\modelformats\HatchModel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\source\engine\resourcetypes\modelformats\Importer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\source\engine\resourcetypes\modelformats\MD3Model.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\source\engine\resourcetypes\modelformats\RSDKModel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\source\engine\resourcetypes\ResourceManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
Expand Down
4 changes: 2 additions & 2 deletions source/Engine/Bytecode/StandardLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7363,15 +7363,15 @@ VMValue Model_GetAnimationIndex(int argCount, VMValue* args, Uint32 threadID) {
}
/***
* Model.GetFrameCount
* \desc Returns how many frames exist in the model.
* \desc Returns how many frames exist in the model. (Deprecated; use <linkto ref="Model.GetAnimationLength"></linkto> instead.)
* \param model (Integer): The model index to check.
* \return The frame count. Will always return <code>0</code> for skeletal-animated models.
* \ns Model
*/
VMValue Model_GetFrameCount(int argCount, VMValue* args, Uint32 threadID) {
CHECK_ARGCOUNT(1);
IModel* model = GET_ARG(0, GetModel);
return INTEGER_VAL((int)model->FrameCount);
return INTEGER_VAL((int)model->Meshes[0]->FrameCount);
}
/***
* Model.GetAnimationLength
Expand Down
8 changes: 4 additions & 4 deletions source/Engine/Rendering/FaceInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ PUBLIC void FaceInfo::SetMaterial(Material* material) {
UseMaterial = true;
MaterialInfo.Texture = NULL;

Image* image = material->ImagePtr;
Image* image = material->TextureDiffuse;
if (image && image->TexturePtr)
MaterialInfo.Texture = (Texture*)image->TexturePtr;

for (unsigned i = 0; i < 4; i++) {
MaterialInfo.Specular[i] = material->Specular[i] * 0x100;
MaterialInfo.Ambient[i] = material->Ambient[i] * 0x100;
MaterialInfo.Diffuse[i] = material->Diffuse[i] * 0x100;
MaterialInfo.Specular[i] = material->ColorSpecular[i] * 0x100;
MaterialInfo.Ambient[i] = material->ColorAmbient[i] * 0x100;
MaterialInfo.Diffuse[i] = material->ColorDiffuse[i] * 0x100;
}
}

Expand Down
66 changes: 38 additions & 28 deletions source/Engine/Rendering/Material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,54 @@

class Material {
public:
float Diffuse[4];
float Specular[4];
float Ambient[4];
float Emissive[4];

float Shininess;
float ShininessStrength;
float Opacity;
float IndexOfRefraction;

Image* ImagePtr;
char* Name = nullptr;

float ColorDiffuse[4];
float ColorSpecular[4];
float ColorAmbient[4];
float ColorEmissive[4];

float Shininess = 0.0f;
float ShininessStrength = 1.0f;
float Opacity = 1.0f;

char* TextureDiffuseName = nullptr;
char* TextureSpecularName = nullptr;
char* TextureAmbientName = nullptr;
char* TextureEmissiveName = nullptr;

Image* TextureDiffuse = nullptr;
Image* TextureSpecular = nullptr;
Image* TextureAmbient = nullptr;
Image* TextureEmissive = nullptr;
};
#endif

#include <Engine/Rendering/Material.h>

#include <Engine/Diagnostics/Memory.h>

PUBLIC Material::Material() {
for (int i = 0; i < 3; i++) {
Diffuse[i] =
Specular[i] =
Ambient[i] =
Emissive[i] = 0.0f;
for (int i = 0; i < 4; i++) {
ColorDiffuse[i] =
ColorSpecular[i] =
ColorAmbient[i] =
ColorEmissive[i] = 1.0f;
}

Diffuse[3] =
Specular[3] =
Ambient[3] =
Emissive[3] = 1.0f;

Shininess = 0.0f;
ShininessStrength = 1.0f;
Opacity = 1.0f;

ImagePtr = nullptr;
}

PUBLIC void Material::Dispose() {
delete ImagePtr;
delete TextureDiffuse;
delete TextureSpecular;
delete TextureAmbient;
delete TextureEmissive;

Memory::Free(Name);

Memory::Free(TextureDiffuseName);
Memory::Free(TextureSpecularName);
Memory::Free(TextureAmbientName);
Memory::Free(TextureEmissiveName);
}

PUBLIC Material::~Material() {
Expand Down
27 changes: 21 additions & 6 deletions source/Engine/Rendering/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,27 +107,42 @@ struct NodeAnim {
}
};

struct ModelAnim {
char* Name;
struct ModelAnim;

struct SkeletalAnim {
ModelAnim* ParentAnim;

vector<NodeAnim*> Channels;
HashMap<NodeAnim*>* NodeLookup;

Uint32 Length;
Uint32 DurationInFrames;

double BaseDuration;
double TicksPerSecond;

~ModelAnim() {
Memory::Free(Name);

~SkeletalAnim() {
for (size_t i = 0; i < Channels.size(); i++)
delete Channels[i];

delete NodeLookup;
}
};

struct ModelAnim {
char* Name = nullptr;

Uint32 StartFrame = 0;
Uint32 Length = 0;

SkeletalAnim* Skeletal = nullptr;

~ModelAnim() {
Memory::Free(Name);

delete Skeletal;
}
};

struct Skeleton {
MeshBone** Bones;
size_t NumBones;
Expand Down
31 changes: 19 additions & 12 deletions source/Engine/Rendering/ModelRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,17 @@ PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Skeleton* skelet
DrawMesh(model, mesh, positionBuffer, normalBuffer, uvBuffer, mvpMatrix);
}

PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Uint32 frame, Matrix4x4& mvpMatrix) {
PRIVATE void ModelRenderer::DrawMesh(IModel* model, Mesh* mesh, Uint16 animation, Uint32 frame, Matrix4x4& mvpMatrix) {
Vector3* positionBuffer = mesh->PositionBuffer;
Vector3* normalBuffer = mesh->NormalBuffer;
Vector2* uvBuffer = mesh->UVBuffer;

if (model->UseVertexAnimation && mesh->FrameCount) {
model->DoVertexFrameInterpolation(mesh, frame, &positionBuffer, &normalBuffer, &uvBuffer);
if (model->UseVertexAnimation) {
ModelAnim* anim = nullptr;
if (animation < model->AnimationCount)
anim = model->Animations[animation];

model->DoVertexFrameInterpolation(mesh, anim, frame, &positionBuffer, &normalBuffer, &uvBuffer);
}

DrawMesh(model, mesh, positionBuffer, normalBuffer, uvBuffer, mvpMatrix);
Expand Down Expand Up @@ -399,7 +403,7 @@ PRIVATE void ModelRenderer::DrawNode(IModel* model, ModelNode* node, Matrix4x4*
DrawNode(model, node->Children[i], world);
}

PUBLIC void ModelRenderer::DrawModel(IModel* model, Uint32 frame) {
PRIVATE void ModelRenderer::DrawModelInternal(IModel* model, Uint16 animation, Uint32 frame) {
if (DoProjection)
Graphics::CalculateMVPMatrix(&MVPMatrix, ModelMatrix, ViewMatrix, ProjectionMatrix);
else
Expand All @@ -414,23 +418,26 @@ PUBLIC void ModelRenderer::DrawModel(IModel* model, Uint32 frame) {
else {
// Just render every mesh directly
for (size_t i = 0; i < model->MeshCount; i++)
DrawMesh(model, model->Meshes[i], frame, MVPMatrix);
DrawMesh(model, model->Meshes[i], animation, frame, MVPMatrix);
}
}

PUBLIC void ModelRenderer::DrawModel(IModel* model, Uint16 animation, Uint32 frame) {
Uint16 numAnims = model->AnimationCount;
if (numAnims > 0) {
if (animation >= numAnims)
animation = numAnims - 1;
}
else
animation = 0;

if (!model->UseVertexAnimation) {
if (ArmaturePtr == nullptr)
ArmaturePtr = model->BaseArmature;

Uint16 numAnims = model->AnimationCount;
if (numAnims > 0) {
if (animation >= numAnims)
animation = numAnims - 1;

if (numAnims > 0)
model->Animate(ArmaturePtr, model->Animations[animation], frame);
}
}

DrawModel(model, frame);
DrawModelInternal(model, animation, frame);
}
2 changes: 1 addition & 1 deletion source/Engine/Rendering/PolygonRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ PUBLIC void PolygonRenderer::DrawModelSkinned(IModel* model, Uint16 armature) {
rend.ClipFaces = DoProjection;
rend.ArmaturePtr = model->ArmatureList[armature];
rend.SetMatrices(ModelMatrix, ViewMatrix, ProjectionMatrix, NormalMatrix);
rend.DrawModel(model, 0);
rend.DrawModel(model, 0, 0);
}
PUBLIC void PolygonRenderer::DrawVertexBuffer() {
Matrix4x4 mvpMatrix;
Expand Down
2 changes: 1 addition & 1 deletion source/Engine/Rendering/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ PUBLIC bool Texture::ConvertToPalette(Uint32 *palColors, unsigned numPa
Uint32 color = pixels[i];
if (color & 0xFF000000) {
if (!colorsHash->GetIfExists(color, &nearestColor)) {
Uint32 rgb[3];
Uint8 rgb[3];
ColorUtils::SeparateRGB(color, rgb);
nearestColor = ColorUtils::NearestColor(rgb[0], rgb[1], rgb[2], palColors, numPaletteColors);
colorsHash->Put(color, nearestColor);
Expand Down
50 changes: 40 additions & 10 deletions source/Engine/ResourceTypes/IModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class IModel {
size_t MeshCount;

size_t VertexCount;
size_t FrameCount;
size_t VertexIndexCount;

Uint8 VertexPerFace;
Expand Down Expand Up @@ -41,15 +40,15 @@ class IModel {
#include <Engine/IO/MemoryStream.h>
#include <Engine/IO/ResourceStream.h>
#include <Engine/ResourceTypes/ModelFormats/Importer.h>
#include <Engine/ResourceTypes/ModelFormats/RSDKModel.h>
#include <Engine/ResourceTypes/ModelFormats/HatchModel.h>
#include <Engine/ResourceTypes/ModelFormats/MD3Model.h>
#include <Engine/ResourceTypes/ModelFormats/RSDKModel.h>
#include <Engine/ResourceTypes/ResourceManager.h>
#include <Engine/Utilities/StringUtils.h>
#include <Engine/Diagnostics/Clock.h>

PUBLIC IModel::IModel() {
VertexCount = 0;
FrameCount = 0;

Meshes = nullptr;
MeshCount = 0;
Expand Down Expand Up @@ -86,7 +85,9 @@ PUBLIC bool IModel::Load(Stream* stream, const char* filename) {

Clock::Start();

if (MD3Model::IsMagic(stream))
if (HatchModel::IsMagic(stream))
success = HatchModel::Convert(this, stream, filename);
else if (MD3Model::IsMagic(stream))
success = MD3Model::Convert(this, stream, filename);
else if (RSDKModel::IsMagic(stream))
success = RSDKModel::Convert(this, stream);
Expand Down Expand Up @@ -158,7 +159,7 @@ PUBLIC bool IModel::HasBones() {
return BaseArmature->NumSkeletons > 0;
}

PUBLIC void IModel::AnimateNode(ModelNode* node, ModelAnim* animation, Uint32 frame, Matrix4x4* parentMatrix) {
PUBLIC void IModel::AnimateNode(ModelNode* node, SkeletalAnim* animation, Uint32 frame, Matrix4x4* parentMatrix) {
NodeAnim* nodeAnim = animation->NodeLookup->Get(node->Name);
if (nodeAnim)
UpdateChannel(node->LocalTransform, nodeAnim, frame);
Expand All @@ -173,7 +174,7 @@ PUBLIC void IModel::Pose() {
BaseArmature->RootNode->Transform();
}

PUBLIC void IModel::Pose(Armature* armature, ModelAnim* animation, Uint32 frame) {
PUBLIC void IModel::Pose(Armature* armature, SkeletalAnim* animation, Uint32 frame) {
Matrix4x4 identity;
Matrix4x4::Identity(&identity);

Expand Down Expand Up @@ -283,9 +284,23 @@ PUBLIC Sint64 IModel::GetInBetween(Uint32 frame) {
return inbetween;
}

PUBLIC void IModel::DoVertexFrameInterpolation(Mesh* mesh, Uint32 frame, Vector3** positionBuffer, Vector3** normalBuffer, Vector2** uvBuffer) {
Uint32 keyframe = GetKeyFrame(frame) % mesh->FrameCount;
Uint32 nextKeyframe = (keyframe + 1) % mesh->FrameCount;
PUBLIC void IModel::DoVertexFrameInterpolation(Mesh* mesh, ModelAnim* animation, Uint32 frame, Vector3** positionBuffer, Vector3** normalBuffer, Vector2** uvBuffer) {
Uint32 startFrame = 0;
Uint32 animLength;

if (animation) {
animLength = animation->Length % (mesh->FrameCount + 1);
if (!animLength)
animLength = 1;
startFrame = animation->StartFrame % animLength;
}
else if (mesh->FrameCount)
animLength = mesh->FrameCount;
else
animLength = 1;

Uint32 keyframe = startFrame + (GetKeyFrame(frame) % animLength);
Uint32 nextKeyframe = startFrame + ((keyframe + 1) % animLength);
Sint64 inbetween = GetInBetween(frame);

if (inbetween == 0 || inbetween == 0x10000) {
Expand Down Expand Up @@ -362,11 +377,26 @@ PRIVATE void IModel::UpdateChannel(Matrix4x4* out, NodeAnim* channel, Uint32 fra
}

PUBLIC void IModel::Animate(Armature* armature, ModelAnim* animation, Uint32 frame) {
Pose(armature, animation, frame);
if (animation->Skeletal == nullptr)
return;

if (armature == nullptr)
armature = BaseArmature;

Pose(armature, animation->Skeletal, frame);

armature->UpdateSkeletons();
}

PUBLIC void IModel::Animate(Uint16 animation, Uint32 frame) {
if (AnimationCount > 0) {
if (animation >= AnimationCount)
animation = AnimationCount - 1;

Animate(nullptr, Animations[animation], frame);
}
}

PUBLIC int IModel::GetAnimationIndex(const char* animationName) {
if (!AnimationCount)
return -1;
Expand Down
Loading

0 comments on commit 20e562d

Please sign in to comment.