diff --git a/src/engine/include/loaders/md2_loader.hpp b/src/engine/include/loaders/md2_loader.hpp index d84bbc4..6044e92 100644 --- a/src/engine/include/loaders/md2_loader.hpp +++ b/src/engine/include/loaders/md2_loader.hpp @@ -83,8 +83,7 @@ public: MD2Loader(); ~MD2Loader(); - /** Returns frames count */ - u32 load(MeshFrame *o_result, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT); + MeshFrame *load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT); private: }; diff --git a/src/engine/include/models/anim_state.hpp b/src/engine/include/models/anim_state.hpp index 0c208be..c0da8b0 100644 --- a/src/engine/include/models/anim_state.hpp +++ b/src/engine/include/models/anim_state.hpp @@ -18,6 +18,8 @@ typedef struct { u32 startFrame; u32 endFrame; + u32 stayFrame; + u8 isStayFrameSet; float speed; float interpolation; u32 animType; diff --git a/src/engine/include/models/mesh.hpp b/src/engine/include/models/mesh.hpp index 720347a..af9e876 100644 --- a/src/engine/include/models/mesh.hpp +++ b/src/engine/include/models/mesh.hpp @@ -26,41 +26,17 @@ class Mesh { public: - Vector3 position, rotation; - u8 shouldBeLighted, shouldBeBackfaceCulled, shouldBeFrustumCulled; - - float scale; - color_t color; - Mesh(); ~Mesh(); - void loadObj(char *t_subfolder, char *t_objFile, Vector3 &t_initPos, float t_scale, u16 t_framesCount, u8 t_invertT); - // void setObj(Vector3 &t_initPos); // TODO - void loadDff(char *t_subfolder, char *t_dffFile, Vector3 &t_initPos, float t_scale, u8 t_invertT); - // void setDff(Vector3 &t_initPos, DffModel *t_dffModel); - void loadMD2(char *t_subfolder, char *t_md2File, Vector3 &t_initPos, float t_scale, u8 t_invertT); - void getMinMax(Vector3 *t_min, Vector3 *t_max); - void playAnimation(u32 t_startFrame, u32 t_endFrame); - u32 getVertexCount(); - void setAnimSpeed(float t_value); - u8 isInFrustum(Plane *t_frustumPlanes); + Vector3 position, rotation; + float scale; + u8 shouldBeLighted, shouldBeBackfaceCulled, shouldBeFrustumCulled; + color_t color; - u8 isMd2Loaded, isObjLoaded, isSpecInitialized; - clutbuffer_t clut; - lod_t lod; - u32 id; - MeshTexture *textures; - - // NOWE TODO - - u16 framesCount; - MeshFrame *frames; - AnimState animState; - void animate(); - u32 getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos); - u32 getFacesCount(); - u8 isMemoryAllocated; + // ---- + // Getters + // ---- /** Array of materials. Size of getMaterialsCount() */ MeshMaterial *getMaterials() const { return frames[0].getMaterials(); }; @@ -76,15 +52,116 @@ public: */ MeshMaterial *getMaterialById(const u32 &t_id) const { return frames[0].getMaterialById(t_id); } + /** Returns bounding box vertex at given index with added mesh position. + * @param o_result Result + * @param offset 0-7. Because, bounding box have 8 corners + */ + void getCurrentBoundingBoxVertex(Vector3 &o_result, const u32 &t_index); + + // ---- + // Setters + // ---- + + // ---- + // Other + // ---- + + /** + * Load mesh data from .obj files. Animation not supported. + * Be aware that texture names will be grabbed from material name. + * So no .mtl file is needed. Please check if material names in .obj file + * are equal to texture file names. + * @param t_subfolder Relative path. Example "meshes/blocks" + * @param t_objFile File name without extension. Example "sand" + * @param t_scale Scale. For 1:1, type 1.0F + * @param t_framesCount Amount of frames. + * Example: 2. + * Searched files: sand_000001.obj, sand_000002.obj + * @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true. + * Converts Y coordinate texture from Y to 1.0F - Y + */ + void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT); + + /** + * Load mesh data from .obj file. Animation supported. + * Be aware that texture names will be grabbed from material name. + * So no .mtl file is needed. Please check if material names in .obj file + * are equal to texture file names. + * @param t_subfolder Relative path. Example "meshes/blocks" + * @param t_objFile File name without extension. Example "sand" + * @param t_scale Scale. For 1:1, type 1.0F + * @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true. + * Converts Y coordinate texture from Y to 1.0F - Y + */ + void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u8 &t_invertT); + + /** + * Load mesh data from RenderWare .dff file. Animation not supported + * @param t_subfolder Relative path. Example "meshes/blocks" + * @param t_objFile File name without extension. Example "sand" + * @param t_scale Scale. For 1:1, type 1.0F + * @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true. + * Converts Y coordinate texture from Y to 1.0F - Y + */ + void loadDff(char *t_subfolder, char *t_dffFile, const float &t_scale, const u8 &t_invertT); + + /** + * Load mesh data from Quake II .md2 file. Animation supported. + * @param t_subfolder Relative path. Example "meshes/blocks" + * @param t_objFile File name without extension. Example "sand" + * @param t_scale Scale. For 1:1, type 1.0F + * @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true. + * Converts Y coordinate texture from Y to 1.0F - Y + */ + void loadMD2(char *t_subfolder, char *t_md2File, const float &t_scale, const u8 &t_invertT); + + /** Copy by reference mesh data from other mesh */ + void loadFrom(const Mesh &t_mesh); + + /** Check if are there any frames */ + u8 isDataLoaded() const { return framesCount > 0; }; + + /** Loop in one frame */ + void playAnimation(const u32 &t_frame) { playAnimation(t_frame, t_frame); } + + /** Play animation in loop from startFrame to endFrame */ + void playAnimation(const u32 &t_startFrame, const u32 &t_endFrame); + + /** Play animation from startFrame to endFrame and after loop in stayFrame */ + void playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame); + + /** + * Check if this class loaded mesh data first. + * Meshes which use loadFrom() method have false there. + */ + const u8 &isMother() const { return _isMother; }; + + // TODO + + // void getMinMax(Vector3 *t_min, Vector3 *t_max); + u32 getVertexCount(); + void setAnimSpeed(float t_value); + u8 isInFrustum(Plane *t_frustumPlanes); + + clutbuffer_t clut; + lod_t lod; + u32 id; + + // NOWE TODO + + u32 framesCount; + MeshFrame *frames; + AnimState animState; + void animate(); + u32 getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos); + u32 getFacesCount(); + u8 isMemoryAllocated; + private: + u8 _isMother; Vector3 calc3Vectors[3]; void setupLodAndClut(); - void setDefaultWrapSettings(texwrap_t &t_wrapSettings); - u32 verticesCount; - Vector3 *vertices; - void setVerticesReference(u32 t_verticesCount, Vector3 *t_verticesRef); void setDefaultColor(); - void getFarthestVertex(Vector3 *o_result, int t_offset); }; #endif diff --git a/src/engine/loaders/dff_loader.cpp b/src/engine/loaders/dff_loader.cpp index 7aa9aa0..d57c62c 100644 --- a/src/engine/loaders/dff_loader.cpp +++ b/src/engine/loaders/dff_loader.cpp @@ -54,11 +54,11 @@ void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_ PRINT_LOG("Dff file loaded!"); } -void DffLoader::convert(MeshFrame *frames, RwClump &t_clump, u8 t_invertT) +void DffLoader::convert(MeshFrame *o_result, RwClump &t_clump, u8 t_invertT) { #define GEOMETRY t_clump.geometryList.geometries[0] - MeshFrame *frame = &frames[0]; + MeshFrame *frame = &o_result[0]; u32 vertNormalStCount = GEOMETRY.data.dataHeader.vertexCount; frame->allocateVertices(vertNormalStCount); frame->allocateNormals(vertNormalStCount); // can be optimized @@ -103,6 +103,8 @@ void DffLoader::convert(MeshFrame *frames, RwClump &t_clump, u8 t_invertT) frame->getMaterial(i).setSTFace(j, CURR_SPLIT.vertexInformation[j].vertex1); } } + + frame->calculateBoundingBox(); } void DffLoader::serialize(RwClump &t_clump, u8 *t_data, float t_scale) diff --git a/src/engine/loaders/md2_loader.cpp b/src/engine/loaders/md2_loader.cpp index f6db0d6..5fc260f 100644 --- a/src/engine/loaders/md2_loader.cpp +++ b/src/engine/loaders/md2_loader.cpp @@ -16,7 +16,6 @@ #include "../include/models/math/vector3.hpp" #include "../include/models/math/point.hpp" #include -#include // ---- // Constructors/Destructors @@ -30,25 +29,33 @@ MD2Loader::~MD2Loader() {} // Methods // ---- -/** Load, parse .obj file and load data into given MeshSpec */ -u32 MD2Loader::load(MeshFrame *o_result, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT) +int MEM_fread(char *buf, size_t size, size_t n, const FILE *f) +{ + memcpy(buf, f, size * n); + f += size * n; + return n; +} + +/** + * Sandro: Possible PS2SDK bug here? + * When I wanted to fopen() -> fread() -> allocate frames memory (vertices etc) -> fclose() = I had in about 10x errors in console + * When I did fopen() -> fread() -> fclose() -> allocate frames memory = I had no errors 🤨 + * It looks like memory allocation during fopen()-fread()-fclose() is broken. + */ +MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT) { PRINT_LOG("Loading new MD2 file"); char *part1 = String::createConcatenated(t_subpath, t_nameWithoutExtension); char *finalPath = String::createConcatenated(part1, ".md2"); // "folder/object.md2" delete[] part1; - - PRINT_LOG("Loading new MD2 file"); - md2_t header; // md2 header - - char *buffer; // buffer storing frame data + md2_t header; FILE *file = fopen(finalPath, "rb"); if (file == NULL) { PRINT_ERR("Failed to load .md2 file!"); - return 0; + return NULL; } fread((char *)&header, sizeof(md2_t), 1, file); @@ -56,7 +63,7 @@ u32 MD2Loader::load(MeshFrame *o_result, char *t_subpath, char *t_nameWithoutExt if ((header.ident != MD2_IDENT) && (header.version != MD2_VERSION)) { PRINT_ERR("This MD2 file was not in correct format!"); - return 0; + return NULL; } u32 framesCount = header.num_frames; @@ -64,87 +71,82 @@ u32 MD2Loader::load(MeshFrame *o_result, char *t_subpath, char *t_nameWithoutExt u32 stsCount = header.num_st; u32 trianglesCount = header.num_tris; - // o_result = new MeshFrame[framesCount]; - - buffer = new char[framesCount * header.framesize]; + char framesBuffer[framesCount * header.framesize]; fseek(file, header.ofs_frames, SEEK_SET); - fread((char *)buffer, framesCount * header.framesize, 1, file); + fread(&framesBuffer, framesCount * header.framesize, 1, file); - frame_t *frame; // temporary vars + char stsBuffer[stsCount * sizeof(texCoord_t)]; + fseek(file, header.ofs_st, SEEK_SET); + fread(&stsBuffer, stsCount * sizeof(texCoord_t), 1, file); + + char trianglesBuffer[trianglesCount * sizeof(triangle_t)]; + fseek(file, header.ofs_tris, SEEK_SET); + fread(&trianglesBuffer, trianglesCount * sizeof(triangle_t), 1, file); + + fclose(file); + + MeshFrame *resultFrames = new MeshFrame[26]; + + frame_t *frame; Vector3 tempVec = Vector3(); - for (u32 j = 0; j < framesCount; j++) { - o_result[j].allocateVertices(vertexCount); - o_result[j].allocateNormals(vertexCount); // can be optimized - o_result[j].allocateSTs(stsCount); - o_result[j].allocateMaterials(1); - printf("Materials count:%d\n", o_result[j].getMaterialsCount()); - o_result[j].getMaterial(0).allocateFaces(trianglesCount * 3); - o_result[j].getMaterial(0).setName(t_nameWithoutExtension); - - frame = (frame_t *)&buffer[header.framesize * j]; - + resultFrames[j].allocateVertices(vertexCount); + resultFrames[j].allocateNormals(vertexCount); // can be optimized + resultFrames[j].allocateSTs(stsCount); + resultFrames[j].allocateMaterials(1); + resultFrames[j].getMaterial(0).allocateFaces(trianglesCount * 3); + resultFrames[j].getMaterial(0).setName(t_nameWithoutExtension); + frame = (frame_t *)&framesBuffer[header.framesize * j]; for (u32 i = 0; i < vertexCount; i++) { tempVec.set( ((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) * t_scale, ((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) * t_scale, ((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) * t_scale); - o_result[j].setVertex(i, tempVec); + resultFrames[j].setVertex(i, tempVec); tempVec.set( ANORMS[frame->verts[i].lightnormalindex][0], ANORMS[frame->verts[i].lightnormalindex][1], ANORMS[frame->verts[i].lightnormalindex][2]); - o_result[j].setNormal(i, tempVec); + resultFrames[j].setNormal(i, tempVec); } } - delete[] buffer; - - buffer = new char[stsCount * sizeof(texCoord_t)]; - fseek(file, header.ofs_st, SEEK_SET); - fread((char *)buffer, stsCount * sizeof(texCoord_t), 1, file); Point tempPoint = Point(); texCoord_t *texCoord; for (u32 i = 0; i < stsCount; i++) { - texCoord = (texCoord_t *)&buffer[sizeof(texCoord_t) * i]; + texCoord = (texCoord_t *)&stsBuffer[sizeof(texCoord_t) * i]; tempPoint.set( (float)texCoord->s / header.skinwidth, (float)texCoord->t / header.skinheight); if (t_invertT) tempPoint.y = 1.0F - tempPoint.y; for (u32 j = 0; j < framesCount; j++) - o_result[j].setST(i, tempPoint); + resultFrames[j].setST(i, tempPoint); } - delete[] buffer; - buffer = new char[trianglesCount * sizeof(triangle_t)]; - fseek(file, header.ofs_tris, SEEK_SET); - fread((char *)buffer, trianglesCount * sizeof(triangle_t), 1, file); - - triangle_t *triangle; // temporary var - // vertex array initialization + triangle_t *triangle; for (u32 i = 0; i < trianglesCount; i++) { - triangle = (triangle_t *)&buffer[sizeof(triangle_t) * i]; + triangle = (triangle_t *)&trianglesBuffer[sizeof(triangle_t) * i]; for (u8 j = 0; j < 3; j++) { for (u32 x = 0; x < framesCount; x++) { - o_result[x].getMaterial(0).setVertexFace((i * 3) + j, triangle->index_xyz[j]); - o_result[x].getMaterial(0).setSTFace((i * 3) + j, triangle->index_st[j]); - o_result[x].getMaterial(0).setNormalFace((i * 3) + j, triangle->index_xyz[j]); + resultFrames[x].getMaterial(0).setVertexFace((i * 3) + j, triangle->index_xyz[j]); + resultFrames[x].getMaterial(0).setSTFace((i * 3) + j, triangle->index_st[j]); + resultFrames[x].getMaterial(0).setNormalFace((i * 3) + j, triangle->index_xyz[j]); } } } - delete[] buffer; - fclose(file); PRINT_LOG("MD2 file loaded!"); - delete[] finalPath; - return framesCount; + o_framesCount = framesCount; + for (u32 i = 0; i < framesCount; i++) + resultFrames[i].calculateBoundingBox(); + return resultFrames; } diff --git a/src/engine/models/mesh.cpp b/src/engine/models/mesh.cpp index 9c493fc..e920e5d 100644 --- a/src/engine/models/mesh.cpp +++ b/src/engine/models/mesh.cpp @@ -27,9 +27,6 @@ Mesh::Mesh() shouldBeFrustumCulled = true; shouldBeBackfaceCulled = false; shouldBeLighted = false; - isMd2Loaded = false; - isObjLoaded = false; - isSpecInitialized = false; id = rand() % 1000000; scale = 1.0F; framesCount = 0; @@ -38,20 +35,128 @@ Mesh::Mesh() animState.interpolation = 0.0F; animState.animType = 0; animState.currentFrame = 0; + animState.stayFrame = 0; + animState.isStayFrameSet = false; animState.nextFrame = 0; animState.speed = 0.1F; - // filename = String::createWithoutExtension(t_objFile); + _isMother = false; + setDefaultColor(); } Mesh::~Mesh() { - // TODO + if (_isMother) + delete[] frames; } // ---- // Methods // ---- +void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u8 &t_invertT) +{ + ObjLoader loader = ObjLoader(); + framesCount = 1; + frames = new MeshFrame[framesCount]; + char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object" + char *finalPath = String::createConcatenated(part1, ".obj"); // "folder/object.obj" + loader.load(&frames[0], finalPath, t_scale, t_invertT); + delete[] part1; + delete[] finalPath; + _isMother = true; +} + +void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT) +{ + if (t_framesCount == 0) + PRINT_ERR("Frames count cannot be 0!"); + else if (t_framesCount == 1) + loadObj(t_subfolder, t_objFile, t_scale, t_invertT); + else + { + ObjLoader loader = ObjLoader(); + framesCount = t_framesCount; + frames = new MeshFrame[framesCount]; + char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object" + char *part2 = String::createConcatenated(part1, "_"); // "folder/object_" + for (u32 i = 0; i < framesCount; i++) + { + char *part3 = String::createU32ToString(i + 1); // 0 -> "1" + char *part4 = String::createWithLeadingZeros(part3); // "000001" + char *part5 = String::createConcatenated(part2, part4); // "folder/object_000001" + char *finalPath = String::createConcatenated(part5, ".obj"); // "folder/object_000001.obj" + loader.load(&frames[i], finalPath, t_scale, t_invertT); + delete[] part3; + delete[] part4; + delete[] part5; + delete[] finalPath; + } + delete[] part2; + delete[] part1; + _isMother = true; + } +} + +void Mesh::loadDff(char *t_subfolder, char *t_dffFile, const float &t_scale, const u8 &t_invertT) +{ + DffLoader loader = DffLoader(); + char *part1 = String::createConcatenated(t_subfolder, t_dffFile); + char *dffPath = String::createConcatenated(part1, ".dff"); + framesCount = 1; + frames = new MeshFrame[1]; + loader.load(frames, dffPath, t_scale, t_invertT); + delete[] part1; + delete[] dffPath; + _isMother = true; +} + +void Mesh::loadMD2(char *t_subfolder, char *t_md2File, const float &t_scale, const u8 &t_invertT) +{ + MD2Loader loader = MD2Loader(); + frames = loader.load(framesCount, t_subfolder, t_md2File, t_scale, t_invertT); + _isMother = true; +} + +void Mesh::loadFrom(const Mesh &t_mesh) +{ + frames = t_mesh.frames; + framesCount = t_mesh.framesCount; +} + +void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame) +{ + if (framesCount > 1) + { + if (t_endFrame >= framesCount) + PRINT_ERR("End frame value is too high. Valid range: (0, getFramesCount()-1)"); + animState.startFrame = t_startFrame; + animState.endFrame = t_endFrame; + animState.nextFrame = t_startFrame; + } + else if (framesCount == 0) + PRINT_ERR("Cant play animation, because no mesh data was loaded!"); + else if (framesCount == 1) + PRINT_ERR("Cant play animation, because this mesh have only one frame."); +} + +void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame) +{ + if (framesCount > 1) + { + if (t_endFrame >= framesCount) + PRINT_ERR("End frame value is too high. Valid range: (0, getFramesCount()-1)"); + animState.startFrame = t_startFrame; + animState.endFrame = t_endFrame; + animState.isStayFrameSet = true; + animState.stayFrame = t_stayFrame; + animState.nextFrame = t_startFrame; + } + else if (framesCount == 0) + PRINT_ERR("Cant play animation, because no mesh data was loaded!"); + else if (framesCount == 1) + PRINT_ERR("Cant play animation, because this mesh have only one frame."); +} + u32 Mesh::getFacesCount() { u32 result = 0; // TODO @@ -68,25 +173,32 @@ void Mesh::animate() animState.interpolation = 0.0F; animState.currentFrame = animState.nextFrame; if (++animState.nextFrame > animState.endFrame) - animState.nextFrame = animState.startFrame; + { + if (animState.isStayFrameSet) + { + animState.isStayFrameSet = false; + animState.nextFrame = animState.stayFrame; + animState.startFrame = animState.stayFrame; + animState.endFrame = animState.stayFrame; + } + else + animState.nextFrame = animState.startFrame; + } } } u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos) { - if (!frames) - PRINT_ERR("Can't draw, because no mesh data was loaded!"); #define CURR_FRAME frames[animState.currentFrame] #define NEXT_FRAME frames[animState.nextFrame] #define MATERIAL CURR_FRAME.getMaterial(t_materialIndex) #define CURR_VERT CURR_FRAME.getVertex(MATERIAL.getVertexFace(matI + vertI)) #define NEXT_VERT NEXT_FRAME.getVertex(MATERIAL.getVertexFace(matI + vertI)) u32 addedFaces = 0; - for (u32 matI = 0; matI < MATERIAL.getFacesCount(); matI += 3) { for (u32 vertI = 0; vertI < 3; vertI++) - if (animState.startFrame != animState.endFrame) + if (animState.currentFrame != animState.nextFrame) calc3Vectors[vertI].setByLerp(CURR_VERT, NEXT_VERT, animState.interpolation, scale); if (!shouldBeBackfaceCulled || @@ -95,7 +207,7 @@ u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals for (u32 vertI = 0; vertI < 3; vertI++) { - if (animState.startFrame == animState.endFrame) + if (animState.currentFrame == animState.nextFrame) { o_vertices[addedFaces][0] = CURR_FRAME.getVertex(MATERIAL.getVertexFace(matI + vertI)).x; o_vertices[addedFaces][1] = CURR_FRAME.getVertex(MATERIAL.getVertexFace(matI + vertI)).y; @@ -123,68 +235,11 @@ u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals return addedFaces; } -void Mesh::loadDff(char *t_subfolder, char *t_dffFile, Vector3 &t_initPos, float t_scale, u8 t_invertT) -{ - DffLoader loader = DffLoader(); - char *dffPath = String::createConcatenated(t_subfolder, t_dffFile); - framesCount = 1; - frames = new MeshFrame[1]; - loader.load(frames, dffPath, t_scale, t_invertT); - delete[] dffPath; - position = t_initPos; - setVerticesReference(getFacesCount(), frames[0].getVertices()); - setDefaultColor(); - isObjLoaded = true; -} - -void Mesh::loadObj(char *t_subfolder, char *t_objFile, Vector3 &t_initPos, float t_scale, u16 t_framesCount, u8 t_invertT) -{ - ObjLoader loader = ObjLoader(); - framesCount = t_framesCount; - frames = new MeshFrame[framesCount]; - char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object" - if (framesCount == 1) - { - char *finalPath = String::createConcatenated(part1, ".obj"); // "folder/object.obj" - loader.load(&frames[0], finalPath, t_scale, t_invertT); - delete[] finalPath; - } - else - { - char *part2 = String::createConcatenated(part1, "_"); // "folder/object_" - for (u16 i = 0; i < framesCount; i++) - { - char *part3 = String::createU32ToString(i + 1); // 0 -> "1" - char *part4 = String::createWithLeadingZeros(part3); // "000001" - char *part5 = String::createConcatenated(part2, part4); // "folder/object_000001" - char *finalPath = String::createConcatenated(part5, ".obj"); // "folder/object_000001.obj" - loader.load(&frames[i], finalPath, t_scale, t_invertT); - delete[] part3; - delete[] part4; - delete[] part5; - delete[] finalPath; - } - delete[] part2; - } - delete[] part1; - - position = t_initPos; - setVerticesReference(getFacesCount(), frames[0].getVertices()); - setDefaultColor(); - isObjLoaded = true; -} - void Mesh::setAnimSpeed(float t_value) { animState.speed = t_value; } -void Mesh::setVerticesReference(u32 t_verticesCount, Vector3 *t_verticesRef) -{ - verticesCount = t_verticesCount; - vertices = t_verticesRef; -} - u32 Mesh::getVertexCount() { if (framesCount > 0) @@ -196,30 +251,6 @@ u32 Mesh::getVertexCount() } } -void Mesh::setDefaultWrapSettings(texwrap_t &t_wrapSettings) -{ - // t_wrapSettings.horizontal = WRAP_REPEAT; - // t_wrapSettings.vertical = WRAP_REPEAT; - // t_wrapSettings.maxu = 0; - // t_wrapSettings.maxv = 0; - // t_wrapSettings.minu = 0; - // t_wrapSettings.minv = 0; -} - -/** Set object position and specification - * @param t_md2File without extension -*/ -void Mesh::loadMD2(char *t_subfolder, char *t_md2File, Vector3 &t_initPos, float t_scale, u8 t_invertT) -{ - MD2Loader loader = MD2Loader(); - frames = new MeshFrame[26]; - framesCount = loader.load(frames, t_subfolder, t_md2File, t_scale, t_invertT); - position = t_initPos; - setVerticesReference(getFacesCount(), frames[0].getVertices()); - setDefaultColor(); - isObjLoaded = true; -} - /** Set's default object color + no transparency */ void Mesh::setDefaultColor() { @@ -231,61 +262,43 @@ void Mesh::setDefaultColor() } /** Calculates minimum and maximum X, Y, Z of this 3D objects vertices + current position */ -void Mesh::getMinMax(Vector3 *t_min, Vector3 *t_max) +// void Mesh::getMinMax(Vector3 *t_min, Vector3 *t_max) +// { +// Vector3 calc = Vector3(); +// u8 isInitialized = 0; +// for (u32 i = 0; i < 8; i++) +// { +// getFarthestVertex(&calc, i); +// if (isInitialized == 0) +// { +// isInitialized = 1; +// t_min->set(calc); +// t_max->set(calc); +// } + +// if (t_min->x > calc.x) +// t_min->x = calc.x; +// if (calc.x > t_max->x) +// t_max->x = calc.x; + +// if (t_min->y > calc.y) +// t_min->y = calc.y; +// if (calc.y > t_max->y) +// t_max->y = calc.y; + +// if (t_min->z > calc.z) +// t_min->z = calc.z; +// if (calc.z > t_max->z) +// t_max->z = calc.z; +// } +// } + +void Mesh::getCurrentBoundingBoxVertex(Vector3 &o_result, const u32 &t_index) { - Vector3 calc = Vector3(); - u8 isInitialized = 0; - for (u32 i = 0; i < 8; i++) - { - getFarthestVertex(&calc, i); - if (isInitialized == 0) - { - isInitialized = 1; - t_min->set(calc); - t_max->set(calc); - } - - if (t_min->x > calc.x) - t_min->x = calc.x; - if (calc.x > t_max->x) - t_max->x = calc.x; - - if (t_min->y > calc.y) - t_min->y = calc.y; - if (calc.y > t_max->y) - t_max->y = calc.y; - - if (t_min->z > calc.z) - t_min->z = calc.z; - if (calc.z > t_max->z) - t_max->z = calc.z; - } -} - -void Mesh::playAnimation(u32 t_startFrame, u32 t_endFrame) -{ - if (framesCount > 1) - { - if (t_endFrame >= framesCount) - PRINT_ERR("End frame value is too high. Valid range: (0, getFramesCount()-1)"); - animState.startFrame = t_startFrame; - animState.endFrame = t_endFrame; - } - else if (framesCount == 0) - PRINT_ERR("Cant play animation, because no mesh data was loaded!"); - else if (framesCount == 1) - PRINT_ERR("Cant play animation, because this mesh have only one frame."); -} - -/** Returns next farthest vertex of 3D object - * @param offset Max 8 (because, box have 8 corners) - */ -void Mesh::getFarthestVertex(Vector3 *o_result, int t_offset) -{ - // TODO current frame - o_result->x = frames[animState.currentFrame].getBoundingBox(t_offset).x + position.x; - o_result->y = frames[animState.currentFrame].getBoundingBox(t_offset).y + position.y; - o_result->z = frames[animState.currentFrame].getBoundingBox(t_offset).z + position.z; + o_result.set( + frames[animState.currentFrame].getBoundingBox(t_index).x + position.x, + frames[animState.currentFrame].getBoundingBox(t_index).y + position.y, + frames[animState.currentFrame].getBoundingBox(t_index).z + position.z); } /** Sets texture level of details settings and CLUT settings */ @@ -322,7 +335,7 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes) // both inside and out of the frustum for (int y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) { - getFarthestVertex(&boxCalcTemp, y); + getCurrentBoundingBoxVertex(boxCalcTemp, y); if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0) boxOut++; else diff --git a/src/engine/models/mesh_frame.cpp b/src/engine/models/mesh_frame.cpp index 2d40d1c..62b280e 100644 --- a/src/engine/models/mesh_frame.cpp +++ b/src/engine/models/mesh_frame.cpp @@ -95,7 +95,7 @@ void MeshFrame::calculateBoundingBox() { if (!_areVerticesAllocated) { - PRINT_ERR("Can't calculate bounding box, because vertices was not allocated!"); + PRINT_ERR("Can't calculate bounding box, because vertices were not allocated!"); return; } float lowX, lowY, lowZ, hiX, hiY, hiZ; diff --git a/src/engine/modules/renderer.cpp b/src/engine/modules/renderer.cpp index cf5e2ff..16b92b1 100644 --- a/src/engine/modules/renderer.cpp +++ b/src/engine/modules/renderer.cpp @@ -206,27 +206,20 @@ void Renderer::draw(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount) { beginFrameIfNeeded(); // TODO VU1 send single list here - if (!t_mesh->isObjLoaded && !t_mesh->isMd2Loaded) - return; + if (!t_mesh->isDataLoaded()) + PRINT_ERR("Can't draw, because no mesh data was loaded!"); + u32 vertCount = t_mesh->getVertexCount(); VECTOR *vertices = new VECTOR[vertCount]; VECTOR *normals = new VECTOR[vertCount]; VECTOR *coordinates = new VECTOR[vertCount]; - if (t_mesh->isObjLoaded) + + if (t_mesh->animState.currentFrame != t_mesh->animState.nextFrame) + t_mesh->animate(); + for (u32 i = 0; i < t_mesh->getMaterialsCount(); i++) { - if (t_mesh->animState.startFrame != t_mesh->animState.endFrame) - t_mesh->animate(); - for (u32 i = 0; i < t_mesh->getMaterialsCount(); i++) - { - changeTexture(t_mesh, t_mesh->getMaterial(i).getId()); - vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition); - vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer); - } - } - else if (t_mesh->isMd2Loaded) - { - changeTexture(t_mesh, 0); - vertCount = t_mesh->getDrawData(0, vertices, normals, coordinates, *renderData.cameraPosition); + changeTexture(t_mesh, t_mesh->getMaterial(i).getId()); + vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition); vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer); } delete[] vertices; diff --git a/src/samples/ari/ari.cpp b/src/samples/ari/ari.cpp index c75316f..9e9eee1 100644 --- a/src/samples/ari/ari.cpp +++ b/src/samples/ari/ari.cpp @@ -79,53 +79,36 @@ void Ari::onInit() texRepo = engine.renderer->getTextureRepository(); // engine.audio.play(); - // Vector3 islandPos = Vector3(0.0F, 10.0F, 0.0F); - // island = new Mesh(); - // island->rotation.x = -1.6F; - // island->loadDff("sunnyisl/", "sunnyisl.dff", islandPos, 0.1F); - // texRepo->addByMesh("sunnyisl/", *island); - // island->shouldBeFrustumCulled = false; - // island->shouldBeBackfaceCulled = true; - - test = new Mesh(); - Vector3 initPos = Vector3(0.00F, 00.00F, 0.00F); - test->loadMD2("warrior/", "warrior", initPos, 0.2F, true); - texRepo->addByMesh("warrior/", *test); - test->rotation.x = -1.6F; - test->playAnimation(0, 25); - // test->shouldBeBackfaceCulled = false; - // test->shouldBeFrustumCulled = false; - // islandAddons = new Mesh(); // islandAddons->rotation.x = -1.6F; // islandAddons->loadDff("sunnyisl/", "sunnyisl3.dff", islandPos, 0.1F); // islandAddons->shouldBeFrustumCulled = false; - // test = new Mesh(); - // Vector3 testpos = Vector3(0.0F, 00.0F, 0.0F); - // test->loadObj("pillar/", "pillar", testpos, .1F, 1); - // texRepo->addByMesh("pillar/", *test); - // std::vector *textures = texRepo->getAll(); - // textures->at(0)->removeLink(test->id, test->getMaterial(0).getId()); - // MeshTexture *tex = texRepo->add("objanim/", "water"); - // tex->addLink(test->id, test->getMaterial(0).getId()); - // texRepo->removeById(textures->at(0)->getId()); - // test->playAnimation(0, 0); - // test->shouldBeBackfaceCulled = true; - - // TODO 1 - Merge md2 - // TODO 2 - Refactor mesh, loaders - // TODO 3 - const & in parameters - // TODO 4 - Destructor - // TODO 5 - Mesh copy(); + // TODO 1 - Refactor mesh, loaders + // TODO 2 - const & in parameters + // TODO 3 - Destructor mesh + // TODO 4 - Destructor RwClump in dff loader + // TODO 5 - Test mesh copy(); // test->shouldBeFrustumCulled = true; - // skybox = new Mesh(); - // Vector3 skyboxPos = Vector3(0.0F, 10.0F, 0.0F); - // skybox->loadObj("skybox/", "skybox", skyboxPos, 80.0F, 1, false); - // skybox->shouldBeFrustumCulled = true; - // texRepo->addByMesh("skybox/", *skybox); + test = new Mesh(); + skybox = new Mesh(); + island = new Mesh(); + + island->loadDff("sunnyisl/", "sunnyisl", 0.1F, false); + test->loadMD2("warrior/", "warrior", 0.2F, true); + skybox->loadObj("skybox/", "skybox", 80.0F, false); // po zamianie miejscami działa + + test->rotation.x = -1.6F; + test->playAnimation(9, 15, 0); + skybox->position.set(0.0F, 10.0F, 0.0F); + island->rotation.x = -1.6F; + island->position.set(0.0F, 10.0F, 0.0F); + + texRepo->addByMesh("warrior/", *test); + texRepo->addByMesh("skybox/", *skybox); + texRepo->addByMesh("sunnyisl/", *island); // waterFloors = new Mesh *[WATER_TILES_COUNT]; // spirals = new Point[WATER_TILES_COUNT]; @@ -159,13 +142,12 @@ void Ari::initBulb() void Ari::onUpdate() { - if (engine.pad.isCrossClicked) printf("FPS:%f\n", engine.fps); camera->update(engine.pad, player->mesh); engine.renderer->draw(test); - // engine.renderer->draw(skybox); - // engine.renderer->draw(island); + engine.renderer->draw(skybox); + engine.renderer->draw(island); // engine.renderer->draw(islandAddons); // // engine.renderer->draw(&player->mesh); // for (u8 i = 0; i < WATER_TILES_COUNT; i++)