1
0
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:
XProger 2016-09-13 15:51:38 +03:00
parent 578cc74d2b
commit c4c6218604
7 changed files with 92 additions and 41 deletions

Binary file not shown.

View File

@ -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 &center, 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;
}

View File

@ -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 &center, 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;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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
}

View File

@ -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();