2020-05-27 09:21:20 +02:00
|
|
|
#include "framework.h"
|
2020-03-25 07:06:04 +01:00
|
|
|
#include "debris.h"
|
2020-05-27 09:21:20 +02:00
|
|
|
#include "level.h"
|
|
|
|
#include "setup.h"
|
2020-04-24 19:15:05 +02:00
|
|
|
#include "control.h"
|
2020-05-30 15:55:23 +02:00
|
|
|
#include "trmath.h"
|
2020-06-18 15:54:08 +02:00
|
|
|
using std::vector;
|
2020-04-01 07:24:15 +02:00
|
|
|
ShatterImpactInfo ShatterImpactData;
|
|
|
|
SHATTER_ITEM ShatterItem;
|
|
|
|
short SmashedMeshCount;
|
|
|
|
MESH_INFO* SmashedMesh[32];
|
|
|
|
short SmashedMeshRoom[32];
|
2020-05-30 15:55:23 +02:00
|
|
|
vector<DebrisFragment> DebrisFragments = vector<DebrisFragment>(MAX_DEBRIS);
|
2020-06-21 14:27:12 +02:00
|
|
|
using namespace T5M::Renderer;
|
2020-04-01 07:24:15 +02:00
|
|
|
DebrisFragment* GetFreeDebrisFragment()
|
2020-03-29 10:38:29 +02:00
|
|
|
{
|
2020-04-01 07:24:15 +02:00
|
|
|
for (auto frag = DebrisFragments.begin(); frag != DebrisFragments.end(); frag++) {
|
2020-03-29 10:38:29 +02:00
|
|
|
if (!frag->active) {
|
|
|
|
return &*frag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
2020-03-29 20:05:04 +02:00
|
|
|
|
2020-04-01 07:24:15 +02: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;
|
|
|
|
if (mesh) {
|
2020-07-21 09:56:47 +02:00
|
|
|
meshPtr = &g_Level.Meshes[StaticObjects[mesh->staticNumber].meshNumber];
|
2020-03-29 10:38:29 +02:00
|
|
|
yRot = mesh->yRot;
|
|
|
|
pos = Vector3(mesh->x, mesh->y, mesh->z);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
meshPtr = item->meshp;
|
|
|
|
yRot = item->yRot;
|
|
|
|
pos = Vector3(item->sphere.x, item->sphere.y, item->sphere.z);
|
|
|
|
}
|
2020-07-03 07:05:33 +02:00
|
|
|
fragmentsMesh = g_Renderer.getMesh(0);
|
2020-06-28 15:51:33 +02:00
|
|
|
for (int bucket = RENDERER_BUCKET_SOLID; bucket <= RENDERER_BUCKET_TRANSPARENT; bucket++) {
|
2020-03-29 10:38:29 +02:00
|
|
|
RendererBucket renderBucket = fragmentsMesh->Buckets[bucket];
|
|
|
|
vector<RendererVertex>* meshVertices = &renderBucket.Vertices;
|
|
|
|
for (int i = 0; i < renderBucket.Indices.size(); i += 3)
|
|
|
|
{
|
2020-04-01 07:24:15 +02:00
|
|
|
DebrisFragment* fragment = GetFreeDebrisFragment();
|
2020-03-29 10:38:29 +02:00
|
|
|
if (!fragment) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!fragment->active) {
|
2020-04-25 16:23:53 +02:00
|
|
|
Matrix rotationMatrix = Matrix::CreateFromYawPitchRoll(TO_RAD(yRot), 0, 0);
|
2020-03-29 10:38:29 +02:00
|
|
|
RendererVertex vtx0 = meshVertices->at(fragmentsMesh->Buckets[bucket].Indices[i]);
|
|
|
|
RendererVertex vtx1 = meshVertices->at(fragmentsMesh->Buckets[bucket].Indices[i + 1]);
|
|
|
|
RendererVertex vtx2 = meshVertices->at(fragmentsMesh->Buckets[bucket].Indices[i + 2]);
|
|
|
|
//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;
|
|
|
|
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.bucket = (RENDERER_BUCKETS)bucket;
|
|
|
|
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;
|
2020-03-29 10:38:29 +02:00
|
|
|
fragment->angularVelocity = Vector3(frandMinMax(-1, 1) * 0.39, frandMinMax(-1, 1) * 0.39, frandMinMax(-1, 1) * 0.39);
|
2020-04-05 17:36:24 +02:00
|
|
|
fragment->angularDrag = frandMinMax(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;
|
|
|
|
|
2020-03-25 07:06:04 +01:00
|
|
|
|
2020-03-29 10:38:29 +02:00
|
|
|
}
|
|
|
|
}
|
2020-03-25 07:06:04 +01:00
|
|
|
}
|
|
|
|
|
2020-03-29 10:38:29 +02:00
|
|
|
}
|
2020-03-25 07:06:04 +01:00
|
|
|
|
2020-05-30 15:55:23 +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);
|
|
|
|
Vector3 radiusRandomVector = Vector3(frandMinMax(-0.2, 0.2f), frandMinMax(-0.2, 0.2f), frandMinMax(-0.2, 0.2f)) + radiusNormVec;
|
|
|
|
radiusRandomVector.Normalize();
|
|
|
|
Vector3 radiusVelocity = radiusRandomVector * radiusStrenght*40;
|
|
|
|
Vector3 impactDirectionVelocity = (impactDirection + Vector3(frandMinMax(-0.2, 0.2f), frandMinMax(-0.2, 0.2f), frandMinMax(-0.2, 0.2f))) * 80 ;
|
|
|
|
return radiusVelocity + impactDirectionVelocity;
|
2020-03-29 10:38:29 +02:00
|
|
|
}
|
2020-03-25 07:06:04 +01:00
|
|
|
|
2020-04-01 07:24:15 +02:00
|
|
|
void UpdateDebris()
|
2020-03-29 10:38:29 +02:00
|
|
|
{
|
2020-05-30 15:55:23 +02:00
|
|
|
for (auto deb = DebrisFragments.begin(); deb != DebrisFragments.end(); deb++)
|
|
|
|
{
|
|
|
|
if (deb->active)
|
|
|
|
{
|
|
|
|
FLOOR_INFO* floor;
|
|
|
|
short roomNumber;
|
|
|
|
|
2020-03-29 10:38:29 +02:00
|
|
|
deb->velocity *= deb->linearDrag;
|
2020-04-05 17:36:24 +02:00
|
|
|
deb->velocity += deb->gravity;
|
2020-03-29 10:38:29 +02:00
|
|
|
deb->velocity = XMVector3ClampLength(deb->velocity, 0, deb->terminalVelocity);
|
|
|
|
deb->rotation *= Quaternion::CreateFromYawPitchRoll(deb->angularVelocity.x,deb->angularVelocity.y,deb->angularVelocity.z);
|
|
|
|
deb->worldPosition += deb->velocity;
|
|
|
|
deb->angularVelocity *= deb->angularDrag;
|
2020-05-30 15:55:23 +02:00
|
|
|
|
|
|
|
roomNumber = deb->roomNumber;
|
|
|
|
floor = GetFloor(deb->worldPosition.x, deb->worldPosition.y, deb->worldPosition.z,&roomNumber);
|
|
|
|
|
|
|
|
if (deb->worldPosition.y < floor->ceiling)
|
|
|
|
{
|
|
|
|
if (floor->skyRoom != NO_ROOM)
|
2020-04-05 17:36:24 +02:00
|
|
|
deb->roomNumber = floor->skyRoom;
|
|
|
|
}
|
2020-05-30 15:55:23 +02:00
|
|
|
|
|
|
|
if (deb->worldPosition.y > floor->floor)
|
|
|
|
{
|
|
|
|
if (floor->pitRoom != NO_ROOM)
|
2020-04-05 17:36:24 +02:00
|
|
|
deb->roomNumber = floor->pitRoom;
|
2020-05-30 15:55:23 +02:00
|
|
|
|
|
|
|
if (deb->numBounces > 3)
|
|
|
|
{
|
2020-03-29 10:38:29 +02:00
|
|
|
deb->active = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
deb->velocity.y *= -deb->restitution;
|
|
|
|
deb->velocity.x *= deb->friction;
|
|
|
|
deb->velocity.z *= deb->friction;
|
|
|
|
deb->numBounces++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|