TombEngine/TR5Main/Game/effects/debris.cpp

167 lines
5.3 KiB
C++
Raw Normal View History

#include "framework.h"
#include "effects\debris.h"
#include "level.h"
#include "setup.h"
2021-09-19 23:41:26 +03:00
#include "control/control.h"
2021-09-08 18:31:35 +03:00
#include "Specific\trmath.h"
#include "Specific\prng.h"
2021-08-26 19:47:59 +03:00
2020-06-18 15:54:08 +02:00
using std::vector;
2021-08-30 18:03:21 +03:00
using namespace TEN::Renderer;
using namespace TEN::Math::Random;
2021-08-26 19:47:59 +03:00
2020-04-01 07:24:15 +02:00
ShatterImpactInfo ShatterImpactData;
SHATTER_ITEM ShatterItem;
short SmashedMeshCount;
MESH_INFO* SmashedMesh[32];
short SmashedMeshRoom[32];
vector<DebrisFragment> DebrisFragments = vector<DebrisFragment>(MAX_DEBRIS);
2021-08-26 19:47:59 +03:00
2020-04-01 07:24:15 +02:00
DebrisFragment* GetFreeDebrisFragment()
2020-03-29 10:38:29 +02:00
{
2021-08-03 06:54:36 +02:00
for (auto& frag : DebrisFragments) {
if (!frag.active) {
return &frag;
2020-03-29 10:38:29 +02:00
}
}
return nullptr;
}
2020-03-29 20:05:04 +02:00
2021-09-24 13:50:31 +03:00
void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num, short roomNumber, int noZXVel)
2020-03-29 10:38:29 +02:00
{
2020-07-03 07:05:33 +02:00
MESH* meshPtr = nullptr;
2020-03-29 10:38:29 +02:00
RendererMesh* fragmentsMesh;
short yRot = 0;
Vector3 pos;
bool isStatic;
2021-09-13 02:57:14 +03:00
if (mesh)
{
isStatic = false;
meshPtr = &g_Level.Meshes[StaticObjects[mesh->staticNumber].meshNumber];
yRot = mesh->pos.yRot;
pos = Vector3(mesh->pos.xPos, mesh->pos.yPos, mesh->pos.zPos);
2020-03-29 10:38:29 +02:00
}
2021-09-13 02:57:14 +03:00
else
{
isStatic = true;
2020-03-29 10:38:29 +02:00
meshPtr = item->meshp;
yRot = item->yRot;
pos = Vector3(item->sphere.x, item->sphere.y, item->sphere.z);
}
fragmentsMesh = g_Renderer.getRendererMeshFromTrMesh(nullptr, meshPtr, num, 0, 0);
for (auto& renderBucket : fragmentsMesh->buckets) {
2021-08-03 06:54:36 +02:00
vector<RendererVertex>& meshVertices = renderBucket.Vertices;
2020-03-29 10:38:29 +02:00
for (int i = 0; i < renderBucket.Indices.size(); i += 3)
{
2020-04-01 07:24:15 +02:00
DebrisFragment* fragment = GetFreeDebrisFragment();
2021-09-13 02:57:14 +03:00
if (!fragment)
{
2020-03-29 10:38:29 +02:00
break;
}
2021-09-13 02:57:14 +03:00
if (!fragment->active)
{
2020-04-25 16:23:53 +02:00
Matrix rotationMatrix = Matrix::CreateFromYawPitchRoll(TO_RAD(yRot), 0, 0);
2021-08-03 06:54:36 +02:00
RendererVertex vtx0 = meshVertices.at(renderBucket.Indices[i]);
RendererVertex vtx1 = meshVertices.at(renderBucket.Indices[i + 1]);
RendererVertex vtx2 = meshVertices.at(renderBucket.Indices[i + 2]);
2021-09-13 02:57:14 +03:00
2020-03-29 10:38:29 +02:00
//Take the average of all 3 local positions
Vector3 localPos = (vtx0.Position + vtx1.Position + vtx2.Position) / 3;
vtx0.Position -= localPos;
vtx1.Position -= localPos;
vtx2.Position -= localPos;
2021-09-13 02:57:14 +03:00
2020-03-29 10:38:29 +02:00
Vector3 worldPos = Vector3::Transform(localPos, rotationMatrix);
fragment->worldPosition = worldPos + pos;
fragment->mesh.vertices[0] = vtx0;
fragment->mesh.vertices[1] = vtx1;
fragment->mesh.vertices[2] = vtx2;
fragment->mesh.blendMode = renderBucket.blendMode;
fragment->mesh.tex = renderBucket.texture;
fragment->isStatic = isStatic;
2020-03-29 10:38:29 +02:00
fragment->active = true;
2020-04-05 17:36:24 +02:00
fragment->terminalVelocity = 1024;
2020-03-29 10:38:29 +02:00
fragment->gravity = Vector3(0, 7, 0);
2020-04-05 17:36:24 +02:00
fragment->restitution = 0.6f;
fragment->friction = 0.6f;
fragment->linearDrag = .99f;
2021-09-17 16:07:53 +03:00
fragment->angularVelocity = Vector3(GenerateFloat(-1, 1) * 0.39, GenerateFloat(-1, 1) * 0.39, GenerateFloat(-1, 1) * 0.39);
fragment->angularDrag = GenerateFloat(0.9f, 0.999f);
2020-04-01 07:24:15 +02:00
fragment->velocity = CalculateFragmentImpactVelocity(fragment->worldPosition, ShatterImpactData.impactDirection, ShatterImpactData.impactLocation);
2020-03-29 10:38:29 +02:00
fragment->roomNumber = roomNumber;
fragment->numBounces = 0;
}
}
}
delete fragmentsMesh;
2020-03-29 10:38:29 +02:00
}
Vector3 CalculateFragmentImpactVelocity(Vector3 fragmentWorldPosition, Vector3 impactDirection, Vector3 impactLocation)
2020-03-29 10:38:29 +02:00
{
2020-04-05 17:36:24 +02:00
Vector3 radiusVector = (fragmentWorldPosition - impactLocation);
Vector3 radiusNormVec = radiusVector;
radiusNormVec.Normalize();
float radiusStrenght = 1-((fragmentWorldPosition - impactLocation).Length() / 1024);
radiusStrenght = fmax(radiusStrenght, 0);
2021-09-17 16:07:53 +03:00
Vector3 radiusRandomVector = Vector3(GenerateFloat(-0.2, 0.2f), GenerateFloat(-0.2, 0.2f), GenerateFloat(-0.2, 0.2f)) + radiusNormVec;
2020-04-05 17:36:24 +02:00
radiusRandomVector.Normalize();
Vector3 radiusVelocity = radiusRandomVector * radiusStrenght*40;
2021-09-17 16:07:53 +03:00
Vector3 impactDirectionVelocity = (impactDirection + Vector3(GenerateFloat(-0.2, 0.2f), GenerateFloat(-0.2, 0.2f), GenerateFloat(-0.2, 0.2f))) * 80 ;
2020-04-05 17:36:24 +02:00
return radiusVelocity + impactDirectionVelocity;
2020-03-29 10:38:29 +02:00
}
void DisableDebris()
{
2021-08-03 06:54:36 +02:00
for (auto& deb : DebrisFragments)
{
2021-08-03 06:54:36 +02:00
deb.active = false;
}
}
2020-04-01 07:24:15 +02:00
void UpdateDebris()
2020-03-29 10:38:29 +02:00
{
2021-08-03 06:07:51 +02:00
for (auto& deb : DebrisFragments)
{
2021-08-03 06:07:51 +02:00
if (deb.active)
{
FLOOR_INFO* floor;
short roomNumber;
2021-08-03 06:07:51 +02:00
deb.velocity *= deb.linearDrag;
deb.velocity += deb.gravity;
deb.velocity = XMVector3ClampLength(deb.velocity, 0, deb.terminalVelocity);
2021-09-13 02:57:14 +03:00
deb.rotation *= Quaternion::CreateFromYawPitchRoll(deb.angularVelocity.x, deb.angularVelocity.y, deb.angularVelocity.z);
2021-08-03 06:07:51 +02:00
deb.worldPosition += deb.velocity;
deb.angularVelocity *= deb.angularDrag;
2021-08-03 06:07:51 +02:00
roomNumber = deb.roomNumber;
2021-09-11 23:50:54 +03:00
floor = GetFloor(deb.worldPosition.x, deb.worldPosition.y, deb.worldPosition.z, &roomNumber);
if (deb.worldPosition.y < floor->CeilingHeight(deb.worldPosition.x, deb.worldPosition.z))
{
2021-11-08 17:48:57 +03:00
auto roomNumber = floor->RoomAbove(deb.worldPosition.x, deb.worldPosition.y, deb.worldPosition.z).value_or(NO_ROOM);
if (roomNumber != NO_ROOM)
deb.roomNumber = roomNumber;
2020-04-05 17:36:24 +02:00
}
if (deb.worldPosition.y > floor->FloorHeight(deb.worldPosition.x, deb.worldPosition.z))
{
2021-11-08 17:48:57 +03:00
auto roomNumber = floor->RoomBelow(deb.worldPosition.x, deb.worldPosition.y, deb.worldPosition.z).value_or(NO_ROOM);
if (roomNumber != NO_ROOM)
deb.roomNumber = roomNumber;
2021-08-03 06:07:51 +02:00
if (deb.numBounces > 3)
{
2021-08-03 06:07:51 +02:00
deb.active = false;
2020-03-29 10:38:29 +02:00
continue;
}
2021-08-03 06:07:51 +02:00
deb.velocity.y *= -deb.restitution;
deb.velocity.x *= deb.friction;
deb.velocity.z *= deb.friction;
deb.numBounces++;
2020-03-29 10:38:29 +02:00
}
}
}
}