diff --git a/bin/OpenLara.exe b/bin/OpenLara.exe index 52cb0b3..6b08a4e 100644 Binary files a/bin/OpenLara.exe and b/bin/OpenLara.exe differ diff --git a/src/format.h b/src/format.h index 38d0f20..023f3cb 100644 --- a/src/format.h +++ b/src/format.h @@ -1043,6 +1043,10 @@ namespace TR { } }; // struct Level + + bool castShadow(Entity::Type type) { + return (type >= Entity::ENEMY_TWIN && type <= Entity::ENEMY_LARSON) || type == Entity::LARA || type == Entity::LARA_CUT; + } } #endif \ No newline at end of file diff --git a/src/level.h b/src/level.h index 59a2a44..3001fc3 100644 --- a/src/level.h +++ b/src/level.h @@ -356,6 +356,19 @@ struct Level { return ma.getRot().slerp(mb.getRot(), t).normal(); } + void renderShadow(const vec3 &pos, const vec3 &offset, const vec3 &size, float angle) { + mat4 m; + m.identity(); + m.translate(pos); + m.rotateY(angle); + m.translate(vec3(offset.x, 0.0f, offset.z)); + m.scale(vec3(size.x, 0.0f, size.z) / 1024.0f); + + Core::active.shader->setParam(uModel, m); + Core::active.shader->setParam(uColor, vec4(0.0f, 0.0f, 0.0f, 0.5f)); + mesh->renderShadowSpot(); + } + void renderModel(const TR::Model &model, const TR::Entity &entity) { TR::Animation *anim; float fTime; @@ -441,6 +454,12 @@ struct Level { renderMesh(model.mStart + i); Core::mModel = tmp; } + + if (TR::castShadow(entity.type)) { + TR::Level::FloorInfo info; + level.getFloorInfo(entity.room, entity.x, entity.z, info, true); + renderShadow(vec3(entity.x, info.floor - 16.0f, entity.z), (bmax + bmin) * 0.5f, (bmax - bmin) * 0.8f, entity.rotation); + } } void renderSequence(const TR::Entity &entity) { @@ -618,7 +637,7 @@ struct Level { // Debug::Level::rooms(level, lara->pos, lara->getEntity().room); // Debug::Level::lights(level); // Debug::Level::portals(level); - Debug::Level::meshes(level); + // Debug::Level::meshes(level); // Debug::Level::entities(level); Debug::Level::info(level, lara->getEntity(), (int)lara->state, lara->animIndex, int(lara->animTime * 30.0f)); Debug::end(); diff --git a/src/mesh.h b/src/mesh.h index ae2fef7..20e2359 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -73,8 +73,8 @@ struct MeshBuilder { } *meshInfo; int mCount; -// sprite sequences - MeshRange *sequenceRanges; + MeshRange *sequenceRanges; // sprite sequences + MeshRange shadowSpot; // indexed mesh Mesh *mesh; @@ -170,6 +170,13 @@ struct MeshBuilder { vCount += level.spriteSequences[i].sCount * 4; } + // get size of simple shadow spot mesh (8 triangles, 8 vertices) + shadowSpot.vStart = vCount; + shadowSpot.iStart = iCount; + shadowSpot.iCount = 8 * 3; + iCount += shadowSpot.iCount; + vCount += 8; + // make meshes buffer (single vertex buffer object for all geometry & sprites on level) Index *indices = new Index[iCount]; Vertex *vertices = new Vertex[vCount]; @@ -369,6 +376,26 @@ struct MeshBuilder { addSprite(indices, vertices, iCount, vCount, vCount, 0, 0, 0, sprite, 255); } + // build shadow spot + for (int i = 0; i < 8; i++) { + Vertex &v = vertices[vCount + i]; + v.normal = { 0, 0, 0, 1 }; + v.color = { 255, 255, 255, 255 }; + v.texCoord = { 32688, 32688, 0, 0 }; + + float a = i * (PI / 4.0f) + (PI / 8.0f); + short c = short(cosf(a) * 512.0f); + short s = short(sinf(a) * 512.0f); + v.coord = { c, 0, s, 0 }; + + int idx = iCount + i * 3; + indices[idx + 0] = i; + indices[idx + 1] = 0; + indices[idx + 2] = (i + 1) % 8; + } + iCount += shadowSpot.iCount; + vCount += 8; + mesh = new Mesh(indices, iCount, vertices, vCount); delete[] indices; delete[] vertices; @@ -551,6 +578,10 @@ struct MeshBuilder { range.vStart += frame * 4; mesh->render(range); } + + void renderShadowSpot() { + mesh->render(shadowSpot); + } }; #endif \ No newline at end of file