diff --git a/src/core.h b/src/core.h index 603f8c1..777ea9b 100644 --- a/src/core.h +++ b/src/core.h @@ -151,11 +151,11 @@ #define _OS_X360 1 // TODO #elif __NDLESS__ - #define _OS_TNS 1 - #define _GAPI_SW 1 - #include + #define _OS_TNS 1 + #define _GAPI_SW 1 + #include - #undef OS_PTHREAD_MT + #undef OS_PTHREAD_MT #endif #if !defined(_OS_PSP) && !defined(_OS_TNS) diff --git a/src/extension.h b/src/extension.h index d44dea3..b787842 100644 --- a/src/extension.h +++ b/src/extension.h @@ -12,35 +12,226 @@ namespace Extension { + const float MESH_SCALE = 1.0f / 256.0f; + #ifdef GEOMETRY_EXPORT - void exportTexture(const char *name, Texture *tex) { + void exportTexture(const char *dir, const char *name, Texture *tex) { char *data32 = new char[tex->width * tex->height * 4]; tex->bind(sDiffuse); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data32); - Texture::SaveBMP(name, data32, tex->width, tex->height); + char path[256]; + sprintf(path, "%s/%s", dir, name); + Texture::SaveBMP(path, data32, tex->width, tex->height); delete[] data32; } - void exportModel(IGame *game, TR::Model &model) { + void exportRooms(IGame *game, const char *dir) { TR::Level *level = game->getLevel(); MeshBuilder *mesh = game->getMesh(); + typedef uint32 MeshIndex; + + struct MeshVertex { + vec3 coord; + vec3 normal; + vec2 texCoord; + ubyte4 color; + }; + + char name[256]; + sprintf(name, "%s/rooms.glb", dir); + + LOG("export rooms: %s\n", name); + + FILE *file = fopen(name, "wb"); + if (!file) { + LOG("dump: can't dump rooms to file \"%s\"!\n", name); + return; + } + + Index *indices = new Index[1024 * 1024]; + Vertex *vertices = new Vertex[1024 * 1024]; + + mat4 flip = mat4( + -1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ); + mat4 flipInv = flip.inverseOrtho(); + + struct RoomParams { + int iStart; + int vStart; + int iCount; + int vCount; + } roomParams[1024]; + + int iCount = 0, vCount = 0; + + // get geometry data + for (int roomIndex = 0; roomIndex < level->roomsCount; roomIndex++) { + RoomParams ¶ms = roomParams[roomIndex]; + params.iStart = iCount; + params.vStart = vCount; + + MeshBuilder::Geometry geom; + + for (int transp = 0; transp < 3; transp++) { + int blendMask = mesh->getBlendMask(transp); + + TR::Room &room = level->rooms[roomIndex]; + + // room geometry + mesh->buildRoom(geom, NULL, blendMask, room, level, indices, vertices, iCount, vCount, params.vStart); + + // static meshes + for (int j = 0; j < room.meshesCount; j++) { + TR::Room::Mesh &m = room.meshes[j]; + TR::StaticMesh *s = &level->staticMeshes[m.meshIndex]; + if (!level->meshOffsets[s->mesh]) continue; + TR::Mesh &staticMesh = level->meshes[level->meshOffsets[s->mesh]]; + + int x = m.x - room.info.x; + int y = m.y; + int z = m.z - room.info.z; + int d = m.rotation.value / 0x4000; + mesh->buildMesh(geom, blendMask, staticMesh, level, indices, vertices, iCount, vCount, params.vStart, 0, x, y, z, d, m.color, true, false); + } + } + + params.iCount = iCount - params.iStart; + params.vCount = vCount - params.vStart; + } + + for (int i = 0; i < iCount; i += 3) { // CCW -> CW + swap(indices[i], indices[i + 2]); + } + + // get model geometry + int verticesOffset = 0; + int indicesOffset = verticesOffset + vCount * sizeof(MeshVertex); + int bufferSize = indicesOffset + iCount * sizeof(MeshIndex); + + char *bufferData = new char[bufferSize]; + + MeshVertex *gVertices = (MeshVertex*)(bufferData + verticesOffset); + for (int i = 0; i < vCount; i++) { + Vertex &src = vertices[i]; + MeshVertex &dst = gVertices[i]; + + dst.coord = src.coord; + + dst.normal = src.normal; + dst.texCoord = src.texCoord; + dst.normal = dst.normal.normal(); + + dst.coord = flip * (dst.coord * MESH_SCALE); + dst.normal = flip * dst.normal; + + dst.texCoord *= (1.0f / 32767.0f); + dst.color = src.light; + } + + for (int i = 0; i < iCount; i++) { + MeshIndex &dst = ((MeshIndex*)(bufferData + indicesOffset))[i]; + dst = indices[i]; + } + + GLTF *gltf = new GLTF(); + + JSON *nodes; + gltf->addScene("Scene", &nodes); + + int accessorIndex = 0; + int nodeIndex = 0; + + for (int roomIndex = 0; roomIndex < level->roomsCount; roomIndex++) { + TR::Room &room = level->rooms[roomIndex]; + + RoomParams ¶ms = roomParams[roomIndex]; + if (params.iCount == 0) { + continue; + } + + sprintf(name, "%d_mesh", roomIndex); + gltf->addMesh(name, 0, accessorIndex + 0, accessorIndex + 1, accessorIndex + 2, accessorIndex + 3, accessorIndex + 4, -1, -1); + + sprintf(name, "%d", roomIndex); + gltf->addNode(name, nodeIndex, -1, vec3(float(-room.info.x), 0, float(room.info.z)) * MESH_SCALE, quat(0, 0, 0, 1)); + nodes->add(NULL, nodeIndex); // mesh + nodeIndex++; + + vec4 vMin(+INF), vMax(-INF); + + for (int i = params.vStart; i < params.vStart + params.vCount; i++) { + MeshVertex &v = gVertices[i]; + + vMin.x = min(vMin.x, v.coord.x); + vMin.y = min(vMin.y, v.coord.y); + vMin.z = min(vMin.z, v.coord.z); + + vMax.x = max(vMax.x, v.coord.x); + vMax.y = max(vMax.y, v.coord.y); + vMax.z = max(vMax.z, v.coord.z); + } + + gltf->addAccessor(0, sizeof(MeshIndex), params.iStart * sizeof(MeshIndex), params.iCount, GLTF::SCALAR, GL_UNSIGNED_INT); // 0 + gltf->addAccessor(1, sizeof(MeshVertex), params.vStart * sizeof(MeshVertex) + (int)OFFSETOF(MeshVertex, coord), params.vCount, GLTF::VEC3, GL_FLOAT, false, vMin, vMax); // 1 + gltf->addAccessor(1, sizeof(MeshVertex), params.vStart * sizeof(MeshVertex) + (int)OFFSETOF(MeshVertex, normal), params.vCount, GLTF::VEC3, GL_FLOAT); // 2 + gltf->addAccessor(1, sizeof(MeshVertex), params.vStart * sizeof(MeshVertex) + (int)OFFSETOF(MeshVertex, texCoord), params.vCount, GLTF::VEC2, GL_FLOAT); // 3 + gltf->addAccessor(1, sizeof(MeshVertex), params.vStart * sizeof(MeshVertex) + (int)OFFSETOF(MeshVertex, color), params.vCount, GLTF::VEC4, GL_UNSIGNED_BYTE, true); // 4 + + accessorIndex += 5; + } + + gltf->addSampler(GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT); + gltf->addImage("rooms.bmp"); + gltf->addTexture("texture", 0, 0); + gltf->addMaterial("material", 0, 0, 1.0f, 0.0f); + + delete[] vertices; + delete[] indices; + + gltf->addBufferView(0, 0, indicesOffset, sizeof(MeshIndex) * iCount); // 0 + gltf->addBufferView(0, sizeof(MeshVertex), verticesOffset, sizeof(MeshVertex) * vCount); // 1 + + gltf->addBuffer(bufferData, bufferSize); // 0 + + delete[] bufferData; + + char *buffer = new char[gltf->getBufferSize()]; + int size = gltf->save(buffer); + delete gltf; + + fwrite(buffer, 1, size, file); + + delete[] buffer; + + fclose(file); + } + + void exportModel(IGame *game, const char *dir, TR::Model &model) { + TR::Level *level = game->getLevel(); + MeshBuilder *mesh = game->getMesh(); + + typedef uint32 MeshIndex; + struct ModelVertex { vec3 coord; vec3 normal; vec2 texCoord; - ubyte4 color; ubyte4 joints; ubyte4 weights; }; - typedef uint32 ModelIndex; - char name[256]; - sprintf(name, "models/dump/%d.glb", int(model.type)); + sprintf(name, "%s/model_%d.glb", dir, int(model.type)); + + LOG("export model: %s\n", name); FILE *file = fopen(name, "wb"); if (!file) { @@ -61,6 +252,7 @@ namespace Extension { anim->setAnim(0); animRate = max((int)(anim->anims + anim->index)->frameRate, 1); animFrames = anim->framesCount / animRate; + ASSERT(animFrames > 0); } // get model geometry @@ -89,7 +281,7 @@ namespace Extension { int rotationOffset = translationOffset + animFrames * sizeof(vec3); int verticesOffset = rotationOffset + model.mCount * animFrames * sizeof(quat); int indicesOffset = verticesOffset + vCount * sizeof(ModelVertex); - int bufferSize = indicesOffset + iCount * sizeof(ModelIndex); + int bufferSize = indicesOffset + iCount * sizeof(MeshIndex); char *bufferData = new char[bufferSize]; @@ -113,11 +305,10 @@ namespace Extension { dst.texCoord = src.texCoord; dst.normal = dst.normal.normal(); - dst.coord = flip * dst.coord; + dst.coord = flip * (dst.coord * MESH_SCALE); dst.normal = flip * dst.normal; dst.texCoord *= (1.0f / 32767.0f); - dst.color = src.color; dst.joints = ubyte4(uint8(src.coord.w / 2), 0, 0, 0); dst.weights = ubyte4(255, 0, 0, 0); @@ -131,29 +322,28 @@ namespace Extension { } for (int i = 0; i < iCount; i++) { - ModelIndex &dst = ((ModelIndex*)(bufferData + indicesOffset))[i]; + MeshIndex &dst = ((MeshIndex*)(bufferData + indicesOffset))[i]; dst = indices[i]; } GLTF *gltf = new GLTF(); gltf->addSampler(GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT); - gltf->addImage("objects.bmp"); + gltf->addImage("models.bmp"); gltf->addTexture("texture", 0, 0); gltf->addMaterial("material", 0, 0, 1.0f, 0.0f); delete[] vertices; delete[] indices; - gltf->addAccessor(0, 0, iCount, GLTF::SCALAR, GL_UNSIGNED_INT); // 0 - gltf->addAccessor(1, (int)OFFSETOF(ModelVertex, coord), vCount, GLTF::VEC3, GL_FLOAT, false, vMin, vMax); // 1 - gltf->addAccessor(1, (int)OFFSETOF(ModelVertex, normal), vCount, GLTF::VEC3, GL_FLOAT); // 2 - gltf->addAccessor(1, (int)OFFSETOF(ModelVertex, texCoord), vCount, GLTF::VEC2, GL_FLOAT); // 3 - //gltf->addAccessor(1, (int)OFFSETOF(ModelVertex, color), vCount, GLTF::VEC4, GL_UNSIGNED_BYTE); // TODO - gltf->addAccessor(1, (int)OFFSETOF(ModelVertex, joints), vCount, GLTF::VEC4, GL_UNSIGNED_BYTE); // 4 - gltf->addAccessor(1, (int)OFFSETOF(ModelVertex, weights), vCount, GLTF::VEC4, GL_UNSIGNED_BYTE, true); // 5 + gltf->addAccessor(0, sizeof(MeshIndex), 0, iCount, GLTF::SCALAR, GL_UNSIGNED_INT); // 0 + gltf->addAccessor(1, sizeof(ModelVertex), (int)OFFSETOF(ModelVertex, coord), vCount, GLTF::VEC3, GL_FLOAT, false, vMin, vMax); // 1 + gltf->addAccessor(1, sizeof(ModelVertex), (int)OFFSETOF(ModelVertex, normal), vCount, GLTF::VEC3, GL_FLOAT); // 2 + gltf->addAccessor(1, sizeof(ModelVertex), (int)OFFSETOF(ModelVertex, texCoord), vCount, GLTF::VEC2, GL_FLOAT); // 3 + gltf->addAccessor(1, sizeof(ModelVertex), (int)OFFSETOF(ModelVertex, joints), vCount, GLTF::VEC4, GL_UNSIGNED_BYTE); // 4 + gltf->addAccessor(1, sizeof(ModelVertex), (int)OFFSETOF(ModelVertex, weights), vCount, GLTF::VEC4, GL_UNSIGNED_BYTE, true); // 5 - gltf->addBufferView(0, 0, indicesOffset, sizeof(ModelIndex) * iCount); // 0 + gltf->addBufferView(0, 0, indicesOffset, sizeof(MeshIndex) * iCount); // 0 gltf->addBufferView(0, sizeof(ModelVertex), verticesOffset, sizeof(ModelVertex) * vCount); // 1 sprintf(name, "%d_mesh", int(model.type)); @@ -182,13 +372,13 @@ namespace Extension { timeline[i] = i * animRate / 30.0f; } gltf->addBufferView(0, 0, timelineOffset, animFrames * sizeof(float)); // 2 - gltf->addAccessor(2, 0, animFrames, GLTF::SCALAR, GL_FLOAT, false, vec4(timeline[0], 0, 0, 0), vec4(timeline[animFrames - 1], 0, 0, 1)); // 6 + gltf->addAccessor(2, 0, 0, animFrames, GLTF::SCALAR, GL_FLOAT, false, vec4(timeline[0], 0, 0, 0), vec4(timeline[animFrames - 1], 0, 0, 1)); // 6 } { // root translation (output) vec3 *translation = (vec3*)(bufferData + translationOffset); gltf->addBufferView(0, 0, translationOffset, animFrames * sizeof(vec3)); // 3 - gltf->addAccessor(3, 0, animFrames, GLTF::VEC3, GL_FLOAT); // 7+ + gltf->addAccessor(3, 0, 0, animFrames, GLTF::VEC3, GL_FLOAT); // 7+ JSON *sampler = samplers->add(JSON::OBJECT); // 0 sampler->add("input", 6); // timeline @@ -203,8 +393,7 @@ namespace Extension { for (int j = 0; j < animFrames; j++) { TR::AnimFrame *frame = anim->getFrame(anim->anims + anim->index, j); - translation[j] = frame->pos; - translation[j] = flip * translation[j]; + translation[j] = flip * (vec3((float)frame->pos.x, (float)frame->pos.y, (float)frame->pos.z) * MESH_SCALE); } } @@ -227,7 +416,7 @@ namespace Extension { *ptr = matrix.getRot(); ptr++; } - gltf->addAccessor(4, i * animFrames * sizeof(quat), animFrames, GLTF::VEC4, GL_FLOAT); // 8+ + gltf->addAccessor(4, 0, i * animFrames * sizeof(quat), animFrames, GLTF::VEC4, GL_FLOAT); // 8+ JSON *sampler = samplers->add(JSON::OBJECT); // 1+ sampler->add("input", 6); // timeline @@ -271,7 +460,7 @@ namespace Extension { for (int i = 0; i < model.mCount; i++) { sprintf(name, "joint_%d", i + 1); - JSON* node = gltf->addNode(name, -1, -1, jointPos, quat(0, 0, 0, 1)); + JSON* node = gltf->addNode(name, -1, -1, jointPos * MESH_SCALE, quat(0, 0, 0, 1)); JSON* children = new JSON(JSON::ARRAY, "children"); for (int j = 0; j < model.mCount; j++) { @@ -287,13 +476,13 @@ namespace Extension { } joints[i] = i + 1; + TR::Node &t = *((TR::Node*)&level->nodesData[model.node] + i); jointPos = flip * vec3((float)t.x, (float)t.y, (float)t.z); } gltf->addSkin("skin", -1, 1, joints, model.mCount); - char *buffer = new char[gltf->getBufferSize()]; int size = gltf->save(buffer); delete gltf; @@ -302,24 +491,27 @@ namespace Extension { delete[] buffer; - LOG("export model: %s\n", name); - fclose(file); } void exportGeometry(IGame *game, Texture *atlasRooms, Texture *atlasObjects, Texture *atlasSprites) { - CreateDirectory("models", NULL); - CreateDirectory("models/dump/", NULL); - exportTexture("models/dump/rooms", atlasRooms); - exportTexture("models/dump/objects", atlasObjects); - exportTexture("models/dump/sprites", atlasSprites); + char dir[256]; + sprintf(dir, "dump/%s", TR::LEVEL_INFO[game->getLevel()->id].name); + + CreateDirectory("dump", NULL); + CreateDirectory(dir, NULL); + + exportTexture(dir, "rooms", atlasRooms); + exportTexture(dir, "models", atlasObjects); TR::Level *level = game->getLevel(); MeshBuilder *mesh = game->getMesh(); + exportRooms(game, dir); + for (int i = 0; i < level->modelsCount; i++) { - exportModel(game, level->models[i]); + exportModel(game, dir, level->models[i]); } } #endif diff --git a/src/gapi/gl.h b/src/gapi/gl.h index 8baf60f..64e635d 100644 --- a/src/gapi/gl.h +++ b/src/gapi/gl.h @@ -67,61 +67,61 @@ #include #if defined(_GAPI_GLES) // Default in SDL2 is GLES3. If we want GLES2, pass -D_GAPI_GLES2. - #if defined (_GAPI_GLES2) // We want GLES2 on SDL2 - #include - #include + #if defined (_GAPI_GLES2) // We want GLES2 on SDL2 + #include + #include - #define GL_CLAMP_TO_BORDER 0x812D - #define GL_TEXTURE_BORDER_COLOR 0x1004 + #define GL_CLAMP_TO_BORDER 0x812D + #define GL_TEXTURE_BORDER_COLOR 0x1004 - #define GL_TEXTURE_COMPARE_MODE 0x884C - #define GL_TEXTURE_COMPARE_FUNC 0x884D - #define GL_COMPARE_REF_TO_TEXTURE 0x884E + #define GL_TEXTURE_COMPARE_MODE 0x884C + #define GL_TEXTURE_COMPARE_FUNC 0x884D + #define GL_COMPARE_REF_TO_TEXTURE 0x884E - #undef GL_RG - #undef GL_RG32F - #undef GL_RG16F - #undef GL_RGBA32F - #undef GL_RGBA16F - #undef GL_HALF_FLOAT + #undef GL_RG + #undef GL_RG32F + #undef GL_RG16F + #undef GL_RGBA32F + #undef GL_RGBA16F + #undef GL_HALF_FLOAT - #define GL_RG GL_RGBA - #define GL_RGBA32F GL_RGBA - #define GL_RGBA16F GL_RGBA - #define GL_RG32F GL_RGBA - #define GL_RG16F GL_RGBA - #define GL_HALF_FLOAT GL_HALF_FLOAT_OES + #define GL_RG GL_RGBA + #define GL_RGBA32F GL_RGBA + #define GL_RGBA16F GL_RGBA + #define GL_RG32F GL_RGBA + #define GL_RG16F GL_RGBA + #define GL_HALF_FLOAT GL_HALF_FLOAT_OES - #define GL_TEXTURE_WRAP_R 0 - #define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES - #define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES - //We need this on GLES2, too. - #define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE + #define GL_TEXTURE_WRAP_R 0 + #define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES + #define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES + //We need this on GLES2, too. + #define GL_TEXTURE_MAX_LEVEL GL_TEXTURE_MAX_LEVEL_APPLE - #define glTexImage3D(...) 0 - #ifndef GL_TEXTURE_3D // WUUUUUT!? - #define GL_TEXTURE_3D GL_TEXTURE_3D_OES - #endif + #define glTexImage3D(...) 0 + #ifndef GL_TEXTURE_3D // WUUUUUT!? + #define GL_TEXTURE_3D GL_TEXTURE_3D_OES + #endif - #define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES + #define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES #else // We want GLES3 on SDL2 - #include - #include - #include + #include + #include + #include #endif //GAPI_GLES2 - // These are needed for both GLES2 and GLES3 on SDL2 - #define glGenVertexArrays(...) - #define glDeleteVertexArrays(...) - #define glBindVertexArray(...) - #define glGetProgramBinary(...) - #define glProgramBinary(...) + // These are needed for both GLES2 and GLES3 on SDL2 + #define glGenVertexArrays(...) + #define glDeleteVertexArrays(...) + #define glBindVertexArray(...) + #define glGetProgramBinary(...) + #define glProgramBinary(...) - #define PFNGLGENVERTEXARRAYSPROC PFNGLGENVERTEXARRAYSOESPROC - #define PFNGLDELETEVERTEXARRAYSPROC PFNGLDELETEVERTEXARRAYSOESPROC - #define PFNGLBINDVERTEXARRAYPROC PFNGLBINDVERTEXARRAYOESPROC - #define PFNGLGETPROGRAMBINARYPROC PFNGLGETPROGRAMBINARYOESPROC - #define PFNGLPROGRAMBINARYPROC PFNGLPROGRAMBINARYOESPROC + #define PFNGLGENVERTEXARRAYSPROC PFNGLGENVERTEXARRAYSOESPROC + #define PFNGLDELETEVERTEXARRAYSPROC PFNGLDELETEVERTEXARRAYSOESPROC + #define PFNGLBINDVERTEXARRAYPROC PFNGLBINDVERTEXARRAYOESPROC + #define PFNGLGETPROGRAMBINARYPROC PFNGLGETPROGRAMBINARYOESPROC + #define PFNGLPROGRAMBINARYPROC PFNGLPROGRAMBINARYOESPROC #else // We want OpenGL on SDL2, not GLES #include diff --git a/src/gltf.h b/src/gltf.h index 6430cca..b5e7c8e 100644 --- a/src/gltf.h +++ b/src/gltf.h @@ -26,9 +26,9 @@ struct GLTF { JSON *textures; JSON *materials; JSON *nodes; + JSON *scenes; JSON *skins; JSON *animations; - JSON *scenes; char *binaryData; int binarySize; @@ -46,9 +46,9 @@ struct GLTF { accessors = root->add(JSON::ARRAY, "accessors"); meshes = root->add(JSON::ARRAY, "meshes"); nodes = root->add(JSON::ARRAY, "nodes"); - skins = root->add(JSON::ARRAY, "skins"); - animations = root->add(JSON::ARRAY, "animations"); scenes = root->add(JSON::ARRAY, "scenes"); + skins = NULL;//root->add(JSON::ARRAY, "skins"); + animations = NULL;//root->add(JSON::ARRAY, "animations"); asset->add("generator", "OpenLara"); asset->add("version", "2.0"); @@ -120,13 +120,17 @@ struct GLTF { return header->length; } - JSON* addAccessor(int bufferView, int byteOffset, int count, AccessorType type, int format, bool normalized = false, const vec4 &vMin = vec4(0.0f), const vec4 &vMax = vec4(0.0f)) { + JSON* addAccessor(int bufferView, int byteStride, int byteOffset, int count, AccessorType type, int format, bool normalized = false, const vec4 &vMin = vec4(0.0f), const vec4 &vMax = vec4(0.0f)) { static const char *AccessorTypeName[ACCESSOR_TYPE_MAX] = { ACCESSOR_TYPES(DECL_STR) }; JSON *item = accessors->add(JSON::OBJECT); item->add("bufferView", bufferView); + if (byteStride) { + //item->add("byteStride", byteStride); + } + if (byteOffset) { item->add("byteOffset", byteOffset); } @@ -280,6 +284,10 @@ struct GLTF { } JSON *addSkin(const char *name, int inverseBindMatrices, int skeleton, int *joints, int jointsCount) { + if (!skins) { + skins = root->add(JSON::ARRAY, "skins"); + } + JSON *item = skins->add(JSON::OBJECT); if (name) { @@ -301,6 +309,9 @@ struct GLTF { } JSON* addAnimation(const char *name, JSON **samplers, JSON **channels) { + if (!animations) { + animations = root->add(JSON::ARRAY, "animations"); + } JSON *item = animations->add(JSON::OBJECT); if (name) item->add("name", name); diff --git a/src/lang.h b/src/lang.h index 2c0738e..b57c9fc 100644 --- a/src/lang.h +++ b/src/lang.h @@ -273,7 +273,7 @@ enum StringID { , "Suomi" \ , "{Cesky" \ , "\x11\x02\x8A\x02\x6C\x01\x54\x03\x02\xFF\xFF" \ - , "Magyar" + , "Magyar" #define LANG_PREFIXES "_EN", "_FR", "_DE", "_ES", "_IT", "_PL", "_PT", "_RU", "_JA", "_GR", "_FI", "_CZ", "_CN", "_HU" @@ -341,7 +341,7 @@ void ensureLanguage(int lang) { ASSERT(COUNT(STR_CZ) == STR_MAX); ASSERT(COUNT(STR_CN) == STR_MAX); ASSERT(COUNT(STR_HU) == STR_MAX); - + lang += STR_LANG_EN; switch (lang) { diff --git a/src/mesh.h b/src/mesh.h index cf6e17e..20d7edf 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -348,8 +348,8 @@ struct MeshBuilder { Geometry &geom = range.geometry[transp]; - // rooms geometry - buildRoom(geom, range.dynamic[transp], blendMask, room, level, indices, vertices, iCount, vCount, vStartRoom); + // room geometry + buildRoom(geom, range.dynamic + transp, blendMask, room, level, indices, vertices, iCount, vCount, vStartRoom); // static meshes for (int j = 0; j < room.meshesCount; j++) { @@ -1004,11 +1004,13 @@ struct MeshBuilder { return 1 << texAttribute; } - void buildRoom(Geometry &geom, Dynamic &dyn, int blendMask, const TR::Room &room, TR::Level *level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart) { + void buildRoom(Geometry &geom, Dynamic *dyn, int blendMask, const TR::Room &room, TR::Level *level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart) { const TR::Room::Data &d = room.data; - dyn.count = 0; - dyn.faces = NULL; + if (dyn) { + dyn->count = 0; + dyn->faces = NULL; + } for (int j = 0; j < d.fCount; j++) { TR::Face &f = d.faces[j]; @@ -1023,9 +1025,9 @@ struct MeshBuilder { if (!(blendMask & getBlendMask(t.attribute))) continue; - if (t.animated) { - ASSERT(dyn.count < 0xFFFF); - dyn.count++; + if (dyn && t.animated) { + ASSERT(dyn->count < 0xFFFF); + dyn->count++; continue; } @@ -1036,9 +1038,9 @@ struct MeshBuilder { } // if room has non-static polygons, fill the list of dynamic faces - if (dyn.count) { - dyn.faces = new uint16[dyn.count]; - dyn.count = 0; + if (dyn && dyn->count) { + dyn->faces = new uint16[dyn->count]; + dyn->count = 0; for (int j = 0; j < d.fCount; j++) { TR::Face &f = d.faces[j]; TR::TextureInfo &t = level->objectTextures[f.flags.texture]; @@ -1049,7 +1051,7 @@ struct MeshBuilder { continue; if (t.animated) - dyn.faces[dyn.count++] = j; + dyn->faces[dyn->count++] = j; } } }