1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-10 23:24:06 +02:00

Merge remote-tracking branch 'refs/remotes/XProger/master'

This commit is contained in:
Gh0stBlade
2017-05-04 11:17:20 +01:00
11 changed files with 265 additions and 38 deletions

View File

@@ -6,3 +6,7 @@ Classic Tomb Raider open-source engine
inspired by OpenTomb project http://opentomb.github.io/
[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://opensource.org/licenses/BSD-2-Clause)
## Links
* [Discord channel](https://discord.gg/EF8JaQB)
* [Tomb Raider Forums thread](http://www.tombraiderforums.com/showthread.php?t=216618)

View File

@@ -142,11 +142,13 @@ struct Camera : Controller {
if (owner->velocity != 0.0f && advTimer < 0.0f && !Input::down[ikMouseL])
advTimer = -advTimer;
#ifndef LEVEL_EDITOR
if (advTimer == 0.0f && advAngle != 0.0f) {
float t = 10.0f * Core::deltaTime;
advAngle.x = lerp(clampAngle(advAngle.x), 0.0f, t);
advAngle.y = lerp(clampAngle(advAngle.y), 0.0f, t);
}
#endif
angle = owner->angle + advAngle;
angle.z = 0.0f;

View File

@@ -31,11 +31,26 @@ struct Character : Controller {
float angleExt;
float speed;
int zone;
int box;
bool flying;
Collision collision;
Character(IGame *game, int entity, int health) : Controller(game, entity), target(-1), health(health), tilt(0.0f), stand(STAND_GROUND), lastInput(0), velocity(0.0f), angleExt(0.0f) {
animation.initOverrides();
rotHead = rotChest = quat(0, 0, 0, 1);
flying = getEntity().type == TR::Entity::ENEMY_BAT;
updateZone();
}
void updateZone() {
TR::Level *level = game->getLevel();
int dx, dz;
box = level->getSector(getRoomIndex(), int(pos.x), int(pos.z), dx, dz).boxIndex;
zone = flying ? level->zones[0].fly[box] : level->zones[0].ground1[box];
}
void rotateY(float delta) {
@@ -141,8 +156,10 @@ struct Character : Controller {
Controller::update();
updateVelocity();
updatePosition();
if (p != pos)
if (p != pos) {
updateLights();
updateZone();
}
}
virtual void cmdJump(const vec3 &vel) {

View File

@@ -192,7 +192,7 @@ struct Controller {
int floor = NO_OVERLAP;
int delta = NO_OVERLAP;
TR::Overlap *o = &level->overlaps[b.overlap & 0x7FFF];
TR::Overlap *o = &level->overlaps[b.overlap.index];
do {
TR::Box &ob = level->boxes[o->boxIndex];
if (ob.contains(toX, toZ)) { // get min delta

View File

@@ -185,7 +185,14 @@ namespace Debug {
namespace Level {
void debugFloor(const TR::Level &level, int roomIndex, int x, int y, int z) {
void debugFloor(const TR::Level &level, int roomIndex, int x, int y, int z, int zone = -1) {
if (zone != -1) {
int dx, dz;
TR::Room::Sector &s = level.getSector(roomIndex, x, z, dx, dz);
if (zone != level.zones[0].ground1[s.boxIndex])
return;
}
TR::Level::FloorInfo info;
vec3 rf[4], rc[4], f[4], c[4];
@@ -270,23 +277,47 @@ namespace Debug {
glEnd();
}
void blocks(const TR::Level &level) {
Core::setDepthTest(false);
char buf[64];
for (int j = 0; j < level.roomsCount; j++) {
TR::Room &r = level.rooms[j];
for (int z = 0; z < r.zSectors; z++)
for (int x = 0; x < r.xSectors; x++) {
TR::Room::Sector &s = r.sectors[x * r.zSectors + z];
if (s.boxIndex != 0xFFFF) {
bool blockable = level.boxes[s.boxIndex].overlap.value & 0x8000;
bool block = level.boxes[s.boxIndex].overlap.value & 0x4000;
int floor = level.boxes[s.boxIndex].floor;
if (blockable || block) {
sprintf(buf, "blocked: %s", block ? "true" : "false");
Debug::Draw::text(vec3(r.info.x + x * 1024 + 512, floor, r.info.z + z * 1024 + 512), vec4(1, 1, 0, 1), buf);
}
}
}
}
Core::setDepthTest(true);
}
void debugOverlaps(const TR::Level &level, int boxIndex) {
glColor4f(1.0f, 1.0f, 0.0f, 0.25f);
TR::Overlap *o = &level.overlaps[level.boxes[boxIndex].overlap & 0x7FFF];
TR::Overlap *o = &level.overlaps[level.boxes[boxIndex].overlap.index];
do {
TR::Box &b = level.boxes[o->boxIndex];
debugBox(b);
} while (!(o++)->end);
}
void sectors(const TR::Level &level, int roomIndex, int y) {
void sectors(const TR::Level &level, int roomIndex, int y, int zone = -1) {
TR::Room &room = level.rooms[roomIndex];
// glDisable(GL_DEPTH_TEST);
for (int z = 0; z < room.zSectors; z++)
for (int x = 0; x < room.xSectors; x++)
debugFloor(level, roomIndex, room.info.x + x * 1024, y, room.info.z + z * 1024);
// glEnable(GL_DEPTH_TEST);
debugFloor(level, roomIndex, room.info.x + x * 1024, y, room.info.z + z * 1024, zone);
}
void rooms(const TR::Level &level, const vec3 &pos, int roomIndex) {
@@ -350,6 +381,24 @@ namespace Debug {
}
}
void zones(const TR::Level &level, Lara *lara) {
Core::setDepthTest(false);
for (int i = 0; i < level.roomsCount; i++)
sectors(level, i, int(lara->pos.y), lara->zone);
Core::setDepthTest(true);
char buf[64];
for (int i = 0; i < level.entitiesCount; i++) {
TR::Entity &e = level.entities[i];
if (e.type < TR::Entity::LARA || e.type > TR::Entity::ENEMY_GIANT_MUTANT)
continue;
sprintf(buf, "zone: %d", ((Character*)e.controller)->zone );
Debug::Draw::text(vec3(e.x, e.y - 128, e.z), vec4(0, 1.0, 0.8, 1), buf);
}
}
void lights(const TR::Level &level, int room, Controller *lara) {
// int roomIndex = level.entities[lara->entity].room;
// int lightIndex = getLightIndex(lara->pos, roomIndex);
@@ -394,14 +443,16 @@ namespace Debug {
sm->getBox(true, m.rotation, box);
Debug::Draw::box(offset + box.min - vec3(10.0f), offset + box.max + vec3(10.0f), vec4(1, 0, 0, 0.50));
}
/*
TR::Mesh *mesh = (TR::Mesh*)&level.meshData[level.meshOffsets[sm->mesh] / 2];
{ //if (mesh->collider.info || mesh->collider.flags) {
if (!level.meshOffsets[sm->mesh]) continue;
const TR::Mesh &mesh = level.meshes[level.meshOffsets[sm->mesh]];
{
char buf[255];
sprintf(buf, "radius %d info %d flags %d", (int)mesh->collider.radius, (int)mesh->collider.info, (int)mesh->collider.flags);
Debug::Draw::text(offset + (min + max) * 0.5f, vec4(0.5, 0.5, 0.5, 1), buf);
sprintf(buf, "flags %d", (int)mesh.flags.value);
Debug::Draw::text(offset + (box.min + box.max) * 0.5f, vec4(0.5, 0.5, 1.0, 1), buf);
}
*/
}
}
// dynamic objects
@@ -466,13 +517,13 @@ namespace Debug {
TR::Mesh *mesh = (TR::Mesh*)&level.meshes[offset];
//if (!mesh->flags) continue;
Debug::Draw::sphere(matrix * joint * mesh->center, mesh->radius, vec4(0, 1, 1, 0.5f));
/*
{ //if (e.id != 0) {
char buf[255];
sprintf(buf, "(%d) radius %d flags %d", (int)e.type, (int)mesh->radius, (int)mesh->flags);
sprintf(buf, "(%d) radius %d flags %d", (int)e.type, (int)mesh->radius, (int)mesh->flags.value);
Debug::Draw::text(matrix * joint * mesh->center, vec4(0.5, 1, 0.5, 1), buf);
}
*/
}
Debug::Draw::box(matrix, frame->box.min(), frame->box.max(), vec4(1.0));
@@ -587,7 +638,7 @@ namespace Debug {
case_name(TR::Entity, ENEMY_RAT_WATER );
case_name(TR::Entity, ENEMY_REX );
case_name(TR::Entity, ENEMY_RAPTOR );
case_name(TR::Entity, ENEMY_MUTANT );
case_name(TR::Entity, ENEMY_MUTANT_1 );
case_name(TR::Entity, ENEMY_CENTAUR );
case_name(TR::Entity, ENEMY_MUMMY );
case_name(TR::Entity, ENEMY_LARSON );

View File

@@ -348,7 +348,12 @@ namespace TR {
TR::Vertex center;
uint16 radius;
uint16 flags;
union {
struct {
uint16 transparent:1, reserved:15;
};
uint16 value;
} flags;
int16 vCount;
int16 rCount;
int16 tCount;
@@ -374,7 +379,7 @@ namespace TR {
LARA_SHOTGUN = 2,
LARA_MAGNUMS = 3,
LARA_UZIS = 4,
LARA_SPEC = 5,
ENEMY_TWIN = 6,
ENEMY_WOLF = 7,
ENEMY_BEAR = 8,
@@ -389,12 +394,19 @@ namespace TR {
ENEMY_RAT_WATER = 17,
ENEMY_REX = 18,
ENEMY_RAPTOR = 19,
ENEMY_MUTANT = 20,
ENEMY_MUTANT_1 = 20,
ENEMY_MUTANT_2 = 21,
ENEMY_MUTANT_3 = 22,
ENEMY_CENTAUR = 23,
ENEMY_MUMMY = 24,
ENEMY_LARSON = 27,
ENEMY_PIERRE = 28,
ENEMY_SKATEBOARD = 29,
ENEMY_SKATEBOY = 30,
ENEMY_COWBOY = 31,
ENEMY_MR_T = 32,
ENEMY_NATLA = 33,
ENEMY_GIANT_MUTANT = 34,
TRAP_FLOOR = 35,
TRAP_BLADE = 36,
TRAP_SPIKES = 37,
@@ -512,6 +524,13 @@ namespace TR {
bool isBlock() {
return type >= TR::Entity::BLOCK_1 && type <= TR::Entity::BLOCK_2;
}
static void fixOpaque(Type type, bool &opaque) {
if (type >= LARA && type <= ENEMY_GIANT_MUTANT && type != ENEMY_MUMMY && type != ENEMY_CENTAUR && type != ENEMY_MUTANT_1 && type != ENEMY_NATLA && type != DOOR_BIG_1 && type != DOOR_BIG_2)
opaque = true;
if (type == SWITCH || type == SWITCH_WATER)
opaque = true;
}
};
struct Animation {
@@ -668,7 +687,12 @@ namespace TR {
uint32 minZ, maxZ; // Horizontal dimensions in global units
uint32 minX, maxX;
int16 floor; // Height value in global units
uint16 overlap; // Index into Overlaps[].
union {
struct {
uint16 index:14, block:1, blockable:1; // Index into Overlaps[].
};
uint16 value;
} overlap;
bool contains(uint32 x, uint32 z) {
return x >= minX && x <= maxX && z >= minZ && z <= maxZ;
@@ -676,11 +700,9 @@ namespace TR {
};
struct Zone {
struct {
uint16 groundZone1;
uint16 groundZone2;
uint16 flyZone;
} normal, alternate;
uint16 *ground1;
uint16 *ground2;
uint16 *fly;
};
struct SoundInfo {
@@ -761,7 +783,7 @@ namespace TR {
Box *boxes;
int32 overlapsCount;
Overlap *overlaps;
Zone *zones;
Zone zones[2]; // default and alternative
int32 animTexturesDataSize;
uint16 *animTexturesData;
@@ -989,8 +1011,13 @@ namespace TR {
stream.read(soundSources, stream.read(soundSourcesCount));
// AI
stream.read(boxes, stream.read(boxesCount));
stream.read(overlaps, stream.read(overlapsCount));
stream.read(zones, boxesCount);
for (int i = 0; i < 2; i++) {
stream.read(zones[i].ground1, boxesCount);
stream.read(zones[i].ground2, boxesCount);
stream.read(zones[i].fly, boxesCount);
}
// animated textures
stream.read(animTexturesData, stream.read(animTexturesDataSize));
// entities (enemies, items, lara etc.)
@@ -1112,7 +1139,11 @@ namespace TR {
delete[] soundSources;
delete[] boxes;
delete[] overlaps;
delete[] zones;
for (int i = 0; i < 2; i++) {
delete[] zones[i].ground1;
delete[] zones[i].ground2;
delete[] zones[i].fly;
}
delete[] animTexturesData;
delete[] entities;
delete[] palette;

View File

@@ -435,7 +435,35 @@ struct Lara : Character {
delete braid;
}
int getRoomByPos(const vec3 &pos) {
int x = int(pos.x),
y = int(pos.y),
z = int(pos.z);
for (int i = 0; i < level->roomsCount; i++) {
TR::Room &r = level->rooms[i];
int mx = r.info.x + r.xSectors * 1024;
int mz = r.info.z + r.zSectors * 1024;
if (x >= r.info.x && x < mx && z >= r.info.z && z < mz && y >= r.info.yTop && y < r.info.yBottom)
return i;
}
return TR::NO_ROOM;
}
void reset(int room, const vec3 &pos, float angle, bool onwater = false) {
if (room == TR::NO_ROOM) {
stand = STAND_AIR;
room = getRoomByPos(pos);
}
if (room == TR::NO_ROOM)
return;
if (level->rooms[room].flags.water)
stand = STAND_UNDERWATER;
velocity = vec3(0.0f);
getEntity().room = room;
this->pos = pos;
this->angle = vec3(0.0f, angle, 0.0f);

View File

@@ -138,7 +138,9 @@ struct Level : IGame {
case TR::Entity::ENEMY_RAT_WATER :
case TR::Entity::ENEMY_REX :
case TR::Entity::ENEMY_RAPTOR :
case TR::Entity::ENEMY_MUTANT :
case TR::Entity::ENEMY_MUTANT_1 :
case TR::Entity::ENEMY_MUTANT_2 :
case TR::Entity::ENEMY_MUTANT_3 :
case TR::Entity::ENEMY_CENTAUR :
case TR::Entity::ENEMY_MUMMY :
case TR::Entity::ENEMY_LARSON :
@@ -490,7 +492,7 @@ struct Level : IGame {
// if (entity.type == TR::Entity::LARA && ((Lara*)entity.controller)->state == Lara::STATE_WATER_OUT)
// roomIndex = ((Lara*)entity.controller)->roomPrev;
setRoomParams(roomIndex, type, 1.0f, intensityf(lum), controller->specular, 1.0f, isModel ? mesh->models[entity.modelIndex].opaque : true);
setRoomParams(roomIndex, type, 1.0f, intensityf(lum), controller->specular, 1.0f, isModel ? !mesh->models[entity.modelIndex - 1].opaque : true);
if (isModel) { // model
vec3 pos = controller->getPos();
@@ -517,6 +519,12 @@ struct Level : IGame {
}
void update() {
#ifdef LEVEL_EDITOR
if (Input::down[ikCtrl]) {
Input::down[ikCtrl] = false;
lara->reset(TR::NO_ROOM, camera->pos, camera->angle.y, false);
}
#endif
params->time += Core::deltaTime;
for (int i = 0; i < level.entitiesCount; i++) {
@@ -810,20 +818,23 @@ struct Level : IGame {
glEnd();
Core::setDepthTest(true);
Debug::Draw::sphere(lara->mainLightPos, lara->mainLightColor.w, vec4(1, 1, 0, 1));
// Debug::Draw::sphere(lara->mainLightPos, lara->mainLightColor.w, vec4(1, 1, 0, 1));
Box bbox = lara->getBoundingBox();
Debug::Draw::box(bbox.min, bbox.max, vec4(1, 0, 1, 1));
Core::setBlending(bmAlpha);
// Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
Debug::Level::lights(level, lara->getRoomIndex(), lara);
// Debug::Level::lights(level, lara->getRoomIndex(), lara);
// Debug::Level::sectors(level, lara->getRoomIndex(), (int)lara->pos.y);
// Core::setDepthTest(false);
// Debug::Level::portals(level);
// Core::setDepthTest(true);
// Debug::Level::meshes(level);
// Debug::Level::entities(level);
Debug::Level::zones(level, lara);
Debug::Level::blocks(level);
Core::setBlending(bmNone);
/*

View File

@@ -120,10 +120,10 @@
<input type="button" value="Browse Level" onclick="document.getElementById('browseFile').click();" /> (.PHD, .PSX)
<input type="checkbox" id="isHome"><label>alternative model (home suit, gold etc.)</label>
<br><br>
<a target="_blank" href="https://github.com/XProger/OpenLara">OpenLara on github</a><br>
OpenLara on <a target="_blank" href="https://github.com/XProger/OpenLara">github</a> & <a target="_blank" href="https://www.facebook.com/OpenLaraTR">facebook</a><br>
controls:<br>
keyboad: move - WASD / arrows, jump - Space, action - E/Ctrl, draw weapon - Q, change weapon - 1-4, walk - Shift, side steps - ZX/walk+direction, camera - MouseR)<br>
gamepad: PSX controls on XBox controller<br>
gamepad: PSX controls for Xbox controller<br>
Change view: V<br>
Time Control: R - slow motion, T - fast motion<br>
FullScreen: Alt + Enter

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\..\libs\minimp3\minimp3.cpp" />
<ClCompile Include="..\..\libs\stb_vorbis\stb_vorbis.c" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\animation.h" />
<ClInclude Include="..\..\cache.h" />
<ClInclude Include="..\..\camera.h" />
<ClInclude Include="..\..\character.h" />
<ClInclude Include="..\..\collision.h" />
<ClInclude Include="..\..\controller.h" />
<ClInclude Include="..\..\core.h" />
<ClInclude Include="..\..\debug.h" />
<ClInclude Include="..\..\enemy.h" />
<ClInclude Include="..\..\frustum.h" />
<ClInclude Include="..\..\game.h" />
<ClInclude Include="..\..\ui.h" />
<ClInclude Include="..\..\input.h" />
<ClInclude Include="..\..\inventory.h" />
<ClInclude Include="..\..\lara.h" />
<ClInclude Include="..\..\level.h" />
<ClInclude Include="..\..\libs\minimp3\libc.h" />
<ClInclude Include="..\..\libs\minimp3\minimp3.h" />
<ClInclude Include="..\..\mesh.h" />
<ClInclude Include="..\..\shader.h" />
<ClInclude Include="..\..\sound.h" />
<ClInclude Include="..\..\sprite.h" />
<ClInclude Include="..\..\texture.h" />
<ClInclude Include="..\..\format.h" />
<ClInclude Include="..\..\trigger.h" />
<ClInclude Include="..\..\utils.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\shaders\depth.glsl">
<Filter>shaders</Filter>
</None>
<None Include="..\..\shaders\filter.glsl">
<Filter>shaders</Filter>
</None>
<None Include="..\..\shaders\gui.glsl">
<Filter>shaders</Filter>
</None>
<None Include="..\..\shaders\shader.glsl">
<Filter>shaders</Filter>
</None>
<None Include="..\..\shaders\shadow.glsl">
<Filter>shaders</Filter>
</None>
<None Include="..\..\shaders\volume.glsl">
<Filter>shaders</Filter>
</None>
<None Include="..\..\shaders\water.glsl">
<Filter>shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Filter Include="shaders">
<UniqueIdentifier>{3fcb6c00-268a-4570-b6ca-3bf1cf1e10d7}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Editor|Win32'">
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>