1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-02-23 06:53:00 +01:00

TR4 Lara's joints mesh

This commit is contained in:
XProger 2019-07-21 04:27:32 +03:00
parent 15d8bd5c3d
commit 4ae25e37a6
10 changed files with 106 additions and 23 deletions

View File

@ -272,7 +272,7 @@ struct Character : Controller {
}
void addSparks(uint32 mask) {
Sphere spheres[MAX_SPHERES];
Sphere spheres[MAX_JOINTS];
int count = getSpheres(spheres);
for (int i = 0; i < count; i++)
if (mask & (1 << i)) {

View File

@ -10,7 +10,6 @@
#define SPRITE_FPS 10.0f
#define MAX_LAYERS 4
#define MAX_SPHERES 32
#define UNLIMITED_AMMO 10000
@ -831,7 +830,7 @@ struct Controller {
int getSpheres(Sphere *spheres) {
const TR::Model *m = getModel();
ASSERT(m->mCount <= MAX_SPHERES);
ASSERT(m->mCount <= MAX_JOINTS);
int jFrame = jointsFrame;
updateJoints();
@ -848,7 +847,7 @@ struct Controller {
}
Box getSpheresBox(bool local = false) {
Sphere spheres[MAX_SPHERES];
Sphere spheres[MAX_JOINTS];
int count = getSpheres(spheres);
if (count) {
@ -880,8 +879,8 @@ struct Controller {
ASSERT(a->mCount <= 34);
ASSERT(b->mCount <= 34);
Sphere aSpheres[MAX_SPHERES];
Sphere bSpheres[MAX_SPHERES];
Sphere aSpheres[MAX_JOINTS];
Sphere bSpheres[MAX_JOINTS];
int aCount = getSpheres(aSpheres);
int bCount = controller->getSpheres(bSpheres);

View File

@ -624,7 +624,7 @@ namespace Debug {
Box box = controller->getBoundingBoxLocal();
Debug::Draw::box(matrix, box.min, box.max, bboxIntersect ? vec4(1, 0, 0, 1): vec4(1));
Sphere spheres[MAX_SPHERES];
Sphere spheres[MAX_JOINTS];
int count = controller->getSpheres(spheres);
for (int joint = 0; joint < count; joint++) {

View File

@ -9,6 +9,7 @@
#define MAX_TRIGGER_COMMANDS 32
#define MAX_MESHES 512
#define MAX_WEAPONS 4
#define MAX_JOINTS 32
// Lara's height in units / height in meters
#define ONE_METER (768.0f / 1.8f)
@ -2405,7 +2406,7 @@ namespace TR {
REMAP_4( AI_MODIFY );
REMAP_4( AI_FOLLOW );
REMAP_4( KILL_ALL_TRIGGERS );
REMAP_4( GLYPHS );
//REMAP_4( GLYPHS );
REMAP_4( MISC_SPRITES );
default : return type;
@ -3107,6 +3108,7 @@ namespace TR {
int16 braid;
int16 laraSpec;
int16 laraSkin;
int16 laraJoints;
int16 meshSwap[3];
int16 sky;
int16 smoke;
@ -4778,6 +4780,7 @@ namespace TR {
case Entity::LARA_BRAID : extra.braid = i; break;
case Entity::LARA_SPEC : extra.laraSpec = i; break;
case Entity::LARA_SKIN : extra.laraSkin = i; break;
case Entity::LARA_SKIN_JOINTS : extra.laraJoints = i; break;
case Entity::CUT_1 : extra.meshSwap[0] = i; break;
case Entity::CUT_2 : extra.meshSwap[1] = i; break;
case Entity::CUT_3 : extra.meshSwap[2] = i; break;
@ -4839,7 +4842,7 @@ namespace TR {
default : ;
}
ASSERT(extra.glyphs != -1);
//ASSERT(extra.glyphs != -1);
}
void initCutscene() {

View File

@ -4,7 +4,7 @@
#include "core.h"
#if defined(_DEBUG) || defined(PROFILE)
//#define _DEBUG_SHADERS
//#define _DEBUG_SHADERS "../../OpenLara/src/shaders/"
#endif
#ifdef _OS_WIN
@ -521,13 +521,13 @@ namespace GAPI {
#ifdef _DEBUG_SHADERS
Stream *stream = NULL;
switch (pass) {
case Core::passCompose : stream = new Stream("../../src/shaders/compose.glsl"); break;
case Core::passShadow : stream = new Stream("../../src/shaders/shadow.glsl"); break;
case Core::passAmbient : stream = new Stream("../../src/shaders/ambient.glsl"); break;
case Core::passSky : stream = new Stream("../../src/shaders/sky.glsl"); break;
case Core::passWater : stream = new Stream("../../src/shaders/water.glsl"); break;
case Core::passFilter : stream = new Stream("../../src/shaders/filter.glsl"); break;
case Core::passGUI : stream = new Stream("../../src/shaders/gui.glsl"); break;
case Core::passCompose : stream = new Stream(_DEBUG_SHADERS "compose.glsl"); break;
case Core::passShadow : stream = new Stream(_DEBUG_SHADERS "shadow.glsl"); break;
case Core::passAmbient : stream = new Stream(_DEBUG_SHADERS "ambient.glsl"); break;
case Core::passSky : stream = new Stream(_DEBUG_SHADERS "sky.glsl"); break;
case Core::passWater : stream = new Stream(_DEBUG_SHADERS "water.glsl"); break;
case Core::passFilter : stream = new Stream(_DEBUG_SHADERS "filter.glsl"); break;
case Core::passGUI : stream = new Stream(_DEBUG_SHADERS "gui.glsl"); break;
default : ASSERT(false); return;
}

View File

@ -545,7 +545,7 @@ struct Inventory {
TR::Level *level = game->getLevel();
TR::Model &m = level->models[desc.model];
Basis joints[MAX_SPHERES];
Basis joints[MAX_JOINTS];
mat4 matrix;
matrix.identity();

View File

@ -1506,7 +1506,7 @@ struct Lara : Character {
if (box.intersect(m, from, v, t)) {
t *= v.length();
v = v.normal();
Sphere spheres[MAX_SPHERES];
Sphere spheres[MAX_JOINTS];
int count = target->getSpheres(spheres);
for (int i = 0; i < count; i++) {
float st;
@ -3779,6 +3779,16 @@ struct Lara : Character {
if (Core::pass != Core::passShadow && camera->firstPerson && camera->viewIndex == -1 && game->getCamera() == camera) // hide head in first person view // TODO: fix for firstPerson with viewIndex always == -1
visibleMask &= ~JOINT_MASK_HEAD;
Controller::render(frustum, mesh, type, caustics);
if (level->extra.laraJoints > -1) {
const TR::Model *model = getModel();
for (int i = 0; i < model->mCount; i++) {
joints[i].w = 1.0f;
}
Core::setBasis(joints, model->mCount);
mesh->renderModel(level->extra.laraJoints, caustics);
}
visibleMask = visMask;
if (braid)

View File

@ -3052,7 +3052,7 @@ struct Level : IGame {
setDefaultTarget(eye, view, invBG);
if (Core::settings.detail.stereo == Core::Settings::STEREO_SPLIT) {
camera->aspect = setViewport(invBG ? -1 : view, invBG ? 0 : eye);
camera->aspect = setViewport(invBG ? -1 : view, invBG ? 0 : eye);
} else {
camera->aspect = setViewport(view, invBG ? 0 : eye);
}

View File

@ -166,6 +166,8 @@ struct MeshBuilder {
struct ModelRange {
int parts[3][32];
Geometry geometry[3];
int vStart;
int vCount;
} *models;
// procedured
@ -260,8 +262,10 @@ struct MeshBuilder {
}
// get models info
int vStartModel = vCount;
models = new ModelRange[level->modelsCount];
for (int i = 0; i < level->modelsCount; i++) {
models[i].vStart = vCount;
TR::Model &model = level->models[i];
for (int j = 0; j < model.mCount; j++) {
int index = level->meshOffsets[model.mStart + j];
@ -271,6 +275,8 @@ struct MeshBuilder {
iCount += (mesh.rCount * 6 + mesh.tCount * 3) * DOUBLE_SIDED;
vCount += (mesh.rCount * 4 + mesh.tCount * 3);
}
models[i].vCount = vCount - models[i].vStart;
models[i].vStart -= vStartModel;
}
// shadow blob mesh (8 triangles, 8 vertices)
@ -381,12 +387,11 @@ struct MeshBuilder {
ASSERT(vCount - vStartRoom <= 0xFFFF);
// build models geometry
int vStartModel = vCount;
vStartModel = vCount;
aCount++;
for (int i = 0; i < level->modelsCount; i++) {
TR::Model &model = level->models[i];
int vCountStart = vCount;
for (int transp = 0; transp < 3; transp++) {
@ -442,6 +447,9 @@ struct MeshBuilder {
}
}
}
weldSkinJoints(vertices + vStartModel);
ASSERT(vCount - vStartModel <= 0xFFFF);
// build common primitives
@ -688,6 +696,69 @@ struct MeshBuilder {
return false;
}
void weldSkinJoints(Vertex *vertices) {
if (level->extra.laraSkin == -1 || level->extra.laraJoints == -1) {
return;
}
int t = Core::getTime();
ASSERT(level->models[level->extra.laraSkin].mCount == level->models[level->extra.laraJoints].mCount);
const TR::Model *model = level->models + level->extra.laraSkin;
const TR::Node *node = (TR::Node*)level->nodesData + model->node;
int sIndex = 0;
short4 stack[16];
short4 pos(0, 0, 0, 0);
short4 jointsPos[MAX_JOINTS];
for (int i = 0; i < model->mCount; i++) {
if (i > 0 && node) {
const TR::Node &t = node[i - 1];
if (t.flags & 0x01) pos = stack[--sIndex];
if (t.flags & 0x02) stack[sIndex++] = pos;
pos.x += t.x;
pos.y += t.y;
pos.z += t.z;
}
jointsPos[i] = pos;
}
const ModelRange &rangeSkin = models[level->extra.laraSkin];
const ModelRange &rangeJoints = models[level->extra.laraJoints];
#define COORD_FILL(VAR,RANGE)\
short4 *VAR = new short4[RANGE.vCount];\
for (int i = 0; i < RANGE.vCount; i++) {\
VAR[i] = vertices[RANGE.vStart + i].coord;\
VAR[i].x += jointsPos[VAR[i].w].x;\
VAR[i].y += jointsPos[VAR[i].w].y;\
VAR[i].z += jointsPos[VAR[i].w].z;\
}
COORD_FILL(vSkin, rangeSkin);
COORD_FILL(vJoints, rangeJoints);
// bruteforce :(
for (int j = 0; j < rangeJoints.vCount; j++) {
for (int i = 0; i < rangeSkin.vCount; i++) {
if (abs(vSkin[i].x - vJoints[j].x) <= 1 &&
abs(vSkin[i].y - vJoints[j].y) <= 1 &&
abs(vSkin[i].z - vJoints[j].z) <= 1) { // compare position
vertices[rangeJoints.vStart + j].coord = vertices[rangeSkin.vStart + i].coord; // set bone index
vertices[rangeJoints.vStart + j].normal = vertices[rangeSkin.vStart + i].normal;
break;
}
}
}
delete[] vSkin;
delete[] vJoints;
#undef COORD_FILL
LOG("remap joints: %d\n", Core::getTime() - t);
}
int calcWaterLevel(int16 roomIndex, bool flip) {
TR::Room &room = level->rooms[roomIndex];

View File

@ -795,7 +795,7 @@ namespace UI {
vec3 lightOffset = vec3(UI::width - 64.0f, UI::height - 64.0f, 2048.0f);
setupInventoryShading(lightOffset);
Basis joints[MAX_SPHERES];
Basis joints[MAX_JOINTS];
Core::setDepthTest(true);
Core::setDepthWrite(true);