mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-10 15:14:28 +02:00
add VBO support
add shaders support todo: animated textures, billboards
This commit is contained in:
@@ -4,8 +4,10 @@
|
||||
#include "format.h"
|
||||
|
||||
struct Controller {
|
||||
TR::Level *level;
|
||||
TR::Animation *anim;
|
||||
TR::Level *level;
|
||||
int entity;
|
||||
|
||||
TR::Animation *anim;
|
||||
float fTime;
|
||||
|
||||
vec3 pos;
|
||||
@@ -14,9 +16,13 @@ struct Controller {
|
||||
int state; // LaraState
|
||||
int lastFrame;
|
||||
|
||||
Controller(TR::Level *level) : level(level), pos(0.0f), angle(0.0f), fTime(0.0f) {
|
||||
Controller(TR::Level *level, int entity) : level(level), entity(entity), pos(0.0f), angle(0.0f), fTime(0.0f) {
|
||||
anim = &level->anims[0];
|
||||
lastFrame = 0;
|
||||
|
||||
TR::Entity &e = level->entities[entity];
|
||||
pos = vec3(e.x, e.y, e.z);
|
||||
angle = e.rotation / 16384.0f * PI * 0.5f;
|
||||
}
|
||||
|
||||
void update() {
|
||||
@@ -181,8 +187,43 @@ struct Controller {
|
||||
float speed = anim->speed.toFloat() + anim->accel.toFloat() * (fTime * 30.0f);
|
||||
pos = pos + vec3(sinf(d), 0, cosf(d)) * (speed * Core::deltaTime * 30.0f);
|
||||
|
||||
|
||||
lastFrame = fIndex;
|
||||
|
||||
TR::Entity &e = level->entities[entity];
|
||||
|
||||
e.x = int(pos.x);
|
||||
e.y = int(pos.y);
|
||||
e.z = int(pos.z);
|
||||
e.rotation = int(angle / (PI * 0.5f) * 16384.0f);
|
||||
|
||||
/*
|
||||
TR::Room &room = level->rooms[level->entities[entity].room];
|
||||
for (int i = 0; i < room.portalsCount; i++) {
|
||||
if (insideRoom(pos, room.portals[i].roomIndex)) {
|
||||
level->entities[entity].room = room.portals[i].roomIndex;
|
||||
LOG("set room: %d\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < level->roomsCount; i++)
|
||||
if (insideRoom(pos, i) && i != level->entities[entity].room) {
|
||||
level->entities[entity].room = i;
|
||||
LOG("set room: %d\n", i);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool insideRoom(const vec3 &pos, int room) {
|
||||
TR::Room &r = level->rooms[room];
|
||||
vec3 min = vec3(r.info.x, r.info.yTop, r.info.z);
|
||||
vec3 max = min + vec3(r.xSectors * 1024, r.info.yBottom - r.info.yTop, r.zSectors * 1024);
|
||||
|
||||
return pos.x >= min.x && pos.x <= max.x &&
|
||||
pos.y >= min.y && pos.y <= max.y &&
|
||||
pos.z >= min.z && pos.z <= max.z;
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -50,6 +50,10 @@ namespace Core {
|
||||
int width, height;
|
||||
float deltaTime;
|
||||
mat4 mView, mProj, mViewProj, mModel;
|
||||
vec3 lightPos;
|
||||
vec4 lightColor;
|
||||
vec3 ambient;
|
||||
vec4 color;
|
||||
}
|
||||
|
||||
#include "texture.h"
|
||||
|
76
src/format.h
76
src/format.h
@@ -211,7 +211,7 @@ namespace TR {
|
||||
int16 lightsCount;
|
||||
struct Light {
|
||||
int32 x, y, z; // Position of light, in world coordinates
|
||||
uint16 Intensity1; // Light intensity
|
||||
uint16 Intensity; // Light intensity
|
||||
uint32 fade; // Falloff value
|
||||
} *lights;
|
||||
|
||||
@@ -499,7 +499,7 @@ namespace TR {
|
||||
// read version
|
||||
stream.read(version);
|
||||
// tiles
|
||||
stream.readArray(tiles, stream.read(tilesCount));
|
||||
stream.read(tiles, stream.read(tilesCount));
|
||||
stream.read(unused);
|
||||
// rooms
|
||||
rooms = new Room[stream.read(roomsCount)];
|
||||
@@ -511,69 +511,69 @@ namespace TR {
|
||||
// room data
|
||||
stream.read(d.size);
|
||||
int pos = stream.pos;
|
||||
stream.readArray(d.vertices, stream.read(d.vCount));
|
||||
stream.readArray(d.rectangles, stream.read(d.rCount));
|
||||
stream.readArray(d.triangles, stream.read(d.tCount));
|
||||
stream.readArray(d.sprites, stream.read(d.sCount));
|
||||
stream.read(d.vertices, stream.read(d.vCount));
|
||||
stream.read(d.rectangles, stream.read(d.rCount));
|
||||
stream.read(d.triangles, stream.read(d.tCount));
|
||||
stream.read(d.sprites, stream.read(d.sCount));
|
||||
stream.setPos(pos + d.size * 2);
|
||||
// portals
|
||||
stream.readArray(r.portals, stream.read(r.portalsCount));
|
||||
stream.read(r.portals, stream.read(r.portalsCount));
|
||||
// sectors
|
||||
stream.read(r.zSectors);
|
||||
stream.read(r.xSectors);
|
||||
stream.readArray(r.sectors, r.zSectors * r.xSectors);
|
||||
stream.read(r.sectors, r.zSectors * r.xSectors);
|
||||
// ambient light luminance
|
||||
stream.read(r.ambient);
|
||||
// lights
|
||||
stream.readArray(r.lights, stream.read(r.lightsCount));
|
||||
stream.read(r.lights, stream.read(r.lightsCount));
|
||||
// meshes
|
||||
stream.readArray(r.meshes, stream.read(r.meshesCount));
|
||||
stream.read(r.meshes, stream.read(r.meshesCount));
|
||||
stream.read(r.alternateRoom);
|
||||
stream.read(r.flags);
|
||||
}
|
||||
// floors
|
||||
stream.readArray(floors, stream.read(floorsCount));
|
||||
stream.read(floors, stream.read(floorsCount));
|
||||
// meshes
|
||||
stream.readArray(meshData, stream.read(meshDataSize));
|
||||
stream.readArray(meshOffsets, stream.read(meshOffsetsCount));
|
||||
stream.read(meshData, stream.read(meshDataSize));
|
||||
stream.read(meshOffsets, stream.read(meshOffsetsCount));
|
||||
// animations
|
||||
stream.readArray(anims, stream.read(animsCount));
|
||||
stream.readArray(states, stream.read(statesCount));
|
||||
stream.readArray(ranges, stream.read(rangesCount));
|
||||
stream.readArray(commands, stream.read(commandsCount));
|
||||
stream.readArray(nodesData, stream.read(nodesDataSize));
|
||||
stream.readArray(frameData, stream.read(frameDataSize));
|
||||
stream.read(anims, stream.read(animsCount));
|
||||
stream.read(states, stream.read(statesCount));
|
||||
stream.read(ranges, stream.read(rangesCount));
|
||||
stream.read(commands, stream.read(commandsCount));
|
||||
stream.read(nodesData, stream.read(nodesDataSize));
|
||||
stream.read(frameData, stream.read(frameDataSize));
|
||||
// models
|
||||
stream.readArray(models, stream.read(modelsCount));
|
||||
stream.readArray(staticMeshes, stream.read(staticMeshesCount));
|
||||
stream.read(models, stream.read(modelsCount));
|
||||
stream.read(staticMeshes, stream.read(staticMeshesCount));
|
||||
// textures & UV
|
||||
stream.readArray(objectTextures, stream.read(objectTexturesCount));
|
||||
stream.readArray(spriteTextures, stream.read(spriteTexturesCount));
|
||||
stream.readArray(spriteSequences, stream.read(spriteSequencesCount));
|
||||
stream.read(objectTextures, stream.read(objectTexturesCount));
|
||||
stream.read(spriteTextures, stream.read(spriteTexturesCount));
|
||||
stream.read(spriteSequences, stream.read(spriteSequencesCount));
|
||||
// cameras
|
||||
stream.readArray(camera, stream.read(camerasCount));
|
||||
stream.read(camera, stream.read(camerasCount));
|
||||
// sound sources
|
||||
stream.readArray(soundSources, stream.read(soundSourcesCount));
|
||||
stream.read(soundSources, stream.read(soundSourcesCount));
|
||||
// AI
|
||||
stream.readArray(boxes, stream.read(boxesCount));
|
||||
stream.readArray(overlaps, stream.read(overlapsCount));
|
||||
stream.readArray(zones, boxesCount);
|
||||
stream.read(boxes, stream.read(boxesCount));
|
||||
stream.read(overlaps, stream.read(overlapsCount));
|
||||
stream.read(zones, boxesCount);
|
||||
// animated textures
|
||||
stream.readArray(animTexturesData, stream.read(animTexturesDataSize));
|
||||
stream.read(animTexturesData, stream.read(animTexturesDataSize));
|
||||
// entities (enemies, items, lara etc.)
|
||||
stream.readArray(entities, stream.read(entitiesCount));
|
||||
stream.read(entities, stream.read(entitiesCount));
|
||||
// palette
|
||||
stream.seek(32 * 256); // skip lightmap palette
|
||||
stream.readArray(palette, 256);
|
||||
stream.read(palette, 256);
|
||||
// cinematic frames for cameras
|
||||
stream.readArray(cameraFrames, stream.read(cameraFramesCount));
|
||||
stream.read(cameraFrames, stream.read(cameraFramesCount));
|
||||
// demo data
|
||||
stream.readArray(demoData, stream.read(demoDataSize));
|
||||
stream.read(demoData, stream.read(demoDataSize));
|
||||
// sounds
|
||||
stream.readArray(soundsMap, 256);
|
||||
stream.readArray(soundsInfo, stream.read(soundsInfoCount));
|
||||
stream.readArray(soundData, stream.read(soundDataSize));
|
||||
stream.readArray(soundOffsets, stream.read(soundOffsetsCount));
|
||||
stream.read(soundsMap, 256);
|
||||
stream.read(soundsInfo, stream.read(soundsInfoCount));
|
||||
stream.read(soundData, stream.read(soundDataSize));
|
||||
stream.read(soundOffsets, stream.read(soundOffsetsCount));
|
||||
|
||||
// modify palette colors from 6-bit Amiga colorspace
|
||||
int m = 0;
|
||||
|
725
src/level.h
725
src/level.h
@@ -6,19 +6,103 @@
|
||||
#include "format.h"
|
||||
#include "controller.h"
|
||||
|
||||
const char SHADER[] = \
|
||||
"varying vec3 vLightVec;\n"\
|
||||
"varying vec2 vTexCoord;\n"\
|
||||
"varying vec4 vNormal;\n"\
|
||||
"varying vec4 vColor;\n"\
|
||||
\
|
||||
"#ifdef VERTEX\n"\
|
||||
" uniform mat4 uViewProj;\n"\
|
||||
" uniform mat4 uModel;\n"\
|
||||
" uniform vec3 uLightPos;\n"\
|
||||
\
|
||||
" attribute vec3 aCoord;\n"\
|
||||
" attribute vec2 aTexCoord;\n"\
|
||||
" attribute vec4 aNormal;\n"\
|
||||
" attribute vec4 aColor;\n"\
|
||||
\
|
||||
" void main() {\n"\
|
||||
" vec4 coord = uModel * vec4(aCoord, 1.0);\n"\
|
||||
" vLightVec = uLightPos - coord.xyz;\n"\
|
||||
" vTexCoord = aTexCoord + vec2(0.5/1024.0);\n"\
|
||||
" vNormal = vec4(mat3(uModel[0].xyz, uModel[1].xyz, uModel[2].xyz) * (aNormal.xyz * 2.0 - 1.0), aNormal.w);\n"\
|
||||
" vColor = aColor;\n"\
|
||||
" gl_Position = uViewProj * coord;\n"\
|
||||
" }\n"\
|
||||
"#else\n"\
|
||||
" uniform sampler2D sDiffuse;\n"\
|
||||
" uniform vec4 uColor;\n"\
|
||||
" uniform vec3 uAmbient;\n"\
|
||||
" uniform vec4 uLightColor;\n"\
|
||||
\
|
||||
" void main() {\n"\
|
||||
" vec4 color = texture2D(sDiffuse, vTexCoord) * vColor * uColor;\n"\
|
||||
" color.xyz = pow(color.xyz, vec3(2.2));\n"\
|
||||
" vec3 light = uLightColor.xyz * max(vNormal.w, dot(normalize(vNormal.xyz), normalize(vLightVec)));\n"\
|
||||
" light += uAmbient;\n"\
|
||||
" color.xyz *= light;\n"\
|
||||
" color.xyz = pow(color.xyz, vec3(1.0/2.2));\n"\
|
||||
" gl_FragColor = color;\n"\
|
||||
" }\n"\
|
||||
"#endif";
|
||||
|
||||
|
||||
ubyte4 packNormal(const TR::Vertex &n) {
|
||||
vec3 vn = (vec3(n.x, n.y, n.z).normal() * 0.5f + vec3(0.5f)) * 255.0f;
|
||||
ubyte4 v;
|
||||
// v.x = (int)n.x * 255 / (2 * 16300) + 127;
|
||||
// v.y = (int)n.y * 255 / (2 * 16300) + 127;
|
||||
// v.z = (int)n.z * 255 / (2 * 16300) + 127;
|
||||
v.x = (int)vn.x;
|
||||
v.y = (int)vn.y;
|
||||
v.z = (int)vn.z;
|
||||
v.w = 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
struct Level {
|
||||
TR::Level level;
|
||||
Texture *atlas;
|
||||
float time;
|
||||
Controller *lara;
|
||||
TR::Level level;
|
||||
Shader *shader;
|
||||
Texture *atlas;
|
||||
Mesh *mesh;
|
||||
|
||||
Controller *lara;
|
||||
|
||||
float time;
|
||||
|
||||
MeshRange *rangeRooms;
|
||||
|
||||
int mCount;
|
||||
struct MeshInfo : MeshRange {
|
||||
int offset;
|
||||
TR::Vertex center;
|
||||
int32 radius;
|
||||
} *meshInfo;
|
||||
|
||||
Level(const char *name) : level(Stream(name)), time(0.0f) {
|
||||
shader = new Shader(SHADER);
|
||||
initAtlas();
|
||||
lara = new Controller(&level);
|
||||
initMesh();
|
||||
|
||||
int entity = 0;
|
||||
for (int i = 0; i < level.entitiesCount; i++)
|
||||
if (level.entities[i].id == ENTITY_LARA) {
|
||||
entity = i;
|
||||
break;
|
||||
}
|
||||
|
||||
lara = new Controller(&level, entity);
|
||||
}
|
||||
|
||||
~Level() {
|
||||
delete shader;
|
||||
delete atlas;
|
||||
delete mesh;
|
||||
delete[] rangeRooms;
|
||||
delete[] meshInfo;
|
||||
|
||||
delete lara;
|
||||
}
|
||||
|
||||
void initAtlas() {
|
||||
@@ -46,23 +130,315 @@ struct Level {
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = 1020; y < 1024; y++)
|
||||
for (int x = 1020; x < 1024; x++) {
|
||||
int i = y * 1024 + x;
|
||||
data[i].r = data[i].g = data[i].b = data[i].a = 255; // white texel for colored triangles
|
||||
}
|
||||
|
||||
atlas = new Texture(1024, 1024, 0, data);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
void bindTexture(int tile) {
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glTranslatef((tile % 4) * 0.25f, (tile / 4) * 0.25f, 0.0f);
|
||||
glScalef(0.25f, 0.25f, 1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
void initMesh() {
|
||||
// TODO: sort by texture attribute (t.attribute == 2 ? bmAdd : bmAlpha)
|
||||
|
||||
void setTexture(int objTexture) {
|
||||
auto &t = level.objectTextures[objTexture];
|
||||
Core::setBlending(t.attribute == 2 ? bmAdd : bmAlpha);
|
||||
bindTexture(t.tileAndFlag & 0x7FFF);
|
||||
rangeRooms = new MeshRange[level.roomsCount];
|
||||
|
||||
int iCount = 0, vCount = 0;
|
||||
|
||||
// get rooms mesh info
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
rangeRooms[i].vStart = vCount;
|
||||
rangeRooms[i].iStart = iCount;
|
||||
TR::Room::Data &d = level.rooms[i].data;
|
||||
iCount += d.rCount * 6 + d.tCount * 3;
|
||||
vCount += d.rCount * 4 + d.tCount * 3;
|
||||
rangeRooms[i].iCount = iCount - rangeRooms[i].iStart;
|
||||
}
|
||||
// get objects mesh info
|
||||
#define OFFSET(bytes) (ptr = (TR::Mesh*)((char*)ptr + (bytes) - sizeof(char*)))
|
||||
|
||||
mCount = 0;
|
||||
TR::Mesh *ptr = (TR::Mesh*)level.meshData;
|
||||
while ( ((int)ptr - (int)level.meshData) < level.meshDataSize * 2 ) {
|
||||
mCount++;
|
||||
|
||||
OFFSET(ptr->vCount * sizeof(TR::Vertex));
|
||||
if (ptr->nCount > 0)
|
||||
OFFSET(ptr->nCount * sizeof(TR::Vertex));
|
||||
else
|
||||
OFFSET(-ptr->nCount * sizeof(int16));
|
||||
|
||||
iCount += ptr->rCount * 6;
|
||||
vCount += ptr->rCount * 4;
|
||||
OFFSET(ptr->rCount * sizeof(TR::Rectangle));
|
||||
|
||||
iCount += ptr->tCount * 3;
|
||||
vCount += ptr->tCount * 3;
|
||||
OFFSET(ptr->tCount * sizeof(TR::Triangle));
|
||||
|
||||
iCount += ptr->crCount * 6;
|
||||
vCount += ptr->crCount * 4;
|
||||
OFFSET(ptr->crCount * sizeof(TR::Rectangle));
|
||||
|
||||
iCount += ptr->ctCount * 3;
|
||||
vCount += ptr->ctCount * 3;
|
||||
OFFSET(ptr->ctCount * sizeof(TR::Triangle) + sizeof(TR::Mesh));
|
||||
ptr = (TR::Mesh*)(((int)ptr + 3) & ~3);
|
||||
}
|
||||
meshInfo = new MeshInfo[mCount];
|
||||
|
||||
Index *indices = new Index[iCount];
|
||||
Vertex *vertices = new Vertex[vCount];
|
||||
iCount = vCount = 0;
|
||||
|
||||
// rooms geometry
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
TR::Room::Data &d = level.rooms[i].data;
|
||||
|
||||
int vStart = vCount;
|
||||
|
||||
for (int j = 0; j < d.rCount; j++) {
|
||||
auto &f = d.rectangles[j];
|
||||
auto &t = level.objectTextures[f.texture];
|
||||
|
||||
int tile = t.tileAndFlag & 0x7FFF;
|
||||
int tx = (tile % 4) * 256;
|
||||
int ty = (tile / 4) * 256;
|
||||
|
||||
int vIndex = vCount - vStart;
|
||||
|
||||
indices[iCount + 0] = vIndex + 0;
|
||||
indices[iCount + 1] = vIndex + 1;
|
||||
indices[iCount + 2] = vIndex + 2;
|
||||
|
||||
indices[iCount + 3] = vIndex + 0;
|
||||
indices[iCount + 4] = vIndex + 2;
|
||||
indices[iCount + 5] = vIndex + 3;
|
||||
|
||||
iCount += 6;
|
||||
|
||||
for (int k = 0; k < 4; k++) {
|
||||
auto &v = d.vertices[f.vertices[k]];
|
||||
uint8 a = 255 - (v.lighting >> 5);
|
||||
|
||||
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z };
|
||||
vertices[vCount].color = { a, a, a, 255 };
|
||||
vertices[vCount].normal = { 0, 0, 0, 255 };
|
||||
vertices[vCount].texCoord = { (tx + t.vertices[k].Xpixel) << 5, (ty + t.vertices[k].Ypixel) << 5 };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < d.tCount; j++) {
|
||||
auto &f = d.triangles[j];
|
||||
auto &t = level.objectTextures[f.texture];
|
||||
|
||||
int tile = t.tileAndFlag & 0x7FFF;
|
||||
int tx = (tile % 4) * 256;
|
||||
int ty = (tile / 4) * 256;
|
||||
|
||||
int vIndex = vCount - vStart;
|
||||
|
||||
indices[iCount + 0] = vIndex + 0;
|
||||
indices[iCount + 1] = vIndex + 1;
|
||||
indices[iCount + 2] = vIndex + 2;
|
||||
|
||||
iCount += 3;
|
||||
|
||||
for (int k = 0; k < 3; k++) {
|
||||
auto &v = d.vertices[f.vertices[k]];
|
||||
uint8 a = 255 - (v.lighting >> 5);
|
||||
|
||||
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z };
|
||||
vertices[vCount].color = { a, a, a, 255 };
|
||||
vertices[vCount].normal = { 0, 0, 0, 255 };
|
||||
vertices[vCount].texCoord = { (tx + t.vertices[k].Xpixel) << 5, (ty + t.vertices[k].Ypixel) << 5 };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// objects geometry
|
||||
mCount = 0;
|
||||
ptr = (TR::Mesh*)level.meshData;
|
||||
while ( ((int)ptr - (int)level.meshData) < level.meshDataSize * sizeof(uint16) ) {
|
||||
MeshInfo &info = meshInfo[mCount++];
|
||||
info.offset = (int)ptr - (int)level.meshData;
|
||||
info.vStart = vCount;
|
||||
info.iStart = iCount;
|
||||
info.center = ptr->center;
|
||||
info.radius = ptr->radius;
|
||||
|
||||
TR::Vertex *mVertices = (TR::Vertex*)&ptr->vertices;
|
||||
|
||||
OFFSET(ptr->vCount * sizeof(TR::Vertex));
|
||||
|
||||
TR::Vertex *normals = NULL;
|
||||
int16 *lights = NULL;
|
||||
int nCount = ptr->nCount;
|
||||
|
||||
if (ptr->nCount > 0) {
|
||||
normals = (TR::Vertex*)&ptr->normals;
|
||||
OFFSET(ptr->nCount * sizeof(TR::Vertex));
|
||||
} else {
|
||||
lights = (int16*)&ptr->lights;
|
||||
OFFSET(-ptr->nCount * sizeof(int16));
|
||||
}
|
||||
|
||||
int vStart = vCount;
|
||||
// rectangles
|
||||
for (int j = 0; j < ptr->rCount; j++) {
|
||||
auto &f = ((TR::Rectangle*)&ptr->rectangles)[j];
|
||||
auto &t = level.objectTextures[f.texture];
|
||||
|
||||
int tile = t.tileAndFlag & 0x7FFF;
|
||||
int tx = (tile % 4) * 256;
|
||||
int ty = (tile / 4) * 256;
|
||||
|
||||
int vIndex = vCount - vStart;
|
||||
|
||||
indices[iCount + 0] = vIndex + 0;
|
||||
indices[iCount + 1] = vIndex + 1;
|
||||
indices[iCount + 2] = vIndex + 2;
|
||||
|
||||
indices[iCount + 3] = vIndex + 0;
|
||||
indices[iCount + 4] = vIndex + 2;
|
||||
indices[iCount + 5] = vIndex + 3;
|
||||
|
||||
iCount += 6;
|
||||
|
||||
for (int k = 0; k < 4; k++) {
|
||||
auto &v = mVertices[f.vertices[k]];
|
||||
|
||||
vertices[vCount].coord = { v.x, v.y, v.z };
|
||||
|
||||
if (nCount > 0) {
|
||||
vertices[vCount].normal = packNormal(normals[f.vertices[k]]);
|
||||
vertices[vCount].color = { 255, 255, 255, 255 };
|
||||
} else {
|
||||
uint8 a = 255 - (lights[f.vertices[k]] >> 5);
|
||||
vertices[vCount].normal = { 0, 0, 0, 255 };
|
||||
vertices[vCount].color = { a, a, a, 255 };
|
||||
}
|
||||
vertices[vCount].texCoord = { (tx + t.vertices[k].Xpixel) << 5, (ty + t.vertices[k].Ypixel) << 5 };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
OFFSET(ptr->rCount * sizeof(TR::Rectangle));
|
||||
|
||||
// triangles
|
||||
for (int j = 0; j < ptr->tCount; j++) {
|
||||
auto &f = ((TR::Triangle*)&ptr->triangles)[j];
|
||||
auto &t = level.objectTextures[f.texture];
|
||||
|
||||
int tile = t.tileAndFlag & 0x7FFF;
|
||||
int tx = (tile % 4) * 256;
|
||||
int ty = (tile / 4) * 256;
|
||||
|
||||
int vIndex = vCount - vStart;
|
||||
|
||||
indices[iCount + 0] = vIndex + 0;
|
||||
indices[iCount + 1] = vIndex + 1;
|
||||
indices[iCount + 2] = vIndex + 2;
|
||||
|
||||
iCount += 3;
|
||||
|
||||
for (int k = 0; k < 3; k++) {
|
||||
auto &v = mVertices[f.vertices[k]];
|
||||
vertices[vCount].coord = { v.x, v.y, v.z };
|
||||
|
||||
if (nCount > 0) {
|
||||
vertices[vCount].normal = packNormal(normals[f.vertices[k]]);
|
||||
vertices[vCount].color = { 255, 255, 255, 255 };
|
||||
} else {
|
||||
uint8 a = 255 - (lights[f.vertices[k]] >> 5);
|
||||
vertices[vCount].normal = { 0, 0, 0, 255 };
|
||||
vertices[vCount].color = { a, a, a, 255 };
|
||||
}
|
||||
vertices[vCount].texCoord = { (tx + t.vertices[k].Xpixel) << 5, (ty + t.vertices[k].Ypixel) << 5 };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
OFFSET(ptr->tCount * sizeof(TR::Triangle));
|
||||
|
||||
// color rectangles
|
||||
for (int j = 0; j < ptr->crCount; j++) {
|
||||
auto &f = ((TR::Rectangle*)&ptr->crectangles)[j];
|
||||
auto &c = level.palette[f.texture & 0xFF];
|
||||
|
||||
int vIndex = vCount - vStart;
|
||||
|
||||
indices[iCount + 0] = vIndex + 0;
|
||||
indices[iCount + 1] = vIndex + 1;
|
||||
indices[iCount + 2] = vIndex + 2;
|
||||
|
||||
indices[iCount + 3] = vIndex + 0;
|
||||
indices[iCount + 4] = vIndex + 2;
|
||||
indices[iCount + 5] = vIndex + 3;
|
||||
|
||||
iCount += 6;
|
||||
|
||||
for (int k = 0; k < 4; k++) {
|
||||
auto &v = mVertices[f.vertices[k]];
|
||||
|
||||
vertices[vCount].coord = { v.x, v.y, v.z };
|
||||
|
||||
if (nCount > 0) {
|
||||
vertices[vCount].normal = packNormal(normals[f.vertices[k]]);
|
||||
vertices[vCount].color = { c.r, c.g, c.b, 255 };
|
||||
} else {
|
||||
uint8 a = 255 - (lights[f.vertices[k]] >> 5);
|
||||
vertices[vCount].normal = { 0, 0, 0, 255 };
|
||||
vertices[vCount].color = { a, a, a, 255 }; // TODO: apply color
|
||||
}
|
||||
vertices[vCount].texCoord = { 1022 << 5, 1022 << 5 };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
OFFSET(ptr->crCount * sizeof(TR::Rectangle));
|
||||
|
||||
// color triangles
|
||||
for (int j = 0; j < ptr->ctCount; j++) {
|
||||
auto &f = ((TR::Triangle*)&ptr->ctriangles)[j];
|
||||
auto &c = level.palette[f.texture & 0xFF];
|
||||
|
||||
int vIndex = vCount - vStart;
|
||||
|
||||
indices[iCount + 0] = vIndex + 0;
|
||||
indices[iCount + 1] = vIndex + 1;
|
||||
indices[iCount + 2] = vIndex + 2;
|
||||
|
||||
iCount += 3;
|
||||
|
||||
for (int k = 0; k < 3; k++) {
|
||||
auto &v = mVertices[f.vertices[k]];
|
||||
|
||||
vertices[vCount].coord = { v.x, v.y, v.z };
|
||||
|
||||
if (nCount > 0) {
|
||||
vertices[vCount].normal = packNormal(normals[f.vertices[k]]);
|
||||
vertices[vCount].color = { c.r, c.g, c.b, 255 };
|
||||
} else {
|
||||
uint8 a = 255 - (lights[f.vertices[k]] >> 5);
|
||||
vertices[vCount].normal = { 0, 0, 0, 255 };
|
||||
vertices[vCount].color = { a, a, a, 255 }; // TODO: apply color
|
||||
}
|
||||
vertices[vCount].texCoord = { 1022 << 5, 1022 << 5 };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
OFFSET(ptr->ctCount * sizeof(TR::Triangle) + sizeof(TR::Mesh));
|
||||
|
||||
ptr = (TR::Mesh*)(((int)ptr + 3) & ~3);
|
||||
|
||||
info.iCount = iCount - info.iStart;
|
||||
}
|
||||
|
||||
mesh = new Mesh(indices, iCount, vertices, vCount);
|
||||
delete[] indices;
|
||||
delete[] vertices;
|
||||
}
|
||||
|
||||
TR::StaticMesh* getMeshByID(int id) {
|
||||
@@ -74,213 +450,56 @@ struct Level {
|
||||
|
||||
#define SCALE (1.0f / 1024.0f / 2.0f)
|
||||
|
||||
void renderRoom(const TR::Room &room) {
|
||||
glPushMatrix();
|
||||
glTranslatef(room.info.x, 0.0f, room.info.z);
|
||||
void renderRoom(int index) {
|
||||
TR::Room &room = level.rooms[index];
|
||||
|
||||
// rectangles
|
||||
for (int j = 0; j < room.data.rCount; j++) {
|
||||
auto &f = room.data.rectangles[j];
|
||||
auto &t = level.objectTextures[f.texture];
|
||||
setTexture(f.texture);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
for (int k = 0; k < 4; k++) {
|
||||
auto &v = room.data.vertices[f.vertices[k]];
|
||||
float a = 1.0f - v.lighting / 8191.0f;
|
||||
glColor3f(a, a, a);
|
||||
glTexCoord2f(t.vertices[k].Xpixel / 256.0f, t.vertices[k].Ypixel / 256.0f);
|
||||
glVertex3sv((GLshort*)&v.vertex);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// triangles
|
||||
for (int j = 0; j < room.data.tCount; j++) {
|
||||
auto &f = room.data.triangles[j];
|
||||
auto &t = level.objectTextures[f.texture];
|
||||
setTexture(f.texture);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int k = 0; k < 3; k++) {
|
||||
auto &v = room.data.vertices[f.vertices[k]];
|
||||
float a = 1.0f - v.lighting / 8191.0f;
|
||||
glColor3f(a, a, a);
|
||||
glTexCoord2f(t.vertices[k].Xpixel / 256.0f, t.vertices[k].Ypixel / 256.0f);
|
||||
glVertex3sv((GLshort*)&v.vertex);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glPopMatrix();
|
||||
mat4 m = Core::mModel;
|
||||
Core::mModel.translate(vec3(room.info.x, 0.0f, room.info.z));
|
||||
shader->setParam(uModel, Core::mModel);
|
||||
mesh->render(rangeRooms[index]);
|
||||
Core::mModel = m;
|
||||
|
||||
Core::color = vec4(1.0f);
|
||||
shader->setParam(uColor, Core::color);
|
||||
|
||||
// meshes
|
||||
float a = 1.0f - room.ambient / 8191.0f;
|
||||
|
||||
for (int j = 0; j < room.meshesCount; j++) {
|
||||
auto rMesh = room.meshes[j];
|
||||
auto sMesh = getMeshByID(rMesh.meshID);
|
||||
ASSERT(sMesh != NULL);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(rMesh.x, rMesh.y, rMesh.z);
|
||||
glRotatef((rMesh.rotation >> 14) * 90.0f, 0, 1, 0);
|
||||
|
||||
renderMesh(sMesh->mesh, vec3(a));
|
||||
mat4 m = Core::mModel;
|
||||
Core::mModel.translate(vec3(rMesh.x, rMesh.y, rMesh.z));
|
||||
Core::mModel.rotateY((rMesh.rotation >> 14) * 90.0f * DEG2RAD);
|
||||
|
||||
glPopMatrix();
|
||||
getLight(vec3(rMesh.x, rMesh.y, rMesh.z), index);
|
||||
shader->setParam(uAmbient, Core::ambient);
|
||||
shader->setParam(uLightPos, Core::lightPos);
|
||||
shader->setParam(uLightColor, Core::lightColor);
|
||||
|
||||
renderMesh(sMesh->mesh);
|
||||
|
||||
Core::mModel = m;
|
||||
}
|
||||
|
||||
/*
|
||||
// sprites
|
||||
Core::setBlending(bmAlpha);
|
||||
for (int j = 0; j < room.data.sCount; j++)
|
||||
renderSprite(room, room.data.sprites[j]);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void renderMesh(uint32 meshOffset, const vec3 &color) {
|
||||
// remap mesh
|
||||
#define OFFSET(bytes) (ptr = (TR::Mesh*)((char*)ptr + bytes - sizeof(char*)))
|
||||
void renderMesh(uint32 meshOffset) {
|
||||
if (!level.meshOffsets[meshOffset] && meshOffset)
|
||||
return;
|
||||
|
||||
TR::Mesh *ptr = (TR::Mesh*)((char*)level.meshData + level.meshOffsets[meshOffset]);
|
||||
TR::Mesh mesh;
|
||||
mesh.center = ptr->center;
|
||||
mesh.radius = ptr->radius;
|
||||
mesh.vCount = ptr->vCount;
|
||||
mesh.vertices = (TR::Vertex*)&ptr->vertices;
|
||||
OFFSET(mesh.vCount * sizeof(TR::Vertex));
|
||||
mesh.nCount = ptr->nCount;
|
||||
mesh.normals = (TR::Vertex*)&ptr->normals;
|
||||
if (mesh.nCount > 0)
|
||||
OFFSET(mesh.nCount * sizeof(TR::Vertex));
|
||||
else
|
||||
OFFSET(-mesh.nCount * sizeof(int16));
|
||||
|
||||
mesh.rCount = ptr->rCount;
|
||||
mesh.rectangles = (TR::Rectangle*)&ptr->rectangles;
|
||||
OFFSET(mesh.rCount * sizeof(TR::Rectangle));
|
||||
|
||||
mesh.tCount = ptr->tCount;
|
||||
mesh.triangles = (TR::Triangle*)&ptr->triangles;
|
||||
OFFSET(mesh.tCount * sizeof(TR::Triangle));
|
||||
|
||||
mesh.crCount = ptr->crCount;
|
||||
mesh.crectangles = (TR::Rectangle*)&ptr->crectangles;
|
||||
OFFSET(mesh.crCount * sizeof(TR::Rectangle));
|
||||
|
||||
mesh.ctCount = ptr->ctCount;
|
||||
mesh.ctriangles = (TR::Triangle*)&ptr->ctriangles;
|
||||
OFFSET(mesh.ctCount * sizeof(TR::Triangle));
|
||||
|
||||
if (mesh.nCount > 0)
|
||||
glEnable(GL_LIGHTING);
|
||||
glColor3f(color.x, color.y, color.z);
|
||||
|
||||
// triangles
|
||||
for (int j = 0; j < mesh.tCount; j++) {
|
||||
auto &f = mesh.triangles[j];
|
||||
auto &t = level.objectTextures[f.texture];
|
||||
setTexture(f.texture);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int k = 0; k < 3; k++) {
|
||||
auto &v = mesh.vertices[f.vertices[k]];
|
||||
|
||||
if (mesh.nCount > 0) {
|
||||
auto vn = mesh.normals[f.vertices[k]];
|
||||
// vec3 n = vec3(vn.x, vn.y, vn.z).normal();
|
||||
glNormal3sv((GLshort*)&vn);
|
||||
} else {
|
||||
auto l = mesh.lights[f.vertices[k]];
|
||||
float a = 1.0f - l / 8191.0f;
|
||||
glColor3f(a, a, a);
|
||||
}
|
||||
|
||||
glTexCoord2f(t.vertices[k].Xpixel / 256.0f, t.vertices[k].Ypixel / 256.0f);
|
||||
glVertex3sv((GLshort*)&v);
|
||||
for (int i = 0; i < mCount; i++)
|
||||
if (meshInfo[i].offset == level.meshOffsets[meshOffset]) {
|
||||
shader->setParam(uModel, Core::mModel);
|
||||
mesh->render(meshInfo[i]);
|
||||
break;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// rectangles
|
||||
for (int j = 0; j < mesh.rCount; j++) {
|
||||
auto &f = mesh.rectangles[j];
|
||||
auto &t = level.objectTextures[f.texture];
|
||||
setTexture(f.texture);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
for (int k = 0; k < 4; k++) {
|
||||
auto &v = mesh.vertices[f.vertices[k]];
|
||||
|
||||
if (mesh.nCount > 0) {
|
||||
auto vn = mesh.normals[f.vertices[k]];
|
||||
// vec3 n = vec3(vn.x, vn.y, vn.z).normal();
|
||||
glNormal3sv((GLshort*)&vn);
|
||||
} else {
|
||||
auto l = mesh.lights[f.vertices[k]];
|
||||
float a = 1.0f - l / 8191.0f;
|
||||
glColor3f(a, a, a);
|
||||
}
|
||||
glTexCoord2f(t.vertices[k].Xpixel / 256.0f, t.vertices[k].Ypixel / 256.0f);
|
||||
glVertex3sv((GLshort*)&v);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
// debug normals
|
||||
|
||||
// triangles (colored)
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int j = 0; j < mesh.ctCount; j++) {
|
||||
auto &f = mesh.ctriangles[j];
|
||||
auto &c = level.palette[f.texture & 0xFF];
|
||||
|
||||
for (int k = 0; k < 3; k++) {
|
||||
auto &v = mesh.vertices[f.vertices[k]];
|
||||
|
||||
if (mesh.nCount > 0) {
|
||||
auto vn = mesh.normals[f.vertices[k]];
|
||||
// vec3 n = vec3(vn.x, vn.y, vn.z).normal();
|
||||
glColor3f(c.r / 255.0f * color.x, c.g / 255.0f * color.y, c.b / 255.0f * color.z);
|
||||
glNormal3sv((GLshort*)&vn);
|
||||
} else {
|
||||
auto l = mesh.lights[f.vertices[k]];
|
||||
float a = (1.0f - l / 8191.0f) / 255.0f;
|
||||
glColor3f(c.r * a, c.g * a, c.b * a);
|
||||
}
|
||||
glVertex3sv((GLshort*)&v);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// rectangles (colored)
|
||||
glBegin(GL_QUADS);
|
||||
for (int j = 0; j < mesh.crCount; j++) {
|
||||
auto &f = mesh.crectangles[j];
|
||||
auto &c = level.palette[f.texture & 0xFF];
|
||||
|
||||
for (int k = 0; k < 4; k++) {
|
||||
auto &v = mesh.vertices[f.vertices[k]];
|
||||
|
||||
if (mesh.nCount > 0) {
|
||||
auto vn = mesh.normals[f.vertices[k]];
|
||||
// vec3 n = vec3(vn.x, vn.y, vn.z).normal();
|
||||
glColor3f(c.r / 255.0f * color.x, c.g / 255.0f * color.y, c.b / 255.0f * color.z);
|
||||
glNormal3sv((GLshort*)&vn);
|
||||
} else {
|
||||
auto l = mesh.lights[f.vertices[k]];
|
||||
float a = (1.0f - l / 8191.0f) / 255.0f;
|
||||
glColor3f(c.r * a, c.g * a, c.b * a);
|
||||
}
|
||||
glVertex3sv((GLshort*)&v);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
if (mesh.nCount > 0)
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
void renderSprite(const TR::SpriteTexture &sprite) {
|
||||
@@ -299,7 +518,7 @@ struct Level {
|
||||
p[2] = right * sprite.l + up * sprite.t;
|
||||
p[3] = right * sprite.r + up * sprite.t;
|
||||
|
||||
bindTexture(sprite.tile);
|
||||
// bindTexture(sprite.tile);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(u0, v1);
|
||||
glVertex3fv((GLfloat*)&p[0]);
|
||||
@@ -363,13 +582,8 @@ struct Level {
|
||||
|
||||
return ma.getRot().slerp(mb.getRot(), t).normal();
|
||||
}
|
||||
|
||||
float debugTime = 0.0f;
|
||||
|
||||
void renderModel(const TR::Model &model) {
|
||||
mat4 m;
|
||||
m.identity();
|
||||
|
||||
|
||||
void renderModel(const TR::Model &model) {
|
||||
TR::Animation *anim = &level.anims[model.animation];
|
||||
|
||||
float fTime = time;
|
||||
@@ -377,8 +591,6 @@ struct Level {
|
||||
if (model.id == ENTITY_LARA) {
|
||||
anim = lara->anim;
|
||||
fTime = lara->fTime;
|
||||
m.translate(lara->pos);
|
||||
m.rotateY(lara->angle);
|
||||
}
|
||||
|
||||
float k = fTime * 30.0f / anim->frameRate;
|
||||
@@ -422,6 +634,8 @@ struct Level {
|
||||
int sIndex = 0;
|
||||
mat4 stack[20];
|
||||
|
||||
mat4 m;
|
||||
m.identity();
|
||||
m.translate(vec3(frameA->x, frameA->y, frameA->z).lerp(vec3(frameB->x, frameB->y, frameB->z), k));
|
||||
|
||||
for (int i = 0; i < model.mCount; i++) {
|
||||
@@ -447,39 +661,67 @@ struct Level {
|
||||
// m.rotateX(angle.x);
|
||||
// m.rotateZ(angle.z);
|
||||
|
||||
|
||||
glPushMatrix();
|
||||
glMultMatrixf((GLfloat*)&m);
|
||||
renderMesh(model.mStart + i, vec3(1.0f));
|
||||
glPopMatrix();
|
||||
mat4 tmp = Core::mModel;
|
||||
Core::mModel = Core::mModel * m;
|
||||
renderMesh(model.mStart + i);
|
||||
Core::mModel = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void getLight(const vec3 &pos, int room) {
|
||||
int idx = -1;
|
||||
float dist;
|
||||
for (int i = 0; i < level.rooms[room].lightsCount; i++) {
|
||||
TR::Room::Light &light = level.rooms[room].lights[i];
|
||||
float d = (pos - vec3(light.x, light.y, light.z)).length();
|
||||
if (idx == -1 || d < dist) {
|
||||
idx = i;
|
||||
dist = d;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx > -1) {
|
||||
TR::Room::Light &light = level.rooms[room].lights[idx];
|
||||
float c = level.rooms[room].lights[idx].Intensity / 8191.0f;
|
||||
Core::lightPos = vec3(-light.x, -light.y, light.z);
|
||||
Core::lightColor = vec4(c, c, c, 0.0f);
|
||||
} else {
|
||||
Core::lightPos = vec3(0.0f);
|
||||
Core::lightColor = vec4(0.0f);
|
||||
}
|
||||
Core::ambient = vec3(1.0f - level.rooms[room].ambient / 8191.0f);
|
||||
}
|
||||
|
||||
void renderEntity(const TR::Entity &entity) {
|
||||
glPushMatrix();
|
||||
glTranslatef(entity.x, entity.y, entity.z);
|
||||
mat4 m = Core::mModel;
|
||||
Core::mModel.translate(vec3(entity.x, entity.y, entity.z));
|
||||
|
||||
if (entity.intensity > -1) {
|
||||
float a = 1.0f - entity.intensity / (float)0x1FFF;
|
||||
glColor3f(a, a, a);
|
||||
} else
|
||||
glColor3f(1, 1, 1);
|
||||
|
||||
float c = (entity.intensity > -1) ? (1.0f - entity.intensity / (float)0x1FFF) : 1.0f;
|
||||
float l = 1.0f;
|
||||
|
||||
Core::color = vec4(c, c, c, 1.0);
|
||||
getLight(vec3(entity.x, entity.y, entity.z), entity.room);
|
||||
|
||||
shader->setParam(uColor, Core::color);
|
||||
shader->setParam(uAmbient, Core::ambient);
|
||||
shader->setParam(uLightPos, Core::lightPos);
|
||||
shader->setParam(uLightColor, Core::lightColor);
|
||||
|
||||
for (int i = 0; i < level.modelsCount; i++)
|
||||
if (entity.id == level.models[i].id) {
|
||||
glRotatef((entity.rotation >> 14) * 90.0f, 0, 1, 0);
|
||||
Core::mModel.rotateY(entity.rotation / 16384.0f * PI * 0.5f);
|
||||
// Core::mModel.rotateY((entity.rotation >> 14) * 90.0f * DEG2RAD);
|
||||
renderModel(level.models[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
for (int i = 0; i < level.spriteSequencesCount; i++)
|
||||
if (entity.id == level.spriteSequences[i].id) {
|
||||
renderSprite(level.spriteTextures[level.spriteSequences[i].sStart]);
|
||||
break;
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
*/
|
||||
Core::mModel = m;
|
||||
}
|
||||
|
||||
|
||||
@@ -749,22 +991,33 @@ struct Level {
|
||||
}
|
||||
|
||||
void render() {
|
||||
shader->bind();
|
||||
atlas->bind(0);
|
||||
mesh->bind();
|
||||
|
||||
shader->setParam(uViewProj, Core::mViewProj);
|
||||
shader->setParam(uModel, Core::mModel);
|
||||
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER, 0.9f);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_NORMALIZE);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glEnable(GL_LIGHT0);
|
||||
//glEnable(GL_LIGHT0);
|
||||
|
||||
Core::setCulling(cfFront);
|
||||
glColor3f(1, 1, 1);
|
||||
|
||||
glScalef(-SCALE, -SCALE, SCALE);
|
||||
Core::mModel.identity();
|
||||
Core::mModel.scale(vec3(-SCALE, -SCALE, SCALE));
|
||||
|
||||
Core::color = vec4(1.0f);
|
||||
Core::ambient = vec3(0.0f);
|
||||
|
||||
shader->setParam(uColor, Core::color);
|
||||
shader->setParam(uAmbient, Core::ambient);
|
||||
|
||||
for (int i = 0; i < level.roomsCount; i++)
|
||||
renderRoom(level.rooms[i]);
|
||||
renderRoom(i);
|
||||
|
||||
for (int i = 0; i < level.entitiesCount; i++)
|
||||
renderEntity(level.entities[i]);
|
||||
|
49
src/mesh.h
49
src/mesh.h
@@ -6,30 +6,30 @@
|
||||
typedef unsigned short Index;
|
||||
|
||||
struct Vertex {
|
||||
vec3 coord;
|
||||
vec3 normal;
|
||||
vec2 texCoord;
|
||||
short3 coord;
|
||||
short2 texCoord;
|
||||
ubyte4 normal;
|
||||
ubyte4 color;
|
||||
};
|
||||
|
||||
struct MeshRange {
|
||||
int iStart;
|
||||
int iCount;
|
||||
int vStart;
|
||||
};
|
||||
|
||||
struct Mesh {
|
||||
GLuint ID[2];
|
||||
int iCount;
|
||||
int vCount;
|
||||
/*
|
||||
Mesh(const char *name) {
|
||||
Stream stream(name);
|
||||
Index *indices = stream.readArray<Index> (stream.read(iCount));
|
||||
Vertex *vertices = stream.readArray<Vertex>(stream.read(vCount));
|
||||
|
||||
Mesh(Index *indices, int iCount, Vertex *vertices, int vCount) : iCount(iCount), vCount(vCount) {
|
||||
glGenBuffers(2, ID);
|
||||
bind();
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iCount * sizeof(Index), indices, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, vCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
|
||||
|
||||
delete[] indices;
|
||||
delete[] vertices;
|
||||
}
|
||||
*/
|
||||
|
||||
virtual ~Mesh() {
|
||||
glDeleteBuffers(2, ID);
|
||||
}
|
||||
@@ -37,25 +37,20 @@ struct Mesh {
|
||||
void bind() {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ID[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ID[1]);
|
||||
}
|
||||
|
||||
void render() {
|
||||
bind();
|
||||
|
||||
glEnableVertexAttribArray(aCoord);
|
||||
glEnableVertexAttribArray(aNormal);
|
||||
glEnableVertexAttribArray(aTexCoord);
|
||||
glEnableVertexAttribArray(aNormal);
|
||||
glEnableVertexAttribArray(aColor);
|
||||
}
|
||||
|
||||
|
||||
Vertex *v = NULL;
|
||||
glVertexAttribPointer(aCoord, 3, GL_FLOAT, false, sizeof(Vertex), &v->coord);
|
||||
glVertexAttribPointer(aNormal, 3, GL_FLOAT, false, sizeof(Vertex), &v->normal);
|
||||
glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, false, sizeof(Vertex), &v->texCoord);
|
||||
glDrawElements(GL_TRIANGLES, iCount, GL_UNSIGNED_SHORT, NULL);
|
||||
|
||||
glDisableVertexAttribArray(aCoord);
|
||||
glDisableVertexAttribArray(aNormal);
|
||||
glDisableVertexAttribArray(aTexCoord);
|
||||
void render(const MeshRange &range) {
|
||||
Vertex *v = (Vertex*)(range.vStart * sizeof(Vertex));
|
||||
glVertexAttribPointer(aCoord, 3, GL_SHORT, false, sizeof(Vertex), &v->coord);
|
||||
glVertexAttribPointer(aTexCoord, 2, GL_SHORT, true, sizeof(Vertex), &v->texCoord);
|
||||
glVertexAttribPointer(aNormal, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), &v->normal);
|
||||
glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), &v->color);
|
||||
glDrawElements(GL_TRIANGLES, range.iCount, GL_UNSIGNED_SHORT, (GLvoid*)(range.iStart * sizeof(Index)));
|
||||
}
|
||||
};
|
||||
|
||||
|
23
src/shader.h
23
src/shader.h
@@ -3,25 +3,19 @@
|
||||
|
||||
#include "core.h"
|
||||
|
||||
enum AttribType { aCoord, aTexCoord, aNormal, aMAX };
|
||||
enum SamplerType { sTex0, sMAX };
|
||||
enum UniformType { uViewProj, uModel, uLightVec, uMAX };
|
||||
enum AttribType { aCoord, aTexCoord, aNormal, aColor, aMAX };
|
||||
enum SamplerType { sDiffuse, sMAX };
|
||||
enum UniformType { uViewProj, uModel, uColor, uAmbient, uLightPos, uLightColor, uMAX };
|
||||
|
||||
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal" };
|
||||
const char *SamplerName[sMAX] = { "sTex0" };
|
||||
const char *UniformName[uMAX] = { "uViewProj", "uModel", "uLightVec" };
|
||||
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal", "aColor" };
|
||||
const char *SamplerName[sMAX] = { "sDiffuse" };
|
||||
const char *UniformName[uMAX] = { "uViewProj", "uModel", "uColor", "uAmbient", "uLightPos", "uLightColor" };
|
||||
|
||||
struct Shader {
|
||||
GLuint ID;
|
||||
GLint uID[uMAX];
|
||||
|
||||
Shader(const char *name, int param) {
|
||||
Stream stream(name);
|
||||
|
||||
char *text = new char[stream.size + 1];
|
||||
stream.read(text, stream.size);
|
||||
text[stream.size] = '\0';
|
||||
|
||||
Shader(const char *text) {
|
||||
#define GLSL_DEFINE "#version 110\n"
|
||||
|
||||
const int type[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
|
||||
@@ -44,7 +38,6 @@ struct Shader {
|
||||
glAttachShader(ID, obj);
|
||||
glDeleteShader(obj);
|
||||
}
|
||||
delete[] text;
|
||||
|
||||
for (int at = 0; at < aMAX; at++)
|
||||
glBindAttribLocation(ID, at, AttribName[at]);
|
||||
@@ -68,8 +61,6 @@ struct Shader {
|
||||
|
||||
void bind() {
|
||||
glUseProgram(ID);
|
||||
setParam(uViewProj, Core::mViewProj);
|
||||
setParam(uModel, Core::mModel);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec3 &value, int count = 1) {
|
||||
|
39
src/utils.h
39
src/utils.h
@@ -31,6 +31,18 @@ typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
struct ubyte4 {
|
||||
uint8 x, y, z, w;
|
||||
};
|
||||
|
||||
struct short2 {
|
||||
int16 x, y;
|
||||
};
|
||||
|
||||
struct short3 {
|
||||
int16 x, y, z;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline const T& min(const T &a, const T &b) {
|
||||
return a < b ? a : b;
|
||||
@@ -52,8 +64,9 @@ struct vec2 {
|
||||
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 cross(const vec2 &v) const { return x*v.y - y*v.x; }
|
||||
float length() const { return sqrtf(dot(*this)); }
|
||||
vec2 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
|
||||
float length2() const { return dot(*this); }
|
||||
float length() const { return sqrtf(length2()); }
|
||||
vec2 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
|
||||
};
|
||||
|
||||
struct vec3 {
|
||||
@@ -68,11 +81,11 @@ struct vec3 {
|
||||
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); }
|
||||
|
||||
|
||||
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); }
|
||||
float length() const { return sqrtf(x*x + y*y + z*z); }
|
||||
vec3 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
|
||||
float length2() const { return dot(*this); }
|
||||
float length() const { return sqrtf(length2()); }
|
||||
vec3 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
|
||||
|
||||
vec3 lerp(const vec3 &v, const float t) const {
|
||||
return *this + (v - *this) * t;
|
||||
@@ -86,6 +99,7 @@ struct vec4 {
|
||||
};
|
||||
|
||||
vec4() {}
|
||||
vec4(float s) : x(s), y(s), z(s), w(s) {}
|
||||
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
|
||||
};
|
||||
|
||||
@@ -437,23 +451,24 @@ struct Stream {
|
||||
pos += offset;
|
||||
}
|
||||
|
||||
int read(void *data, int size) {
|
||||
int raw(void *data, int size) {
|
||||
pos += size;
|
||||
return fread(data, 1, size, f);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& read(T &x) {
|
||||
read(&x, sizeof(x));
|
||||
raw(&x, sizeof(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* readArray(T *&a, int count) {
|
||||
if (!count)
|
||||
return NULL;
|
||||
a = new T[count];
|
||||
read(a, count * sizeof(T));
|
||||
T* read(T *&a, int count) {
|
||||
if (count) {
|
||||
a = new T[count];
|
||||
raw(a, count * sizeof(T));
|
||||
} else
|
||||
a = NULL;
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
@@ -1,3 +1,7 @@
|
||||
#ifdef _DEBUG
|
||||
#include "crtdbg.h"
|
||||
#endif
|
||||
|
||||
#include "game.h"
|
||||
|
||||
DWORD getTime() {
|
||||
@@ -171,6 +175,12 @@ void freeGL(HGLRC hRC) {
|
||||
}
|
||||
|
||||
int main() {
|
||||
#ifdef _DEBUG
|
||||
_CrtMemState _ms;
|
||||
_CrtMemCheckpoint(&_ms);
|
||||
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
|
||||
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
|
||||
#endif
|
||||
RECT r = { 0, 0, 1280, 720 };
|
||||
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);
|
||||
|
||||
@@ -223,6 +233,10 @@ int main() {
|
||||
ReleaseDC(hWnd, hDC);
|
||||
|
||||
DestroyWindow(hWnd);
|
||||
|
||||
#ifdef _DEBUG
|
||||
_CrtMemDumpAllObjectsSince(&_ms);
|
||||
system("pause");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user