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:
@@ -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
|
||||||
|
@@ -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)) {
|
||||||
|
33
src/core.h
33
src/core.h
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -60,8 +60,9 @@ namespace Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void render() {
|
void render() {
|
||||||
|
Core::beginFrame();
|
||||||
level->render();
|
level->render();
|
||||||
Core::frameIndex++;
|
Core::endFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
197
src/lara.h
197
src/lara.h
@@ -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;
|
||||||
|
67
src/level.h
67
src/level.h
@@ -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);
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
78
src/utils.h
78
src/utils.h
@@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user