mirror of
https://github.com/XProger/OpenLara.git
synced 2025-01-29 10:38:04 +01:00
resolved #5 visibility check for animated bounding box, #8 invert mouse rotation (vertical), #4 turn off hit on the wall for up-jump & reach animations
This commit is contained in:
parent
578cc74d2b
commit
c4c6218604
BIN
bin/OpenLara.exe
BIN
bin/OpenLara.exe
Binary file not shown.
24
src/camera.h
24
src/camera.h
@ -100,6 +100,7 @@ struct Frustum {
|
||||
return count >= 4;
|
||||
}
|
||||
|
||||
// AABB visibility check
|
||||
bool isVisible(const vec3 &min, const vec3 &max) const {
|
||||
if (count < 4) return false;
|
||||
|
||||
@ -120,6 +121,27 @@ struct Frustum {
|
||||
return true;
|
||||
}
|
||||
|
||||
// OBB visibility check
|
||||
bool isVisible(const mat4 &matrix, const vec3 &min, const vec3 &max) {
|
||||
vec4 origPlanes[MAX_CLIP_PLANES];
|
||||
memcpy(origPlanes, planes, count * sizeof(vec4));
|
||||
|
||||
// transform clip planes (relative)
|
||||
mat4 m = matrix.inverse();
|
||||
for (int i = 0; i < count; i++) {
|
||||
vec4 &p = planes[i];
|
||||
vec4 o = m * vec4(p.xyz * (-p.w), 1.0f);
|
||||
vec4 n = m * vec4(p.xyz, 0.0f);
|
||||
p.xyz = n.xyz;
|
||||
p.w = -o.xyz.dot(n.xyz);
|
||||
}
|
||||
bool visible = isVisible(min, max);
|
||||
|
||||
memcpy(planes, origPlanes, count * sizeof(vec4));
|
||||
return visible;
|
||||
}
|
||||
|
||||
// Sphere visibility check
|
||||
bool isVisible(const vec3 ¢er, float radius) {
|
||||
if (count < 4) return false;
|
||||
|
||||
@ -172,7 +194,7 @@ struct Camera : Controller {
|
||||
#endif
|
||||
if (Input::down[ikMouseR]) {
|
||||
vec2 delta = Input::mouse.pos - Input::mouse.start.R;
|
||||
angleAdv.x += delta.y * 0.01f;
|
||||
angleAdv.x -= delta.y * 0.01f;
|
||||
angleAdv.y += delta.x * 0.01f;
|
||||
Input::mouse.start.R = Input::mouse.pos;
|
||||
}
|
||||
|
55
src/debug.h
55
src/debug.h
@ -3,8 +3,7 @@
|
||||
|
||||
#include "core.h"
|
||||
#include "format.h"
|
||||
|
||||
extern HDC hDC;
|
||||
#include "controller.h"
|
||||
|
||||
namespace Debug {
|
||||
|
||||
@ -12,7 +11,7 @@ namespace Debug {
|
||||
|
||||
void init() {
|
||||
font = glGenLists(256);
|
||||
HDC hdc = hDC;
|
||||
HDC hdc = GetDC(0);
|
||||
HFONT hfont = CreateFontA(-MulDiv(10, GetDeviceCaps(hdc, LOGPIXELSY), 72), 0,
|
||||
0, 0, FW_BOLD, 0, 0, 0,
|
||||
ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
@ -85,6 +84,13 @@ namespace Debug {
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void box(const mat4 &m, const vec3 &min, const vec3 &max, const vec4 &color) {
|
||||
glPushMatrix();
|
||||
glMultMatrixf((GLfloat*)&m);
|
||||
box(min, max, color);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void sphere(const vec3 ¢er, const float radius, const vec4 &color) {
|
||||
const float k = PI * 2.0f / 18.0f;
|
||||
|
||||
@ -441,10 +447,17 @@ namespace Debug {
|
||||
// dynamic objects
|
||||
for (int i = 0; i < level.entitiesCount; i++) {
|
||||
TR::Entity &e = level.entities[i];
|
||||
Controller *controller = (Controller*)e.controller;
|
||||
|
||||
mat4 matrix;
|
||||
matrix.identity();
|
||||
matrix.translate(vec3(e.x, e.y, e.z));
|
||||
matrix.rotateY(e.rotation / 16384.0f * PI * 0.5f);
|
||||
if (controller) {
|
||||
matrix.rotateY(controller->angle.y);
|
||||
matrix.rotateX(controller->angle.x);
|
||||
matrix.rotateZ(controller->angle.z);
|
||||
} else
|
||||
matrix.rotateY(e.rotation / 16384.0f * PI * 0.5f);
|
||||
|
||||
for (int j = 0; j < level.modelsCount; j++) {
|
||||
TR::Model &m = level.models[j];
|
||||
@ -452,21 +465,25 @@ namespace Debug {
|
||||
|
||||
if (!node) continue; // ???
|
||||
|
||||
TR::Animation *anim = m.animation < 0xFFFF ? &level.anims[m.animation] : NULL;
|
||||
TR::AnimFrame *frame = anim ? (TR::AnimFrame*)&level.frameData[anim->frameOffset >> 1] : NULL;
|
||||
|
||||
//mat4 m;
|
||||
//m.identity();
|
||||
// m.translate(vec3(frame->x, frame->y, frame->z).lerp(vec3(frameB->x, frameB->y, frameB->z), k));
|
||||
|
||||
int sIndex = 0;
|
||||
mat4 stack[20];
|
||||
mat4 joint;
|
||||
|
||||
joint.identity();
|
||||
if (frame) joint.translate(frame->pos);
|
||||
|
||||
if (e.id == m.id) {
|
||||
ASSERT(m.animation < 0xFFFF);
|
||||
|
||||
int fSize = sizeof(TR::AnimFrame) + m.mCount * sizeof(uint16) * 2;
|
||||
|
||||
TR::Animation *anim = controller ? &level.anims[controller->animIndex] : &level.anims[m.animation];
|
||||
TR::AnimFrame *frame = (TR::AnimFrame*)&level.frameData[anim->frameOffset + (controller ? int((controller->animTime * 30.0f / anim->frameRate)) * fSize : 0) >> 1];
|
||||
|
||||
//mat4 m;
|
||||
//m.identity();
|
||||
//m.translate(vec3(frame->x, frame->y, frame->z).lerp(vec3(frameB->x, frameB->y, frameB->z), k));
|
||||
|
||||
int sIndex = 0;
|
||||
mat4 stack[20];
|
||||
mat4 joint;
|
||||
|
||||
joint.identity();
|
||||
if (frame) joint.translate(frame->pos);
|
||||
|
||||
for (int k = 0; k < m.mCount; k++) {
|
||||
|
||||
if (k > 0 && node) {
|
||||
@ -501,6 +518,8 @@ namespace Debug {
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Debug::Draw::box(matrix, frame->box.min(), frame->box.max(), vec4(1.0));
|
||||
break;
|
||||
}
|
||||
|
||||
|
14
src/format.h
14
src/format.h
@ -298,9 +298,15 @@ namespace TR {
|
||||
int16 nextFrame; // Frame offset to dispatch to
|
||||
};
|
||||
|
||||
struct MinMax {
|
||||
int16 minX, maxX, minY, maxY, minZ, maxZ;
|
||||
|
||||
vec3 min() const { return vec3((float)minX, (float)minY, (float)minZ); }
|
||||
vec3 max() const { return vec3((float)maxX, (float)maxY, (float)maxZ); }
|
||||
};
|
||||
|
||||
struct AnimFrame {
|
||||
TR::Vertex min; // Bounding box (low)
|
||||
TR::Vertex max; // Bounding box (high)
|
||||
MinMax box;
|
||||
TR::Vertex pos; // Starting offset for this model
|
||||
int16 aCount;
|
||||
uint16 angles[0]; // angle frames in YXZ order
|
||||
@ -338,9 +344,7 @@ namespace TR {
|
||||
struct StaticMesh {
|
||||
uint32 id; // Static Mesh Identifier
|
||||
uint16 mesh; // Mesh (offset into MeshPointers[])
|
||||
struct MinMax {
|
||||
int16 minX, maxX, minY, maxY, minZ, maxZ;
|
||||
} box[2]; // visible (minX, maxX, minY, maxY, minZ, maxZ) & collision
|
||||
MinMax box[2]; // visible (minX, maxX, minY, maxY, minZ, maxZ) & collision
|
||||
uint16 flags;
|
||||
|
||||
void getBox(bool collision, int rotation, vec3 &min, vec3 &max) {
|
||||
|
15
src/lara.h
15
src/lara.h
@ -477,7 +477,7 @@ struct Lara : Controller {
|
||||
|
||||
switch (stand) {
|
||||
case STAND_AIR :
|
||||
canPassGap = ((int)p.y - d) <= 512 && (pos.y - height - info.ceiling > -256);
|
||||
canPassGap = ((int)p.y - d) <= 512 && (info.roomAbove != 0xFF || (pos.y - height - info.ceiling > -256));
|
||||
break;
|
||||
case STAND_UNDERWATER :
|
||||
canPassGap = ((int)p.y - d) < 128;
|
||||
@ -499,13 +499,16 @@ struct Lara : Controller {
|
||||
// hit the wall
|
||||
switch (stand) {
|
||||
case STAND_AIR :
|
||||
setAnimation(ANIM_SMASH_JUMP);
|
||||
velocity.x = -velocity.x * 0.5f;
|
||||
velocity.z = -velocity.z * 0.5f;
|
||||
velocity.y = 0.0f;
|
||||
if (state != STATE_UP_JUMP && state != STATE_REACH) {
|
||||
setAnimation(ANIM_SMASH_JUMP);
|
||||
velocity.x = -velocity.x * 0.5f;
|
||||
velocity.z = -velocity.z * 0.5f;
|
||||
velocity.y = 0.0f;
|
||||
} else
|
||||
velocity.x = velocity.z = 0.0f;
|
||||
break;
|
||||
case STAND_GROUND :
|
||||
if (delta >= 256 * 4 && state == STATE_RUN)
|
||||
if (delta <= -256 * 4 && state == STATE_RUN)
|
||||
setAnimation(ANIM_SMASH_RUN_LEFT); // TODO: RIGHT
|
||||
else
|
||||
setAnimation(ANIM_STAND);
|
||||
|
22
src/level.h
22
src/level.h
@ -291,10 +291,8 @@ struct Level {
|
||||
MeshBuilder::MeshInfo *m = getMeshInfoByOffset(meshOffset);
|
||||
if (!m) return; // invisible mesh (level.meshOffsets[meshOffset] == 0) camera target entity etc.
|
||||
|
||||
if (!m->collider.radius || camera->frustum->isVisible(Core::mModel * m->center, m->collider.radius * 2)) {
|
||||
Core::active.shader->setParam(uModel, Core::mModel);
|
||||
mesh->renderMesh(m);
|
||||
}
|
||||
Core::active.shader->setParam(uModel, Core::mModel);
|
||||
mesh->renderMesh(m);
|
||||
}
|
||||
|
||||
float lerpAngle(float a, float b, float t) {
|
||||
@ -335,9 +333,9 @@ struct Level {
|
||||
Controller *controller = (Controller*)entity.controller;
|
||||
|
||||
if (controller) {
|
||||
anim = &level.anims[controller->animIndex];
|
||||
angle = controller->angle;
|
||||
fTime = controller->animTime;
|
||||
anim = &level.anims[controller->animIndex];
|
||||
} else {
|
||||
anim = &level.anims[model.animation];
|
||||
angle = vec3(0.0f, entity.rotation / 16384.0f * PI * 0.5f, 0.0f);
|
||||
@ -367,15 +365,21 @@ struct Level {
|
||||
nextAnim = anim;
|
||||
|
||||
TR::AnimFrame *frameB = (TR::AnimFrame*)&level.frameData[(nextAnim->frameOffset + fIndexB * fSize) >> 1];
|
||||
TR::Node *node = (int)model.node < level.nodesDataSize ? (TR::Node*)&level.nodesData[model.node] : NULL;
|
||||
|
||||
int sIndex = 0;
|
||||
mat4 stack[20];
|
||||
vec3 bmin = frameA->box.min().lerp(frameB->box.min(), k);
|
||||
vec3 bmax = frameA->box.max().lerp(frameB->box.max(), k);
|
||||
if (!camera->frustum->isVisible(Core::mModel, bmin, bmax))
|
||||
return;
|
||||
|
||||
TR::Node *node = (int)model.node < level.nodesDataSize ? (TR::Node*)&level.nodesData[model.node] : NULL;
|
||||
|
||||
mat4 m;
|
||||
m.identity();
|
||||
m.translate(((vec3)frameA->pos).lerp(frameB->pos, k));
|
||||
|
||||
int sIndex = 0;
|
||||
mat4 stack[20];
|
||||
|
||||
for (int i = 0; i < model.mCount; i++) {
|
||||
|
||||
if (i > 0 && node) {
|
||||
@ -552,7 +556,7 @@ struct Level {
|
||||
// Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
|
||||
// Debug::Level::lights(level);
|
||||
// Debug::Level::portals(level);
|
||||
// Debug::Level::meshes(level);
|
||||
Debug::Level::meshes(level);
|
||||
Debug::end();
|
||||
#endif
|
||||
}
|
||||
|
@ -174,7 +174,6 @@ void freeGL(HGLRC hRC) {
|
||||
wglDeleteContext(hRC);
|
||||
}
|
||||
|
||||
HDC hDC;
|
||||
|
||||
int main() {
|
||||
#ifdef _DEBUG
|
||||
@ -190,7 +189,7 @@ int main() {
|
||||
|
||||
joyInit();
|
||||
|
||||
hDC = GetDC(hWnd);
|
||||
HDC hDC = GetDC(hWnd);
|
||||
HGLRC hRC = initGL(hDC);
|
||||
Game::init();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user