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

#8 add camera interface; #15 fix floating point textures for FireFox and warnings; #22 fix moving block

This commit is contained in:
XProger 2017-09-06 03:10:56 +03:00
parent 1c9d0b4199
commit b4a0c8e68c
10 changed files with 109 additions and 63 deletions

View File

@ -643,6 +643,10 @@ struct WaterCache {
if (!refract || w != refract->width || h != refract->height) {
delete refract;
refract = new Texture(w, h, Texture::RGBA, false);
Core::setTarget(refract, true);
Core::validateRenderState(); // immediate clear
Core::invalidateTarget(false, true);
Core::setTarget(NULL);
}
Core::copyTarget(refract, 0, 0, 0, 0, w, h); // copy framebuffer into refraction texture
}

View File

@ -8,7 +8,7 @@
#define CAMERA_OFFSET (1024.0f + 256.0f)
struct Camera : Controller {
struct Camera : ICamera {
enum {
STATE_FOLLOW,
@ -17,13 +17,15 @@ struct Camera : Controller {
STATE_COMBAT,
STATE_CUTSCENE,
STATE_HEAVY
};
} state;
IGame *game;
TR::Level *level;
Character *owner;
Frustum *frustum;
float fov, znear, zfar;
vec3 target, destPos, lastDest, advAngle;
vec3 target, pos, destPos, lastDest, angle, advAngle;
float advTimer;
mat4 mViewInv;
int room;
@ -32,7 +34,6 @@ struct Camera : Controller {
float shake;
Basis prevBasis;
vec4 *reflectPlane;
int viewIndex;
int viewIndexLast;
@ -42,7 +43,7 @@ struct Camera : Controller {
bool firstPerson;
bool isVR;
Camera(IGame *game, Character *owner) : Controller(game, owner ? owner->entity : 0), owner(owner), frustum(new Frustum()), timer(-1.0f), reflectPlane(NULL), viewIndex(-1), viewIndexLast(-1), viewTarget(NULL), isVR(false) {
Camera(IGame *game, Character *owner) : ICamera(), game(game), level(game->getLevel()), owner(owner), frustum(new Frustum()), timer(-1.0f), shake(0.0f), viewIndex(-1), viewIndexLast(-1), viewTarget(NULL), isVR(false) {
changeView(false);
if (owner->getEntity().type != TR::Entity::LARA && level->cameraFrames) {
state = STATE_CUTSCENE;
@ -63,7 +64,7 @@ struct Camera : Controller {
virtual void checkRoom() {
if (state == STATE_CUTSCENE) {
for (int i = 0; i < level->roomsCount; i++)
if (insideRoom(pos, i)) {
if (owner->insideRoom(pos, i)) {
room = i;
break;
}
@ -105,7 +106,7 @@ struct Camera : Controller {
}
void setView(int viewIndex, float timer, float speed) {
if (viewIndex == viewIndexLast) return;
// if (viewIndex == viewIndexLast) return;
viewIndexLast = viewIndex;
state = STATE_STATIC;
@ -129,7 +130,7 @@ struct Camera : Controller {
shake = max(0.0f, shake - Core::deltaTime);
if (state == STATE_CUTSCENE) {
timer += Core::deltaTime * 15.0f;
timer += Core::deltaTime * 30.0f;
float t = timer - int(timer);
int indexA = int(timer) % level->cameraFramesCount;
int indexB = (indexA + 1) % level->cameraFramesCount;
@ -260,16 +261,16 @@ struct Camera : Controller {
if (lookAt) {
dir = (lookAt->pos - target).normal();
} else
dir = getDir();
dir = vec3(angle.x, angle.y);
int destRoom;
if ((state == STATE_COMBAT || owner->state != 25) || lookAt) { // TODO: FUUU! 25 == Lara::STATE_BACK_JUMP
vec3 eye = target - dir * CAMERA_OFFSET;
destPos = trace(owner->getRoomIndex(), target, eye, destRoom, true);
destPos = owner->trace(owner->getRoomIndex(), target, eye, destRoom, true);
lastDest = destPos;
} else {
vec3 eye = lastDest + dir.cross(vec3(0, 1, 0)).normal() * 2048.0f - vec3(0.0f, 512.0f, 0.0f);
destPos = trace(owner->getRoomIndex(), target, eye, destRoom, true);
destPos = owner->trace(owner->getRoomIndex(), target, eye, destRoom, true);
}
room = destRoom;

View File

@ -16,11 +16,19 @@
struct Controller;
struct ICamera {
vec4 *reflectPlane;
ICamera() : reflectPlane(NULL) {}
virtual void setup(bool calcMatrices) {}
};
struct IGame {
virtual ~IGame() {}
virtual TR::Level* getLevel() { return NULL; }
virtual MeshBuilder* getMesh() { return NULL; }
virtual Controller* getCamera() { return NULL; }
virtual ICamera* getCamera() { return NULL; }
virtual Controller* getLara() { return NULL; }
virtual bool isCutscene() { return false; }
virtual uint16 getRandomBox(uint16 zone, uint16 *zones) { return 0; }
@ -96,7 +104,7 @@ struct Controller {
e.flags.once = false;
}
if (e.flags.active == 0x1F) {
if (e.flags.active == TR::ACTIVE) {
e.flags.active = 0;
e.flags.reverse = true;
activate();
@ -115,7 +123,7 @@ struct Controller {
bool isActive() {
TR::Entity &e = getEntity();
if (e.flags.active != 0x1F)
if (e.flags.active != TR::ACTIVE)
return e.flags.reverse;
if (timer == 0.0f)
@ -603,8 +611,6 @@ struct Controller {
Core::setBlending(bmMultiply);
mesh->renderShadowBlob();
Core::setBlending(bmNone);
Core::active.shader->setParam(uViewProj, Core::mViewProj);
}
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) { // TODO: animation.calcJoints

View File

@ -680,8 +680,8 @@ namespace Debug {
const char *ent = (cmd.action == TR::Action::ACTIVATE || cmd.action == TR::Action::CAMERA_TARGET) ? getEntityName(level, level.entities[cmd.args]) : "";
sprintf(buf, "%s -> %s (%d)", getTriggerAction(level, cmd.action), ent, cmd.args);
if (cmd.action == TR::Action::CAMERA_SWITCH) {
sprintf(buf, "%s delay: %d speed: %d", buf, int(info.trigCmd[i].timer), int(info.trigCmd[i].speed) * 8 + 1);
i++;
sprintf(buf, "%s delay: %d speed: %d", buf, int(info.trigCmd[i].timer), int(info.trigCmd[i].speed) * 8 + 1);
}
Debug::Draw::text(vec2(16, y += 16), vec4(0.1f, 0.6f, 0.1f, 1.0f), buf);

View File

@ -209,6 +209,7 @@ namespace TR {
NO_FLOOR = -127,
NO_ROOM = 0xFF,
NO_BOX = 0xFFFF,
ACTIVE = 0x1F,
};
enum {
@ -351,9 +352,11 @@ namespace TR {
Limit BLOCK = {
0, -612, 30, {{-300, 0, -692}, {300, 0, -512}}, true, false
};
}
#pragma pack(push, 1)
Limit SCION = {
640, 310, 30, {{-256, 540, -350}, {256, 740, -200}}, true, false
};
}
struct fixed {
uint16 L;
@ -557,11 +560,6 @@ namespace TR {
uint16 :8, once:1, active:5, :2;
};
//struct Collider {
// uint16 radius:10, info:6;
// uint16 flags:16;
//};
// internal mesh structure
struct Mesh {
@ -909,8 +907,6 @@ namespace TR {
} flags;
};
#pragma pack(pop)
enum Version : uint32 {
VER_TR1_PC = 0x00000020,
VER_TR1_PSX = 0x56414270,
@ -1777,7 +1773,6 @@ namespace TR {
t.clut = c;\
t.tile = d.tile;\
t.attribute = d.attribute;\
t.repeat = false;\
t.texCoord[0] = { d.x0, d.y0 };\
t.texCoord[1] = { d.x1, d.y1 };\
t.texCoord[2] = { d.x2, d.y2 };\

View File

@ -604,6 +604,7 @@ struct Inventory {
void render() {
// background
Core::setDepthTest(false);
Core::setBlending(bmNone);
if (background[0]) {
background[0]->bind(sDiffuse); // orignal image

View File

@ -454,6 +454,7 @@ struct Lara : Character {
//reset(51, vec3(41015, 3584, 34494), -PI); // level 3a (t-rex)
//reset(5, vec3(38643, -3072, 92370), PI * 0.5f); // level 3a (gears)
//reset(43, vec3(64037, 6656, 48229), PI); // level 3b (movingblock)
//reset(5, vec3(73394, 3840, 60758), 0); // level 3b (scion)
//reset(99, vec3(45562, -3328, 63366), 225 * DEG2RAD); // level 7a (flipmap)
//reset(0, vec3(40913, -1012, 42252), PI); // level 8c
//reset(10, vec3(90443, 11264 - 256, 114614), PI, STAND_ONWATER); // villa mortal 2
@ -1388,6 +1389,9 @@ struct Lara : Character {
controller->angle.x = -25 * DEG2RAD;
controller->angle.y = angle.y;
if (item.type == TR::Entity::SCION_1)
limit = TR::Limits::SCION;
if (!checkInteraction(controller, limit, (input & ACTION) != 0))
continue;
@ -1395,6 +1399,15 @@ struct Lara : Character {
angle.x = -25 * DEG2RAD;
pickupEntity = &item;
if (item.type == TR::Entity::SCION_1) {
animation.setAnim(level->models[level->entities[TR::MODEL_LARA_SPEC].modelIndex].animation);
((Controller*)level->cameraController)->state = Camera::STATE_CUTSCENE;
level->cutMatrix.identity();
level->cutMatrix.setPos(pos);
} else
state = STATE_PICK_UP;
return true;
}
}
@ -1507,7 +1520,7 @@ struct Lara : Character {
KeyHole *controller = (KeyHole*)entity.controller;
if (controller->activeState == asNone) {
if (entity.flags.active == 0x1F || state != STATE_STOP)
if (entity.flags.active == TR::ACTIVE || state != STATE_STOP)
return;
actionState = entity.isPuzzleHole() ? STATE_USE_PUZZLE : STATE_USE_KEY;
@ -1583,7 +1596,7 @@ struct Lara : Character {
else
flags.active |= info.trigInfo.mask;
if (flags.active != 0x1F)
if (flags.active != TR::ACTIVE)
break;
flags.once |= info.trigInfo.once;
@ -1603,7 +1616,7 @@ struct Lara : Character {
if (info.trigger == TR::Level::Trigger::SWITCH && info.trigInfo.timer && switchIsDown)
break;
if (info.trigger == TR::Level::Trigger::SWITCH || cmd.args != camera->viewIndexLast) {
{//if (info.trigger == TR::Level::Trigger::SWITCH || cmd.args != camera->viewIndexLast) {
level->cameras[cmd.args].flags.once |= cam.once;
camera->setView(cmd.args, cam.timer == 1 ? EPS : float(cam.timer), cam.speed * 8.0f);
}
@ -1623,20 +1636,20 @@ struct Lara : Character {
else
flip.active |= info.trigInfo.mask;
if (flip.active == 0x1F)
if (flip.active == TR::ACTIVE)
flip.once |= info.trigInfo.once;
if ((flip.active == 0x1F) ^ level->isFlipped)
if ((flip.active == TR::ACTIVE) ^ level->isFlipped)
needFlip = true;
break;
}
case TR::Action::FLIP_ON :
if (level->flipmap[cmd.args].active == 0x1F && !level->isFlipped)
if (level->flipmap[cmd.args].active == TR::ACTIVE && !level->isFlipped)
needFlip = true;
break;
case TR::Action::FLIP_OFF :
if (level->flipmap[cmd.args].active == 0x1F && level->isFlipped)
if (level->flipmap[cmd.args].active == TR::ACTIVE && level->isFlipped)
needFlip = true;
break;
case TR::Action::CAMERA_TARGET :
@ -1663,7 +1676,7 @@ struct Lara : Character {
else
flags.active |= info.trigInfo.mask;
if (flags.active == 0x1F) {
if (flags.active == TR::ACTIVE) {
flags.once |= info.trigInfo.once;
game->playTrack(track);
} else
@ -1856,7 +1869,7 @@ struct Lara : Character {
angle.x = 0.0f;
if ((state == STATE_STOP || state == STATE_TREAD) && (input & ACTION) && emptyHands() && doPickUp())
return STATE_PICK_UP;
return state;
if ((input & (FORTH | ACTION)) == (FORTH | ACTION) && (animation.index == ANIM_STAND || animation.index == ANIM_STAND_NORMAL) && emptyHands() && collision.side == Collision::FRONT) { // TODO: get rid of animation.index
int floor = collision.info[Collision::FRONT].floor;
@ -2041,7 +2054,7 @@ struct Lara : Character {
virtual int getStateUnderwater() {
if (input == ACTION && doPickUp())
return STATE_PICK_UP;
return state;
if (state == STATE_FORWARD_JUMP || state == STATE_UP_JUMP || state == STATE_BACK_JUMP || state == STATE_LEFT_JUMP || state == STATE_RIGHT_JUMP || state == STATE_FALL || state == STATE_REACH || state == STATE_SLIDE || state == STATE_SLIDE_BACK) {
game->waterDrop(pos, 256.0f, 0.2f);

View File

@ -54,12 +54,12 @@ struct Level : IGame {
return &level;
}
virtual MeshBuilder* getMesh() {
virtual MeshBuilder* getMesh() {
return mesh;
}
virtual Controller* getCamera() {
return camera;
virtual ICamera* getCamera() {
return camera;
}
virtual Controller* getLara() {
@ -555,8 +555,8 @@ struct Level : IGame {
// repack texture tiles
Atlas *tiles = new Atlas(level.objectTexturesCount + level.spriteTexturesCount + 3, &level, fillCallback);
// add textures
int startIdx = level.version == TR::VER_TR1_PSX ? 256 : 0; // skip palette color for PSX version
for (int i = startIdx; i < level.objectTexturesCount; i++) {
int texIdx = level.version == TR::VER_TR1_PSX ? 256 : 0; // skip palette color for PSX version
for (int i = texIdx; i < level.objectTexturesCount; i++) {
TR::ObjectTexture &t = level.objectTextures[i];
int16 tx = (t.tile.index % 4) * 256;
int16 ty = (t.tile.index / 4) * 256;
@ -567,7 +567,7 @@ struct Level : IGame {
uv.z = tx + max(max(t.texCoord[0].x, t.texCoord[1].x), t.texCoord[2].x) + 1;
uv.w = ty + max(max(t.texCoord[0].y, t.texCoord[1].y), t.texCoord[2].y) + 1;
tiles->add(uv, i);
tiles->add(uv, texIdx++);
}
// add sprites
for (int i = 0; i < level.spriteTexturesCount; i++) {
@ -581,14 +581,14 @@ struct Level : IGame {
uv.z = tx + t.texCoord[1].x + 1;
uv.w = ty + t.texCoord[1].y + 1;
tiles->add(uv, level.objectTexturesCount + i);
tiles->add(uv, texIdx++);
}
// add white color
tiles->add(short4(2048, 2048, 2048, 2048), level.objectTexturesCount + level.spriteTexturesCount);
tiles->add(short4(2048, 2048, 2048, 2048), texIdx++);
// add health bar
tiles->add(short4(2048, 2048, 2048, 2048 + 4), level.objectTexturesCount + level.spriteTexturesCount + 1);
tiles->add(short4(2048, 2048, 2048, 2048 + 4), texIdx++);
// add oxygen bar
tiles->add(short4(4096, 4096, 4096, 4096 + 4), level.objectTexturesCount + level.spriteTexturesCount + 2);
tiles->add(short4(4096, 4096, 4096, 4096 + 4), texIdx++);
// get result texture
atlas = tiles->pack();
@ -817,6 +817,9 @@ struct Level : IGame {
}
void update() {
if (isCutscene() && !sndSoundtrack)
return;
if (Input::state[cInventory] && level.id != TR::TITLE)
inventory.toggle();
@ -839,7 +842,7 @@ struct Level : IGame {
c = next;
}
if (camera->state != Camera::STATE_STATIC)
if (!isCutscene() && camera->state != Camera::STATE_STATIC)
camera->state = lara->emptyHands() ? Camera::STATE_FOLLOW : Camera::STATE_COMBAT;
camera->update();
@ -898,7 +901,7 @@ struct Level : IGame {
for (int i = 0; i < level.entitiesCount; i++) {
TR::Entity &entity = level.entities[i];
if (entity.flags.rendered)
if (entity.controller && entity.flags.rendered)
((Controller*)entity.controller)->renderShadow(mesh);
}
}

View File

@ -85,6 +85,7 @@ struct Texture {
};
FormatDesc desc = formats[format];
/*
if ((format == RGBA_FLOAT && !Core::support.colorFloat) || (format == RGBA_HALF && !Core::support.colorHalf)) {
desc.ifmt = GL_RGBA;
#ifdef MOBILE
@ -92,6 +93,22 @@ struct Texture {
desc.type = GL_HALF_FLOAT_OES;
#endif
}
*/
#ifdef MOBILE
if (format == RGBA_FLOAT) {
if (Core::support.texFloat) {
desc.ifmt = GL_RGBA;
desc.type = GL_FLOAT;
}
}
if (format == RGBA_HALF) {
if (Core::support.texHalf) {
desc.ifmt = GL_RGBA;
desc.type = GL_HALF_FLOAT_OES;
}
}
#endif
for (int i = 0; i < 6; i++) {
glTexImage2D(cube ? (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i) : GL_TEXTURE_2D, 0, desc.ifmt, width, height, 0, desc.fmt, desc.type, data);

View File

@ -35,7 +35,7 @@ struct Switch : Controller {
virtual void update() {
updateAnimation(true);
getEntity().flags.active = 0x1F;
getEntity().flags.active = TR::ACTIVE;
if (!isActive())
animation.setState(STATE_UP);
}
@ -141,7 +141,7 @@ struct Boulder : Controller {
Boulder(IGame *game, int entity) : Controller(game, entity) {}
virtual void update() {
if (getEntity().flags.active == 0x1F) {
if (getEntity().flags.active == TR::ACTIVE) {
updateAnimation(true);
updateEntity();
}
@ -226,7 +226,8 @@ struct Block : Controller {
struct MovingBlock : Controller {
enum {
STATE_STOP,
STATE_BEGIN,
STATE_END,
STATE_MOVE,
};
@ -236,6 +237,7 @@ struct MovingBlock : Controller {
}
void updateFloor(bool rise) {
updateEntity();
TR::Entity &e = getEntity();
TR::Level::FloorInfo info;
level->getFloorInfo(e.room, e.x, e.y, e.z, info);
@ -246,22 +248,26 @@ struct MovingBlock : Controller {
s.floor += rise ? -8 : 8;
}
virtual bool activate() {
if (Controller::activate()) {
updateFloor(false);
animation.setState(STATE_MOVE);
return true;
}
return false;
}
virtual void update() {
updateAnimation(true);
if (isActive()) {
if (state == STATE_BEGIN) {
updateFloor(false);
animation.setState(STATE_END);
}
} else {
if (state == STATE_END) {
updateFloor(false);
animation.setState(STATE_BEGIN);
}
}
if (activeState == asInactive) {
if (getEntity().flags.active == TR::ACTIVE)
activeState = asActive; // stay in active items list
pos.x = int(pos.x / 1024.0f) * 1024.0f + 512.0f;
pos.z = int(pos.z / 1024.0f) * 1024.0f + 512.0f;
animation.setState(STATE_STOP);
updateFloor(true);
return;
}
@ -503,7 +509,7 @@ struct KeyHole : Controller {
virtual bool activate() {
if (!Controller::activate()) return false;
getEntity().flags.active = 0x1F;
getEntity().flags.active = TR::ACTIVE;
if (getEntity().isPuzzleHole()) {
int doneIdx = TR::Entity::convToInv(TR::Entity::getItemForHole(getEntity().type)) - TR::Entity::INV_PUZZLE_1;
meshSwap(0, level->extra.puzzleDone[doneIdx]);