mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-06 13:16:52 +02:00
#5 fix portals culling, add camera controller
This commit is contained in:
BIN
bin/OpenLara.exe
BIN
bin/OpenLara.exe
Binary file not shown.
333
src/camera.h
333
src/camera.h
@@ -2,135 +2,194 @@
|
||||
#define H_CAMERA
|
||||
|
||||
#include "core.h"
|
||||
#include "controller.h"
|
||||
|
||||
#define MAX_CLIP_PLANES 16
|
||||
#define MAX_CLIP_PLANES 10
|
||||
|
||||
struct Camera {
|
||||
|
||||
struct Frustum {
|
||||
struct Frustum {
|
||||
|
||||
struct Poly {
|
||||
vec3 vertices[MAX_CLIP_PLANES];
|
||||
int count;
|
||||
};
|
||||
struct Poly {
|
||||
vec3 vertices[MAX_CLIP_PLANES];
|
||||
int count;
|
||||
};
|
||||
|
||||
vec3 pos;
|
||||
vec4 planes[MAX_CLIP_PLANES];
|
||||
int count;
|
||||
vec3 pos;
|
||||
vec4 planes[MAX_CLIP_PLANES];
|
||||
int count;
|
||||
#ifdef _DEBUG
|
||||
int dbg;
|
||||
Poly debugPoly;
|
||||
#endif
|
||||
void calcPlanes(const mat4 &m) {
|
||||
#ifdef _DEBUG
|
||||
dbg = 0;
|
||||
#endif
|
||||
count = 5;
|
||||
planes[0] = vec4(m.e30 - m.e20, m.e31 - m.e21, m.e32 - m.e22, m.e33 - m.e23); // near
|
||||
planes[1] = vec4(m.e30 - m.e10, m.e31 - m.e11, m.e32 - m.e12, m.e33 - m.e13); // top
|
||||
planes[2] = vec4(m.e30 - m.e00, m.e31 - m.e01, m.e32 - m.e02, m.e33 - m.e03); // right
|
||||
planes[3] = vec4(m.e30 + m.e10, m.e31 + m.e11, m.e32 + m.e12, m.e33 + m.e13); // bottom
|
||||
planes[4] = vec4(m.e30 + m.e00, m.e31 + m.e01, m.e32 + m.e02, m.e33 + m.e03); // left
|
||||
for (int i = 0; i < count; i++)
|
||||
planes[i] *= 1.0f / planes[i].xyz.length();
|
||||
}
|
||||
|
||||
void calcPlanes(const mat4 &m) {
|
||||
count = 4;
|
||||
planes[0] = vec4(m.e30 - m.e00, m.e31 - m.e01, m.e32 - m.e02, m.e33 - m.e03); // right
|
||||
planes[1] = vec4(m.e30 + m.e00, m.e31 + m.e01, m.e32 + m.e02, m.e33 + m.e03); // left
|
||||
planes[2] = vec4(m.e30 - m.e10, m.e31 - m.e11, m.e32 - m.e12, m.e33 - m.e13); // top
|
||||
planes[3] = vec4(m.e30 + m.e10, m.e31 + m.e11, m.e32 + m.e12, m.e33 + m.e13); // bottom
|
||||
for (int i = 0; i < count; i++)
|
||||
planes[i] *= 1.0f / planes[i].xyz.length();
|
||||
void calcPlanes(const Poly &poly) {
|
||||
count = 1 + poly.count; // add one for near plane (not changing)
|
||||
ASSERT(count < MAX_CLIP_PLANES);
|
||||
if (count < 4) return;
|
||||
|
||||
vec3 e1 = poly.vertices[0] - pos;
|
||||
for (int i = 1; i < count; i++) {
|
||||
vec3 e2 = poly.vertices[i % poly.count] - pos;
|
||||
planes[i].xyz = e1.cross(e2).normal();
|
||||
planes[i].w = -(pos.dot(planes[i].xyz));
|
||||
e1 = e2;
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
dbg++;
|
||||
debugPoly = poly;
|
||||
#endif
|
||||
}
|
||||
|
||||
void calcPlanes(const Poly &poly) {
|
||||
count = poly.count;
|
||||
ASSERT(count < MAX_CLIP_PLANES);
|
||||
if (!count) return;
|
||||
#ifdef _DEBUG
|
||||
void debug() {
|
||||
if (debugPoly.count < 3) return;
|
||||
|
||||
vec3 e1 = poly.vertices[0] - pos;
|
||||
for (int i = 0; i < count; i++) {
|
||||
vec3 e2 = poly.vertices[(i + 1) % count] - pos;
|
||||
planes[i].xyz = e1.cross(e2).normal();
|
||||
planes[i].w = -(pos.dot(planes[i].xyz));
|
||||
e1 = e2;
|
||||
glUseProgram(0);
|
||||
Core::setBlending(bmAdd);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int i = 0; i < debugPoly.count; i++) {
|
||||
glVertex3fv((GLfloat*)&pos);
|
||||
glVertex3fv((GLfloat*)&debugPoly.vertices[i]);
|
||||
glVertex3fv((GLfloat*)&debugPoly.vertices[(i + 1) % debugPoly.count]);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glColor3f(0, 1, 0);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i <= debugPoly.count; i++) {
|
||||
glVertex3fv((GLfloat*)&debugPoly.vertices[i % debugPoly.count]);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
Core::setBlending(bmAlpha);
|
||||
}
|
||||
#endif
|
||||
|
||||
void clipPlane(const Poly &src, Poly &dst, const vec4 &plane) {
|
||||
dst.count = 0;
|
||||
if (!src.count) return;
|
||||
|
||||
float t1 = src.vertices[0].dot(plane.xyz) + plane.w;
|
||||
|
||||
for (int i = 0; i < src.count; i++) {
|
||||
const vec3 &v1 = src.vertices[i];
|
||||
const vec3 &v2 = src.vertices[(i + 1) % src.count];
|
||||
|
||||
float t2 = v2.dot(plane.xyz) + plane.w;
|
||||
|
||||
// hack for big float numbers
|
||||
int s1 = sign((int)t1);
|
||||
int s2 = sign((int)t2);
|
||||
|
||||
if (s1 >= 0) {
|
||||
dst.vertices[dst.count++] = v1;
|
||||
ASSERT(dst.count < MAX_CLIP_PLANES);
|
||||
}
|
||||
}
|
||||
|
||||
void clipPlane(const Poly &src, Poly &dst, const vec4 &plane) {
|
||||
dst.count = 0;
|
||||
if (!src.count) return;
|
||||
|
||||
float t1 = src.vertices[0].dot(plane.xyz) + plane.w;
|
||||
|
||||
for (int i = 0; i < src.count; i++) {
|
||||
const vec3 &v1 = src.vertices[i];
|
||||
const vec3 &v2 = src.vertices[(i + 1) % src.count];
|
||||
|
||||
float t2 = v2.dot(plane.xyz) + plane.w;
|
||||
|
||||
if (t1 >= 0.0f) {
|
||||
dst.vertices[dst.count++] = v1;
|
||||
ASSERT(dst.count < MAX_CLIP_PLANES);
|
||||
}
|
||||
|
||||
if (t1 * t2 < 0.0f) {
|
||||
float k1 = t2 / (t2 - t1);
|
||||
float k2 = t1 / (t2 - t1);
|
||||
dst.vertices[dst.count++] = v1 * k1 - v2 * k2;
|
||||
ASSERT(dst.count < MAX_CLIP_PLANES);
|
||||
}
|
||||
|
||||
t1 = t2;
|
||||
if (s1 * s2 < 0) {
|
||||
float k1 = t2 / (t2 - t1);
|
||||
float k2 = t1 / (t2 - t1);
|
||||
dst.vertices[dst.count++] = v1 * (float)k1 - v2 * (float)k2;
|
||||
ASSERT(dst.count < MAX_CLIP_PLANES);
|
||||
}
|
||||
}
|
||||
|
||||
bool clipByPortal(const vec3 *vertices, const vec3 &normal) { // 4 vertices
|
||||
if (normal.dot(pos - vertices[0]) < 0.0f) // check portal winding order
|
||||
t1 = t2;
|
||||
}
|
||||
}
|
||||
|
||||
bool clipByPortal(const vec3 *vertices, int vCount, const vec3 &normal) {
|
||||
if (normal.dot(pos - vertices[0]) < 0.0f) // check portal winding order
|
||||
return false;
|
||||
|
||||
Poly poly[2];
|
||||
|
||||
poly[0].count = vCount;
|
||||
memmove(poly[0].vertices, vertices, sizeof(vec3) * poly[0].count);
|
||||
#ifdef _DEBUG
|
||||
debugPoly.count = 0;
|
||||
#endif
|
||||
int j = 0;
|
||||
for (int i = 1; i < count; i++, j ^= 1)
|
||||
clipPlane(poly[j], poly[j ^ 1], planes[i]);
|
||||
|
||||
calcPlanes(poly[j]);
|
||||
return count >= 4;
|
||||
}
|
||||
|
||||
bool isVisible(const vec3 &min, const vec3 &max) const {
|
||||
if (count < 4) return false;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
const vec3 &n = planes[i].xyz;
|
||||
const float d = -planes[i].w;
|
||||
|
||||
if (n.dot(max) < d &&
|
||||
n.dot(min) < d &&
|
||||
n.dot(vec3(min.x, max.y, max.z)) < d &&
|
||||
n.dot(vec3(max.x, min.y, max.z)) < d &&
|
||||
n.dot(vec3(min.x, min.y, max.z)) < d &&
|
||||
n.dot(vec3(max.x, max.y, min.z)) < d &&
|
||||
n.dot(vec3(min.x, max.y, min.z)) < d &&
|
||||
n.dot(vec3(max.x, min.y, min.z)) < d)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Poly poly[2];
|
||||
bool isVisible(const vec3 ¢er, float radius) {
|
||||
if (count < 4) return false;
|
||||
|
||||
poly[0].count = 4;
|
||||
memmove(poly[0].vertices, vertices, sizeof(vec3) * poly[0].count);
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < count; i++, j ^= 1)
|
||||
clipPlane(poly[j], poly[j ^ 1], planes[i]);
|
||||
|
||||
if (poly[j].count < 3)
|
||||
for (int i = 0; i < count; i++)
|
||||
if (planes[i].xyz.dot(center) + planes[i].w < -radius)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
calcPlanes(poly[j]);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool isVisible(const vec3 &min, const vec3 &max) const {
|
||||
if (count < 3) return false;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
const vec3 &n = planes[i].xyz;
|
||||
const float d = -planes[i].w;
|
||||
|
||||
if (n.dot(max) < d &&
|
||||
n.dot(vec3(min.x, max.y, max.z)) < d &&
|
||||
n.dot(vec3(max.x, min.y, max.z)) < d &&
|
||||
n.dot(vec3(min.x, min.y, max.z)) < d &&
|
||||
n.dot(vec3(max.x, max.y, min.z)) < d &&
|
||||
n.dot(vec3(min.x, max.y, min.z)) < d &&
|
||||
n.dot(vec3(max.x, min.y, min.z)) < d &&
|
||||
n.dot(min) < d)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isVisible(const vec3 ¢er, float radius) {
|
||||
if (count < 3) return false;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
if (planes[i].xyz.dot(center) + planes[i].w < -radius)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} *frustum;
|
||||
struct Camera : Controller {
|
||||
Controller *owner;
|
||||
Frustum *frustum;
|
||||
|
||||
float fov, znear, zfar;
|
||||
vec3 pos, angle, offset, deltaPos, deltaAngle, targetDeltaPos, targetAngle;
|
||||
vec3 pos, target;
|
||||
|
||||
Camera() : frustum(new Frustum()) {}
|
||||
int room;
|
||||
|
||||
Camera(TR::Level *level, Controller *owner) : Controller(level, owner->entity), owner(owner), frustum(new Frustum()) {
|
||||
fov = 75.0f;
|
||||
znear = 0.1f * 2048.0f;
|
||||
zfar = 1000.0f * 2048.0f;
|
||||
angle.y += PI;
|
||||
|
||||
room = owner->getEntity().room;
|
||||
}
|
||||
|
||||
~Camera() {
|
||||
delete frustum;
|
||||
}
|
||||
|
||||
void update() {
|
||||
virtual TR::Room& getRoom() {
|
||||
return level->rooms[room];
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
#ifdef FREE_CAMERA
|
||||
vec3 dir = vec3(sinf(angle.y - PI) * cosf(-angle.x), -sinf(-angle.x), cosf(angle.y - PI) * cosf(-angle.x));
|
||||
vec3 v = vec3(0);
|
||||
@@ -141,35 +200,73 @@ struct Camera {
|
||||
if (Input::down[ikA]) v = v - dir.cross(vec3(0, 1, 0));
|
||||
pos = pos + v.normal() * (Core::deltaTime * 2048.0f);
|
||||
#endif
|
||||
deltaPos = deltaPos.lerp(targetDeltaPos, Core::deltaTime * 10.0f);
|
||||
angle = angle.lerp(targetAngle, Core::deltaTime);
|
||||
// deltaPos = deltaPos.lerp(targetDeltaPos, Core::deltaTime * 10.0f);
|
||||
// angle = angle.lerp(targetAngle, Core::deltaTime);
|
||||
|
||||
|
||||
if (Input::down[ikMouseL]) {
|
||||
vec2 delta = Input::mouse.pos - Input::mouse.start.L;
|
||||
deltaAngle.x -= delta.y * 0.01f;
|
||||
deltaAngle.y -= delta.x * 0.01f;
|
||||
deltaAngle.x = min(max(deltaAngle.x + angle.x, -PI * 0.5f + EPS), PI * 0.5f - EPS) - angle.x;
|
||||
angle.x += delta.y * 0.01f;
|
||||
// angle.y -= delta.x * 0.01f;
|
||||
Input::mouse.start.L = Input::mouse.pos;
|
||||
}
|
||||
|
||||
// angle.x = owner->angle.x;
|
||||
angle.y = PI - owner->angle.y;
|
||||
angle.z = 0.0f;
|
||||
|
||||
angle.x = min(max(angle.x, -80 * DEG2RAD), 80 * DEG2RAD);
|
||||
|
||||
vec3 dir = vec3(sinf(PI - angle.y) * cosf(-angle.x), -sinf(-angle.x), cosf(PI - angle.y) * cosf(-angle.x));
|
||||
|
||||
float height = owner->inWater ? 256.0f : 768.0f;
|
||||
|
||||
target = vec3(owner->pos.x, owner->pos.y - height, owner->pos.z);
|
||||
pos = target - dir * 1024.0;
|
||||
|
||||
FloorInfo info = getFloorInfo((int)pos.x, (int)pos.z);
|
||||
|
||||
if (info.roomNext != 255)
|
||||
room = info.roomNext;
|
||||
|
||||
if (pos.y < info.ceiling) {
|
||||
if (info.roomAbove != 255)
|
||||
room = info.roomAbove;
|
||||
else
|
||||
if (info.ceiling != 0xffff8100)
|
||||
pos.y = info.ceiling;
|
||||
}
|
||||
|
||||
if (pos.y > info.floor) {
|
||||
if (info.roomBelow != 255)
|
||||
room = info.roomBelow;
|
||||
else
|
||||
if (info.floor != 0xffff8100)
|
||||
pos.y = info.floor;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Core::mView.identity();
|
||||
Core::mView.translate(vec3(-offset.x, -offset.y, -offset.z));
|
||||
Core::mView.rotateZ(-(angle.z + deltaAngle.z));
|
||||
Core::mView.rotateX(-(angle.x + deltaAngle.x));
|
||||
Core::mView.rotateY(-(angle.y + deltaAngle.y));
|
||||
Core::mView.translate(deltaPos - pos);
|
||||
Core::mView.scale(vec3(-1, -1, 1));
|
||||
Core::mViewInv = mat4(pos, target, vec3(0, -1, 0));
|
||||
Core::mView = Core::mViewInv.inverse();
|
||||
Core::mProj = mat4(fov, (float)Core::width / (float)Core::height, znear, zfar);
|
||||
|
||||
Core::mProj = mat4(fov, (float)Core::width / (float)Core::height, znear, zfar);
|
||||
|
||||
Core::mViewProj = Core::mProj * Core::mView;
|
||||
Core::mViewInv = Core::mView.inverse();
|
||||
Core::viewPos = Core::mViewInv.getPos();
|
||||
Core::mViewProj = Core::mProj * Core::mView;
|
||||
Core::viewPos = Core::mViewInv.offset.xyz;
|
||||
|
||||
frustum->pos = Core::viewPos;
|
||||
frustum->calcPlanes(Core::mViewProj);
|
||||
|
||||
#ifdef _DEBUG
|
||||
vec3 offset = vec3(0.0f) - (Input::down[ikR] ? (Core::mViewInv.dir.xyz * 2048 - vec3(0, 2048, 0)) : vec3(0.0f));
|
||||
|
||||
Core::mViewInv = mat4(pos - offset, target - offset, vec3(0, -1, 0));
|
||||
Core::mView = Core::mViewInv.inverse();
|
||||
Core::mProj = mat4(fov, (float)Core::width / (float)Core::height, znear, zfar);
|
||||
|
||||
Core::mViewProj = Core::mProj * Core::mView;
|
||||
Core::viewPos = Core::mViewInv.offset.xyz;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -65,7 +65,7 @@ struct Controller {
|
||||
return level->models[0];
|
||||
}
|
||||
|
||||
TR::Room& getRoom() {
|
||||
virtual TR::Room& getRoom() {
|
||||
int index = getEntity().room;
|
||||
ASSERT(index >= 0 && index < level->roomsCount);
|
||||
return level->rooms[index];
|
||||
@@ -73,9 +73,13 @@ struct Controller {
|
||||
|
||||
TR::Room::Sector& getSector(int x, int z, int &dx, int &dz) {
|
||||
TR::Room &room = getRoom();
|
||||
|
||||
|
||||
int sx = x - room.info.x;
|
||||
int sz = z - room.info.z;
|
||||
|
||||
sx = clamp(sx, 0, (room.xSectors - 1) << 10);
|
||||
sz = clamp(sz, 0, (room.zSectors - 1) << 10);
|
||||
|
||||
dx = sx & 1023; // mod 1024
|
||||
dz = sz & 1023;
|
||||
sx >>= 10; // div 1024
|
||||
@@ -118,11 +122,6 @@ struct Controller {
|
||||
return exists;
|
||||
}
|
||||
|
||||
struct FloorInfo {
|
||||
int floor, ceiling;
|
||||
int roomNext, roomBelow, roomAbove;
|
||||
};
|
||||
|
||||
int getOverlap(int fromX, int fromY, int fromZ, int toX, int toZ, int &delta) {
|
||||
int dx, dz;
|
||||
TR::Room::Sector &s = getSector(fromX, fromZ, dx, dz);
|
||||
@@ -154,6 +153,11 @@ struct Controller {
|
||||
return floor;
|
||||
}
|
||||
|
||||
struct FloorInfo {
|
||||
int floor, ceiling;
|
||||
int roomNext, roomBelow, roomAbove;
|
||||
};
|
||||
|
||||
FloorInfo getFloorInfo(int x, int z) {
|
||||
int dx, dz;
|
||||
TR::Room::Sector &s = getSector(x, z, dx, dz);
|
||||
@@ -259,8 +263,6 @@ struct Controller {
|
||||
#define GLIDE_SPEED 50.0f
|
||||
|
||||
struct Lara : Controller {
|
||||
int sc;
|
||||
bool lState;
|
||||
|
||||
Lara(TR::Level *level, int entity) : Controller(level, entity) {
|
||||
/*
|
||||
@@ -268,6 +270,11 @@ struct Lara : Controller {
|
||||
angle = vec3(0.0f, -0.68f, 0.0f);
|
||||
getEntity().room = 15;
|
||||
*/
|
||||
/*
|
||||
pos = vec3(41015, 3584, 34494);
|
||||
angle = vec3(0.0f, -PI, 0.0f);
|
||||
getEntity().room = 51;
|
||||
*/
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
@@ -425,7 +432,7 @@ struct Lara : Controller {
|
||||
|
||||
#ifdef _DEBUG
|
||||
// show state transitions for current animation
|
||||
|
||||
static bool lState = false;
|
||||
if (Input::down[ikEnter]) {
|
||||
if (!lState) {
|
||||
lState = true;
|
||||
@@ -600,11 +607,11 @@ struct Lara : Controller {
|
||||
fIndex = anim->nextFrame - nextAnim->frameStart;
|
||||
fTime = fIndex / 30.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
move(velocity * dt);
|
||||
collide();
|
||||
|
||||
updateEntity();
|
||||
|
||||
lastFrame = fIndex;
|
||||
}
|
||||
|
97
src/debug.h
97
src/debug.h
@@ -17,6 +17,8 @@ namespace Debug {
|
||||
glPointSize(32);
|
||||
|
||||
glUseProgram(0);
|
||||
Core::active.shader = NULL;
|
||||
Core::active.testures[0] = NULL;
|
||||
}
|
||||
|
||||
void end() {
|
||||
@@ -25,7 +27,8 @@ namespace Debug {
|
||||
|
||||
namespace Draw {
|
||||
|
||||
void box(const vec3 &min, const vec3 &max) {
|
||||
void box(const vec3 &min, const vec3 &max, const vec4 &color) {
|
||||
glColor4fv((GLfloat*)&color);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(min.x, min.y, min.z);
|
||||
glVertex3f(max.x, min.y, min.z);
|
||||
@@ -350,6 +353,98 @@ namespace Debug {
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void meshes(const TR::Level &level) {
|
||||
// static objects
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
TR::Room &r = level.rooms[i];
|
||||
|
||||
for (int j = 0; j < r.meshesCount; j++) {
|
||||
TR::Room::Mesh &m = r.meshes[j];
|
||||
|
||||
TR::StaticMesh *sm = level.getMeshByID(m.meshID);
|
||||
ASSERT(sm != NULL);
|
||||
|
||||
vec3 min, max, offset = vec3(m.x, m.y, m.z);
|
||||
sm->getBox(false, m.rotation, min, max); // visible box
|
||||
|
||||
Debug::Draw::box(offset + min, offset + max, vec4(1, 1, 0, 0.25));
|
||||
|
||||
if (sm->flags == 2) { // collision box
|
||||
sm->getBox(true, m.rotation, min, max);
|
||||
Debug::Draw::box(offset + min - vec3(10.0f), offset + max + vec3(10.0f), vec4(1, 0, 0, 0.50));
|
||||
}
|
||||
|
||||
TR::Mesh *mesh = (TR::Mesh*)&level.meshData[level.meshOffsets[sm->mesh] / 2];
|
||||
|
||||
ASSERT(mesh->radius == 0 || mesh->radius == 0x10000);
|
||||
|
||||
Debug::Draw::sphere(offset + (min + max) * 0.5f, 128, mesh->radius == 0 ? vec4(0, 0, 1, 1) : vec4(0, 1, 0, 1));
|
||||
}
|
||||
}
|
||||
// dynamic objects
|
||||
for (int i = 0; i < level.entitiesCount; i++) {
|
||||
TR::Entity &e = level.entities[i];
|
||||
mat4 matrix;
|
||||
matrix.identity();
|
||||
matrix.translate(vec3(e.x, e.y, e.z));
|
||||
matrix.rotateY(e.rotation / 16384.0f * PI * 0.5f);
|
||||
|
||||
for (int j = 0; j < level.modelsCount; j++) {
|
||||
TR::Model &m = level.models[j];
|
||||
TR::Node *node = m.node < level.nodesDataSize ? (TR::Node*)&level.nodesData[m.node] : NULL;
|
||||
|
||||
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) {
|
||||
for (int k = 0; k < m.mCount; k++) {
|
||||
|
||||
if (k > 0 && node) {
|
||||
TR::Node &t = node[k - 1];
|
||||
|
||||
if (t.flags & 0x01) joint = stack[--sIndex];
|
||||
if (t.flags & 0x02) stack[sIndex++] = joint;
|
||||
|
||||
ASSERT(sIndex >= 0 && sIndex < 20);
|
||||
|
||||
joint.translate(vec3(t.x, t.y, t.z));
|
||||
}
|
||||
|
||||
vec3 a = frame ? frame->getAngle(k) : vec3(0.0f);
|
||||
|
||||
mat4 rot;
|
||||
rot.identity();
|
||||
rot.rotateY(a.y);
|
||||
rot.rotateX(a.x);
|
||||
rot.rotateZ(a.z);
|
||||
|
||||
joint = joint * rot;
|
||||
|
||||
int offset = level.meshOffsets[m.mStart + k];
|
||||
TR::Mesh *mesh = (TR::Mesh*)&level.meshData[offset / 2];
|
||||
Debug::Draw::sphere(matrix * joint * mesh->center, mesh->radius & 0x3FF, mesh->radius > 0x3FF ? vec4(1, 0, 0, 0.5f) : vec4(0, 1, 1, 0.5f));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
61
src/format.h
61
src/format.h
@@ -244,7 +244,7 @@ namespace TR {
|
||||
uint16 rotation;
|
||||
uint16 intensity;
|
||||
uint16 meshID;
|
||||
uint16 align; // ! not exists in file !
|
||||
uint16 flags; // ! not exists in file !
|
||||
} *meshes;
|
||||
};
|
||||
|
||||
@@ -342,11 +342,20 @@ namespace TR {
|
||||
};
|
||||
|
||||
struct AnimFrame {
|
||||
int16 minX, minY, minZ; // Bounding box (low)
|
||||
int16 maxX, maxY, maxZ; // Bounding box (high)
|
||||
int16 x, y, z; // Starting offset for this model
|
||||
TR::Vertex min; // Bounding box (low)
|
||||
TR::Vertex max; // Bounding box (high)
|
||||
TR::Vertex pos; // Starting offset for this model
|
||||
int16 aCount;
|
||||
uint16 angles[0]; // angle frames in YXZ order
|
||||
|
||||
vec3 getAngle(int index) {
|
||||
#define ANGLE_SCALE (2.0f * PI / 1024.0f)
|
||||
|
||||
uint16 b = angles[index * 2 + 0];
|
||||
uint16 a = angles[index * 2 + 1];
|
||||
|
||||
return vec3((a & 0x3FF0) >> 4, ( ((a & 0x000F) << 6) | ((b & 0xFC00) >> 10)), b & 0x03FF) * ANGLE_SCALE;
|
||||
}
|
||||
};
|
||||
|
||||
struct AnimTexture {
|
||||
@@ -372,9 +381,40 @@ namespace TR {
|
||||
struct StaticMesh {
|
||||
uint32 id; // Static Mesh Identifier
|
||||
uint16 mesh; // Mesh (offset into MeshPointers[])
|
||||
Vertex vBox[2];
|
||||
Vertex cBox[2];
|
||||
struct MinMax {
|
||||
int16 minX, maxX, minY, maxY, minZ, maxZ;
|
||||
} box[2]; // visible (minX, maxX, minY, maxY, minZ, maxZ) & collision
|
||||
uint16 flags;
|
||||
|
||||
void getBox(bool collision, int rotation, vec3 &min, vec3 &max) {
|
||||
int k = rotation / 16384;
|
||||
|
||||
MinMax &m = box[collision];
|
||||
|
||||
ASSERT(m.minX <= m.maxX && m.minY <= m.maxY && m.minZ <= m.maxZ);
|
||||
|
||||
switch (k) {
|
||||
case 0 :
|
||||
min = vec3(m.minX, m.minY, m.minZ);
|
||||
max = vec3(m.maxX, m.maxY, m.maxZ);
|
||||
break;
|
||||
case 1 :
|
||||
min = vec3(m.minZ, m.minY, -m.maxX);
|
||||
max = vec3(m.maxZ, m.maxY, -m.minX);
|
||||
break;
|
||||
case 2 :
|
||||
min = vec3(-m.maxX, m.minY, -m.maxZ);
|
||||
max = vec3(-m.minX, m.maxY, -m.minZ);
|
||||
break;
|
||||
case 3 :
|
||||
min = vec3(-m.maxZ, m.minY, m.minX);
|
||||
max = vec3(-m.minZ, m.maxY, m.maxX);
|
||||
break;
|
||||
default :
|
||||
ASSERT(false);
|
||||
}
|
||||
ASSERT(min.x <= max.x && min.y <= max.y && min.z <= max.z);
|
||||
}
|
||||
};
|
||||
|
||||
struct Tile {
|
||||
@@ -589,7 +629,7 @@ namespace TR {
|
||||
// meshes
|
||||
r.meshes = new Room::Mesh[stream.read(r.meshesCount)];
|
||||
for (int i = 0; i < r.meshesCount; i++)
|
||||
stream.raw(&r.meshes[i], sizeof(r.meshes[i]) - sizeof(r.meshes[i].align));
|
||||
stream.raw(&r.meshes[i], sizeof(r.meshes[i]) - sizeof(r.meshes[i].flags));
|
||||
// misc flags
|
||||
stream.read(r.alternateRoom);
|
||||
stream.read(r.flags);
|
||||
@@ -706,6 +746,13 @@ namespace TR {
|
||||
delete[] soundData;
|
||||
delete[] soundOffsets;
|
||||
}
|
||||
|
||||
TR::StaticMesh* getMeshByID(int id) const { // TODO: map this
|
||||
for (int i = 0; i < staticMeshesCount; i++)
|
||||
if (staticMeshes[i].id == id)
|
||||
return &staticMeshes[i];
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
230
src/level.h
230
src/level.h
@@ -7,6 +7,7 @@
|
||||
#include "controller.h"
|
||||
#include "camera.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#include "debug.h"
|
||||
#endif
|
||||
@@ -24,9 +25,9 @@ struct Level {
|
||||
MeshBuilder *mesh;
|
||||
|
||||
Controller *lara;
|
||||
Camera *camera;
|
||||
|
||||
float time;
|
||||
Camera camera;
|
||||
|
||||
Level(Stream &stream) : level{stream}, time(0.0f) {
|
||||
mesh = new MeshBuilder(level);
|
||||
@@ -42,15 +43,8 @@ struct Level {
|
||||
break;
|
||||
}
|
||||
|
||||
lara = new Lara(&level, entity);
|
||||
|
||||
camera.fov = 75.0f;
|
||||
camera.znear = 0.1f * 2048.0f;
|
||||
camera.zfar = 1000.0f * 2048.0f;
|
||||
camera.offset = vec3(0, 0, 1024);
|
||||
camera.deltaPos = vec3(0.0f, 768.0f, 0.0f);
|
||||
camera.deltaAngle = vec3(0.0f, PI, 0.0f);
|
||||
camera.angle = vec3(0.0f);
|
||||
lara = new Lara(&level, entity);
|
||||
camera = new Camera(&level, lara);
|
||||
}
|
||||
|
||||
~Level() {
|
||||
@@ -59,6 +53,7 @@ struct Level {
|
||||
delete atlas;
|
||||
delete mesh;
|
||||
|
||||
delete camera;
|
||||
delete lara;
|
||||
}
|
||||
|
||||
@@ -144,13 +139,6 @@ struct Level {
|
||||
*/
|
||||
}
|
||||
|
||||
TR::StaticMesh* getMeshByID(int id) {
|
||||
for (int i = 0; i < level.staticMeshesCount; i++)
|
||||
if (level.staticMeshes[i].id == id)
|
||||
return &level.staticMeshes[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Shader *setRoomShader(const TR::Room &room, float intensity) {
|
||||
if (room.flags & TR::ROOM_FLAG_WATER) {
|
||||
Core::color = vec4(0.6f * intensity, 0.9f * intensity, 0.9f * intensity, 1.0f);
|
||||
@@ -161,107 +149,120 @@ struct Level {
|
||||
}
|
||||
}
|
||||
|
||||
void renderRoom(int index) {
|
||||
ASSERT(index >= 0 && index < level.roomsCount);
|
||||
|
||||
TR::Room &room = level.rooms[index];
|
||||
|
||||
if (room.flags & TR::ROOM_FLAG_VISIBLE) return; // already rendered
|
||||
room.flags |= TR::ROOM_FLAG_VISIBLE;
|
||||
void renderRoom(int roomIndex, int from = -1) {
|
||||
ASSERT(roomIndex >= 0 && roomIndex < level.roomsCount);
|
||||
|
||||
TR::Room &room = level.rooms[roomIndex];
|
||||
vec3 offset = vec3(room.info.x, 0.0f, room.info.z);
|
||||
|
||||
mat4 m = Core::mModel;
|
||||
Core::mModel.translate(offset);
|
||||
Core::ambient = vec3(1.0f);
|
||||
Core::lightColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
Shader *sh = setRoomShader(room, 1.0f);
|
||||
|
||||
sh->bind();
|
||||
sh->setParam(uModel, Core::mModel);
|
||||
sh->setParam(uColor, Core::color);
|
||||
sh->setParam(uAmbient, Core::ambient);
|
||||
sh->setParam(uLightColor, Core::lightColor);
|
||||
|
||||
// render room geometry
|
||||
mesh->renderRoomGeometry(index);
|
||||
|
||||
// render room sprites
|
||||
if (mesh->hasRoomSprites(index)) {
|
||||
sh = shaders[shSprite];
|
||||
sh->bind();
|
||||
sh->setParam(uModel, Core::mModel);
|
||||
sh->setParam(uColor, Core::color);
|
||||
mesh->renderRoomSprites(index);
|
||||
}
|
||||
|
||||
Core::mModel = m;
|
||||
|
||||
// meshes
|
||||
// room static meshes
|
||||
for (int i = 0; i < room.meshesCount; i++) {
|
||||
TR::Room::Mesh &rMesh = room.meshes[i];
|
||||
TR::StaticMesh *sMesh = getMeshByID(rMesh.meshID);
|
||||
if ((rMesh.flags & TR::ROOM_FLAG_VISIBLE)) continue; // skip if already rendered
|
||||
|
||||
TR::StaticMesh *sMesh = level.getMeshByID(rMesh.meshID);
|
||||
ASSERT(sMesh != NULL);
|
||||
|
||||
mat4 m = Core::mModel;
|
||||
Core::mModel.translate(vec3((float)rMesh.x, (float)rMesh.y, (float)rMesh.z));
|
||||
// check visibility
|
||||
vec3 min, max, offset = vec3(rMesh.x, rMesh.y, rMesh.z);
|
||||
sMesh->getBox(false, rMesh.rotation, min, max);
|
||||
if (!camera->frustum->isVisible(offset + min, offset + max))
|
||||
continue;
|
||||
rMesh.flags |= TR::ROOM_FLAG_VISIBLE;
|
||||
|
||||
// set light parameters
|
||||
getLight(offset, roomIndex);
|
||||
|
||||
// render static mesh
|
||||
mat4 mTemp = Core::mModel;
|
||||
Core::mModel.translate(offset);
|
||||
Core::mModel.rotateY(rMesh.rotation / 16384.0f * PI * 0.5f);
|
||||
|
||||
// TODO: check visibility for sMesh.vBox
|
||||
|
||||
getLight(vec3(rMesh.x, rMesh.y, rMesh.z), index);
|
||||
|
||||
renderMesh(sMesh->mesh);
|
||||
|
||||
Core::mModel = m;
|
||||
Core::mModel = mTemp;
|
||||
}
|
||||
|
||||
Camera::Frustum *camFrustum = camera.frustum; // push camera frustum
|
||||
Camera::Frustum frustum = *camFrustum;
|
||||
camera.frustum = &frustum;
|
||||
|
||||
// room geometry & sprites
|
||||
if (!(room.flags & TR::ROOM_FLAG_VISIBLE)) { // skip if already rendered
|
||||
room.flags |= TR::ROOM_FLAG_VISIBLE;
|
||||
|
||||
Core::lightColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
Core::ambient = vec3(1.0f);
|
||||
sh->setParam(uLightColor, Core::lightColor);
|
||||
sh->setParam(uAmbient, Core::ambient);
|
||||
|
||||
mat4 mTemp = Core::mModel;
|
||||
Core::mModel.translate(offset);
|
||||
|
||||
// render room geometry
|
||||
sh->setParam(uModel, Core::mModel);
|
||||
mesh->renderRoomGeometry(roomIndex);
|
||||
|
||||
// render room sprites
|
||||
if (mesh->hasRoomSprites(roomIndex)) {
|
||||
sh = shaders[shSprite];
|
||||
sh->bind();
|
||||
sh->setParam(uModel, Core::mModel);
|
||||
sh->setParam(uColor, Core::color);
|
||||
mesh->renderRoomSprites(roomIndex);
|
||||
}
|
||||
|
||||
Core::mModel = mTemp;
|
||||
}
|
||||
|
||||
// render rooms through portals recursively
|
||||
Frustum *camFrustum = camera->frustum; // push camera frustum
|
||||
Frustum frustum;
|
||||
camera->frustum = &frustum;
|
||||
|
||||
for (int i = 0; i < room.portalsCount; i++) {
|
||||
TR::Room::Portal &p = room.portals[i];
|
||||
|
||||
vec3 v[4] = {
|
||||
if (p.roomIndex == from) continue;
|
||||
|
||||
vec3 v[] = {
|
||||
offset + p.vertices[0],
|
||||
offset + p.vertices[1],
|
||||
offset + p.vertices[2],
|
||||
offset + p.vertices[3],
|
||||
};
|
||||
|
||||
if (frustum.clipByPortal(v, p.normal)) {
|
||||
renderRoom(p.roomIndex);
|
||||
frustum = *camFrustum;
|
||||
}
|
||||
frustum = *camFrustum;
|
||||
if (frustum.clipByPortal(v, 4, p.normal))
|
||||
renderRoom(p.roomIndex, roomIndex);
|
||||
}
|
||||
camera.frustum = camFrustum; // pop camera frustum
|
||||
camera->frustum = camFrustum; // pop camera frustum
|
||||
|
||||
#ifdef _DEBUG
|
||||
glColor3f(0, 0.05, 0);
|
||||
camera->frustum->debug();
|
||||
#endif
|
||||
}
|
||||
|
||||
MeshBuilder::MeshInfo* getMeshInfoByOffset(uint32 meshOffset) {
|
||||
if (!level.meshOffsets[meshOffset] && meshOffset)
|
||||
return NULL;
|
||||
|
||||
for (int i = 0; i < mesh->mCount; i++)
|
||||
if (mesh->meshInfo[i].offset == level.meshOffsets[meshOffset])
|
||||
return &mesh->meshInfo[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void renderMesh(uint32 meshOffset) {
|
||||
if (!level.meshOffsets[meshOffset] && meshOffset)
|
||||
return;
|
||||
MeshBuilder::MeshInfo *m = getMeshInfoByOffset(meshOffset);
|
||||
ASSERT(m != NULL);
|
||||
if (!m) return;
|
||||
|
||||
for (int i = 0; i < mesh->mCount; i++)
|
||||
if (mesh->meshInfo[i].offset == level.meshOffsets[meshOffset]) {
|
||||
MeshBuilder::MeshInfo &m = mesh->meshInfo[i];
|
||||
|
||||
if (camera.frustum->isVisible(Core::mModel * m.center, m.radius)) {
|
||||
Core::active.shader->setParam(uModel, Core::mModel);
|
||||
mesh->renderMesh(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 getAngle(TR::AnimFrame *frame, int index) {
|
||||
#define ANGLE_SCALE (2.0f * PI / 1024.0f)
|
||||
|
||||
uint16 b = frame->angles[index * 2 + 0];
|
||||
uint16 a = frame->angles[index * 2 + 1];
|
||||
|
||||
return vec3((a & 0x3FF0) >> 4, ( ((a & 0x000F) << 6) | ((b & 0xFC00) >> 10)), b & 0x03FF) * ANGLE_SCALE;
|
||||
if ((m->radius & 0xFFFF) == 0 || camera->frustum->isVisible(Core::mModel * m->center, (m->radius & 0x3FF)) * 2) {
|
||||
Core::active.shader->setParam(uModel, Core::mModel);
|
||||
mesh->renderMesh(m);
|
||||
}
|
||||
}
|
||||
|
||||
float lerpAngle(float a, float b, float t) {
|
||||
@@ -327,23 +328,7 @@ struct Level {
|
||||
} else
|
||||
nextAnim = anim;
|
||||
|
||||
// LOG("%d %f\n", fIndexA, fTime);
|
||||
|
||||
|
||||
TR::AnimFrame *frameB = (TR::AnimFrame*)&level.frameData[(nextAnim->frameOffset + fIndexB * fSize) >> 1];
|
||||
|
||||
|
||||
|
||||
// ASSERT(fpSize == fSize);
|
||||
// fSize = fpSize;
|
||||
|
||||
// LOG("%d\n", fIndex % fCount);
|
||||
//if (fCount > 1) LOG("%d %d\n", model->id, fCount);
|
||||
// LOG("%d\n", fIndex % fCount);
|
||||
|
||||
|
||||
// Debug::Draw::box(Box(vec3(frameA->minX, frameA->minY, frameA->minZ), vec3(frameA->maxX, frameA->maxY, frameA->maxZ)));
|
||||
|
||||
TR::Node *node = (int)model.node < level.nodesDataSize ? (TR::Node*)&level.nodesData[model.node] : NULL;
|
||||
|
||||
int sIndex = 0;
|
||||
@@ -351,7 +336,7 @@ struct Level {
|
||||
|
||||
mat4 m;
|
||||
m.identity();
|
||||
m.translate(vec3(frameA->x, frameA->y, frameA->z).lerp(vec3(frameB->x, frameB->y, frameB->z), k));
|
||||
m.translate(((vec3)frameA->pos).lerp(frameB->pos, k));
|
||||
|
||||
for (int i = 0; i < model.mCount; i++) {
|
||||
|
||||
@@ -361,13 +346,12 @@ struct Level {
|
||||
if (t.flags & 0x01) m = stack[--sIndex];
|
||||
if (t.flags & 0x02) stack[sIndex++] = m;
|
||||
|
||||
ASSERT(sIndex >= 0);
|
||||
ASSERT(sIndex < 20);
|
||||
ASSERT(sIndex >= 0 && sIndex < 20);
|
||||
|
||||
m.translate(vec3(t.x, t.y, t.z));
|
||||
}
|
||||
|
||||
quat q = lerpAngle(getAngle(frameA, i), getAngle(frameB, i), k);
|
||||
quat q = lerpAngle(frameA->getAngle(i), frameB->getAngle(i), k);
|
||||
m = m * mat4(q, vec3(0.0f));
|
||||
|
||||
|
||||
@@ -403,6 +387,7 @@ struct Level {
|
||||
void getLight(const vec3 &pos, int roomIndex) {
|
||||
int room = roomIndex;
|
||||
int idx = getLightIndex(pos, room);
|
||||
|
||||
if (idx > -1) {
|
||||
TR::Room::Light &light = level.rooms[room].lights[idx];
|
||||
float c = level.rooms[room].lights[idx].intensity / 8191.0f;
|
||||
@@ -412,6 +397,7 @@ struct Level {
|
||||
Core::lightPos = vec3(0);
|
||||
Core::lightColor = vec4(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
Core::ambient = vec3(1.0f - level.rooms[roomIndex].ambient / 8191.0f);
|
||||
Core::active.shader->setParam(uAmbient, Core::ambient);
|
||||
Core::active.shader->setParam(uLightPos, Core::lightPos);
|
||||
@@ -470,13 +456,7 @@ struct Level {
|
||||
void update() {
|
||||
time += Core::deltaTime;
|
||||
lara->update();
|
||||
|
||||
#ifndef FREE_CAMERA
|
||||
camera.pos = vec3(-lara->pos.x, -lara->pos.y, lara->pos.z);
|
||||
#endif
|
||||
camera.targetDeltaPos = lara->inWater ? vec3(0.0f, -256.0f, 0.0f) : vec3(0.0f, -768.0f, 0.0f);
|
||||
camera.targetAngle = vec3(lara->angle.x, -lara->angle.y, 0.0f); //-lara->angle.z);
|
||||
camera.update();
|
||||
camera->update();
|
||||
}
|
||||
|
||||
int getCameraRoomIndex() {
|
||||
@@ -489,7 +469,7 @@ struct Level {
|
||||
void render() {
|
||||
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
camera.setup();;
|
||||
camera->setup();;
|
||||
|
||||
atlas->bind(0);
|
||||
mesh->bind();
|
||||
@@ -510,12 +490,17 @@ struct Level {
|
||||
|
||||
Core::mModel.identity();
|
||||
|
||||
for (int i = 0; i < level.roomsCount; i++)
|
||||
level.rooms[i].flags &= ~TR::ROOM_FLAG_VISIBLE; // clear visible flag
|
||||
// clear visible flags for rooms & static meshes
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
TR::Room &room = level.rooms[i];
|
||||
room.flags &= ~TR::ROOM_FLAG_VISIBLE; // clear visible flag for room geometry & sprites
|
||||
|
||||
for (int j = 0; j < room.meshesCount; j++)
|
||||
room.meshes[j].flags &= ~TR::ROOM_FLAG_VISIBLE; // clear visible flag for room static meshes
|
||||
}
|
||||
|
||||
// TODO: collision detection for camera
|
||||
renderRoom(getCameraRoomIndex());
|
||||
renderRoom(lara->getEntity().room);
|
||||
renderRoom(camera->room);
|
||||
|
||||
shaders[shStatic]->bind();
|
||||
for (int i = 0; i < level.entitiesCount; i++)
|
||||
@@ -523,9 +508,10 @@ struct Level {
|
||||
|
||||
#ifdef _DEBUG
|
||||
Debug::begin();
|
||||
Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
|
||||
// Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
|
||||
// Debug::Level::lights(level);
|
||||
Debug::Level::portals(level);
|
||||
// Debug::Level::portals(level);
|
||||
Debug::Level::meshes(level);
|
||||
Debug::end();
|
||||
#endif
|
||||
}
|
||||
|
19
src/mesh.h
19
src/mesh.h
@@ -393,13 +393,7 @@ struct MeshBuilder {
|
||||
}
|
||||
|
||||
void initAnimTextures(TR::Level &level) {
|
||||
if (!level.animTexturesDataSize) {
|
||||
animTexRangesCount = animTexOffsetsCount = 1;
|
||||
animTexRanges = new vec2[1];
|
||||
animTexOffsets = new vec2[1];
|
||||
animTexRanges[0] = vec2(0.0f, 1.0f);
|
||||
animTexOffsets[0] = vec2(0.0f);
|
||||
}
|
||||
ASSERT(level.animTexturesDataSize);
|
||||
|
||||
uint16 *ptr = &level.animTexturesData[0];
|
||||
animTexRangesCount = *ptr++ + 1;
|
||||
@@ -507,8 +501,9 @@ struct MeshBuilder {
|
||||
|
||||
Vertex *quad = &vertices[vCount];
|
||||
|
||||
quad[0].coord = quad[1].coord = quad[2].coord = quad[3].coord = { x, y, z, 0 };
|
||||
quad[0].coord = quad[1].coord = quad[2].coord = quad[3].coord = { x, y, z, 0 };
|
||||
quad[0].normal = quad[1].normal = quad[2].normal = quad[3].normal = { 0, 0, 0, 0 };
|
||||
quad[0].color = quad[1].color = quad[2].color = quad[3].color = { intensity, intensity, intensity, 255 };
|
||||
|
||||
int tx = (sprite.tile % 4) * 256;
|
||||
int ty = (sprite.tile / 4) * 256;
|
||||
@@ -523,8 +518,6 @@ struct MeshBuilder {
|
||||
quad[2].texCoord = { u1, v1, sprite.l, sprite.b };
|
||||
quad[3].texCoord = { u0, v1, sprite.r, sprite.b };
|
||||
|
||||
quad[0].color = quad[1].color = quad[2].color = quad[3].color = { intensity, intensity, intensity, 255 };
|
||||
|
||||
vCount += 4;
|
||||
}
|
||||
|
||||
@@ -544,8 +537,12 @@ struct MeshBuilder {
|
||||
return roomRanges[roomIndex].sprites.iCount > 0;
|
||||
}
|
||||
|
||||
void renderMesh(MeshInfo *meshInfo) {
|
||||
mesh->render(*meshInfo);
|
||||
}
|
||||
|
||||
void renderMesh(int meshIndex) {
|
||||
mesh->render(meshInfo[meshIndex]);
|
||||
renderMesh(&meshInfo[meshIndex]);
|
||||
}
|
||||
|
||||
void renderSprite(int spriteIndex) {
|
||||
|
12
src/utils.h
12
src/utils.h
@@ -278,6 +278,18 @@ struct mat4 {
|
||||
e23 = 2.0f * zfar * znear / (znear - zfar);
|
||||
}
|
||||
|
||||
mat4(const vec3 &from, const vec3 &at, const vec3 &up) {
|
||||
vec3 r, u, d;
|
||||
d = (from - at).normal();
|
||||
r = up.cross(d).normal();
|
||||
u = d.cross(r);
|
||||
|
||||
this->right = vec4(r, 0.0f);
|
||||
this->up = vec4(u, 0.0f);
|
||||
this->dir = vec4(d, 0.0f);
|
||||
this->offset = vec4(from, 1.0f);
|
||||
}
|
||||
|
||||
void identity() {
|
||||
e10 = e20 = e30 = e01 = e21 = e31 = e02 = e12 = e32 = e03 = e13 = e23 = 0.0f;
|
||||
e00 = e11 = e22 = e33 = 1.0f;
|
||||
|
Reference in New Issue
Block a user