mirror of
https://github.com/XProger/OpenLara.git
synced 2025-01-17 21:09:00 +01:00
#16 transform meshes by quaternion & pos instead of matrix
This commit is contained in:
parent
d1bd39abfd
commit
687db8a01a
BIN
bin/OpenLara.exe
BIN
bin/OpenLara.exe
Binary file not shown.
@ -200,46 +200,46 @@ struct Animation {
|
||||
return lerpAngle(frameA->getAngle(joint), frameB->getAngle(joint), delta);
|
||||
}
|
||||
|
||||
mat4 getJoints(mat4 matrix, int joint, bool postRot = false, mat4 *joints = NULL) {
|
||||
Basis getJoints(Basis basis, int joint, bool postRot = false, Basis *joints = NULL) {
|
||||
ASSERT(model);
|
||||
vec3 offset = isPrepareToNext ? this->offset : vec3(0.0f);
|
||||
matrix.translate(((vec3)frameA->pos).lerp(offset + frameB->pos, delta));
|
||||
basis.translate(((vec3)frameA->pos).lerp(offset + frameB->pos, delta));
|
||||
|
||||
TR::Node *node = (int)model->node < level->nodesDataSize ? (TR::Node*)&level->nodesData[model->node] : NULL;
|
||||
|
||||
int sIndex = 0;
|
||||
mat4 stack[16];
|
||||
Basis stack[16];
|
||||
|
||||
for (int i = 0; i < model->mCount; i++) {
|
||||
|
||||
if (i > 0 && node) {
|
||||
TR::Node &t = node[i - 1];
|
||||
|
||||
if (t.flags & 0x01) matrix = stack[--sIndex];
|
||||
if (t.flags & 0x02) stack[sIndex++] = matrix;
|
||||
if (t.flags & 0x01) basis = stack[--sIndex];
|
||||
if (t.flags & 0x02) stack[sIndex++] = basis;
|
||||
|
||||
ASSERT(sIndex >= 0 && sIndex < 16);
|
||||
|
||||
matrix.translate(vec3((float)t.x, (float)t.y, (float)t.z));
|
||||
basis.translate(vec3((float)t.x, (float)t.y, (float)t.z));
|
||||
}
|
||||
|
||||
if (i == joint && !postRot)
|
||||
return matrix;
|
||||
return basis;
|
||||
|
||||
quat q;
|
||||
if (overrideMask & (1 << i))
|
||||
q = overrides[i];
|
||||
else
|
||||
q = getJointRot(i);
|
||||
matrix = matrix * mat4(q, vec3(0.0f));
|
||||
basis.rotate(q);
|
||||
|
||||
if (i == joint && postRot)
|
||||
return matrix;
|
||||
return basis;
|
||||
|
||||
if (joints)
|
||||
joints[i] = matrix;
|
||||
joints[i] = basis;
|
||||
}
|
||||
return matrix;
|
||||
return basis;
|
||||
}
|
||||
|
||||
Box getBoundingBox(const vec3 &pos, int dir) {
|
||||
|
@ -22,7 +22,7 @@ struct Controller {
|
||||
vec3 pos;
|
||||
vec3 angle;
|
||||
|
||||
mat4 *joints;
|
||||
Basis *joints;
|
||||
int frameIndex;
|
||||
|
||||
vec3 ambient[6];
|
||||
@ -49,7 +49,7 @@ struct Controller {
|
||||
pos = vec3((float)e.x, (float)e.y, (float)e.z);
|
||||
angle = vec3(0.0f, e.rotation, 0.0f);
|
||||
TR::Model *m = getModel();
|
||||
joints = m ? new mat4[m->mCount] : NULL;
|
||||
joints = m ? new Basis[m->mCount] : NULL;
|
||||
frameIndex = -1;
|
||||
specular = 0.0f;
|
||||
}
|
||||
@ -85,8 +85,8 @@ struct Controller {
|
||||
Box box = ((Controller*)e.controller)->getBoundingBox();
|
||||
vec3 t = (box.min + box.max) * 0.5f;
|
||||
|
||||
mat4 m = animation.getJoints(getMatrix(), joint);
|
||||
vec3 delta = (m.inverse() * t).normal();
|
||||
Basis b = animation.getJoints(Basis(getMatrix()), joint);
|
||||
vec3 delta = (b.inverse() * t).normal();
|
||||
|
||||
float angleY = clampAngle(atan2f(delta.x, delta.z));
|
||||
float angleX = clampAngle(asinf(delta.y));
|
||||
@ -99,7 +99,7 @@ struct Controller {
|
||||
|
||||
rot = ay * ax;
|
||||
if (rotAbs)
|
||||
*rotAbs = m.getRot() * rot;
|
||||
*rotAbs = b.rot * rot;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -470,13 +470,13 @@ struct Controller {
|
||||
mask |= layers[i].mask;
|
||||
// set meshes visibility
|
||||
for (int j = 0; j < model->mCount; j++)
|
||||
joints[j].e33 = (vmask & (1 << j)) ? 1.0f : -1.0f;
|
||||
joints[j].w = (vmask & (1 << j)) ? 1.0f : -1.0f; // AHAHA
|
||||
// render
|
||||
Core::active.shader->setParam(uModel, joints[0], model->mCount);
|
||||
Core::active.shader->setParam(uBasis, joints[0], model->mCount);
|
||||
mesh->renderModel(layers[i].model);
|
||||
}
|
||||
} else {
|
||||
Core::active.shader->setParam(uModel, joints[0], model->mCount);
|
||||
Core::active.shader->setParam(uBasis, joints[0], model->mCount);
|
||||
mesh->renderModel(entity.modelIndex - 1);
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,8 @@ namespace Core {
|
||||
int width, height;
|
||||
int frameIndex;
|
||||
float deltaTime;
|
||||
mat4 mView, mProj, mViewProj, mViewInv, mModel, mLightProj;
|
||||
mat4 mView, mProj, mViewProj, mViewInv, mLightProj;
|
||||
Basis basis;
|
||||
vec3 viewPos;
|
||||
vec3 lightPos[MAX_LIGHTS];
|
||||
vec4 lightColor[MAX_LIGHTS];
|
||||
|
@ -211,7 +211,7 @@ struct Wolf : Enemy {
|
||||
if ((state == STATE_JUMP || state == STATE_BITE) && !bitten) {
|
||||
float dist;
|
||||
if (getTargetInfo(0, NULL, NULL, NULL, &dist) && dist < 256.0f)
|
||||
bite(animation.getJoints(getMatrix(), JOINT_HEAD, true).getPos(), state == STATE_BITE ? 100 : 50);
|
||||
bite(animation.getJoints(getMatrix(), JOINT_HEAD, true).pos, state == STATE_BITE ? 100 : 50);
|
||||
}
|
||||
|
||||
if (state == STATE_JUMP)
|
||||
@ -300,7 +300,7 @@ struct Bear : Enemy {
|
||||
if ((state == STATE_ATTACK || state == STATE_BITE) && !bitten) {
|
||||
float dist;
|
||||
if (getTargetInfo(0, NULL, NULL, NULL, &dist) && dist < 256.0f)
|
||||
bite(animation.getJoints(getMatrix(), JOINT_HEAD, true).getPos(), state == STATE_BITE ? 100 : 50);
|
||||
bite(animation.getJoints(getMatrix(), JOINT_HEAD, true).pos, state == STATE_BITE ? 100 : 50);
|
||||
}
|
||||
|
||||
return state;
|
||||
|
20
src/lara.h
20
src/lara.h
@ -300,7 +300,7 @@ struct Lara : Character {
|
||||
*/
|
||||
updateEntity();
|
||||
#endif
|
||||
chestOffset = animation.getJoints(getMatrix(), 7).getPos();
|
||||
chestOffset = animation.getJoints(getMatrix(), 7).pos;
|
||||
if (getRoom().flags.water)
|
||||
animation.setAnim(ANIM_UNDERWATER);
|
||||
}
|
||||
@ -561,7 +561,7 @@ struct Lara : Character {
|
||||
|
||||
int joint = wpnCurrent == Weapon::SHOTGUN ? 8 : (i ? 11 : 8);
|
||||
|
||||
vec3 p = animation.getJoints(getMatrix(), joint, false).getPos();
|
||||
vec3 p = animation.getJoints(getMatrix(), joint, false).pos;
|
||||
vec3 d = arm->rotAbs * vec3(0, 0, 1);
|
||||
vec3 t = p + d * (24.0f * 1024.0f) + ((vec3(randf(), randf(), randf()) * 2.0f) - vec3(1.0f)) * 1024.0f;
|
||||
|
||||
@ -582,7 +582,7 @@ struct Lara : Character {
|
||||
}
|
||||
}
|
||||
|
||||
Core::lightPos[1 + armIndex] = animation.getJoints(getMatrix(), armIndex == 0 ? 10 : 13, false).getPos();
|
||||
Core::lightPos[1 + armIndex] = animation.getJoints(getMatrix(), armIndex == 0 ? 10 : 13, false).pos;
|
||||
Core::lightColor[1 + armIndex] = FLASH_LIGHT_COLOR;
|
||||
}
|
||||
|
||||
@ -1050,7 +1050,7 @@ struct Lara : Character {
|
||||
}
|
||||
|
||||
vec3 getViewPoint() {
|
||||
vec3 offset = chestOffset = animation.getJoints(getMatrix(), 7).getPos();
|
||||
vec3 offset = chestOffset = animation.getJoints(getMatrix(), 7).pos;
|
||||
if (stand != STAND_UNDERWATER)
|
||||
offset.y -= 256.0f;
|
||||
if (!emptyHands())
|
||||
@ -1768,23 +1768,23 @@ struct Lara : Character {
|
||||
}
|
||||
|
||||
|
||||
void renderMuzzleFlash(MeshBuilder *mesh, const mat4 &matrix, const vec3 &offset, float time) {
|
||||
void renderMuzzleFlash(MeshBuilder *mesh, const Basis &basis, const vec3 &offset, float time) {
|
||||
ASSERT(level->extra.muzzleFlash);
|
||||
if (time > MUZZLE_FLASH_TIME) return;
|
||||
float alpha = min(1.0f, (0.1f - time) * 20.0f);
|
||||
float lum = 3.0f;
|
||||
mat4 m(matrix);
|
||||
m.rotateX(-PI * 0.5f);
|
||||
m.translate(offset);
|
||||
Basis b(basis);
|
||||
b.rotate(quat(vec3(1, 0, 0), -PI * 0.5f));
|
||||
b.translate(offset);
|
||||
|
||||
Core::active.shader->setParam(uColor, vec4(lum, lum, lum, alpha));
|
||||
Core::active.shader->setParam(uModel, m);
|
||||
Core::active.shader->setParam(uBasis, b);
|
||||
mesh->renderModel(level->extra.muzzleFlash);
|
||||
}
|
||||
|
||||
virtual void render(Frustum *frustum, MeshBuilder *mesh) {
|
||||
Controller::render(frustum, mesh);
|
||||
chestOffset = animation.getJoints(getMatrix(), 7).getPos(); // TODO: move to update func
|
||||
chestOffset = animation.getJoints(getMatrix(), 7).pos; // TODO: move to update func
|
||||
|
||||
if (wpnCurrent != Weapon::SHOTGUN && Core::pass != Core::passShadow && (arms[0].shotTimer < MUZZLE_FLASH_TIME || arms[1].shotTimer < MUZZLE_FLASH_TIME)) {
|
||||
mat4 matrix = getMatrix();
|
||||
|
17
src/level.h
17
src/level.h
@ -557,14 +557,13 @@ struct Level {
|
||||
|
||||
if (Core::pass != Core::passShadow) {
|
||||
setRoomParams(room, intensityf(room.ambient));
|
||||
|
||||
Basis qTemp = Core::basis;
|
||||
Core::basis.translate(offset);
|
||||
|
||||
Shader *sh = Core::active.shader;
|
||||
|
||||
sh->setParam(uType, Shader::ROOM);
|
||||
|
||||
mat4 mTemp = Core::mModel;
|
||||
Core::mModel.translate(offset);
|
||||
|
||||
sh->setParam(uModel, Core::mModel);
|
||||
sh->setParam(uBasis, Core::basis);
|
||||
|
||||
// render room geometry
|
||||
mesh->renderRoomGeometry(roomIndex);
|
||||
@ -577,7 +576,7 @@ struct Level {
|
||||
mesh->renderRoomSprites(roomIndex);
|
||||
}
|
||||
|
||||
Core::mModel = mTemp;
|
||||
Core::basis = qTemp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -728,7 +727,7 @@ struct Level {
|
||||
sh->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount);
|
||||
sh->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount);
|
||||
|
||||
Core::mModel.identity();
|
||||
Core::basis.identity();
|
||||
|
||||
// clear visibility flag for rooms
|
||||
for (int i = 0; i < level.roomsCount; i++)
|
||||
@ -786,7 +785,7 @@ struct Level {
|
||||
}
|
||||
|
||||
bool setupLightCamera() {
|
||||
vec3 pos = (lara->animation.getJoints(lara->getMatrix(), 0, false, NULL)).getPos();
|
||||
vec3 pos = (lara->animation.getJoints(lara->getMatrix(), 0, false, NULL)).pos;
|
||||
|
||||
// omni-spot light shadows
|
||||
int room = lara->getRoomIndex();
|
||||
|
17
src/mesh.h
17
src/mesh.h
@ -211,7 +211,8 @@ struct MeshBuilder {
|
||||
TR::Model &model = level.models[i];
|
||||
for (int j = 0; j < model.mCount; j++) {
|
||||
int index = level.meshOffsets[model.mStart + j];
|
||||
if (!index && model.mCount == 1) continue;
|
||||
if (!index && model.mStart + j > 0)
|
||||
continue;
|
||||
aCount++;
|
||||
TR::Mesh &mesh = level.meshes[index];
|
||||
iCount += mesh.rCount * 6 + mesh.tCount * 3;
|
||||
@ -337,7 +338,7 @@ struct MeshBuilder {
|
||||
|
||||
for (int j = 0; j < model.mCount; j++) {
|
||||
int index = level.meshOffsets[model.mStart + j];
|
||||
if (!index && model.mCount == 1) continue;
|
||||
if (!index && model.mStart + j > 0) continue;
|
||||
|
||||
TR::Mesh &mesh = level.meshes[index];
|
||||
buildMesh(mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0);
|
||||
@ -725,9 +726,9 @@ struct MeshBuilder {
|
||||
|
||||
Core::active.shader->setParam(uColor, color);
|
||||
//text = "a: b";
|
||||
mat4 m;
|
||||
m.identity();
|
||||
m.translate(vec3(pos.x, pos.y, 0.0f));
|
||||
Basis basis;
|
||||
basis.identity();
|
||||
basis.translate(vec3(pos.x, pos.y, 0.0f));
|
||||
// text = "A";
|
||||
while (char c = *text++) {
|
||||
|
||||
@ -749,13 +750,13 @@ struct MeshBuilder {
|
||||
}
|
||||
*/
|
||||
if (c == ' ' || c == '_') {
|
||||
m.translate(vec3(char_width[0], 0.0f, 0.0f));
|
||||
basis.translate(vec3(char_width[0], 0.0f, 0.0f));
|
||||
continue;
|
||||
}
|
||||
|
||||
Core::active.shader->setParam(uModel, m);
|
||||
Core::active.shader->setParam(uBasis, basis);
|
||||
renderSprite(15, frame);
|
||||
m.translate(vec3(char_width[frame], 0.0f, 0.0f));
|
||||
basis.translate(vec3(char_width[frame], 0.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -26,7 +26,7 @@ uniform int uType;
|
||||
|
||||
#ifdef VERTEX
|
||||
uniform mat4 uViewProj;
|
||||
uniform mat4 uModel[32];
|
||||
uniform vec4 uBasis[32 * 2];
|
||||
|
||||
#ifndef PASS_AMBIENT
|
||||
uniform mat4 uViewInv;
|
||||
@ -51,11 +51,21 @@ uniform int uType;
|
||||
#endif
|
||||
|
||||
#define TEXCOORD_SCALE (1.0 / 32767.0)
|
||||
|
||||
vec3 mulQuat(vec4 q, vec3 v) {
|
||||
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
|
||||
}
|
||||
|
||||
vec3 mulBasis(vec4 rot, vec4 pos, vec3 v) {
|
||||
return mulQuat(rot, v) + pos.xyz;
|
||||
}
|
||||
|
||||
void main() {
|
||||
mat4 rJoint = uModel[int(aCoord.w)];
|
||||
int index = int(aCoord.w) * 2;
|
||||
vec4 rBasisRot = uBasis[index];
|
||||
vec4 rBasisPos = uBasis[index + 1];
|
||||
|
||||
vec4 coord = rJoint * vec4(aCoord.xyz, 1.0);
|
||||
vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w);
|
||||
|
||||
#ifdef PASS_COMPOSE
|
||||
if (uType != TYPE_SPRITE) {
|
||||
@ -66,7 +76,7 @@ uniform int uType;
|
||||
vec2 offset = uAnimTexOffsets[int(range.x + f)]; // texCoord offset from first frame
|
||||
|
||||
vTexCoord = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated
|
||||
vNormal = vec4((rJoint * vec4(aNormal.xyz, 0.0)).xyz, aNormal.w);
|
||||
vNormal = vec4(mulQuat(rBasisRot, aNormal.xyz), aNormal.w);
|
||||
} else {
|
||||
coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w;
|
||||
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
|
||||
|
@ -5,11 +5,11 @@
|
||||
|
||||
enum AttribType { aCoord, aTexCoord, aNormal, aColor, aMAX };
|
||||
enum SamplerType { sDiffuse, sShadow, sEnvironment, sMAX };
|
||||
enum UniformType { uType, uCaustics, uTime, uViewProj, uViewInv, uModel, uLightProj, uColor, uAmbient, uViewPos, uLightsCount, uLightPos, uLightColor, uAnimTexRanges, uAnimTexOffsets, uMAX };
|
||||
enum UniformType { uType, uCaustics, uTime, uViewProj, uViewInv, uBasis, uLightProj, uColor, uAmbient, uViewPos, uLightsCount, uLightPos, uLightColor, uAnimTexRanges, uAnimTexOffsets, uMAX };
|
||||
|
||||
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal", "aColor" };
|
||||
const char *SamplerName[sMAX] = { "sDiffuse", "sShadow", "sEnvironment" };
|
||||
const char *UniformName[uMAX] = { "uType", "uCaustics", "uTime", "uViewProj", "uViewInv", "uModel", "uLightProj", "uColor", "uAmbient", "uViewPos", "uLightsCount", "uLightPos", "uLightColor", "uAnimTexRanges", "uAnimTexOffsets" };
|
||||
const char *UniformName[uMAX] = { "uType", "uCaustics", "uTime", "uViewProj", "uViewInv", "uBasis", "uLightProj", "uColor", "uAmbient", "uViewPos", "uLightsCount", "uLightPos", "uLightColor", "uAnimTexRanges", "uAnimTexOffsets" };
|
||||
|
||||
struct Shader {
|
||||
GLuint ID;
|
||||
@ -103,6 +103,11 @@ struct Shader {
|
||||
if (uID[uType] != -1)
|
||||
glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const Basis &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
glUniform4fv(uID[uType], count * 2, (GLfloat*)&value);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@ -60,9 +60,9 @@ struct Sprite : Controller {
|
||||
}
|
||||
|
||||
virtual void render(Frustum *frustum, MeshBuilder *mesh) {
|
||||
mat4 m(Core::mModel);
|
||||
m.translate(pos);
|
||||
Core::active.shader->setParam(uModel, m);
|
||||
Basis basis(Core::basis);
|
||||
basis.translate(pos);
|
||||
Core::active.shader->setParam(uBasis, basis);
|
||||
mesh->renderSprite(-(getEntity().modelIndex + 1), frame);
|
||||
}
|
||||
};
|
||||
|
40
src/utils.h
40
src/utils.h
@ -126,7 +126,8 @@ struct vec3 {
|
||||
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 - () const { return vec3(-x, -y, -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); }
|
||||
@ -509,6 +510,43 @@ struct mat4 {
|
||||
}
|
||||
};
|
||||
|
||||
struct Basis {
|
||||
quat rot;
|
||||
vec3 pos;
|
||||
float w;
|
||||
|
||||
Basis() {}
|
||||
Basis(const quat &rot, const vec3 &pos) : rot(rot), pos(pos), w(1.0f) {}
|
||||
Basis(const mat4 &matrix) : rot(matrix.getRot()), pos(matrix.getPos()), w(1.0f) {}
|
||||
|
||||
void identity() {
|
||||
rot = quat(0, 0, 0, 1);
|
||||
pos = vec3(0, 0, 0);
|
||||
w = 1.0f;
|
||||
}
|
||||
|
||||
Basis operator * (const Basis &basis) const {
|
||||
return Basis(rot * basis.rot, pos + rot * basis.pos);
|
||||
}
|
||||
|
||||
vec3 operator * (const vec3 &v) const {
|
||||
return rot * v + pos;
|
||||
}
|
||||
|
||||
Basis inverse() const {
|
||||
quat q = rot.conjugate();
|
||||
return Basis(q, -(q * pos));
|
||||
}
|
||||
|
||||
void translate(const vec3 &v) {
|
||||
pos += rot * v;
|
||||
}
|
||||
|
||||
void rotate(const quat &q) {
|
||||
rot = rot * q;
|
||||
}
|
||||
};
|
||||
|
||||
struct ubyte2 {
|
||||
uint8 x, y;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user