free ram and tyrobj wip
This commit is contained in:
+2
-5
@@ -1,16 +1,12 @@
|
|||||||
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
|
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
|
||||||
|
|
||||||
--- H4570
|
--- H4570
|
||||||
- [Loaders] Think about ".tyrobj" format - implement it (add multicolor support)
|
- [Loaders] ".tyrobj" format
|
||||||
- [Loaders] DFF loader as static Mesh loader
|
- [Loaders] DFF loader as static Mesh loader
|
||||||
- [Game] Update intellisense from docker
|
- [Game] Update intellisense from docker
|
||||||
- [Texture] Test cache hits with large amount of textures (dolphin sample?)
|
- [Texture] Test cache hits with large amount of textures (dolphin sample?)
|
||||||
- [Demo] Create cool demo which will show all features of Tyra (I will take this one)
|
- [Demo] Create cool demo which will show all features of Tyra (I will take this one)
|
||||||
|
|
||||||
--- Wellinator
|
|
||||||
- [General] Physics and stuff from threeJS
|
|
||||||
|
|
||||||
--- Unassigned
|
|
||||||
|
|
||||||
- [General] Control generated id to avoid duplication. Maybe Just increment from 0? Add interface IIdentificable?
|
- [General] Control generated id to avoid duplication. Maybe Just increment from 0? Add interface IIdentificable?
|
||||||
|
|
||||||
@@ -54,3 +50,4 @@ because Mesh rendering uses only core.render()
|
|||||||
- [3D] Add drawLine(x, y , color, size)
|
- [3D] Add drawLine(x, y , color, size)
|
||||||
- [3D] Add drawBBox(x, y , color, size)
|
- [3D] Add drawBBox(x, y , color, size)
|
||||||
- [File] Async file loading
|
- [File] Async file loading
|
||||||
|
- [tyrobj] Add multicolor support to tyrobj
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <tamtypes.h>
|
#include <tamtypes.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include "time/timer.hpp"
|
#include "time/timer.hpp"
|
||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
@@ -25,8 +26,13 @@ class Info {
|
|||||||
|
|
||||||
const u32& getFps() const { return fps; };
|
const u32& getFps() const { return fps; };
|
||||||
|
|
||||||
|
/** @return Available RAM in MB */
|
||||||
|
float getAvailableRAM();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float calcFps();
|
float calcFps();
|
||||||
|
void* allocateLargestFreeRAMBlock(size_t* size);
|
||||||
|
size_t getFreeRAMSize();
|
||||||
|
|
||||||
u8 fpsDelayer;
|
u8 fpsDelayer;
|
||||||
u32 fps;
|
u32 fps;
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ class MD2Loader : public Loader {
|
|||||||
MD2Loader();
|
MD2Loader();
|
||||||
~MD2Loader();
|
~MD2Loader();
|
||||||
|
|
||||||
MeshBuilderData* load(const char* fullpath, const float& t_scale,
|
MeshBuilderData* load(const char* fullpath, const float& scale,
|
||||||
const u8& t_invertT);
|
const bool& invertT);
|
||||||
|
|
||||||
inline MeshBuilderData* load(const std::string& fullpath,
|
inline MeshBuilderData* load(const std::string& fullpath, const float& scale,
|
||||||
const float& t_scale, const u8& t_invertT) {
|
const bool& invertT) {
|
||||||
return load(fullpath.c_str(), t_scale, t_invertT);
|
return load(fullpath.c_str(), scale, invertT);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../loader.hpp"
|
||||||
|
#include "../builder/mesh_builder_data.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Tyra {
|
||||||
|
|
||||||
|
struct TyraobjData {
|
||||||
|
u32 vertexCount, stsCount, normalsCount, colorsCount, materialsCount,
|
||||||
|
framesCount;
|
||||||
|
u32* materialsFaces;
|
||||||
|
float scale;
|
||||||
|
bool invertT;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TyraobjReadInfo {
|
||||||
|
u32 verticesI, coordsI, normalsI, colorsI, faceI;
|
||||||
|
s16 materialsI;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Class responsible for loading&parsing custom Tyra obj files */
|
||||||
|
class TyrobjLoader : public Loader {
|
||||||
|
public:
|
||||||
|
TyrobjLoader();
|
||||||
|
~TyrobjLoader();
|
||||||
|
|
||||||
|
/** Load multiple tyrobj files (dynamic) */
|
||||||
|
MeshBuilderData* load(const char* fullpath, const u16& count,
|
||||||
|
const float& scale, const bool& invertT);
|
||||||
|
|
||||||
|
inline MeshBuilderData* load(const std::string& fullpath, const u16& count,
|
||||||
|
const float& scale, const bool& invertT) {
|
||||||
|
return load(fullpath.c_str(), count, scale, invertT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TyraobjData scan(FILE* file, const u32& framesCount);
|
||||||
|
void loadFile(FILE* file, const std::string& path, const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData, MeshBuilderData* outputData);
|
||||||
|
|
||||||
|
void initReadInfo(TyraobjReadInfo* info);
|
||||||
|
void readVertices(TyraobjReadInfo* info, FILE* file, const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData, MeshBuilderData* outputData);
|
||||||
|
void readTextureCoords(TyraobjReadInfo* info, FILE* file,
|
||||||
|
const u16& frameIndex, const TyraobjData& inputData,
|
||||||
|
MeshBuilderData* outputData);
|
||||||
|
void readNormals(TyraobjReadInfo* info, FILE* file, const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData, MeshBuilderData* outputData);
|
||||||
|
void readColors(TyraobjReadInfo* info, FILE* file, const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData, MeshBuilderData* outputData);
|
||||||
|
void readMaterials(TyraobjReadInfo* info, FILE* file, const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData, MeshBuilderData* outputData);
|
||||||
|
void readFaces(TyraobjReadInfo* info, FILE* file, const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData, MeshBuilderData* outputData);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Tyra
|
||||||
@@ -18,6 +18,7 @@ class Loader {
|
|||||||
protected:
|
protected:
|
||||||
std::string getFilenameFromPath(const std::string& path);
|
std::string getFilenameFromPath(const std::string& path);
|
||||||
std::string getFilenameWithoutExtension(const std::string& filename);
|
std::string getFilenameWithoutExtension(const std::string& filename);
|
||||||
|
std::string getExtensionOfFilename(const std::string& filename);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tyra
|
} // namespace Tyra
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ class RendererSettings {
|
|||||||
RendererSettings()
|
RendererSettings()
|
||||||
: width(640.0F),
|
: width(640.0F),
|
||||||
height(448.0F),
|
height(448.0F),
|
||||||
|
interlacedHeightF(height / 2),
|
||||||
near(0.1F),
|
near(0.1F),
|
||||||
far(4096.0F),
|
far(4096.0F),
|
||||||
projectionScale(4096.0F),
|
projectionScale(4096.0F),
|
||||||
aspectRatio(width / height) {}
|
aspectRatio(width / height),
|
||||||
|
interlacedHeightUI(static_cast<unsigned int>(interlacedHeightF)) {}
|
||||||
~RendererSettings();
|
~RendererSettings();
|
||||||
|
|
||||||
const float& getWidth() const { return width; }
|
const float& getWidth() const { return width; }
|
||||||
@@ -32,10 +34,9 @@ class RendererSettings {
|
|||||||
const float& getFar() const { return far; }
|
const float& getFar() const { return far; }
|
||||||
const float& getProjectionScale() const { return projectionScale; }
|
const float& getProjectionScale() const { return projectionScale; }
|
||||||
const float& getAspectRatio() const { return aspectRatio; }
|
const float& getAspectRatio() const { return aspectRatio; }
|
||||||
|
const float& getInterlacedHeightF() const { return interlacedHeightF; }
|
||||||
float getInterlacedHeightF() const { return getHeight() / 2; }
|
const unsigned int& getInterlacedHeightUI() const {
|
||||||
unsigned int getInterlacedHeightUI() const {
|
return interlacedHeightUI;
|
||||||
return static_cast<unsigned int>(getInterlacedHeightF());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy(RendererSettings* out, const RendererSettings* in);
|
static void copy(RendererSettings* out, const RendererSettings* in);
|
||||||
@@ -45,7 +46,9 @@ class RendererSettings {
|
|||||||
std::string getPrint() const;
|
std::string getPrint() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float width, height, near, far, projectionScale, aspectRatio;
|
float width, height, interlacedHeightF, near, far, projectionScale,
|
||||||
|
aspectRatio;
|
||||||
|
unsigned int interlacedHeightUI;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tyra
|
} // namespace Tyra
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "info/info.hpp"
|
#include "info/info.hpp"
|
||||||
|
#include "strings.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
|
|
||||||
@@ -36,4 +38,69 @@ float Info::calcFps() {
|
|||||||
return 15625.0F / (float)timeDelta; // PAL
|
return 15625.0F / (float)timeDelta; // PAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Info::getAvailableRAM() {
|
||||||
|
size_t bits = getFreeRAMSize();
|
||||||
|
return bits / 1024.0F / 1024.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Info::allocateLargestFreeRAMBlock(size_t* Size) {
|
||||||
|
size_t s0, s1;
|
||||||
|
void* p;
|
||||||
|
|
||||||
|
s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
|
||||||
|
|
||||||
|
while (s0 && (p = malloc(s0)) == NULL) s0 >>= 1;
|
||||||
|
|
||||||
|
if (p) free(p);
|
||||||
|
|
||||||
|
s1 = s0 >> 1;
|
||||||
|
|
||||||
|
while (s1) {
|
||||||
|
if ((p = malloc(s0 + s1)) != NULL) {
|
||||||
|
s0 += s1;
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
s1 >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (s0 && (p = malloc(s0)) == NULL) s0 ^= s0 & -s0;
|
||||||
|
|
||||||
|
*Size = s0;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Info::getFreeRAMSize() {
|
||||||
|
size_t total = 0;
|
||||||
|
void* pFirst = NULL;
|
||||||
|
void* pLast = NULL;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
size_t largest;
|
||||||
|
void* p = allocateLargestFreeRAMBlock(&largest);
|
||||||
|
|
||||||
|
if (largest < sizeof(void*)) {
|
||||||
|
if (p != NULL) free(p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(void**)p = NULL;
|
||||||
|
|
||||||
|
total += largest;
|
||||||
|
|
||||||
|
if (pFirst == NULL) pFirst = p;
|
||||||
|
|
||||||
|
if (pLast != NULL) *(void**)pLast = p;
|
||||||
|
|
||||||
|
pLast = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pFirst != NULL) {
|
||||||
|
void* p = *(void**)pFirst;
|
||||||
|
free(pFirst);
|
||||||
|
pFirst = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
} // Namespace Tyra
|
} // Namespace Tyra
|
||||||
@@ -40,21 +40,25 @@ MeshBuilderFrameData::~MeshBuilderFrameData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MeshBuilderFrameData::allocateTextureCoords(const u32& count) {
|
void MeshBuilderFrameData::allocateTextureCoords(const u32& count) {
|
||||||
|
if (count == 0) return;
|
||||||
textureCoordsCount = count;
|
textureCoordsCount = count;
|
||||||
textureCoords = new Vec4[count];
|
textureCoords = new Vec4[count];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshBuilderFrameData::allocateVertices(const u32& count) {
|
void MeshBuilderFrameData::allocateVertices(const u32& count) {
|
||||||
|
if (count == 0) return;
|
||||||
verticesCount = count;
|
verticesCount = count;
|
||||||
vertices = new Vec4[count];
|
vertices = new Vec4[count];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshBuilderFrameData::allocateNormals(const u32& count) {
|
void MeshBuilderFrameData::allocateNormals(const u32& count) {
|
||||||
|
if (count == 0) return;
|
||||||
normalsCount = count;
|
normalsCount = count;
|
||||||
normals = new Vec4[count];
|
normals = new Vec4[count];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshBuilderFrameData::allocateColors(const u32& count) {
|
void MeshBuilderFrameData::allocateColors(const u32& count) {
|
||||||
|
if (count == 0) return;
|
||||||
colorsCount = count;
|
colorsCount = count;
|
||||||
colors = new Color[count];
|
colors = new Color[count];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ MD2Loader::MD2Loader() {}
|
|||||||
|
|
||||||
MD2Loader::~MD2Loader() {}
|
MD2Loader::~MD2Loader() {}
|
||||||
|
|
||||||
MeshBuilderData* MD2Loader::load(const char* fullpath, const float& t_scale,
|
MeshBuilderData* MD2Loader::load(const char* fullpath, const float& scale,
|
||||||
const u8& t_invertT) {
|
const bool& invertT) {
|
||||||
std::string path = fullpath;
|
std::string path = fullpath;
|
||||||
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||||
|
|
||||||
@@ -131,11 +131,11 @@ MeshBuilderData* MD2Loader::load(const char* fullpath, const float& t_scale,
|
|||||||
for (u32 i = 0; i < vertexCount; i++) {
|
for (u32 i = 0; i < vertexCount; i++) {
|
||||||
temp.set(
|
temp.set(
|
||||||
((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) *
|
((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) *
|
||||||
t_scale,
|
scale,
|
||||||
((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) *
|
((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) *
|
||||||
t_scale,
|
scale,
|
||||||
((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) *
|
((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) *
|
||||||
t_scale);
|
scale);
|
||||||
|
|
||||||
result->frames[j]->vertices[i].set(temp);
|
result->frames[j]->vertices[i].set(temp);
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ MeshBuilderData* MD2Loader::load(const char* fullpath, const float& t_scale,
|
|||||||
temp.set(static_cast<float>(texCoord->s) / header.skinwidth,
|
temp.set(static_cast<float>(texCoord->s) / header.skinwidth,
|
||||||
static_cast<float>(texCoord->t) / header.skinheight, 1.0F, 0.0F);
|
static_cast<float>(texCoord->t) / header.skinheight, 1.0F, 0.0F);
|
||||||
|
|
||||||
if (t_invertT) temp.y = 1.0F - temp.y;
|
if (invertT) temp.y = 1.0F - temp.y;
|
||||||
|
|
||||||
for (u32 j = 0; j < framesCount; j++)
|
for (u32 j = 0; j < framesCount; j++)
|
||||||
result->frames[j]->textureCoords[i].set(temp);
|
result->frames[j]->textureCoords[i].set(temp);
|
||||||
|
|||||||
@@ -0,0 +1,320 @@
|
|||||||
|
/*
|
||||||
|
# ______ ____ ___
|
||||||
|
# | \/ ____| |___|
|
||||||
|
# | | | \ | |
|
||||||
|
#-----------------------------------------------------------------------
|
||||||
|
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||||
|
# Licenced under Apache License 2.0
|
||||||
|
# Michał Mostowik <mostek3pl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
#include "math/vec2.hpp"
|
||||||
|
#include "math/vec4.hpp"
|
||||||
|
#include "renderer/models/color.hpp"
|
||||||
|
#include "debug/debug.hpp"
|
||||||
|
#include "loaders/3d/tyrobj/tyrobj_loader.hpp"
|
||||||
|
|
||||||
|
namespace Tyra {
|
||||||
|
|
||||||
|
TyrobjLoader::TyrobjLoader() {}
|
||||||
|
|
||||||
|
TyrobjLoader::~TyrobjLoader() {}
|
||||||
|
|
||||||
|
MeshBuilderData* TyrobjLoader::load(const char* fullpath, const u16& count,
|
||||||
|
const float& scale, const bool& invertT) {
|
||||||
|
std::string path = fullpath;
|
||||||
|
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||||
|
|
||||||
|
auto rawFilename = getFilenameWithoutExtension(path);
|
||||||
|
auto extension = getExtensionOfFilename(path);
|
||||||
|
|
||||||
|
auto firstFile = rawFilename + "1." + extension;
|
||||||
|
FILE* firstFileHandler = fopen(firstFile.c_str(), "rb");
|
||||||
|
TYRA_ASSERT(firstFileHandler != nullptr, "Failed to load: ", firstFile);
|
||||||
|
auto data = scan(firstFileHandler, count);
|
||||||
|
data.scale = scale;
|
||||||
|
data.invertT = invertT;
|
||||||
|
fclose(firstFileHandler);
|
||||||
|
|
||||||
|
auto result = new MeshBuilderData();
|
||||||
|
result->allocate(data.framesCount, data.materialsCount);
|
||||||
|
result->normalsEnabled = data.normalsCount > 0;
|
||||||
|
result->textureCoordsEnabled = data.stsCount > 0;
|
||||||
|
result->manyColorsEnabled = data.colorsCount > 0;
|
||||||
|
|
||||||
|
for (u16 i = 1; i <= count; i++) {
|
||||||
|
auto path = rawFilename + std::to_string(i) + "." + extension;
|
||||||
|
FILE* fileHandler = fopen(path.c_str(), "rb");
|
||||||
|
TYRA_ASSERT(fileHandler != nullptr, "Failed to load: ", path);
|
||||||
|
loadFile(fileHandler, path, i - 1, data, result);
|
||||||
|
fclose(fileHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete data.materialsFaces;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TyraobjData TyrobjLoader::scan(FILE* file, const u32& framesCount) {
|
||||||
|
TyraobjData result;
|
||||||
|
result.vertexCount = 0;
|
||||||
|
result.stsCount = 0;
|
||||||
|
result.normalsCount = 0;
|
||||||
|
result.colorsCount = 0;
|
||||||
|
result.materialsCount = 0;
|
||||||
|
result.framesCount = framesCount;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
char lineHeader[128];
|
||||||
|
int res = fscanf(file, "%s", lineHeader);
|
||||||
|
if (res != EOF) {
|
||||||
|
if (strcmp(lineHeader, "v") == 0)
|
||||||
|
result.vertexCount += 1;
|
||||||
|
else if (strcmp(lineHeader, "vt") == 0)
|
||||||
|
result.stsCount += 1;
|
||||||
|
else if (strcmp(lineHeader, "vn") == 0)
|
||||||
|
result.normalsCount += 1;
|
||||||
|
else if (strcmp(lineHeader, "vc") == 0)
|
||||||
|
result.colorsCount += 1;
|
||||||
|
else if (strcmp(lineHeader, "usemtl") == 0)
|
||||||
|
result.materialsCount += 1;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.materialsFaces = new u32[result.materialsCount];
|
||||||
|
s16 currentMatI = -1;
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
u32 facesCounter = 0;
|
||||||
|
while (1) {
|
||||||
|
char lineHeader[128];
|
||||||
|
int res = fscanf(file, "%s", lineHeader);
|
||||||
|
if (res != EOF) {
|
||||||
|
if (strcmp(lineHeader, "usemtl") == 0) {
|
||||||
|
if (currentMatI >= 0) // Skip -1
|
||||||
|
{
|
||||||
|
result.materialsFaces[currentMatI] = facesCounter;
|
||||||
|
facesCounter = 0;
|
||||||
|
}
|
||||||
|
currentMatI++;
|
||||||
|
} else if (strcmp(lineHeader, "f") == 0)
|
||||||
|
facesCounter += 3;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.materialsFaces[currentMatI] = facesCounter; // Allocate last one
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TyrobjLoader::loadFile(FILE* file, const std::string& path,
|
||||||
|
const u16& frameIndex, const TyraobjData& inputData,
|
||||||
|
MeshBuilderData* outputData) {
|
||||||
|
outputData->frames[frameIndex]->allocateVertices(inputData.vertexCount);
|
||||||
|
outputData->frames[frameIndex]->allocateNormals(inputData.normalsCount);
|
||||||
|
outputData->frames[frameIndex]->allocateTextureCoords(inputData.stsCount);
|
||||||
|
outputData->frames[frameIndex]->allocateColors(inputData.colorsCount);
|
||||||
|
|
||||||
|
TyraobjReadInfo readInfo;
|
||||||
|
initReadInfo(&readInfo);
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
char* lineHeader = new char[128];
|
||||||
|
|
||||||
|
while (res != EOF) {
|
||||||
|
res = fscanf(file, "%s", lineHeader);
|
||||||
|
|
||||||
|
if (strcmp(lineHeader, "v") == 0) {
|
||||||
|
readVertices(&readInfo, file, frameIndex, inputData, outputData);
|
||||||
|
} else if (strcmp(lineHeader, "vt") == 0) {
|
||||||
|
readTextureCoords(&readInfo, file, frameIndex, inputData, outputData);
|
||||||
|
} else if (strcmp(lineHeader, "vn") == 0) {
|
||||||
|
readNormals(&readInfo, file, frameIndex, inputData, outputData);
|
||||||
|
} else if (strcmp(lineHeader, "vc") == 0) {
|
||||||
|
readColors(&readInfo, file, frameIndex, inputData, outputData);
|
||||||
|
} else if (strcmp(lineHeader, "usemtl") == 0) {
|
||||||
|
readMaterials(&readInfo, file, frameIndex, inputData, outputData);
|
||||||
|
} else if (strcmp(lineHeader, "f") == 0) {
|
||||||
|
readFaces(&readInfo, file, frameIndex, inputData, outputData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] lineHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TyrobjLoader::initReadInfo(TyraobjReadInfo* info) {
|
||||||
|
info->verticesI = 0;
|
||||||
|
info->coordsI = 0;
|
||||||
|
info->normalsI = 0;
|
||||||
|
info->colorsI = 0;
|
||||||
|
info->faceI = 0;
|
||||||
|
info->materialsI = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TyrobjLoader::readVertices(TyraobjReadInfo* info, FILE* file,
|
||||||
|
const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData,
|
||||||
|
MeshBuilderData* outputData) {
|
||||||
|
Vec4 vector(0.0F, 0.0F, 0.0F, 1.0F);
|
||||||
|
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
|
||||||
|
outputData->frames[frameIndex]->vertices[info->verticesI++].set(
|
||||||
|
vector * inputData.scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TyrobjLoader::readTextureCoords(TyraobjReadInfo* info, FILE* file,
|
||||||
|
const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData,
|
||||||
|
MeshBuilderData* outputData) {
|
||||||
|
Vec2 point(0.0F, 0.0F);
|
||||||
|
fscanf(file, "%f %f\n", &point.x, &point.y);
|
||||||
|
if (inputData.invertT) point.y = 1.0F - point.y;
|
||||||
|
outputData->frames[frameIndex]->textureCoords[info->coordsI++].set(
|
||||||
|
point.x, point.y, 1.0F, 0.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TyrobjLoader::readNormals(TyraobjReadInfo* info, FILE* file,
|
||||||
|
const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData,
|
||||||
|
MeshBuilderData* outputData) {
|
||||||
|
Vec4 vector(0.0F, 0.0F, 0.0F, 1.0F);
|
||||||
|
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
|
||||||
|
outputData->frames[frameIndex]->normals[info->normalsI++].set(vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TyrobjLoader::readColors(TyraobjReadInfo* info, FILE* file,
|
||||||
|
const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData,
|
||||||
|
MeshBuilderData* outputData) {
|
||||||
|
Color color(128.0F, 128.0F, 128.0F, 128.0F);
|
||||||
|
fscanf(file, "%f %f %f %f\n", &color.r, &color.g, &color.b, &color.a);
|
||||||
|
outputData->frames[frameIndex]->colors[info->colorsI++].set(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TyrobjLoader::readMaterials(TyraobjReadInfo* info, FILE* file,
|
||||||
|
const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData,
|
||||||
|
MeshBuilderData* outputData) {
|
||||||
|
char temp[30];
|
||||||
|
fscanf(file, "%s\n", temp);
|
||||||
|
info->materialsI++;
|
||||||
|
outputData->materials[info->materialsI]->allocateFaces(
|
||||||
|
inputData.materialsFaces[info->materialsI]);
|
||||||
|
outputData->materials[info->materialsI]->name = temp;
|
||||||
|
info->faceI = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TyrobjLoader::readFaces(TyraobjReadInfo* info, FILE* file,
|
||||||
|
const u16& frameIndex,
|
||||||
|
const TyraobjData& inputData,
|
||||||
|
MeshBuilderData* outputData) {
|
||||||
|
// int* x = nullptr;
|
||||||
|
// fpos_t start;
|
||||||
|
// fgetpos(file, &start);
|
||||||
|
// int matches =
|
||||||
|
// fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", x, x, x, x, x, x, x, x,
|
||||||
|
// x);
|
||||||
|
// fsetpos(file, &start);
|
||||||
|
// int newerMatches = 0;
|
||||||
|
|
||||||
|
// // TODO: No support of vc!
|
||||||
|
// u32 vertexIndex[3], coordIndex[3], normalIndex[3]; // ,colorIndex[3];
|
||||||
|
// for (u16 i = 0; i < 3; i++) {
|
||||||
|
// vertexIndex[i] = 0;
|
||||||
|
// coordIndex[i] = 0;
|
||||||
|
// normalIndex[i] = 0;
|
||||||
|
// // colorIndex[i] = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// switch (matches) {
|
||||||
|
// /** Vs, VTs and VNs all set */
|
||||||
|
// case 9: {
|
||||||
|
// fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0],
|
||||||
|
// &coordIndex[0], &normalIndex[0], &vertexIndex[1],
|
||||||
|
// &coordIndex[1], &normalIndex[1], &vertexIndex[2],
|
||||||
|
// &coordIndex[2], &normalIndex[2]);
|
||||||
|
// } break;
|
||||||
|
|
||||||
|
// /** Loaded only two digits (V, VT) succesfuly. Not setting
|
||||||
|
// VN. */
|
||||||
|
// case 3: {
|
||||||
|
// fscanf(file, "%d/%d/ %d/%d/ %d/%d/\n", &vertexIndex[0], &coordIndex[0],
|
||||||
|
// &vertexIndex[1], &coordIndex[1], &vertexIndex[2],
|
||||||
|
// &coordIndex[2]);
|
||||||
|
// } break;
|
||||||
|
|
||||||
|
// /** Only V set. Checking for existance of VT or VN. */
|
||||||
|
// case 1: {
|
||||||
|
// /** Check for existance of V/// configuration.. */
|
||||||
|
// newerMatches = fscanf(file, "%d// %d// %d//\n", x, x, x);
|
||||||
|
// fsetpos(file, &start);
|
||||||
|
// if (newerMatches == 3) {
|
||||||
|
// /** Configuration confirmed. */
|
||||||
|
// fscanf(file, "%d// %d// %d//\n", &vertexIndex[0], &vertexIndex[1],
|
||||||
|
// &vertexIndex[2]);
|
||||||
|
// } else {
|
||||||
|
// /** Failed, checking configuration V//VN */
|
||||||
|
// newerMatches = fscanf(file, "%d//%d %d//%d %d//%d", x, x, x, x, x,
|
||||||
|
// x); fsetpos(file, &start); TYRA_ASSERT(newerMatches == 6, "Unknown
|
||||||
|
// .obj face for .obj file!");
|
||||||
|
// /** Configuration confirmed. */
|
||||||
|
// newerMatches = fscanf(file, "%d//%d %d//%d %d//%d", &vertexIndex[0],
|
||||||
|
// &normalIndex[0], &vertexIndex[1],
|
||||||
|
// &normalIndex[1], &vertexIndex[2],
|
||||||
|
// &normalIndex[2]);
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// } break;
|
||||||
|
// default: {
|
||||||
|
// TYRA_TRAP("Unknown faces format in .obj file!");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (matches == 9 || matches == 2 || matches == 1) {
|
||||||
|
// outputData->materials[info->materialsI]->vertexFaces[info->faceI] =
|
||||||
|
// vertexIndex[0] - 1;
|
||||||
|
// outputData->materials[info->materialsI]->vertexFaces[info->faceI + 1] =
|
||||||
|
// vertexIndex[1] - 1;
|
||||||
|
// outputData->materials[info->materialsI]->vertexFaces[info->faceI + 2] =
|
||||||
|
// vertexIndex[2] - 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (matches == 9 || matches == 2) {
|
||||||
|
// outputData->materials[info->materialsI]->textureCoordFaces[info->faceI] =
|
||||||
|
// coordIndex[0] - 1;
|
||||||
|
// outputData->materials[info->materialsI]
|
||||||
|
// ->textureCoordFaces[info->faceI + 1] = coordIndex[1] - 1;
|
||||||
|
// outputData->materials[info->materialsI]
|
||||||
|
// ->textureCoordFaces[info->faceI + 2] = coordIndex[2] - 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (matches == 9) {
|
||||||
|
// outputData->materials[info->materialsI]->normalFaces[info->faceI] =
|
||||||
|
// normalIndex[0] - 1;
|
||||||
|
// outputData->materials[info->materialsI]->normalFaces[info->faceI + 1] =
|
||||||
|
// normalIndex[1] - 1;
|
||||||
|
// outputData->materials[info->materialsI]->normalFaces[info->faceI + 2] =
|
||||||
|
// normalIndex[2] - 1;
|
||||||
|
// info->faceI += 3;
|
||||||
|
// } else if (matches == 2) {
|
||||||
|
// info->faceI += 2;
|
||||||
|
// } else if (matches == 1) {
|
||||||
|
// if (newerMatches == 3) {
|
||||||
|
// info->faceI += 1;
|
||||||
|
// } else if (newerMatches == 6) {
|
||||||
|
// outputData->materials[info->materialsI]->normalFaces[info->faceI] =
|
||||||
|
// normalIndex[0] - 1;
|
||||||
|
// outputData->materials[info->materialsI]->normalFaces[info->faceI + 1] =
|
||||||
|
// normalIndex[1] - 1;
|
||||||
|
// outputData->materials[info->materialsI]->normalFaces[info->faceI + 2] =
|
||||||
|
// normalIndex[2] - 1;
|
||||||
|
// info->faceI += 2;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Tyra
|
||||||
@@ -26,4 +26,9 @@ std::string Loader::getFilenameWithoutExtension(const std::string& filename) {
|
|||||||
return filename.substr(0, lastindex);
|
return filename.substr(0, lastindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Loader::getExtensionOfFilename(const std::string& filename) {
|
||||||
|
auto lastindex = filename.find_last_of(".");
|
||||||
|
return filename.substr(lastindex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Tyra
|
} // namespace Tyra
|
||||||
|
|||||||
@@ -72,11 +72,12 @@ void RendererCore2D::render(Sprite* sprite,
|
|||||||
rect->color.q = 0;
|
rect->color.q = 0;
|
||||||
|
|
||||||
rect->v0.x = sprite->position.x;
|
rect->v0.x = sprite->position.x;
|
||||||
rect->v0.y = sprite->position.y;
|
rect->v0.y = sprite->position.y / 2.0F; // interlacing
|
||||||
rect->v0.z = (u32)-1;
|
rect->v0.z = (u32)-1;
|
||||||
|
|
||||||
rect->v1.x = (sprite->size.x * sprite->scale) + sprite->position.x;
|
rect->v1.x = (sprite->size.x * sprite->scale) + sprite->position.x;
|
||||||
rect->v1.y = (sprite->size.y * sprite->scale) + sprite->position.y;
|
rect->v1.y = (sprite->size.y * sprite->scale) + sprite->position.y;
|
||||||
|
rect->v1.y /= 2.0F; // interlacing
|
||||||
rect->v1.z = (u32)-1;
|
rect->v1.z = (u32)-1;
|
||||||
|
|
||||||
auto* packet = packets[context];
|
auto* packet = packets[context];
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ void RendererSettings::copy(RendererSettings* out, const RendererSettings* in) {
|
|||||||
out->far = in->far;
|
out->far = in->far;
|
||||||
out->projectionScale = in->projectionScale;
|
out->projectionScale = in->projectionScale;
|
||||||
out->aspectRatio = in->aspectRatio;
|
out->aspectRatio = in->aspectRatio;
|
||||||
|
out->interlacedHeightF = in->interlacedHeightF;
|
||||||
|
out->interlacedHeightUI = in->interlacedHeightUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererSettings::set(const RendererSettings& v) { copy(this, &v); }
|
void RendererSettings::set(const RendererSettings& v) { copy(this, &v); }
|
||||||
@@ -38,7 +40,8 @@ std::string RendererSettings::getPrint() const {
|
|||||||
res << "near: " << near << ", ";
|
res << "near: " << near << ", ";
|
||||||
res << "far: " << far << ", ";
|
res << "far: " << far << ", ";
|
||||||
res << "projectionScale: " << projectionScale << ", ";
|
res << "projectionScale: " << projectionScale << ", ";
|
||||||
res << "aspectRatio: " << aspectRatio;
|
res << "aspectRatio: " << aspectRatio << ", ";
|
||||||
|
res << "interlaced height: " << interlacedHeightF;
|
||||||
res << ")";
|
res << ")";
|
||||||
return res.str();
|
return res.str();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class H4570 : public Game {
|
|||||||
private:
|
private:
|
||||||
Engine* engine;
|
Engine* engine;
|
||||||
|
|
||||||
|
DynamicMesh* cube;
|
||||||
StaticMesh* staticMesh;
|
StaticMesh* staticMesh;
|
||||||
DynamicMesh* warrior;
|
DynamicMesh* warrior;
|
||||||
u8 warriorsCount;
|
u8 warriorsCount;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "h4570.hpp"
|
#include "h4570.hpp"
|
||||||
#include "file/file_utils.hpp"
|
#include "file/file_utils.hpp"
|
||||||
#include "loaders/3d/md2/md2_loader.hpp"
|
#include "loaders/3d/md2/md2_loader.hpp"
|
||||||
|
#include "loaders/3d/tyrobj/tyrobj_loader.hpp"
|
||||||
#include "thread/threading.hpp"
|
#include "thread/threading.hpp"
|
||||||
|
|
||||||
namespace Tyra {
|
namespace Tyra {
|
||||||
@@ -29,6 +30,7 @@ H4570::~H4570() {}
|
|||||||
|
|
||||||
StaticMesh* getStaticMesh(Renderer* renderer);
|
StaticMesh* getStaticMesh(Renderer* renderer);
|
||||||
DynamicMesh* getWarrior(Renderer* renderer);
|
DynamicMesh* getWarrior(Renderer* renderer);
|
||||||
|
DynamicMesh* getCube(Renderer* renderer);
|
||||||
StaPipOptions* getStaPipOptions();
|
StaPipOptions* getStaPipOptions();
|
||||||
DynPipOptions* getDynPipOptions();
|
DynPipOptions* getDynPipOptions();
|
||||||
void setPipelineOptions(PipelineOptions* options);
|
void setPipelineOptions(PipelineOptions* options);
|
||||||
@@ -36,7 +38,6 @@ Sprite* get2DPicture(Renderer* renderer);
|
|||||||
|
|
||||||
void H4570::init() {
|
void H4570::init() {
|
||||||
// Song
|
// Song
|
||||||
|
|
||||||
engine->audio.loadSong(FileUtils::fromCwd("mafikizolo-loot.wav"));
|
engine->audio.loadSong(FileUtils::fromCwd("mafikizolo-loot.wav"));
|
||||||
engine->audio.setSongLoop(true);
|
engine->audio.setSongLoop(true);
|
||||||
engine->audio.setSongVolume(30);
|
engine->audio.setSongVolume(30);
|
||||||
@@ -48,6 +49,8 @@ void H4570::init() {
|
|||||||
|
|
||||||
staticMesh = getStaticMesh(&engine->renderer);
|
staticMesh = getStaticMesh(&engine->renderer);
|
||||||
|
|
||||||
|
cube = getCube(&engine->renderer);
|
||||||
|
|
||||||
warrior = getWarrior(&engine->renderer);
|
warrior = getWarrior(&engine->renderer);
|
||||||
warriorTex = engine->renderer.core.texture.repository.getBySpriteOrMesh(
|
warriorTex = engine->renderer.core.texture.repository.getBySpriteOrMesh(
|
||||||
warrior->getMaterial(0)->getId());
|
warrior->getMaterial(0)->getId());
|
||||||
@@ -120,8 +123,9 @@ void H4570::init() {
|
|||||||
u32 counter = 0;
|
u32 counter = 0;
|
||||||
|
|
||||||
void H4570::loop() {
|
void H4570::loop() {
|
||||||
if (counter++ > 30) {
|
if (counter++ > 100) {
|
||||||
// TYRA_LOG(engine->info.getFps());
|
TYRA_LOG("Free RAM: ", engine->info.getAvailableRAM(), " MB");
|
||||||
|
TYRA_LOG("FPS: ", engine->info.getFps());
|
||||||
counter = 0;
|
counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,11 +141,14 @@ void H4570::loop() {
|
|||||||
blocks[i].model = translations[i] * rotations[i] * scales[i];
|
blocks[i].model = translations[i] * rotations[i] * scales[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engine->renderer.renderer2D.render(picture);
|
||||||
|
|
||||||
engine->renderer.renderer3D.usePipeline(&stapip);
|
engine->renderer.renderer3D.usePipeline(&stapip);
|
||||||
{ stapip.render(staticMesh, staOptions); }
|
{ stapip.render(staticMesh, staOptions); }
|
||||||
|
|
||||||
engine->renderer.renderer3D.usePipeline(&dynpip);
|
engine->renderer.renderer3D.usePipeline(&dynpip);
|
||||||
{
|
{
|
||||||
|
// dynpip.render(cube);
|
||||||
Threading::switchThread();
|
Threading::switchThread();
|
||||||
for (u8 i = 0; i < warriorsCount; i++) {
|
for (u8 i = 0; i < warriorsCount; i++) {
|
||||||
dynpip.render(warriors[i], dynOptions);
|
dynpip.render(warriors[i], dynOptions);
|
||||||
@@ -186,6 +193,46 @@ DynamicMesh* getWarrior(Renderer* renderer) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DynamicMesh* getCube(Renderer* renderer) {
|
||||||
|
TyrobjLoader loader;
|
||||||
|
auto* data =
|
||||||
|
loader.load(FileUtils::fromCwd("untitled.tyrobj"), 2, .08F, false);
|
||||||
|
|
||||||
|
TYRA_LOG("Frames count: ", data->framesCount);
|
||||||
|
TYRA_LOG("Materials count: ", data->materialsCount);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < data->framesCount; i++) {
|
||||||
|
TYRA_LOG("Vertex count ", i, ": ", data->frames[i]->verticesCount);
|
||||||
|
for (u32 j = 0; j < data->frames[i]->verticesCount; j++) {
|
||||||
|
TYRA_LOG("Vertex ", j, ": ", data->frames[i]->vertices[j].getPrint());
|
||||||
|
}
|
||||||
|
|
||||||
|
TYRA_LOG("Normals count ", i, ": ", data->frames[i]->normalsCount);
|
||||||
|
for (u32 j = 0; j < data->frames[i]->normalsCount; j++) {
|
||||||
|
TYRA_LOG("Normal ", j, ": ", data->frames[i]->normals[j].getPrint());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < data->materialsCount; i++) {
|
||||||
|
TYRA_LOG("Material ", i, ": ", data->materials[i]->name);
|
||||||
|
TYRA_LOG("Faces count: ", data->materials[i]->count);
|
||||||
|
for (u32 j = 0; j < data->materials[i]->count; j++) {
|
||||||
|
TYRA_LOG("Vertex face ", j, ": ", data->materials[i]->vertexFaces);
|
||||||
|
TYRA_LOG("Normal face ", j, ": ", data->materials[i]->normalFaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TYRA_BREAKPOINT();
|
||||||
|
auto* result = new DynamicMesh(*data);
|
||||||
|
// result->translation.translateZ(-30.0F);
|
||||||
|
delete data;
|
||||||
|
|
||||||
|
result->playAnimation(0, result->getFramesCount() - 1);
|
||||||
|
result->setAnimSpeed(0.15F);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Sprite* get2DPicture(Renderer* renderer) {
|
Sprite* get2DPicture(Renderer* renderer) {
|
||||||
auto* sprite = new Sprite;
|
auto* sprite = new Sprite;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user