1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-18 02:41:29 +02:00

#15 core stats refactoring; gamepad analog fix for web; shadow matrix crop (test)

This commit is contained in:
XProger
2017-03-16 18:21:51 +03:00
parent fd89ab526c
commit f8bd8789a7
11 changed files with 320 additions and 190 deletions

View File

@@ -254,6 +254,10 @@ struct Camera : Controller {
updateListener(); updateListener();
} }
mat4 getProjMatrix() {
return mat4(fov, (float)Core::width / (float)Core::height, znear, zfar);
}
virtual void setup(bool calcMatrices) { virtual void setup(bool calcMatrices) {
if (calcMatrices) { if (calcMatrices) {
if (reflectPlane) { if (reflectPlane) {
@@ -263,7 +267,7 @@ struct Camera : Controller {
Core::mViewInv = mViewInv; Core::mViewInv = mViewInv;
Core::mView = Core::mViewInv.inverse(); Core::mView = Core::mViewInv.inverse();
Core::mProj = mat4(fov, (float)Core::width / (float)Core::height, znear, zfar); Core::mProj = getProjMatrix();
// TODO: camera shake // TODO: camera shake
// TODO: temporal anti-aliasing // TODO: temporal anti-aliasing

View File

@@ -541,7 +541,7 @@ struct Controller {
entity.flags.rendered = true; entity.flags.rendered = true;
if (Core::frameIndex != frameIndex) if (Core::stats.frame != frameIndex)
animation.getJoints(matrix, -1, true, joints); animation.getJoints(matrix, -1, true, joints);
if (layers) { if (layers) {
@@ -563,7 +563,7 @@ struct Controller {
mesh->renderModel(entity.modelIndex - 1); mesh->renderModel(entity.modelIndex - 1);
} }
frameIndex = Core::frameIndex; frameIndex = Core::stats.frame;
// blob shadow // TODO: fake AO // blob shadow // TODO: fake AO
if (!Core::settings.shadows && Core::pass == Core::passCompose && TR::castShadow(entity.type)) { if (!Core::settings.shadows && Core::pass == Core::passCompose && TR::castShadow(entity.type)) {

View File

@@ -186,9 +186,10 @@ struct Texture;
enum CullMode { cfNone, cfBack, cfFront }; enum CullMode { cfNone, cfBack, cfFront };
enum BlendMode { bmNone, bmAlpha, bmAdd, bmMultiply, bmScreen }; enum BlendMode { bmNone, bmAlpha, bmAdd, bmMultiply, bmScreen };
extern int getTime();
namespace Core { namespace Core {
int width, height; int width, height;
int frameIndex;
float deltaTime; float deltaTime;
mat4 mView, mProj, mViewProj, mViewInv, mLightProj; mat4 mView, mProj, mViewProj, mViewInv, mLightProj;
Basis basis; Basis basis;
@@ -221,9 +222,24 @@ namespace Core {
CullMode cullMode; CullMode cullMode;
} active; } active;
struct { struct Stats {
int dips; int dips, tris, frame, fps, fpsTime;
int tris;
Stats() : frame(0), fps(0), fpsTime(0) {}
void start() {
dips = tris = 0;
}
void stop() {
if (fpsTime < getTime()) {
LOG("FPS: %d DIP: %d TRI: %d\n", fps, dips, tris);
fps = frame;
frame = 0;
fpsTime = getTime() + 1000;
} else
frame++;
}
} stats; } stats;
struct { struct {
@@ -360,8 +376,6 @@ namespace Core {
for (int i = 0; i < MAX_LIGHTS; i++) for (int i = 0; i < MAX_LIGHTS; i++)
lightColor[i] = vec4(0, 0, 0, 1); lightColor[i] = vec4(0, 0, 0, 1);
frameIndex = 0;
uint32 data = 0x00000000; uint32 data = 0x00000000;
blackTex = new Texture(1, 1, Texture::RGBA, false, &data, false); blackTex = new Texture(1, 1, Texture::RGBA, false, &data, false);
@@ -532,13 +546,18 @@ namespace Core {
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, x, y, width, height); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, x, y, width, height);
} }
void resetStates() { void beginFrame() {
memset(&active, 0, sizeof(active)); memset(&active, 0, sizeof(active));
setDepthTest(true); setDepthTest(true);
active.blendMode = bmAlpha; active.blendMode = bmAlpha;
active.cullMode = cfNone; active.cullMode = cfNone;
setCulling(cfFront); setCulling(cfFront);
setBlending(bmNone); setBlending(bmNone);
Core::stats.start();
}
void endFrame() {
Core::stats.stop();
} }
} }

View File

@@ -60,8 +60,9 @@ namespace Game {
} }
void render() { void render() {
Core::beginFrame();
level->render(); level->render();
Core::frameIndex++; Core::endFrame();
} }
} }

View File

@@ -54,7 +54,7 @@ struct Lara : Character {
ANIM_STAND_RIGHT = 3, ANIM_STAND_RIGHT = 3,
ANIM_STAND = 11, ANIM_STAND = 11,
ANIM_CLIMB_JUMP = 26, ANIM_CLIMB_JUMP = 26,
ANIM_HANG_FALL = 28, ANIM_HANG_FALL = 28,
@@ -159,7 +159,7 @@ struct Lara : Character {
STATE_HANDSTAND, STATE_HANDSTAND,
STATE_WATER_OUT, STATE_WATER_OUT,
STATE_MAX }; STATE_MAX };
enum : int { enum : int {
BODY_HIP = 0x0001, BODY_HIP = 0x0001,
BODY_LEG_L1 = 0x0002, BODY_LEG_L1 = 0x0002,
@@ -209,7 +209,7 @@ struct Lara : Character {
} arms[2]; } arms[2];
ActionCommand actionList[MAX_TRIGGER_ACTIONS]; ActionCommand actionList[MAX_TRIGGER_ACTIONS];
Inventory inventory; Inventory inventory;
int lastPickUp; int lastPickUp;
int viewTarget; int viewTarget;
@@ -272,10 +272,10 @@ struct Lara : Character {
float DAMPING = 1.5f; float DAMPING = 1.5f;
if (lara->getRoom().flags.water) { if (lara->getRoom().flags.water) {
ACCEL *= -0.5f; ACCEL *= -0.5f;
DAMPING = 4.0f; DAMPING = 4.0f;
} }
DAMPING = 1.0f / (1.0f + DAMPING * TIMESTEP); // Pade approximation DAMPING = 1.0f / (1.0f + DAMPING * TIMESTEP); // Pade approximation
for (int i = 1; i < jointsCount; i++) { for (int i = 1; i < jointsCount; i++) {
@@ -340,7 +340,7 @@ struct Lara : Character {
a.pos -= dir; a.pos -= dir;
b.pos += dir; b.pos += dir;
} else } else
b.pos += dir * (d * 1.0f); b.pos += dir * (d * 1.0f);
} }
} }
@@ -349,7 +349,7 @@ struct Lara : Character {
integrate(); // Verlet integration step integrate(); // Verlet integration step
collide(); // check collision with Lara's mesh collide(); // check collision with Lara's mesh
for (int i = 0; i < jointsCount; i++) // solve connections (springs) for (int i = 0; i < jointsCount; i++) // solve connections (springs)
solve(); solve();
vec3 headDir = getBasis().rot * vec3(0.0f, 0.0f, -1.0f); vec3 headDir = getBasis().rot * vec3(0.0f, 0.0f, -1.0f);
@@ -357,13 +357,13 @@ struct Lara : Character {
vec3 d = (joints[i + 1].pos - joints[i].pos).normal(); vec3 d = (joints[i + 1].pos - joints[i].pos).normal();
vec3 r = d.cross(headDir).normal(); vec3 r = d.cross(headDir).normal();
vec3 u = d.cross(r).normal(); vec3 u = d.cross(r).normal();
mat4 m; mat4 m;
m.up = vec4(u, 0.0f); m.up = vec4(u, 0.0f);
m.dir = vec4(d, 0.0f); m.dir = vec4(d, 0.0f);
m.right = vec4(r, 0.0f); m.right = vec4(r, 0.0f);
m.offset = vec4(0.0f, 0.0f, 0.0f, 1.0f); m.offset = vec4(0.0f, 0.0f, 0.0f, 1.0f);
basis[i].identity(); basis[i].identity();
basis[i].translate(joints[i].pos); basis[i].translate(joints[i].pos);
basis[i].rotate(m.getRot()); basis[i].rotate(m.getRot());
@@ -374,11 +374,11 @@ struct Lara : Character {
Core::active.shader->setParam(uBasis, basis[0], jointsCount); Core::active.shader->setParam(uBasis, basis[0], jointsCount);
mesh->renderModel(lara->level->extra.braid); mesh->renderModel(lara->level->extra.braid);
} }
} *braid; } *braid;
Lara(IGame *game, int entity, bool home) : Character(game, entity, 1000), home(home), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), viewTarget(-1), braid(NULL) { Lara(IGame *game, int entity, bool home) : Character(game, entity, 1000), home(home), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), viewTarget(-1), braid(NULL) {
if (getEntity().type == TR::Entity::LARA) { if (getEntity().type == TR::Entity::LARA) {
if (getRoom().flags.water) if (getRoom().flags.water)
animation.setAnim(ANIM_UNDERWATER); animation.setAnim(ANIM_UNDERWATER);
@@ -408,7 +408,7 @@ struct Lara : Character {
if (level->extra.braid > -1) if (level->extra.braid > -1)
braid = new Braid(this, vec3(-4.0f, 24.0f, -48.0f)); braid = new Braid(this, vec3(-4.0f, 24.0f, -48.0f));
#ifdef _DEBUG #ifdef _DEBUG
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool) //reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
//reset(14, vec3(20215, 6656, 52942), PI); // level 1 (bridge) //reset(14, vec3(20215, 6656, 52942), PI); // level 1 (bridge)
@@ -443,7 +443,7 @@ struct Lara : Character {
} }
updateEntity(); updateEntity();
} }
void wpnSet(Weapon::Type wType) { void wpnSet(Weapon::Type wType) {
wpnCurrent = wType; wpnCurrent = wType;
wpnState = Weapon::IS_FIRING; wpnState = Weapon::IS_FIRING;
@@ -463,9 +463,9 @@ struct Lara : Character {
arm.anim = wAnim; arm.anim = wAnim;
if (wAnimDir > 0.0f) if (wAnimDir > 0.0f)
arm.animation.time = wAnimTime; arm.animation.time = wAnimTime;
else else
if (wAnimDir < 0.0f) if (wAnimDir < 0.0f)
arm.animation.time = arm.animation.timeMax + wAnimTime; arm.animation.time = arm.animation.timeMax + wAnimTime;
arm.animation.updateInfo(); arm.animation.updateInfo();
@@ -490,7 +490,7 @@ struct Lara : Character {
int mask = 0; int mask = 0;
switch (wpnCurrent) { switch (wpnCurrent) {
case Weapon::EMPTY : break; case Weapon::EMPTY : break;
case Weapon::PISTOLS : case Weapon::PISTOLS :
case Weapon::MAGNUMS : case Weapon::MAGNUMS :
case Weapon::UZIS : case Weapon::UZIS :
switch (wState) { switch (wState) {
@@ -518,7 +518,7 @@ struct Lara : Character {
// 2 - shotgun (hands, chest) // 2 - shotgun (hands, chest)
// 3 - angry (head) // 3 - angry (head)
// swap weapon parts // swap weapon parts
if (wpnCurrent != Weapon::SHOTGUN) { if (wpnCurrent != Weapon::SHOTGUN) {
meshSwap(1, level->extra.weapons[wpnCurrent], mask); meshSwap(1, level->extra.weapons[wpnCurrent], mask);
// have a shotgun in inventory place it on the back if another weapon is in use // have a shotgun in inventory place it on the back if another weapon is in use
@@ -529,7 +529,7 @@ struct Lara : Character {
// mesh swap to angry Lara's head while firing (from uzis model) // mesh swap to angry Lara's head while firing (from uzis model)
meshSwap(3, level->extra.weapons[Weapon::UZIS], (wState == Weapon::IS_FIRING) ? BODY_HEAD : 0); meshSwap(3, level->extra.weapons[Weapon::UZIS], (wState == Weapon::IS_FIRING) ? BODY_HEAD : 0);
wpnState = wState; wpnState = wState;
} }
@@ -538,7 +538,7 @@ struct Lara : Character {
} }
bool canLookAt() { bool canLookAt() {
return (stand == STAND_GROUND || stand == STAND_SLIDE) return (stand == STAND_GROUND || stand == STAND_SLIDE)
&& state != STATE_REACH && state != STATE_REACH
&& state != STATE_PUSH_BLOCK && state != STATE_PUSH_BLOCK
&& state != STATE_PULL_BLOCK && state != STATE_PULL_BLOCK
@@ -551,7 +551,7 @@ struct Lara : Character {
&& emptyHands() && emptyHands()
&& animation.index != ANIM_CLIMB_3 && animation.index != ANIM_CLIMB_3
&& animation.index != ANIM_CLIMB_2 && animation.index != ANIM_CLIMB_2
&& state != STATE_DEATH && state != STATE_DEATH
&& state != STATE_HANG && state != STATE_HANG
&& state != STATE_REACH && state != STATE_REACH
&& state != STATE_TREAD && state != STATE_TREAD
@@ -595,7 +595,7 @@ struct Lara : Character {
wpnSetAnim(arms[0], wpnState, Weapon::Anim::PREPARE, 0.0f, 1.0f); wpnSetAnim(arms[0], wpnState, Weapon::Anim::PREPARE, 0.0f, 1.0f);
wpnSetAnim(arms[1], wpnState, Weapon::Anim::PREPARE, 0.0f, 1.0f); wpnSetAnim(arms[1], wpnState, Weapon::Anim::PREPARE, 0.0f, 1.0f);
} else } else
wpnSetAnim(arms[0], wpnState, Weapon::Anim::UNHOLSTER, 0.0f, 1.0f); wpnSetAnim(arms[0], wpnState, Weapon::Anim::UNHOLSTER, 0.0f, 1.0f);
} }
} }
@@ -621,7 +621,7 @@ struct Lara : Character {
case Weapon::Anim::PREPARE : ASSERT(false); break; // rifle has no prepare animation case Weapon::Anim::PREPARE : ASSERT(false); break; // rifle has no prepare animation
case Weapon::Anim::UNHOLSTER : return 1; case Weapon::Anim::UNHOLSTER : return 1;
case Weapon::Anim::HOLSTER : return 3; case Weapon::Anim::HOLSTER : return 3;
case Weapon::Anim::HOLD : case Weapon::Anim::HOLD :
case Weapon::Anim::AIM : return 0; case Weapon::Anim::AIM : return 0;
case Weapon::Anim::FIRE : return 2; case Weapon::Anim::FIRE : return 2;
default : ; default : ;
@@ -631,7 +631,7 @@ struct Lara : Character {
case Weapon::Anim::PREPARE : return 1; case Weapon::Anim::PREPARE : return 1;
case Weapon::Anim::UNHOLSTER : return 2; case Weapon::Anim::UNHOLSTER : return 2;
case Weapon::Anim::HOLSTER : ASSERT(false); break; // pistols has no holster animation (it's reversed unholster) case Weapon::Anim::HOLSTER : ASSERT(false); break; // pistols has no holster animation (it's reversed unholster)
case Weapon::Anim::HOLD : case Weapon::Anim::HOLD :
case Weapon::Anim::AIM : return 0; case Weapon::Anim::AIM : return 0;
case Weapon::Anim::FIRE : return 3; case Weapon::Anim::FIRE : return 3;
default : ; default : ;
@@ -663,7 +663,7 @@ struct Lara : Character {
wpnSetAnim(arms[i], Weapon::IS_ARMED, Weapon::Anim::AIM, 0.0f, -1.0f, target == -1); wpnSetAnim(arms[i], Weapon::IS_ARMED, Weapon::Anim::AIM, 0.0f, -1.0f, target == -1);
} }
// shotgun reload sound // shotgun reload sound
if (wpnCurrent == Weapon::SHOTGUN) { if (wpnCurrent == Weapon::SHOTGUN) {
if (anim.frameIndex == 10) if (anim.frameIndex == 10)
playSound(TR::SND_SHOTGUN_RELOAD, pos, Sound::Flags::PAN); playSound(TR::SND_SHOTGUN_RELOAD, pos, Sound::Flags::PAN);
} }
@@ -681,12 +681,12 @@ struct Lara : Character {
void doShot(bool rightHand, bool leftHand) { void doShot(bool rightHand, bool leftHand) {
int count = wpnCurrent == Weapon::SHOTGUN ? 6 : 2; int count = wpnCurrent == Weapon::SHOTGUN ? 6 : 2;
float nearDist = 32.0f * 1024.0f; float nearDist = 32.0f * 1024.0f;
vec3 nearPos; vec3 nearPos;
bool hasShot = false; bool hasShot = false;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
int armIndex; int armIndex;
if (wpnCurrent == Weapon::SHOTGUN) { if (wpnCurrent == Weapon::SHOTGUN) {
if (!rightHand) continue; if (!rightHand) continue;
@@ -696,7 +696,7 @@ struct Lara : Character {
armIndex = i; armIndex = i;
} }
Arm *arm = &arms[armIndex]; Arm *arm = &arms[armIndex];
arm->shotTimer = 0.0f; arm->shotTimer = 0.0f;
hasShot = true; hasShot = true;
@@ -786,12 +786,12 @@ struct Lara : Character {
float intensity = clamp((0.1f - arms[i].shotTimer) * 20.0f, 0.0f, 1.0f); float intensity = clamp((0.1f - arms[i].shotTimer) * 20.0f, 0.0f, 1.0f);
Core::lightColor[1 + i] = FLASH_LIGHT_COLOR * vec4(intensity, intensity, intensity, sqrtf(intensity)); Core::lightColor[1 + i] = FLASH_LIGHT_COLOR * vec4(intensity, intensity, intensity, sqrtf(intensity));
} }
if (isRifle) if (isRifle)
animateShotgun(); animateShotgun();
else else
animatePistols(); animatePistols();
wpnFire(); // make a shot wpnFire(); // make a shot
} }
} }
@@ -800,7 +800,7 @@ struct Lara : Character {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
Arm &arm = arms[i]; Arm &arm = arms[i];
if (!arm.animation.isEnded) continue; if (!arm.animation.isEnded) continue;
if (arm.animation.dir >= 0.0f) if (arm.animation.dir >= 0.0f)
switch (arm.anim) { switch (arm.anim) {
@@ -815,7 +815,7 @@ struct Lara : Character {
break; break;
default : ; default : ;
}; };
if (arm.animation.dir < 0.0f) if (arm.animation.dir < 0.0f)
switch (arm.anim) { switch (arm.anim) {
case Weapon::Anim::PREPARE : wpnSetAnim(arm, Weapon::IS_HIDDEN, Weapon::Anim::NONE, 0.0f, 1.0f, false); break; case Weapon::Anim::PREPARE : wpnSetAnim(arm, Weapon::IS_HIDDEN, Weapon::Anim::NONE, 0.0f, 1.0f, false); break;
@@ -842,7 +842,7 @@ struct Lara : Character {
break; break;
default : ; default : ;
} }
} else } else
if (arm.animation.frameIndex != arm.animation.framePrev) { if (arm.animation.frameIndex != arm.animation.framePrev) {
float delta = arm.animation.time / arm.animation.timeMax; float delta = arm.animation.time / arm.animation.timeMax;
switch (arm.anim) { switch (arm.anim) {
@@ -857,11 +857,11 @@ struct Lara : Character {
} }
void updateOverrides() { void updateOverrides() {
// head & chest // head & chest
animation.overrideMask |= BODY_CHEST | BODY_HEAD; animation.overrideMask |= BODY_CHEST | BODY_HEAD;
animation.overrides[ 7] = animation.getJointRot( 7); animation.overrides[ 7] = animation.getJointRot( 7);
animation.overrides[14] = animation.getJointRot(14); animation.overrides[14] = animation.getJointRot(14);
/* TODO: shotgun full body animation /* TODO: shotgun full body animation
if (wpnCurrent == Weapon::SHOTGUN) { if (wpnCurrent == Weapon::SHOTGUN) {
@@ -889,14 +889,14 @@ struct Lara : Character {
lookAt(viewTarget); lookAt(viewTarget);
if (wpnCurrent == Weapon::SHOTGUN) if (wpnCurrent == Weapon::SHOTGUN)
aimShotgun(); aimShotgun();
else else
aimPistols(); aimPistols();
} }
void lookAt(int target) { // TODO: character lookAt void lookAt(int target) { // TODO: character lookAt
float speed = 8.0f * Core::deltaTime; float speed = 8.0f * Core::deltaTime;
quat rot; quat rot;
@@ -904,7 +904,7 @@ struct Lara : Character {
// chest // chest
if (can && aim(target, 7, vec4(-PI * 0.4f, PI * 0.4f, -PI * 0.9f, PI * 0.9f), rot)) if (can && aim(target, 7, vec4(-PI * 0.4f, PI * 0.4f, -PI * 0.9f, PI * 0.9f), rot))
rotChest = rotChest.slerp(quat(0, 0, 0, 1).slerp(rot, 0.5f), speed); rotChest = rotChest.slerp(quat(0, 0, 0, 1).slerp(rot, 0.5f), speed);
else else
rotChest = rotChest.slerp(quat(0, 0, 0, 1), speed); rotChest = rotChest.slerp(quat(0, 0, 0, 1), speed);
animation.overrides[7] = rotChest * animation.overrides[7]; animation.overrides[7] = rotChest * animation.overrides[7];
@@ -1010,7 +1010,7 @@ struct Lara : Character {
} else } else
return false; return false;
} }
virtual void cmdEmpty() { virtual void cmdEmpty() {
wpnHide(); wpnHide();
} }
@@ -1034,7 +1034,7 @@ struct Lara : Character {
switch (fx) { switch (fx) {
case TR::EFFECT_FLIP_MAP : break; // TODO case TR::EFFECT_FLIP_MAP : break; // TODO
case TR::EFFECT_LARA_HANDSFREE : break;//meshSwap(1, level->extra.weapons[wpnCurrent], BODY_LEG_L1 | BODY_LEG_R1); break; case TR::EFFECT_LARA_HANDSFREE : break;//meshSwap(1, level->extra.weapons[wpnCurrent], BODY_LEG_L1 | BODY_LEG_R1); break;
case TR::EFFECT_DRAW_RIGHTGUN : case TR::EFFECT_DRAW_RIGHTGUN :
case TR::EFFECT_DRAW_LEFTGUN : drawGun(fx == TR::EFFECT_DRAW_RIGHTGUN); break; case TR::EFFECT_DRAW_LEFTGUN : drawGun(fx == TR::EFFECT_DRAW_RIGHTGUN); break;
default : LOG("unknown effect command %d (anim %d)\n", fx, animation.index); default : LOG("unknown effect command %d (anim %d)\n", fx, animation.index);
} }
@@ -1094,7 +1094,7 @@ struct Lara : Character {
pos -= getDir() * 256.0f; pos -= getDir() * 256.0f;
pos.y -= 256; pos.y -= 256;
} }
updateEntity(); updateEntity();
return true; return true;
} }
} }
@@ -1109,8 +1109,8 @@ struct Lara : Character {
bool useItem(TR::Entity::Type item, TR::Entity::Type slot) { bool useItem(TR::Entity::Type item, TR::Entity::Type slot) {
if (item == TR::Entity::NONE) { if (item == TR::Entity::NONE) {
switch (slot) { switch (slot) {
case TR::Entity::HOLE_KEY : item = TR::Entity::KEY_1; break; // TODO: 1-4 case TR::Entity::HOLE_KEY : item = TR::Entity::KEY_1; break; // TODO: 1-4
case TR::Entity::HOLE_PUZZLE : item = TR::Entity::PUZZLE_1; break; case TR::Entity::HOLE_PUZZLE : item = TR::Entity::PUZZLE_1; break;
default : return false; default : return false;
} }
} }
@@ -1269,13 +1269,13 @@ struct Lara : Character {
if (stand == STAND_SLIDE || (stand == STAND_AIR && velocity.y > 0) || stand == STAND_GROUND) { if (stand == STAND_SLIDE || (stand == STAND_AIR && velocity.y > 0) || stand == STAND_GROUND) {
if (e.y + 8 >= info.floor && (abs(info.slantX) > 2 || abs(info.slantZ) > 2)) { if (e.y + 8 >= info.floor && (abs(info.slantX) > 2 || abs(info.slantZ) > 2)) {
if (stand == STAND_AIR) if (stand == STAND_AIR)
playSound(TR::SND_LANDING, pos, Sound::Flags::PAN); playSound(TR::SND_LANDING, pos, Sound::Flags::PAN);
pos.y = float(info.floor); pos.y = float(info.floor);
updateEntity(); updateEntity();
if (stand == STAND_GROUND || stand == STAND_AIR) if (stand == STAND_GROUND || stand == STAND_AIR)
slideStart(); slideStart();
return STAND_SLIDE; return STAND_SLIDE;
} }
} }
@@ -1314,7 +1314,7 @@ struct Lara : Character {
vec3 p = vec3(pos.x, bounds.min.y, pos.z); vec3 p = vec3(pos.x, bounds.min.y, pos.z);
Collision c = Collision(level, getRoomIndex(), p, getDir() * 32.0f, vec3(0.0f), LARA_RADIUS, angleExt, 0, 0, 0, 0); Collision c = Collision(level, getRoomIndex(), p, getDir() * 32.0f, vec3(0.0f), LARA_RADIUS, angleExt, 0, 0, 0, 0);
if (c.side != Collision::FRONT) if (c.side != Collision::FRONT)
return state; return state;
@@ -1343,7 +1343,7 @@ struct Lara : Character {
if (input & ACTION) return STATE_REACH; if (input & ACTION) return STATE_REACH;
if ((input & (FORTH | WALK)) == (FORTH | WALK)) return STATE_SWAN_DIVE; if ((input & (FORTH | WALK)) == (FORTH | WALK)) return STATE_SWAN_DIVE;
} }
} else } else
if (state != STATE_SWAN_DIVE && state != STATE_REACH && state != STATE_FALL && state != STATE_UP_JUMP && state != STATE_BACK_JUMP && state != STATE_LEFT_JUMP && state != STATE_RIGHT_JUMP) if (state != STATE_SWAN_DIVE && state != STATE_REACH && state != STATE_FALL && state != STATE_UP_JUMP && state != STATE_BACK_JUMP && state != STATE_LEFT_JUMP && state != STATE_RIGHT_JUMP)
return animation.setAnim(ANIM_FALL); return animation.setAnim(ANIM_FALL);
@@ -1373,7 +1373,7 @@ struct Lara : Character {
for (int i = 0; i < level->entitiesCount; i++) { for (int i = 0; i < level->entitiesCount; i++) {
TR::Entity &e = level->entities[i]; TR::Entity &e = level->entities[i];
int q = entityQuadrant(e); int q = entityQuadrant(e);
int dx = abs(int(pos.x) - e.x); int dx = abs(int(pos.x) - e.x);
int dz = abs(int(pos.z) - e.z); int dz = abs(int(pos.z) - e.z);
@@ -1394,10 +1394,10 @@ struct Lara : Character {
if ((input & ACTION) && emptyHands() && doPickUp()) if ((input & ACTION) && emptyHands() && doPickUp())
return STATE_PICK_UP; return STATE_PICK_UP;
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 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; int floor = collision.info[Collision::FRONT].floor;
int h = (int)pos.y - floor; int h = (int)pos.y - floor;
int aIndex = animation.index; int aIndex = animation.index;
if (h <= 2 * 256 + 128) { if (h <= 2 * 256 + 128) {
aIndex = ANIM_CLIMB_2; aIndex = ANIM_CLIMB_2;
@@ -1406,7 +1406,7 @@ struct Lara : Character {
aIndex = ANIM_CLIMB_3; aIndex = ANIM_CLIMB_3;
pos.y = floor + 768.0f; pos.y = floor + 768.0f;
} else if (h <= 7 * 256 + 128) } else if (h <= 7 * 256 + 128)
aIndex = ANIM_CLIMB_JUMP; aIndex = ANIM_CLIMB_JUMP;
if (aIndex != animation.index) { if (aIndex != animation.index) {
alignToWall(-LARA_RADIUS); alignToWall(-LARA_RADIUS);
@@ -1429,29 +1429,29 @@ struct Lara : Character {
} }
// jump button is pressed // jump button is pressed
if (input & JUMP) { if (input & JUMP) {
if ((input & FORTH) && state == STATE_FORWARD_JUMP) if ((input & FORTH) && state == STATE_FORWARD_JUMP)
return STATE_RUN; return STATE_RUN;
if (state == STATE_RUN) if (state == STATE_RUN)
return STATE_FORWARD_JUMP; return STATE_FORWARD_JUMP;
if (animation.index == ANIM_SLIDE_BACK) // TODO: animation index? %) if (animation.index == ANIM_SLIDE_BACK) // TODO: animation index? %)
return STATE_SLIDE_BACK; return STATE_SLIDE_BACK;
return STATE_COMPRESS; return STATE_COMPRESS;
} }
// walk button is pressed // walk button is pressed
if (input & WALK) { if (input & WALK) {
if (input & FORTH) return STATE_WALK; if (input & FORTH) return STATE_WALK;
if (input & BACK) return STATE_BACK; if (input & BACK) return STATE_BACK;
if (input & LEFT) return STATE_STEP_LEFT; if (input & LEFT) return STATE_STEP_LEFT;
if (input & RIGHT) return STATE_STEP_RIGHT; if (input & RIGHT) return STATE_STEP_RIGHT;
return STATE_STOP; return STATE_STOP;
} }
if ((input & ACTION) && emptyHands()) { if ((input & ACTION) && emptyHands()) {
if (state == STATE_PUSH_PULL_READY && (input & (FORTH | BACK))) { if (state == STATE_PUSH_PULL_READY && (input & (FORTH | BACK))) {
int pushState = (input & FORTH) ? STATE_PUSH_BLOCK : STATE_PULL_BLOCK; int pushState = (input & FORTH) ? STATE_PUSH_BLOCK : STATE_PULL_BLOCK;
Block *block = getBlock(); Block *block = getBlock();
if (animation.canSetState(pushState) && block->doMove((input & FORTH) != 0)) { if (animation.canSetState(pushState) && block->doMove((input & FORTH) != 0)) {
alignToWall(-LARA_RADIUS); alignToWall(-LARA_RADIUS);
return pushState; return pushState;
@@ -1519,7 +1519,7 @@ struct Lara : Character {
vec3 p = pos + getDir() * (LARA_RADIUS + 2.0f); vec3 p = pos + getDir() * (LARA_RADIUS + 2.0f);
level->getFloorInfo(getRoomIndex(), (int)p.x, (int)p.y, (int)p.z, info); level->getFloorInfo(getRoomIndex(), (int)p.x, (int)p.y, (int)p.z, info);
if (info.floor - info.ceiling >= LARA_HEIGHT) if (info.floor - info.ceiling >= LARA_HEIGHT)
return (input & WALK) ? STATE_HANDSTAND : STATE_HANG_UP; return (input & WALK) ? STATE_HANDSTAND : STATE_HANG_UP;
} }
return STATE_HANG; return STATE_HANG;
} }
@@ -1535,16 +1535,16 @@ struct Lara : Character {
angle.x = -45.0f * DEG2RAD; angle.x = -45.0f * DEG2RAD;
return animation.setAnim(ANIM_WATER_FALL); // TODO: wronng animation return animation.setAnim(ANIM_WATER_FALL); // TODO: wronng animation
} }
if (state == STATE_SWAN_DIVE) { if (state == STATE_SWAN_DIVE) {
angle.x = -PI * 0.5f; angle.x = -PI * 0.5f;
game->waterDrop(pos, 128.0f, 0.2f); game->waterDrop(pos, 128.0f, 0.2f);
Sprite::add(game, TR::Entity::WATER_SPLASH, getRoomIndex(), (int)pos.x, (int)pos.y, (int)pos.z); Sprite::add(game, TR::Entity::WATER_SPLASH, getRoomIndex(), (int)pos.x, (int)pos.y, (int)pos.z);
return STATE_DIVE; return STATE_DIVE;
} }
if (input & JUMP) return STATE_SWIM; if (input & JUMP) return STATE_SWIM;
if (state == STATE_GLIDE && speed < LARA_SWIM_SPEED * 2.0f / 3.0f) if (state == STATE_GLIDE && speed < LARA_SWIM_SPEED * 2.0f / 3.0f)
return STATE_TREAD; return STATE_TREAD;
@@ -1552,7 +1552,7 @@ struct Lara : Character {
} }
virtual int getStateOnwater() { virtual int getStateOnwater() {
angle.x = 0.0f; angle.x = 0.0f;
if (state == STATE_WATER_OUT) return state; if (state == STATE_WATER_OUT) return state;
@@ -1571,7 +1571,7 @@ struct Lara : Character {
} }
if (input & FORTH) { if (input & FORTH) {
if (input & JUMP) { if (input & JUMP) {
angle.x = -PI * 0.25f; angle.x = -PI * 0.25f;
game->waterDrop(pos, 256.0f, 0.2f); game->waterDrop(pos, 256.0f, 0.2f);
return animation.setAnim(ANIM_TO_UNDERWATER); return animation.setAnim(ANIM_TO_UNDERWATER);
@@ -1584,11 +1584,11 @@ struct Lara : Character {
return STATE_SURF_SWIM; return STATE_SURF_SWIM;
} }
if (input & BACK) return STATE_SURF_BACK; if (input & BACK) return STATE_SURF_BACK;
if (input & WALK) { if (input & WALK) {
if (input & LEFT) return STATE_SURF_LEFT; if (input & LEFT) return STATE_SURF_LEFT;
if (input & RIGHT) return STATE_SURF_RIGHT; if (input & RIGHT) return STATE_SURF_RIGHT;
} }
return STATE_SURF_TREAD; return STATE_SURF_TREAD;
} }
@@ -1636,32 +1636,33 @@ struct Lara : Character {
if (Input::down[ikE] || Input::down[ikCtrl] || Input::down[ikJoyA]) input |= ACTION; if (Input::down[ikE] || Input::down[ikCtrl] || Input::down[ikJoyA]) input |= ACTION;
if (Input::down[ikQ] || Input::down[ikAlt] || Input::down[ikJoyY]) input |= WEAPON; if (Input::down[ikQ] || Input::down[ikAlt] || Input::down[ikJoyY]) input |= WEAPON;
// analog control // analog control
rotFactor = vec2(1.0f); rotFactor = vec2(1.0f);
if (Input::down[ikJoyL]) input = FORTH | BACK; if (Input::down[ikJoyL]) input = FORTH | BACK;
if ((state == STATE_STOP || stand == STATE_SURF_TREAD) && fabsf(Input::joy.L.x) < 0.5f && fabsf(Input::joy.L.y) < 0.5f) if ((state == STATE_STOP || state == STATE_SURF_TREAD || state == STATE_HANG) && fabsf(Input::joy.L.x) < 0.5f && fabsf(Input::joy.L.y) < 0.5f)
return input; return input;
bool moving = state == STATE_RUN || state == STATE_WALK || state == STATE_BACK || state == STATE_FAST_BACK || state == STATE_SURF_SWIM || state == STATE_SURF_BACK; bool moving = state == STATE_RUN || state == STATE_WALK || state == STATE_BACK || state == STATE_FAST_BACK || state == STATE_SURF_SWIM || state == STATE_SURF_BACK;
if (!moving) if (!moving) {
if (fabsf(Input::joy.L.x) < fabsf(Input::joy.L.y)) if (fabsf(Input::joy.L.x) < fabsf(Input::joy.L.y))
Input::joy.L.x = 0.0f; Input::joy.L.x = 0.0f;
else else
Input::joy.L.y = 0.0f; Input::joy.L.y = 0.0f;
}
if (Input::joy.L.x != 0.0f) { if (Input::joy.L.x != 0.0f) {
input |= (Input::joy.L.x < 0.0f) ? LEFT : RIGHT; input |= (Input::joy.L.x < 0.0f) ? LEFT : RIGHT;
if (moving || stand == STAND_UNDERWATER || stand == STAND_ONWATER) if (moving || stand == STAND_UNDERWATER || stand == STAND_ONWATER)
rotFactor.y = min(fabsf(Input::joy.L.x) / 0.75f, 1.0f); rotFactor.y = min(fabsf(Input::joy.L.x) / 0.75f, 1.0f);
} }
if (Input::joy.L.y != 0.0f) { if (Input::joy.L.y != 0.0f) {
input |= (Input::joy.L.y < 0.0f) ? FORTH : BACK; input |= (Input::joy.L.y < 0.0f) ? FORTH : BACK;
if (stand == STAND_UNDERWATER) if (stand == STAND_UNDERWATER)
rotFactor.x = min(fabsf(Input::joy.L.y) / 0.75f, 1.0f); rotFactor.x = min(fabsf(Input::joy.L.y) / 0.75f, 1.0f);
} }
return input; return input;
@@ -1672,7 +1673,7 @@ struct Lara : Character {
case STATE_PICK_UP : { case STATE_PICK_UP : {
TR::Entity &item = level->entities[lastPickUp]; TR::Entity &item = level->entities[lastPickUp];
if (!item.flags.invisible) { if (!item.flags.invisible) {
int pickupFrame = stand == STAND_GROUND ? PICKUP_FRAME_GROUND : PICKUP_FRAME_UNDERWATER; int pickupFrame = stand == STAND_GROUND ? PICKUP_FRAME_GROUND : PICKUP_FRAME_UNDERWATER;
if (animation.isFrameActive(pickupFrame)) { if (animation.isFrameActive(pickupFrame)) {
item.flags.invisible = true; item.flags.invisible = true;
inventory.add(item.type, 1); inventory.add(item.type, 1);
@@ -1716,10 +1717,10 @@ struct Lara : Character {
else if (state == STATE_FAST_BACK) else if (state == STATE_FAST_BACK)
w *= TURN_FAST_BACK; w *= TURN_FAST_BACK;
else if (state == STATE_TURN_LEFT || state == STATE_TURN_RIGHT || state == STATE_WALK) else if (state == STATE_TURN_LEFT || state == STATE_TURN_RIGHT || state == STATE_WALK)
w *= TURN_NORMAL; w *= TURN_NORMAL;
else if (state == STATE_FORWARD_JUMP || state == STATE_BACK) else if (state == STATE_FORWARD_JUMP || state == STATE_BACK)
w *= TURN_SLOW; w *= TURN_SLOW;
else else
w = 0.0f; w = 0.0f;
if (w != 0.0f) if (w != 0.0f)
@@ -1736,7 +1737,7 @@ struct Lara : Character {
case STATE_BACK_JUMP : case STATE_BACK_JUMP :
case STATE_FAST_BACK : case STATE_FAST_BACK :
case STATE_SLIDE_BACK : case STATE_SLIDE_BACK :
case STATE_ROLL_1 : case STATE_ROLL_1 :
angleExt += PI; angleExt += PI;
break; break;
case STATE_LEFT_JUMP : case STATE_LEFT_JUMP :
@@ -1766,7 +1767,7 @@ struct Lara : Character {
case STATE_SURF_SWIM : case STATE_SURF_SWIM :
case STATE_SURF_BACK : case STATE_SURF_BACK :
case STATE_SURF_LEFT : case STATE_SURF_LEFT :
case STATE_SURF_RIGHT : case STATE_SURF_RIGHT :
speed = min(speed + 30.0f * LARA_WATER_ACCEL * Core::deltaTime, LARA_SURF_SPEED); speed = min(speed + 30.0f * LARA_WATER_ACCEL * Core::deltaTime, LARA_SURF_SPEED);
break; break;
default : default :
@@ -1817,7 +1818,7 @@ struct Lara : Character {
if (velocity.length() >= 1.0f) if (velocity.length() >= 1.0f)
move(); move();
if (getEntity().type != TR::Entity::LARA) { if (getEntity().type != TR::Entity::LARA) {
TR::Entity &e = getEntity(); TR::Entity &e = getEntity();
vec3 &p = getPos(); vec3 &p = getPos();
@@ -1827,9 +1828,9 @@ struct Lara : Character {
checkRoom(); checkRoom();
updateEntity(); updateEntity();
} }
if (braid) if (braid)
braid->update(); braid->update();
} }
virtual vec3& getPos() { virtual vec3& getPos() {
@@ -1839,7 +1840,7 @@ struct Lara : Character {
void move() { void move() {
//TR::Entity &e = getEntity(); //TR::Entity &e = getEntity();
//TR::Level::FloorInfo info; //TR::Level::FloorInfo info;
//float f, c; //float f, c;
//bool canPassGap = true; //bool canPassGap = true;
/* /*
@@ -1899,7 +1900,7 @@ struct Lara : Character {
} }
if (stand == STAND_HANG && collision.side != Collision::FRONT) { if (stand == STAND_HANG && collision.side != Collision::FRONT) {
offset.x = offset.z = 0.0f; offset.x = offset.z = 0.0f;
minHeight = LARA_HANG_OFFSET; minHeight = LARA_HANG_OFFSET;
maxDescent = 0xFFFFFF; maxDescent = 0xFFFFFF;
maxAscent = -LARA_HANG_OFFSET; maxAscent = -LARA_HANG_OFFSET;
@@ -1932,10 +1933,10 @@ struct Lara : Character {
} }
} }
} }
// check entities in the room // check entities in the room
if (canPassGap) if (canPassGap)
for (int i = 0; i < level->entitiesCount; i++) for (int i = 0; i < level->entitiesCount; i++)
if (i != entity && level->entities[i].room == e.room && level->entities[i].controller) { if (i != entity && level->entities[i].room == e.room && level->entities[i].controller) {
Box mBox = ((Controller*)level->entities[i].controller)->getBoundingBox(); Box mBox = ((Controller*)level->entities[i].controller)->getBoundingBox();
if (eBox.intersect(mBox)) { if (eBox.intersect(mBox)) {
@@ -1951,7 +1952,7 @@ struct Lara : Character {
if (state == STATE_WALK) rightStart = 13; if (state == STATE_WALK) rightStart = 13;
if (state == STATE_BACK) rightStart = 28; if (state == STATE_BACK) rightStart = 28;
bool isLeftFoot = animation.frameIndex < rightStart || animation.frameIndex > (rightStart + animation.framesCount / 2); bool isLeftFoot = animation.frameIndex < rightStart || animation.frameIndex > (rightStart + animation.framesCount / 2);
if (stand == STAND_UNDERWATER) { if (stand == STAND_UNDERWATER) {
if (collision.side == Collision::TOP) if (collision.side == Collision::TOP)
@@ -1963,7 +1964,7 @@ struct Lara : Character {
if (stand == STAND_AIR && collision.side == Collision::TOP && velocity.y < 0.0f) if (stand == STAND_AIR && collision.side == Collision::TOP && velocity.y < 0.0f)
velocity.y = 30.0f; velocity.y = 30.0f;
if (collision.side == Collision::FRONT) { if (collision.side == Collision::FRONT) {
int floor = collision.info[Collision::FRONT].floor; int floor = collision.info[Collision::FRONT].floor;
// hit the wall // hit the wall
@@ -1997,7 +1998,7 @@ struct Lara : Character {
pos.y = opos.y; pos.y = opos.y;
break; break;
default : ;// no smash animation default : ;// no smash animation
} }
} else { } else {
if (stand == STAND_GROUND) { if (stand == STAND_GROUND) {
int floor = collision.info[Collision::NONE].floor; int floor = collision.info[Collision::NONE].floor;

View File

@@ -330,7 +330,7 @@ struct Level : IGame {
} }
void initReflections() { void initReflections() {
Core::resetStates(); Core::beginFrame();
for (int i = 0; i < level.entitiesBaseCount; i++) { for (int i = 0; i < level.entitiesBaseCount; i++) {
TR::Entity &e = level.entities[i]; TR::Entity &e = level.entities[i];
if (e.type == TR::Entity::CRYSTAL) { if (e.type == TR::Entity::CRYSTAL) {
@@ -338,6 +338,7 @@ struct Level : IGame {
renderEnvironment(c->getRoomIndex(), c->pos - vec3(0, 512, 0), &c->environment); renderEnvironment(c->getRoomIndex(), c->pos - vec3(0, 512, 0), &c->environment);
} }
} }
Core::endFrame();
} }
void setRoomParams(int roomIndex, Shader::Type type, float diffuse, float ambient, float specular, float alpha, bool alphaTest = false) { void setRoomParams(int roomIndex, Shader::Type type, float diffuse, float ambient, float specular, float alpha, bool alphaTest = false) {
@@ -523,7 +524,7 @@ struct Level : IGame {
vec3 pos = controller->getPos(); vec3 pos = controller->getPos();
if (Core::settings.ambient) { if (Core::settings.ambient) {
AmbientCache::Cube cube; AmbientCache::Cube cube;
if (Core::frameIndex != controller->frameIndex) { if (Core::stats.frame != controller->frameIndex) {
ambientCache->getAmbient(entity.room, pos, cube); ambientCache->getAmbient(entity.room, pos, cube);
if (cube.status == AmbientCache::Cube::READY) if (cube.status == AmbientCache::Cube::READY)
memcpy(controller->ambient, cube.colors, sizeof(cube.colors)); // store last calculated ambient into controller memcpy(controller->ambient, cube.colors, sizeof(cube.colors)); // store last calculated ambient into controller
@@ -642,6 +643,29 @@ struct Level : IGame {
Core::mProj = mat4(90, 1.0f, camera->znear, camera->zfar); Core::mProj = mat4(90, 1.0f, camera->znear, camera->zfar);
} }
mat4 calcCromMatrix(const mat4 &lightViewProj, const Box *boxes, int count) {
mat4 cameraViewProjInv = (mat4(camera->fov, float(Core::width) / Core::height, 512.0f, 4096.0f) * camera->mViewInv.inverse()).inverse();
Box frustumBox = Box(vec3(-1.0f), vec3(1.0f)) * cameraViewProjInv;
Box casterBox(vec3(+INF), vec3(-INF));
for (int i = 0; i < count; i++)
casterBox += boxes[i] * lightViewProj;
casterBox -= frustumBox * lightViewProj;
vec3 scale = vec3(2.0f, 2.0f, 1.0f) / casterBox.size();
vec3 center = casterBox.center();
vec3 offset = vec3(center.x, center.y, casterBox.min.z) * scale;
return mat4(scale.x, 0.0f, 0.0f, 0.0f,
0.0f, scale.y, 0.0f, 0.0f,
0.0f, 0.0f, scale.z, 0.0f,
-offset.x, -offset.y, -offset.z, 1.0f);
}
bool setupLightCamera() { bool setupLightCamera() {
vec3 pos = lara->getPos(); vec3 pos = lara->getPos();
@@ -654,12 +678,32 @@ struct Level : IGame {
vec3 shadowLightPos = vec3(float(light.x), float(light.y), float(light.z)); vec3 shadowLightPos = vec3(float(light.x), float(light.y), float(light.z));
Core::mViewInv = mat4(shadowLightPos, pos - vec3(0, 256, 0), vec3(0, -1, 0)); Core::mViewInv = mat4(shadowLightPos, pos - vec3(0, 256, 0), vec3(0, -1, 0));
Core::mView = Core::mViewInv.inverse(); Core::mView = Core::mViewInv.inverse();
Core::mProj = mat4(120, 1.0f, camera->znear, camera->zfar); Core::mProj = mat4(120.0f, 1.0f, camera->znear, camera->zfar);
mat4 bias; mat4 bias;
bias.identity(); bias.identity();
bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f; bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f;
Core::mLightProj = bias * Core::mProj * Core::mView; /*
Box boxes[32];
int bCount = 0;
float rq = light.radius * light.radius;
for (int i = 0; i < level.entitiesCount; i++) {
TR::Entity &e = level.entities[i];
Controller *controller = (Controller*)e.controller;
if (controller && TR::castShadow(e.type) && rq > (shadowLightPos - controller->pos).length2())
boxes[bCount++] = controller->getBoundingBox();
}
*/
/*
vec3 shadowBox(1024.0f, 0.0f, 1024.0f);
boxes[0] = lara->getBoundingBox();
boxes[0] += Box(lara->pos - shadowBox, lara->pos + shadowBox);
bCount++;
Core::mProj = calcCromMatrix(Core::mProj * Core::mView, &boxes[0], bCount) * Core::mProj;
*/
Core::mLightProj = bias * (Core::mProj * Core::mView);
return true; return true;
} }
@@ -672,7 +716,8 @@ struct Level : IGame {
bool colorShadow = shadow->format == Texture::Format::RGBA ? true : false; bool colorShadow = shadow->format == Texture::Format::RGBA ? true : false;
if (colorShadow) if (colorShadow)
Core::setClearColor(vec4(1.0f, 1.0f, 1.0f, 1.0f)); Core::setClearColor(vec4(1.0f, 1.0f, 1.0f, 1.0f));
Core::setTarget(shadow, true); Core::setTarget(shadow);
Core::clear(true, true);
Core::setCulling(cfBack); Core::setCulling(cfBack);
renderScene(roomIndex); renderScene(roomIndex);
Core::invalidateTarget(!colorShadow, colorShadow); Core::invalidateTarget(!colorShadow, colorShadow);
@@ -686,7 +731,6 @@ struct Level : IGame {
params->clipHeight = NO_CLIP_PLANE; params->clipHeight = NO_CLIP_PLANE;
params->clipSign = 1.0f; params->clipSign = 1.0f;
params->waterHeight = params->clipHeight; params->waterHeight = params->clipHeight;
Core::resetStates();
if (ambientCache) if (ambientCache)
ambientCache->precessQueue(); ambientCache->precessQueue();
@@ -695,7 +739,8 @@ struct Level : IGame {
if (shadow) if (shadow)
renderShadows(lara->getRoomIndex()); renderShadows(lara->getRoomIndex());
Core::setTarget(NULL, true); Core::setTarget(NULL);
Core::clear(true, true);
Core::setViewport(0, 0, Core::width, Core::height); Core::setViewport(0, 0, Core::width, Core::height);
if (waterCache) if (waterCache)
@@ -789,10 +834,10 @@ struct Level : IGame {
glLoadIdentity(); glLoadIdentity();
glOrtho(0, Core::width, 0, Core::height, 0, 1); glOrtho(0, Core::width, 0, Core::height, 0, 1);
if (waterCache->count) // if (waterCache->count)
waterCache->refract->bind(sDiffuse); // waterCache->refract->bind(sDiffuse);
else // else
atlas->bind(sDiffuse); shadow->bind(sDiffuse);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);

View File

@@ -33,7 +33,7 @@ void sndInit() {
.rate = 44100, .rate = 44100,
.channels = 2 .channels = 2
}; };
static const pa_buffer_attr attr = { static const pa_buffer_attr attr = {
.maxlength = SND_DATA_SIZE * 2, .maxlength = SND_DATA_SIZE * 2,
.tlength = 0xFFFFFFFF, .tlength = 0xFFFFFFFF,
@@ -44,20 +44,20 @@ void sndInit() {
pthread_mutex_init(&sndMutex, NULL); pthread_mutex_init(&sndMutex, NULL);
int error; int error;
if (!(sndOut = pa_simple_new(NULL, WND_TITLE, PA_STREAM_PLAYBACK, NULL, "game", &spec, NULL, &attr, &error))) { if (!(sndOut = pa_simple_new(NULL, WND_TITLE, PA_STREAM_PLAYBACK, NULL, "game", &spec, NULL, &attr, &error))) {
LOG("pa_simple_new() failed: %s\n", pa_strerror(error)); LOG("pa_simple_new() failed: %s\n", pa_strerror(error));
sndData = NULL; sndData = NULL;
return; return;
} }
sndData = new Sound::Frame[SND_DATA_SIZE / SND_FRAME_SIZE]; sndData = new Sound::Frame[SND_DATA_SIZE / SND_FRAME_SIZE];
pthread_create(&sndThread, NULL, sndFill, NULL); pthread_create(&sndThread, NULL, sndFill, NULL);
} }
void sndFree() { void sndFree() {
if (sndOut) { if (sndOut) {
pthread_cancel(sndThread); pthread_cancel(sndThread);
pthread_mutex_lock(&sndMutex); pthread_mutex_lock(&sndMutex);
// pa_simple_flush(sndOut, NULL); // pa_simple_flush(sndOut, NULL);
// pa_simple_free(sndOut); // pa_simple_free(sndOut);
@@ -102,7 +102,7 @@ void WndProc(const XEvent &e) {
Core::width = e.xconfigure.width; Core::width = e.xconfigure.width;
Core::height = e.xconfigure.height; Core::height = e.xconfigure.height;
break; break;
case KeyPress : case KeyPress :
case KeyRelease : case KeyRelease :
if (e.type == KeyPress && (e.xkey.state & Mod1Mask) && e.xkey.keycode == 36) { if (e.type == KeyPress && (e.xkey.state & Mod1Mask) && e.xkey.keycode == 36) {
// TODO: windowed <-> fullscreen switch // TODO: windowed <-> fullscreen switch
@@ -120,10 +120,15 @@ void WndProc(const XEvent &e) {
case MotionNotify : case MotionNotify :
Input::setPos(ikMouseL, vec2((float)e.xmotion.x, (float)e.xmotion.y)); Input::setPos(ikMouseL, vec2((float)e.xmotion.x, (float)e.xmotion.y));
break; break;
} }
} }
char Stream::cacheDir[255];
char Stream::contentDir[255];
int main() { int main() {
Stream::contentDir[0] = Stream::cacheDir[0] = 0;
static int XGLAttr[] = { static int XGLAttr[] = {
GLX_RGBA, GLX_RGBA,
GLX_DOUBLEBUFFER, GLX_DOUBLEBUFFER,
@@ -142,8 +147,8 @@ int main() {
ButtonMotionMask | PointerMotionMask; ButtonMotionMask | PointerMotionMask;
Window wnd = XCreateWindow(dpy, RootWindow(dpy, vis->screen), Window wnd = XCreateWindow(dpy, RootWindow(dpy, vis->screen),
0, 0, 1280, 720, 0, 0, 0, 1280, 720, 0,
vis->depth, InputOutput, vis->visual, vis->depth, InputOutput, vis->visual,
CWColormap | CWBorderPixel | CWEventMask, &attr); CWColormap | CWBorderPixel | CWEventMask, &attr);
XStoreName(dpy, wnd, WND_TITLE); XStoreName(dpy, wnd, WND_TITLE);
@@ -156,9 +161,9 @@ int main() {
sndInit(); sndInit();
Game::init(); Game::init();
int lastTime = getTime(), fpsTime = lastTime + 1000, fps = 0; int lastTime = getTime();
while (1) { while (1) {
if (XPending(dpy)) { if (XPending(dpy)) {
XEvent event; XEvent event;
@@ -181,20 +186,11 @@ int main() {
pthread_mutex_unlock(&sndMutex); pthread_mutex_unlock(&sndMutex);
lastTime = time; lastTime = time;
Core::stats.dips = 0;
Core::stats.tris = 0;
Game::render(); Game::render();
glXSwapBuffers(dpy, wnd); glXSwapBuffers(dpy, wnd);
if (fpsTime < getTime()) {
LOG("FPS: %d DIP: %d TRI: %d\n", fps, Core::stats.dips, Core::stats.tris);
fps = 0;
fpsTime = getTime() + 1000;
} else
fps++;
} }
}; };
sndFree(); sndFree();
Game::free(); Game::free();

View File

@@ -3,7 +3,7 @@
#include "game.h" #include "game.h"
int lastTime, fpsTime, fps; int lastTime;
EGLDisplay display; EGLDisplay display;
EGLSurface surface; EGLSurface surface;
EGLContext context; EGLContext context;
@@ -23,7 +23,7 @@ extern "C" {
} }
InputKey joyToInputKey(int code) { InputKey joyToInputKey(int code) {
static const int codes[] = { 0, 1, 2, 3, 4, 5, 10, 11, 8, 9, 6, 7 }; static const int codes[] = { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 6, 7 };
for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i++) for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i++)
if (codes[i] == code) if (codes[i] == code)
@@ -63,9 +63,13 @@ void joyUpdate() {
int count = emscripten_get_num_gamepads(); int count = emscripten_get_num_gamepads();
if (count <= 0) if (count <= 0)
return; return;
EmscriptenGamepadEvent state; EmscriptenGamepadEvent state;
if (emscripten_get_gamepad_status(0, &state) != EMSCRIPTEN_RESULT_SUCCESS) for (int i = 0; i < count; i++)
if (emscripten_get_gamepad_status(i, &state) == EMSCRIPTEN_RESULT_SUCCESS && state.numButtons >= 12)
break;
if (state.numButtons < 12)
return; return;
for (int i = 0; i < max(state.numButtons, 12); i++) { for (int i = 0; i < max(state.numButtons, 12); i++) {
@@ -101,17 +105,8 @@ void main_loop() {
} }
lastTime = time; lastTime = time;
Core::stats.dips = 0;
Core::stats.tris = 0;
Game::render(); Game::render();
eglSwapBuffers(display, surface); eglSwapBuffers(display, surface);
if (fpsTime < getTime()) {
LOG("FPS: %d DIP: %d TRI: %d\n", fps, Core::stats.dips, Core::stats.tris);
fps = 0;
fpsTime = getTime() + 1000;
} else
fps++;
} }
bool initGL() { bool initGL() {
@@ -291,8 +286,6 @@ int main() {
resize(); resize();
lastTime = getTime(); lastTime = getTime();
fpsTime = lastTime + 1000;
fps = 0;
emscripten_set_main_loop(main_loop, 0, true); emscripten_set_main_loop(main_loop, 0, true);

View File

@@ -13,15 +13,15 @@
#include "game.h" #include "game.h"
DWORD getTime() { int getTime() {
#ifdef DEBUG #ifdef DEBUG
LARGE_INTEGER Freq, Count; LARGE_INTEGER Freq, Count;
QueryPerformanceFrequency(&Freq); QueryPerformanceFrequency(&Freq);
QueryPerformanceCounter(&Count); QueryPerformanceCounter(&Count);
return (DWORD)(Count.QuadPart * 1000L / Freq.QuadPart); return int(Count.QuadPart * 1000L / Freq.QuadPart);
#else #else
timeBeginPeriod(0); timeBeginPeriod(0);
return timeGetTime(); return int(timeGetTime());
#endif #endif
} }
@@ -232,8 +232,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
break; break;
case WM_KEYDOWN : case WM_KEYDOWN :
case WM_KEYUP : case WM_KEYUP :
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN :
case WM_SYSKEYUP: case WM_SYSKEYUP :
if (msg == WM_SYSKEYDOWN && wParam == VK_RETURN) { // switch to fullscreen or window if (msg == WM_SYSKEYDOWN && wParam == VK_RETURN) { // switch to fullscreen or window
static WINDOWPLACEMENT pLast; static WINDOWPLACEMENT pLast;
DWORD style = GetWindowLong(hWnd, GWL_STYLE); DWORD style = GetWindowLong(hWnd, GWL_STYLE);
@@ -262,6 +262,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
case WM_MBUTTONDOWN : case WM_MBUTTONDOWN :
case WM_MBUTTONUP : case WM_MBUTTONUP :
case WM_MBUTTONDBLCLK : { case WM_MBUTTONDBLCLK : {
if ((GetMessageExtraInfo() & 0xFFFFFF00) == 0xFF515700) break;
InputKey key = mouseToInputKey(msg); InputKey key = mouseToInputKey(msg);
Input::setPos(key, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam))); Input::setPos(key, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam)));
bool down = msg != WM_LBUTTONUP && msg != WM_RBUTTONUP && msg != WM_MBUTTONUP; bool down = msg != WM_LBUTTONUP && msg != WM_RBUTTONUP && msg != WM_MBUTTONUP;
@@ -273,6 +274,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
break; break;
} }
case WM_MOUSEMOVE : case WM_MOUSEMOVE :
if ((GetMessageExtraInfo() & 0xFFFFFF00) == 0xFF515700) break;
Input::setPos(ikMouseL, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam))); Input::setPos(ikMouseL, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam)));
break; break;
// joystick // joystick
@@ -355,7 +357,7 @@ int main(int argc, char** argv) {
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)&WndProc); SetWindowLong(hWnd, GWL_WNDPROC, (LONG)&WndProc);
ShowWindow(hWnd, SW_SHOWDEFAULT); ShowWindow(hWnd, SW_SHOWDEFAULT);
DWORD lastTime = getTime(), fpsTime = lastTime + 1000, fps = 0; DWORD lastTime = getTime();
MSG msg; MSG msg;
do { do {
@@ -379,20 +381,11 @@ int main(int argc, char** argv) {
LeaveCriticalSection(&sndCS); LeaveCriticalSection(&sndCS);
lastTime = time; lastTime = time;
Core::stats.dips = 0;
Core::stats.tris = 0;
Game::render(); Game::render();
SwapBuffers(hDC); SwapBuffers(hDC);
#ifdef _DEBUG #ifdef _DEBUG
Sleep(20); Sleep(20);
#endif #endif
if (fpsTime < getTime()) {
LOG("FPS: %d DIP: %d TRI: %d\n", fps, Core::stats.dips, Core::stats.tris);
fps = 0;
fpsTime = getTime() + 1000;
} else
fps++;
} }
} while (msg.message != WM_QUIT); } while (msg.message != WM_QUIT);

View File

@@ -204,26 +204,28 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
} }
#endif #endif
#define SHADOW_TEXEL (1.5 / 1024.0)
float getShadow(vec4 lightProj) { float getShadow(vec4 lightProj) {
vec3 p = lightProj.xyz / lightProj.w; vec3 p = lightProj.xyz / lightProj.w;
float rShadow = 0.0; float rShadow = 0.0;
rShadow += SHADOW(p + (vec3(-0.94201624, -0.39906216, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3(-0.94201624, -0.39906216, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3( 0.94558609, -0.76890725, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3( 0.94558609, -0.76890725, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3(-0.09418410, -0.92938870, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3(-0.09418410, -0.92938870, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3( 0.34495938, 0.29387760, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3( 0.34495938, 0.29387760, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3(-0.91588581, 0.45771432, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3(-0.91588581, 0.45771432, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3(-0.81544232, -0.87912464, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3(-0.81544232, -0.87912464, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3(-0.38277543, 0.27676845, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3(-0.38277543, 0.27676845, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3( 0.97484398, 0.75648379, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3( 0.97484398, 0.75648379, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3( 0.44323325, -0.97511554, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3( 0.44323325, -0.97511554, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3( 0.53742981, -0.47373420, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3( 0.53742981, -0.47373420, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3(-0.26496911, -0.41893023, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3(-0.26496911, -0.41893023, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3( 0.79197514, 0.19090188, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3( 0.79197514, 0.19090188, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3(-0.24188840, 0.99706507, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3(-0.24188840, 0.99706507, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3(-0.81409955, 0.91437590, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3(-0.81409955, 0.91437590, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3( 0.19984126, 0.78641367, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3( 0.19984126, 0.78641367, 0.0) * SHADOW_TEXEL));
rShadow += SHADOW(p + (vec3( 0.14383161, -0.14100790, 0.0) * (1.5 / 1024.0))); rShadow += SHADOW(p + (vec3( 0.14383161, -0.14100790, 0.0) * SHADOW_TEXEL));
rShadow /= 16.0; rShadow /= 16.0;

View File

@@ -143,16 +143,20 @@ struct vec2 {
vec2& operator += (const vec2 &v) { x += v.x; y += v.y; return *this; } vec2& operator += (const vec2 &v) { x += v.x; y += v.y; return *this; }
vec2& operator -= (const vec2 &v) { x -= v.x; y -= v.y; return *this; } vec2& operator -= (const vec2 &v) { x -= v.x; y -= v.y; return *this; }
vec2& operator *= (const vec2 &v) { x *= v.x; y *= v.y; return *this; } vec2& operator *= (const vec2 &v) { x *= v.x; y *= v.y; return *this; }
vec2& operator /= (const vec2 &v) { x /= v.x; y /= v.y; return *this; }
vec2& operator += (float s) { x += s; y += s; return *this; } vec2& operator += (float s) { x += s; y += s; return *this; }
vec2& operator -= (float s) { x -= s; y -= s; return *this; } vec2& operator -= (float s) { x -= s; y -= s; return *this; }
vec2& operator *= (float s) { x *= s; y *= s; return *this; } vec2& operator *= (float s) { x *= s; y *= s; return *this; }
vec2& operator /= (float s) { x /= s; y /= s; return *this; }
vec2 operator + (const vec2 &v) const { return vec2(x + v.x, y + v.y); } vec2 operator + (const vec2 &v) const { return vec2(x + v.x, y + v.y); }
vec2 operator - (const vec2 &v) const { return vec2(x - v.x, y - v.y); } vec2 operator - (const vec2 &v) const { return vec2(x - v.x, y - v.y); }
vec2 operator * (const vec2 &v) const { return vec2(x * v.x, y * v.y); } vec2 operator * (const vec2 &v) const { return vec2(x * v.x, y * v.y); }
vec2 operator / (const vec2 &v) const { return vec2(x / v.x, y / v.y); }
vec2 operator + (float s) const { return vec2(x + s, y + s ); } vec2 operator + (float s) const { return vec2(x + s, y + s ); }
vec2 operator - (float s) const { return vec2(x - s, y - s ); } vec2 operator - (float s) const { return vec2(x - s, y - s ); }
vec2 operator * (float s) const { return vec2(x * s, y * s ); } vec2 operator * (float s) const { return vec2(x * s, y * s ); }
vec2 operator / (float s) const { return vec2(x / s, y / s ); }
float dot(const vec2 &v) const { return x * v.x + y * v.y; } float dot(const vec2 &v) const { return x * v.x + y * v.y; }
float cross(const vec2 &v) const { return x * v.y - y * v.x; } float cross(const vec2 &v) const { return x * v.y - y * v.x; }
@@ -164,7 +168,11 @@ struct vec2 {
}; };
struct vec3 { struct vec3 {
float x, y, z; union {
struct { vec2 xy; };
struct { float x, y, z; };
};
vec3() {} vec3() {}
vec3(float s) : x(s), y(s), z(s) {} vec3(float s) : x(s), y(s), z(s) {}
vec3(float x, float y, float z) : x(x), y(y), z(z) {} vec3(float x, float y, float z) : x(x), y(y), z(z) {}
@@ -182,16 +190,20 @@ struct vec3 {
vec3& operator += (const vec3 &v) { x += v.x; y += v.y; z += v.z; return *this; } vec3& operator += (const vec3 &v) { x += v.x; y += v.y; z += v.z; return *this; }
vec3& operator -= (const vec3 &v) { x -= v.x; y -= v.y; z -= v.z; return *this; } vec3& operator -= (const vec3 &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
vec3& operator *= (const vec3 &v) { x *= v.x; y *= v.y; z *= v.z; return *this; } vec3& operator *= (const vec3 &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
vec3& operator /= (const vec3 &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
vec3& operator += (float s) { x += s; y += s; z += s; return *this; } vec3& operator += (float s) { x += s; y += s; z += s; return *this; }
vec3& operator -= (float s) { x -= s; y -= s; z -= s; return *this; } vec3& operator -= (float s) { x -= s; y -= s; z -= s; return *this; }
vec3& operator *= (float s) { x *= s; y *= s; z *= s; return *this; } vec3& operator *= (float s) { x *= s; y *= s; z *= s; return *this; }
vec3& operator /= (float s) { x /= s; y /= s; z /= s; return *this; }
vec3 operator + (const vec3 &v) const { return vec3(x + v.x, y + v.y, z + v.z); } vec3 operator + (const vec3 &v) const { return vec3(x + v.x, y + v.y, z + v.z); }
vec3 operator - (const vec3 &v) const { return vec3(x - v.x, y - v.y, z - v.z); } vec3 operator - (const vec3 &v) const { return vec3(x - v.x, y - v.y, z - v.z); }
vec3 operator * (const vec3 &v) const { return vec3(x * v.x, y * v.y, z * v.z); } vec3 operator * (const vec3 &v) const { return vec3(x * v.x, y * v.y, z * v.z); }
vec3 operator / (const vec3 &v) const { return vec3(x / v.x, y / v.y, z / v.z); }
vec3 operator + (float s) const { return vec3(x + s, y + s, z + s); } vec3 operator + (float s) const { return vec3(x + s, y + s, z + s); }
vec3 operator - (float s) const { return vec3(x - s, y - s, z - s); } vec3 operator - (float s) const { return vec3(x - s, y - s, z - s); }
vec3 operator * (float s) const { return vec3(x * s, y * s, z * s); } vec3 operator * (float s) const { return vec3(x * s, y * s, z * s); }
vec3 operator / (float s) const { return vec3(x / s, y / s, z / s); }
float dot(const vec3 &v) const { return x * v.x + y * v.y + z * v.z; } float dot(const vec3 &v) const { return x * v.x + y * v.y + z * v.z; }
vec3 cross(const vec3 &v) const { return vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } vec3 cross(const vec3 &v) const { return vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
@@ -219,6 +231,7 @@ struct vec3 {
struct vec4 { struct vec4 {
union { union {
struct { vec2 xy; };
struct { vec3 xyz; }; struct { vec3 xyz; };
struct { float x, y, z, w; }; struct { float x, y, z, w; };
}; };
@@ -356,6 +369,15 @@ struct mat4 {
mat4() {} mat4() {}
mat4(float e00, float e10, float e20, float e30,
float e01, float e11, float e21, float e31,
float e02, float e12, float e22, float e32,
float e03, float e13, float e23, float e33) :
e00(e00), e10(e10), e20(e20), e30(e30),
e01(e01), e11(e11), e21(e21), e31(e31),
e02(e02), e12(e12), e22(e22), e32(e32),
e03(e03), e13(e13), e23(e23), e33(e33) {}
mat4(const quat &rot, const vec3 &pos) { mat4(const quat &rot, const vec3 &pos) {
setRot(rot); setRot(rot);
setPos(pos); setPos(pos);
@@ -683,6 +705,60 @@ struct Box {
Box() {} Box() {}
Box(const vec3 &min, const vec3 &max) : min(min), max(max) {} Box(const vec3 &min, const vec3 &max) : min(min), max(max) {}
vec3 operator [] (int index) const {
ASSERT(index >= 0 && index <= 7);
switch (index) {
case 0 : return min;
case 1 : return max;
case 2 : return vec3(min.x, max.y, max.z);
case 3 : return vec3(max.x, min.y, max.z);
case 4 : return vec3(min.x, min.y, max.z);
case 5 : return vec3(max.x, max.y, min.z);
case 6 : return vec3(min.x, max.y, min.z);
case 7 : return vec3(max.x, min.y, min.z);
}
return min;
}
Box& operator += (const Box &box) {
min.x = ::min(min.x, box.min.x);
min.y = ::min(min.y, box.min.y);
min.z = ::min(min.z, box.min.z);
max.x = ::max(max.x, box.max.x);
max.y = ::max(max.y, box.max.y);
max.z = ::max(max.z, box.max.z);
return *this;
}
Box& operator += (const vec3 &v) {
min.x = ::min(min.x, v.x);
min.y = ::min(min.y, v.y);
min.z = ::min(min.z, v.z);
max.x = ::max(max.x, v.x);
max.y = ::max(max.y, v.y);
max.z = ::max(max.z, v.z);
return *this;
}
Box& operator -= (const Box &box) {
min.x = ::max(min.x, box.min.x);
min.y = ::max(min.y, box.min.y);
min.z = ::max(min.z, box.min.z);
max.x = ::min(max.x, box.max.x);
max.y = ::min(max.y, box.max.y);
max.z = ::min(max.z, box.max.z);
return *this;
}
Box operator * (const mat4 &m) const {
Box res(vec3(+INF), vec3(-INF));
for (int i = 0; i < 8; i++) {
vec4 v = m * vec4((*this)[i], 1.0f);
res += v.xyz /= v.w;
}
return res;
}
vec3 center() const { vec3 center() const {
return (min + max) * 0.5f; return (min + max) * 0.5f;
} }