WIP adding directory structure

This commit is contained in:
2024-08-17 15:54:20 -07:00
parent a9029193d7
commit 862ffeeaa0
59 changed files with 66 additions and 63 deletions

View File

@@ -0,0 +1,180 @@
//
// KRResource+blend.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRResource.h"
#include "KRScene.h"
#include "KRResource+blend.h"
#include "mimir.h"
using namespace mimir;
KRScene* KRResource::LoadBlenderScene(KRContext& context, const std::string& path)
{
KRScene* pScene = new KRScene(context, mimir::util::GetFileBase(path));
Block data;
if (data.load(path)) {
//KRBlendFile blend_file = KRBlendFile(pFile);
}
return pScene;
}
KRBlendFile::KRBlendFile(const void* pFile)
{
unsigned char* scan = (unsigned char*)pFile;
readHeader(scan);
std::string block_code = "";
while (block_code != "ENDB") {
Block b = Block(this, scan);
block_code = b.getCode();
m_blocks.push_back(b);
printf("Loaded block: %s - %i bytes\n", b.getCode().c_str(), b.getDataSize());
}
}
void KRBlendFile::readHeader(unsigned char*& scan)
{
if (strncmp((char*)scan, "BLENDER", 7) != 0) {
// TODO throw exception
}
scan += 7;
if (scan[0] == '_' && scan[1] == 'v') {
// 32-bit, little-endian
m_file_type = KRBLEND_LITTLEENDIAN_32BIT;
} else if (scan[0] == '_' && scan[1] == 'V') {
// 32-bit, bit-endian
m_file_type = KRBLEND_BIGENDIAN_32BIT;
} else if (scan[0] == '-' && scan[1] == 'v') {
// 64-bit, little-endian
m_file_type = KRBLEND_LITTLEENDIAN_64BIT;
} else if (scan[0] == '-' && scan[1] == 'V') {
// 64-bit, big-endian
m_file_type = KRBLEND_BIGENDIAN_64BIT;
} else {
// TODO - throw exception
}
scan += 5; // Skip and ignore version
}
__int32_t KRBlendFile::readInt(unsigned char*& scan)
{
__int32_t ret = 0;
// read a 32-bit integer and increment scan
switch (m_file_type) {
case KRBLEND_BIGENDIAN_32BIT:
case KRBLEND_BIGENDIAN_64BIT:
ret = (__int32_t)scan[3] + (__int32_t)scan[2] * 0x100 + (__int32_t)scan[1] * 0x10000 + (__int32_t)scan[0] * 0x1000000;
break;
case KRBLEND_LITTLEENDIAN_32BIT:
case KRBLEND_LITTLEENDIAN_64BIT:
ret = (__int32_t)scan[0] + (__int32_t)scan[1] * 0x100 + (__int32_t)scan[2] * 0x10000 + (__int32_t)scan[3] * 0x1000000;
break;
}
scan += 4;
return ret;
}
__int64_t KRBlendFile::readPointer(unsigned char*& scan)
{
__int64_t ret = 0;
// read a 32-bit integer and increment scan
switch (m_file_type) {
case KRBLEND_BIGENDIAN_32BIT:
ret = scan[3] + scan[2] * 0x100 + scan[1] * 0x10000 + scan[0] * 0x1000000;
scan += 4;
break;
case KRBLEND_LITTLEENDIAN_32BIT:
ret = scan[0] + scan[1] * 0x100 + scan[2] * 0x10000 + scan[3] * 0x1000000;
scan += 4;
break;
case KRBLEND_BIGENDIAN_64BIT:
ret = scan[7] + scan[6] * 0x100 + scan[5] * 0x10000 + scan[4] * 0x1000000 + scan[3] * 0x100000000 + scan[2] * 0x10000000000 + scan[1] * 0x1000000000000 + scan[0] * 0x100000000000000;
scan += 8;
break;
case KRBLEND_LITTLEENDIAN_64BIT:
ret = scan[0] + scan[1] * 0x100 + scan[2] * 0x10000 + scan[3] * 0x1000000 + scan[4] * 0x100000000 + scan[5] * 0x10000000000 + scan[6] * 0x1000000000000 + scan[7] * 0x100000000000000;
scan += 8;
break;
}
return ret;
}
KRBlendFile::~KRBlendFile()
{
}
KRBlendFile::Block::Block(KRBlendFile* blendFile, unsigned char*& scan)
{
scan += (__int64_t)scan % 4; // Scan forward until the next 4-byte boundary
char szBlock[5];
szBlock[0] = *scan++;
szBlock[1] = *scan++;
szBlock[2] = *scan++;
szBlock[3] = *scan++;
szBlock[4] = '\0';
m_code = szBlock;
m_dataSize = blendFile->readInt(scan);
m_prev_pointer = blendFile->readPointer(scan);
m_sdna_index = blendFile->readInt(scan);
m_structure_count = blendFile->readInt(scan);
m_data = scan;
scan += m_dataSize;
}
KRBlendFile::Block::~Block()
{
}
std::string KRBlendFile::Block::getCode()
{
return m_code;
}
int KRBlendFile::Block::getDataSize()
{
return m_dataSize;
}

View File

@@ -0,0 +1,71 @@
//
// KRResource+blend.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
class KRBlendFile
{
public:
KRBlendFile(const void* pFile);
~KRBlendFile();
class Block
{
public:
Block(KRBlendFile* blendFile, unsigned char*& scan);
~Block();
std::string getCode();
int getDataSize();
private:
std::string m_code;
__int32_t m_dataSize;
__int32_t m_sdna_index;
__int32_t m_structure_count;
__int64_t m_prev_pointer;
unsigned char* m_data;
};
private:
enum file_type
{
KRBLEND_LITTLEENDIAN_32BIT,
KRBLEND_LITTLEENDIAN_64BIT,
KRBLEND_BIGENDIAN_32BIT,
KRBLEND_BIGENDIAN_64BIT
} m_file_type;
void readHeader(unsigned char*& scan);
__int32_t readInt(unsigned char*& scan);
__int64_t readPointer(unsigned char*& scan);
std::vector<Block> m_blocks;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,366 @@
//
// KRResource+obj.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRResource.h"
#include "KRMesh.h"
#include "mimir.h"
using namespace mimir;
using namespace hydra;
KRMesh* KRResource::LoadObj(KRContext& context, const std::string& path)
{
KRMesh* new_mesh = new KRMesh(context, util::GetFileBase(path));
KRMesh::mesh_info mi;
std::vector<std::string> material_names_t;
Block data;
char szSymbol[500][256];
int* pFaces = NULL;
vector<KRMesh::pack_material*> m_materials;
if (data.load(path)) {
// -----=====----- Get counts -----=====-----
int cVertexData = 0;
int cFaces = 1;
int cMaterialFaceStart = 1;
char* pScan = (char*)data.getStart();
char* pEnd = (char*)data.getEnd();
while (pScan < pEnd) {
// Scan through whitespace
while (pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++;
}
if (*pScan == '#') {
// Line is a comment line
// Scan to the end of the line
while (pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++;
}
} else {
int cSymbols = 0;
while (pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char* pDest = szSymbol[cSymbols++];
while (pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
*pDest++ = *pScan++;
}
*pDest = '\0';
// Scan through whitespace, but don't advance to next line
while (pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++;
}
}
if (strcmp(szSymbol[0], "v") == 0) {
// Vertex (v)
} else if (strcmp(szSymbol[0], "vt") == 0) {
// Vertex Texture UV Coordinate (vt)
} else if (strcmp(szSymbol[0], "vn") == 0) {
// Vertex Normal (vn)
} else if (strcmp(szSymbol[0], "f") == 0) {
// Face (f)
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
cVertexData += cFaceVertexes;
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
} else if (strcmp(szSymbol[0], "usemtl") == 0) {
// Use Material (usemtl)
if (cMaterialFaceStart - cFaces > 0) {
cFaces++;
}
material_names_t.push_back(std::string(szSymbol[1]));
}
}
}
// -----=====----- Populate vertexes and faces -----=====-----
int* pFaces = (int*)malloc(sizeof(int) * (cFaces + 1));
assert(pFaces != NULL);
std::vector<Vector3> indexed_vertices;
std::vector<Vector2> indexed_uva;
std::vector<Vector3> indexed_normals;
int* pFace = pFaces;
int* pMaterialFaces = pFace++;
*pMaterialFaces = 0;
// --------
pScan = (char*)data.getStart();
while (pScan < pEnd) {
// Scan through whitespace
while (pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++;
}
if (*pScan == '#') {
// Line is a comment line
// Scan to the end of the line
while (pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++;
}
} else {
int cSymbols = 0;
while (pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char* pDest = szSymbol[cSymbols++];
while (pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
*pDest++ = *pScan++;
}
*pDest = '\0';
// Scan through whitespace, but don't advance to next line
while (pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++;
}
}
if (strcmp(szSymbol[0], "v") == 0) {
// Vertex (v)
float x, y, z;
char* pChar = szSymbol[1];
x = strtof(pChar, &pChar);
pChar = szSymbol[2];
y = strtof(pChar, &pChar);
pChar = szSymbol[3];
z = strtof(pChar, &pChar);
indexed_vertices.push_back(Vector3::Create(x, y, z));
} else if (strcmp(szSymbol[0], "vt") == 0) {
// Vertex Texture UV Coordinate (vt)
char* pChar = szSymbol[1];
float u, v;
u = strtof(pChar, &pChar);
pChar = szSymbol[2];
v = strtof(pChar, &pChar);
indexed_uva.push_back(Vector2::Create(u, v));
} else if (strcmp(szSymbol[0], "vn") == 0) {
// Vertex Normal (vn)
float x, y, z;
char* pChar = szSymbol[1];
x = strtof(pChar, &pChar);
pChar = szSymbol[2];
y = strtof(pChar, &pChar);
pChar = szSymbol[3];
z = strtof(pChar, &pChar);
indexed_normals.push_back(Vector3::Create(x, y, z));
} else if (strcmp(szSymbol[0], "f") == 0) {
// Face (f)
int cFaceVertices = cSymbols - 1;
*pFace++ = cFaceVertices;
for (int iSymbol = 1; iSymbol < cSymbols; iSymbol++) {
char* pChar = szSymbol[iSymbol];
if (*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
if (*pChar == '/') {
pChar++;
if (*pChar == '/') {
*pFace++ = -1;
} else {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
}
} else {
*pFace++ = -1;
}
if (*pChar == '/') {
pChar++;
if (*pChar == '/') {
*pFace++ = -1;
} else {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
}
} else {
*pFace++ = -1;
}
while (*pChar == '/') {
pChar++;
strtol(pChar, &pChar, 10);
}
}
}
} else if (strcmp(szSymbol[0], "usemtl") == 0) {
// Use Material (usemtl)
if (pFace - pMaterialFaces > 1) {
*pMaterialFaces = (int)(pFace - pMaterialFaces - 1);
pMaterialFaces = pFace++;
}
}
}
}
*pMaterialFaces = (int)(pFace - pMaterialFaces - 1);
*pFace++ = 0;
int iVertex = 0;
std::vector<std::string>::iterator material_itr = material_names_t.begin();
KRMesh::pack_material* pMaterial = new KRMesh::pack_material();
pMaterial->start_vertex = iVertex;
pMaterial->vertex_count = 0;
memset(pMaterial->szName, 0, 256);
if (material_itr < material_names_t.end()) {
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
}
m_materials.push_back(pMaterial);
pFace = pFaces;
while (*pFace != 0 && iVertex < cVertexData) {
pMaterial->start_vertex = iVertex;
int* pMaterialEndFace = pFace + *pFace;
++pFace;
while (pFace < pMaterialEndFace && iVertex < cVertexData) {
int cFaceVertexes = *pFace;
Vector3 firstFaceVertex;
Vector3 prevFaceVertex;
Vector3 firstFaceNormal;
Vector3 prevFaceNormal;
Vector2 firstFaceUva;
Vector2 prevFaceUva;
for (int iFaceVertex = 0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
if (iFaceVertex > 2) {
// There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices
iVertex += 2;
mi.vertices.push_back(firstFaceVertex);
mi.uva.push_back(firstFaceUva);
mi.normals.push_back(firstFaceNormal);
mi.vertices.push_back(prevFaceVertex);
mi.uva.push_back(prevFaceUva);
mi.normals.push_back(prevFaceNormal);
}
Vector3 vertex = indexed_vertices[pFace[iFaceVertex * 3 + 1]];
Vector2 new_uva;
if (pFace[iFaceVertex * 3 + 2] >= 0) {
new_uva = indexed_uva[pFace[iFaceVertex * 3 + 2]];
}
Vector3 normal;
if (pFace[iFaceVertex * 3 + 3] >= 0) {
Vector3 normal = indexed_normals[pFace[iFaceVertex * 3 + 3]];
}
mi.vertices.push_back(vertex);
mi.uva.push_back(new_uva);
mi.normals.push_back(normal);
if (iFaceVertex == 0) {
firstFaceVertex = vertex;
firstFaceUva = new_uva;
firstFaceNormal = normal;
}
prevFaceVertex = vertex;
prevFaceUva = new_uva;
prevFaceNormal = normal;
iVertex++;
}
pFace += cFaceVertexes * 3 + 1;
}
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
if (*pFace != 0) {
pMaterial = new KRMesh::pack_material();
pMaterial->start_vertex = iVertex;
pMaterial->vertex_count = 0;
memset(pMaterial->szName, 0, 256);
if (material_itr < material_names_t.end()) {
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
}
m_materials.push_back(pMaterial);
}
}
for (int iMaterial = 0; iMaterial < m_materials.size(); iMaterial++) {
KRMesh::pack_material* pNewMaterial = m_materials[iMaterial];
if (pNewMaterial->vertex_count > 0) {
mi.material_names.push_back(std::string(pNewMaterial->szName));
mi.submesh_starts.push_back(pNewMaterial->start_vertex);
mi.submesh_lengths.push_back(pNewMaterial->vertex_count);
}
delete pNewMaterial;
}
// TODO: Bones not yet supported for OBJ
// std::vector<std::string> bone_names;
// std::vector<Matrix4> bone_bind_poses;
// std::vector<std::vector<int> > bone_indexes;
// std::vector<std::vector<float> > bone_weights;
//
// std::vector<__uint16_t> vertex_indexes;
// std::vector<std::pair<int, int> > vertex_index_bases;
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
new_mesh->LoadData(mi, true, false);
}
if (pFaces) {
free(pFaces);
}
return new_mesh;
}

73
kraken/resources/KRResource.cpp Executable file
View File

@@ -0,0 +1,73 @@
//
// KRResource.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRResource.h"
#include "resources/bundle/KRBundle.h"
#include "KRContext.h"
using namespace mimir;
KRResource::KRResource(KRContext& context, std::string name) : KRContextObject(context)
{
m_name = name;
context.addResource(this, name);
}
KRResource::~KRResource()
{
m_pContext->removeResource(this);
}
std::string KRResource::getName()
{
return m_name;
}
bool KRResource::save(const std::string& path)
{
Block data;
if (save(data)) {
return data.save(path);
} else {
return false;
}
}
KrResult KRResource::moveToBundle(KRBundle* bundle)
{
Block* data = bundle->append(*this);
if (data == nullptr) {
return KR_ERROR_UNEXPECTED;
}
// TODO(kearwood) - We must re-attach the KRResource to the returned Block
delete data;
return KR_SUCCESS;
}

67
kraken/resources/KRResource.h Executable file
View File

@@ -0,0 +1,67 @@
//
// KRResource.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "block.h"
class KRBundle;
class KRScene;
class KRMesh;
class KRResource : public KRContextObject
{
public:
std::string getName();
virtual std::string getExtension() = 0;
virtual bool save(const std::string& path);
virtual bool save(mimir::Block& data) = 0;
KrResult moveToBundle(KRBundle* bundle);
virtual ~KRResource();
static KRMesh* LoadObj(KRContext& context, const std::string& path);
#if !TARGET_OS_IPHONE
// static KRScene* LoadFbx(KRContext &context, const std::string& path); TODO, FINDME, HACK! - Uncomment
static KRScene* LoadBlenderScene(KRContext& context, const std::string& path);
#endif
protected:
KRResource(KRContext& context, std::string name);
private:
std::string m_name;
};

View File

@@ -0,0 +1,43 @@
//
// KRResourceManager.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRResourceManager.h"
#include "KREngine-common.h"
KRResourceManager::KRResourceManager(KRContext& context) : KRContextObject(context)
{
}
KRResourceManager::~KRResourceManager()
{
}

View File

@@ -0,0 +1,48 @@
//
// KRResourceManager.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "KRResource.h"
#include "KRContextObject.h"
#include "block.h"
class KRResourceManager : public KRContextObject
{
public:
KRResourceManager(KRContext& context);
virtual ~KRResourceManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, mimir::Block* data) = 0;
virtual KRResource* getResource(const std::string& name, const std::string& extension) = 0;
};

View File

@@ -0,0 +1,351 @@
//
// KRAnimation.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimation.h"
#include "KRAnimationManager.h"
#include "KRContext.h"
#include "KRNode.h"
#include "resources/animation_curve/KRAnimationCurve.h"
#include "KREngine-common.h"
using namespace mimir;
KRAnimation::KRAnimation(KRContext& context, std::string name) : KRResource(context, name)
{
m_auto_play = false;
m_loop = false;
m_playing = false;
m_local_time = 0.0f;
m_duration = 0.0f;
m_start_time = 0.0f;
}
KRAnimation::~KRAnimation()
{
for (unordered_map<std::string, KRAnimationLayer*>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr) {
delete (*itr).second;
}
}
std::string KRAnimation::getExtension()
{
return "kranimation";
}
void KRAnimation::addLayer(KRAnimationLayer* layer)
{
m_layers[layer->getName()] = layer;
}
bool KRAnimation::save(Block& data)
{
tinyxml2::XMLDocument doc;
tinyxml2::XMLElement* animation_node = doc.NewElement("animation");
doc.InsertEndChild(animation_node);
animation_node->SetAttribute("loop", m_loop ? "true" : "false");
animation_node->SetAttribute("auto_play", m_auto_play ? "true" : "false");
animation_node->SetAttribute("duration", m_duration);
animation_node->SetAttribute("start_time", m_start_time);
for (unordered_map<std::string, KRAnimationLayer*>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr) {
(*itr).second->saveXML(animation_node);
}
tinyxml2::XMLPrinter p;
doc.Print(&p);
data.append((void*)p.CStr(), strlen(p.CStr()) + 1);
return true;
}
KRAnimation* KRAnimation::Load(KRContext& context, const std::string& name, Block* data)
{
std::string xml_string = data->getString();
tinyxml2::XMLDocument doc;
doc.Parse(xml_string.c_str());
KRAnimation* new_animation = new KRAnimation(context, name);
tinyxml2::XMLElement* animation_node = doc.RootElement();
if (animation_node->QueryFloatAttribute("duration", &new_animation->m_duration) != tinyxml2::XML_SUCCESS) {
new_animation->m_duration = 0.0f; // Default value
}
if (animation_node->QueryFloatAttribute("start_time", &new_animation->m_start_time) != tinyxml2::XML_SUCCESS) {
new_animation->m_start_time = 0.0f; // Default value
}
if (animation_node->QueryBoolAttribute("loop", &new_animation->m_loop) != tinyxml2::XML_SUCCESS) {
new_animation->m_loop = false; // Default value
}
if (animation_node->QueryBoolAttribute("auto_play", &new_animation->m_auto_play) != tinyxml2::XML_SUCCESS) {
new_animation->m_auto_play = false; // Default value
}
for (tinyxml2::XMLElement* child_element = animation_node->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
if (strcmp(child_element->Name(), "layer") == 0) {
KRAnimationLayer* new_layer = new KRAnimationLayer(context);
new_layer->loadXML(child_element);
new_animation->m_layers[new_layer->getName()] = new_layer;
}
}
if (new_animation->m_auto_play) {
new_animation->m_playing = true;
}
// KRNode *n = KRNode::LoadXML(*new_scene, scene_element->FirstChildElement());
delete data;
return new_animation;
}
unordered_map<std::string, KRAnimationLayer*>& KRAnimation::getLayers()
{
return m_layers;
}
KRAnimationLayer* KRAnimation::getLayer(const char* szName)
{
return m_layers[szName];
}
void KRAnimation::update(float deltaTime)
{
if (m_playing) {
m_local_time += deltaTime;
}
if (m_loop) {
while (m_local_time > m_duration) {
m_local_time -= m_duration;
}
} else if (m_local_time > m_duration) {
m_local_time = m_duration;
m_playing = false;
getContext().getAnimationManager()->updateActiveAnimations(this);
}
for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer* layer = (*layer_itr).second;
for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute* attribute = *attribute_itr;
// TODO - Currently only a single layer supported per animation -- need to either implement combining of multiple layers or ask the FBX sdk to bake all layers into one
KRAnimationCurve* curve = attribute->getCurve();
KRNode* target = attribute->getTarget();
KRNode::node_attribute_type attribute_type = attribute->getTargetAttribute();
if (curve != NULL && target != NULL) {
target->SetAttribute(attribute_type, curve->getValue(m_local_time + m_start_time));
}
}
}
}
void KRAnimation::Play()
{
m_playing = true;
getContext().getAnimationManager()->updateActiveAnimations(this);
}
void KRAnimation::Stop()
{
m_playing = false;
getContext().getAnimationManager()->updateActiveAnimations(this);
}
float KRAnimation::getTime()
{
return m_local_time;
}
void KRAnimation::setTime(float time)
{
m_local_time = time;
}
float KRAnimation::getDuration()
{
return m_duration;
}
void KRAnimation::setDuration(float duration)
{
m_duration = duration;
}
float KRAnimation::getStartTime()
{
return m_start_time;
}
void KRAnimation::setStartTime(float start_time)
{
m_start_time = start_time;
}
bool KRAnimation::isPlaying()
{
return m_playing;
}
bool KRAnimation::getAutoPlay() const
{
return m_auto_play;
}
void KRAnimation::setAutoPlay(bool auto_play)
{
m_auto_play = auto_play;
}
bool KRAnimation::getLooping() const
{
return m_loop;
}
void KRAnimation::setLooping(bool looping)
{
m_loop = looping;
}
KRAnimation* KRAnimation::split(const std::string& name, float start_time, float duration, bool strip_unchanging_attributes, bool clone_curves)
{
KRAnimation* new_animation = new KRAnimation(getContext(), name);
new_animation->setStartTime(start_time);
new_animation->setDuration(duration);
new_animation->m_loop = m_loop;
new_animation->m_auto_play = m_auto_play;
int new_curve_count = 0;
for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer* layer = (*layer_itr).second;
KRAnimationLayer* new_layer = new KRAnimationLayer(getContext());
new_layer->setName(layer->getName());
new_layer->setRotationAccumulationMode(layer->getRotationAccumulationMode());
new_layer->setScaleAccumulationMode(layer->getScaleAccumulationMode());
new_layer->setWeight(layer->getWeight());
new_animation->m_layers[new_layer->getName()] = new_layer;
for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute* attribute = *attribute_itr;
// Updated Dec 9, 2013 by Peter to change the way that attributes are stripped.
//
// If we have been asked to strip_unchanging_attributes then we only want to strip those attributes that don't havechanges
// in any of their components (x, y, z). This means that we have to group the attributes before we check for valueChanges().
// The attributes won't come through in order, but they do come through in group order (each group of 3 arrives as x, y, z)
//
// Since this method isn't designed to handle groups, this is a bit of a hack. We simply take whatever channel is coming
// through and then check the other associated curves.
//
int targetAttribute = attribute->getTargetAttribute();
if (targetAttribute > 0) { // we have a valid target that fits within a group of 3
targetAttribute--; // this is now group relative 0,1,2 is the first group .. 3,4,5 is the second group, etc.
KRAnimationCurve* curve = attribute->getCurve(); // this is the curve we are currently handling
int placeInGroup = targetAttribute % 3; // this will be 0, 1 or 2
static long placeLookup[] = { 1, 2, -1, 1, -2, -1 };
KRAnimationAttribute* attribute2 = *(attribute_itr + placeLookup[placeInGroup * 2]);
KRAnimationAttribute* attribute3 = *(attribute_itr + placeLookup[placeInGroup * 2 + 1]);
KRAnimationCurve* curve2 = attribute2->getCurve();
KRAnimationCurve* curve3 = attribute3->getCurve();
bool include_attribute = true;
if (strip_unchanging_attributes) {
include_attribute = curve->valueChanges(start_time, duration) |
curve2->valueChanges(start_time, duration) |
curve3->valueChanges(start_time, duration);
}
if (include_attribute) {
KRAnimationAttribute* new_attribute = new KRAnimationAttribute(getContext());
KRAnimationCurve* new_curve = curve;
if (clone_curves) {
std::string new_curve_name = name + "_curve" + std::to_string(++new_curve_count);
new_curve = curve->split(new_curve_name, start_time, duration);
}
new_attribute->setCurveName(new_curve->getName());
new_attribute->setTargetAttribute(attribute->getTargetAttribute());
new_attribute->setTargetName(attribute->getTargetName());
new_layer->addAttribute(new_attribute);
}
}
}
}
getContext().getAnimationManager()->addAnimation(new_animation);
return new_animation;
}
void KRAnimation::deleteCurves()
{
for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer* layer = (*layer_itr).second;
for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute* attribute = *attribute_itr;
attribute->deleteCurve();
}
}
}
void KRAnimation::_lockData()
{
for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer* layer = (*layer_itr).second;
for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute* attribute = *attribute_itr;
KRAnimationCurve* curve = attribute->getCurve();
if (curve) {
curve->_lockData();
}
}
}
}
void KRAnimation::_unlockData()
{
for (unordered_map<std::string, KRAnimationLayer*>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer* layer = (*layer_itr).second;
for (std::vector<KRAnimationAttribute*>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute* attribute = *attribute_itr;
KRAnimationCurve* curve = attribute->getCurve();
if (curve) {
curve->_unlockData();
}
}
}
}

View File

@@ -0,0 +1,85 @@
//
// KRAnimation.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "block.h"
#include "resources/KRResource.h"
#include "KRAnimationLayer.h"
class KRAnimation : public KRResource
{
public:
KRAnimation(KRContext& context, std::string name);
virtual ~KRAnimation();
virtual std::string getExtension();
virtual bool save(mimir::Block& data);
static KRAnimation* Load(KRContext& context, const std::string& name, mimir::Block* data);
void addLayer(KRAnimationLayer* layer);
unordered_map<std::string, KRAnimationLayer*>& getLayers();
KRAnimationLayer* getLayer(const char* szName);
bool getAutoPlay() const;
void setAutoPlay(bool auto_play);
bool getLooping() const;
void setLooping(bool looping);
void Play();
void Stop();
void update(float deltaTime);
float getTime();
void setTime(float time);
float getDuration();
void setDuration(float duration);
float getStartTime();
void setStartTime(float start_time);
bool isPlaying();
KRAnimation* split(const std::string& name, float start_time, float duration, bool strip_unchanging_attributes = true, bool clone_curves = true);
void deleteCurves();
void _lockData();
void _unlockData();
private:
unordered_map<std::string, KRAnimationLayer*> m_layers;
bool m_auto_play;
bool m_loop;
bool m_playing;
float m_local_time;
float m_duration;
float m_start_time;
};

View File

@@ -0,0 +1,283 @@
//
// KRAnimationAttribute.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimationAttribute.h"
#include "KRContext.h"
#include "KRAnimationManager.h"
#include "resources/animation_curve/KRAnimationCurveManager.h"
KRAnimationAttribute::KRAnimationAttribute(KRContext& context) : KRContextObject(context)
{
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
m_target = NULL;
m_curve = NULL;
}
KRAnimationAttribute::~KRAnimationAttribute()
{
}
tinyxml2::XMLElement* KRAnimationAttribute::saveXML(tinyxml2::XMLNode* parent)
{
tinyxml2::XMLDocument* doc = parent->GetDocument();
tinyxml2::XMLElement* e = doc->NewElement("attribute");
parent->InsertEndChild(e);
e->SetAttribute("curve", m_curve_name.c_str());
e->SetAttribute("target", m_target_name.c_str());
const char* szAttribute = "none";
switch (m_node_attribute) {
case KRNode::KRENGINE_NODE_ATTRIBUTE_NONE:
szAttribute = "none";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X:
szAttribute = "translate_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y:
szAttribute = "translate_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z:
szAttribute = "translate_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X:
szAttribute = "scale_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y:
szAttribute = "scale_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z:
szAttribute = "scale_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X:
szAttribute = "rotate_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y:
szAttribute = "rotate_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z:
szAttribute = "rotate_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X:
szAttribute = "pre_rotate_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y:
szAttribute = "pre_rotate_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z:
szAttribute = "pre_rotate_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X:
szAttribute = "post_rotate_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y:
szAttribute = "post_rotate_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z:
szAttribute = "post_rotate_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X:
szAttribute = "rotate_pivot_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y:
szAttribute = "rotate_pivot_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z:
szAttribute = "rotate_pivot_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X:
szAttribute = "scale_pivot_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y:
szAttribute = "scale_pivot_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z:
szAttribute = "scale_pivot_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X:
szAttribute = "rotate_offset_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y:
szAttribute = "rotate_offset_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z:
szAttribute = "rotate_offset_z";
break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_X:
szAttribute = "scale_offset_x";
break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_Y:
szAttribute = "scale_offset_y";
break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_Z:
szAttribute = "scale_offset_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_COUNT:
// Suppress warning
break;
}
e->SetAttribute("attribute", szAttribute);
return e;
}
void KRAnimationAttribute::loadXML(tinyxml2::XMLElement* e)
{
m_target = NULL;
m_curve = NULL;
m_curve_name = e->Attribute("curve");
m_target_name = e->Attribute("target");
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
const char* szAttribute = e->Attribute("attribute");
if (strcmp(szAttribute, "none") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
} else if (strcmp(szAttribute, "translate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X;
} else if (strcmp(szAttribute, "translate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y;
} else if (strcmp(szAttribute, "translate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z;
} else if (strcmp(szAttribute, "rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X;
} else if (strcmp(szAttribute, "rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y;
} else if (strcmp(szAttribute, "rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z;
} else if (strcmp(szAttribute, "scale_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X;
} else if (strcmp(szAttribute, "scale_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y;
} else if (strcmp(szAttribute, "scale_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z;
} else if (strcmp(szAttribute, "pre_rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X;
} else if (strcmp(szAttribute, "pre_rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y;
} else if (strcmp(szAttribute, "pre_rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z;
} else if (strcmp(szAttribute, "post_rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X;
} else if (strcmp(szAttribute, "post_rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y;
} else if (strcmp(szAttribute, "post_rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z;
} else if (strcmp(szAttribute, "rotate_pivot_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X;
} else if (strcmp(szAttribute, "rotate_pivot_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y;
} else if (strcmp(szAttribute, "rotate_pivot_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z;
} else if (strcmp(szAttribute, "scale_pivot_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X;
} else if (strcmp(szAttribute, "scale_pivot_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y;
} else if (strcmp(szAttribute, "scale_pivot_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z;
} else if (strcmp(szAttribute, "rotate_offset_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X;
} else if (strcmp(szAttribute, "rotate_offset_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y;
} else if (strcmp(szAttribute, "rotate_offset_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z;
} else if (strcmp(szAttribute, "scale_offset_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_X;
} else if (strcmp(szAttribute, "scale_offset_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Y;
} else if (strcmp(szAttribute, "scale_offset_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Z;
} else {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
}
}
KRNode::node_attribute_type KRAnimationAttribute::getTargetAttribute() const
{
return m_node_attribute;
}
void KRAnimationAttribute::setTargetAttribute(KRNode::node_attribute_type target_attribute)
{
m_node_attribute = target_attribute;
}
std::string KRAnimationAttribute::getTargetName() const
{
return m_target_name;
}
void KRAnimationAttribute::setTargetName(const std::string& target_name)
{
m_target_name = target_name;
m_target = NULL;
}
std::string KRAnimationAttribute::getCurveName() const
{
return m_curve_name;
}
void KRAnimationAttribute::setCurveName(const std::string& curve_name)
{
m_curve_name = curve_name;
m_curve = NULL;
}
KRNode* KRAnimationAttribute::getTarget()
{
if (m_target == NULL) {
m_target = getContext().getSceneManager()->getFirstScene()->getRootNode()->find<KRNode>(m_target_name); // FINDME, HACK! - This won't work with multiple scenes in a context; we should move the animations out of KRAnimationManager and attach them to the parent nodes of the animated KRNode's
}
if (m_target == NULL) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Animation attribute could not find object: %s", m_target_name.c_str());
}
return m_target;
}
KRAnimationCurve* KRAnimationAttribute::getCurve()
{
if (m_curve == NULL) {
m_curve = getContext().getAnimationCurveManager()->getAnimationCurve(m_curve_name.c_str());
}
return m_curve;
}
void KRAnimationAttribute::deleteCurve()
{
KRAnimationCurve* curve = getCurve();
if (curve) {
getContext().getAnimationCurveManager()->deleteAnimationCurve(curve);
m_curve = NULL;
}
}

View File

@@ -0,0 +1,69 @@
//
// KRAnimationAttribute.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KRContextObject.h"
#include "KREngine-common.h"
#include "KRNode.h"
#include "resources/animation_curve/KRAnimationCurve.h"
class KRAnimationAttribute : public KRContextObject
{
public:
KRAnimationAttribute(KRContext& context);
~KRAnimationAttribute();
tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
void loadXML(tinyxml2::XMLElement* e);
std::string getCurveName() const;
void setCurveName(const std::string& curve_name);
std::string getTargetName() const;
void setTargetName(const std::string& target_name);
KRNode::node_attribute_type getTargetAttribute() const;
void setTargetAttribute(KRNode::node_attribute_type target_attribute);
KRNode* getTarget();
KRAnimationCurve* getCurve();
void deleteCurve();
private:
std::string m_target_name;
std::string m_curve_name;
KRNode::node_attribute_type m_node_attribute;
KRNode* m_target;
KRAnimationCurve* m_curve;
};

View File

@@ -0,0 +1,198 @@
//
// KRAnimationLayer.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimationLayer.h"
KRAnimationLayer::KRAnimationLayer(KRContext& context) : KRContextObject(context)
{
m_name = "";
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE;
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER;
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY;
}
KRAnimationLayer::~KRAnimationLayer()
{
for (std::vector<KRAnimationAttribute*>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr) {
delete (*itr);
}
}
std::string KRAnimationLayer::getName() const
{
return m_name;
}
void KRAnimationLayer::setName(const std::string& name)
{
m_name = name;
}
tinyxml2::XMLElement* KRAnimationLayer::saveXML(tinyxml2::XMLNode* parent)
{
tinyxml2::XMLDocument* doc = parent->GetDocument();
tinyxml2::XMLElement* e = doc->NewElement("layer");
tinyxml2::XMLNode* n = parent->InsertEndChild(e);
e->SetAttribute("name", m_name.c_str());
e->SetAttribute("weight", m_weight);
switch (m_blend_mode) {
case KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE:
e->SetAttribute("blend_mode", "additive");
break;
case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE:
e->SetAttribute("blend_mode", "override");
break;
case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH:
e->SetAttribute("blend_mode", "override_passthrough");
break;
}
switch (m_rotation_accumulation_mode) {
case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL:
e->SetAttribute("rotation_accumulation_mode", "by_channel");
break;
case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER:
e->SetAttribute("rotation_accumulation_mode", "by_layer");
break;
}
switch (m_scale_accumulation_mode) {
case KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE:
e->SetAttribute("scale_accumulation_mode", "additive");
break;
case KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY:
e->SetAttribute("scale_accumulation_mode", "multiply");
break;
}
for (std::vector<KRAnimationAttribute*>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr) {
(*itr)->saveXML(n);
}
return e;
}
void KRAnimationLayer::loadXML(tinyxml2::XMLElement* e)
{
m_name = e->Attribute("name");
if (e->QueryFloatAttribute("weight", &m_weight) != tinyxml2::XML_SUCCESS) {
m_weight = 1.0f; // default
}
const char* szBlendMode = e->Attribute("blend_mode");
if (strcmp(szBlendMode, "additive") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE;
} else if (strcmp(szBlendMode, "override") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE;
} else if (strcmp(szBlendMode, "override_passthrough") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH;
} else {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE; // default
}
const char* szRotationAccumulationMode = e->Attribute("rotation_accumulation_mode");
if (strcmp(szRotationAccumulationMode, "by_channel") == 0) {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL;
} else if (strcmp(szRotationAccumulationMode, "by_layer") == 0) {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER;
} else {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER; // default
}
const char* szScaleAccumulationMode = e->Attribute("scale_accumulation_mode");
if (strcmp(szScaleAccumulationMode, "additive") == 0) {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE;
} else if (strcmp(szScaleAccumulationMode, "multiply") == 0) {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY;
} else {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY; // default
}
for (tinyxml2::XMLElement* child_element = e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
if (strcmp(child_element->Name(), "attribute") == 0) {
KRAnimationAttribute* new_attribute = new KRAnimationAttribute(getContext());
new_attribute->loadXML(child_element);
m_attributes.push_back(new_attribute);
}
}
}
float KRAnimationLayer::getWeight() const
{
return m_weight;
}
void KRAnimationLayer::setWeight(float weight)
{
m_weight = weight;
}
KRAnimationLayer::blend_mode_t KRAnimationLayer::getBlendMode() const
{
return m_blend_mode;
}
void KRAnimationLayer::setBlendMode(const KRAnimationLayer::blend_mode_t& blend_mode)
{
m_blend_mode = blend_mode;
}
KRAnimationLayer::rotation_accumulation_mode_t KRAnimationLayer::getRotationAccumulationMode() const
{
return m_rotation_accumulation_mode;
}
void KRAnimationLayer::setRotationAccumulationMode(const KRAnimationLayer::rotation_accumulation_mode_t& rotation_accumulation_mode)
{
m_rotation_accumulation_mode = rotation_accumulation_mode;
}
KRAnimationLayer::scale_accumulation_mode_t KRAnimationLayer::getScaleAccumulationMode() const
{
return m_scale_accumulation_mode;
}
void KRAnimationLayer::setScaleAccumulationMode(const KRAnimationLayer::scale_accumulation_mode_t& scale_accumulation_mode)
{
m_scale_accumulation_mode = scale_accumulation_mode;
}
void KRAnimationLayer::addAttribute(KRAnimationAttribute* attribute)
{
m_attributes.push_back(attribute);
}
std::vector<KRAnimationAttribute*>& KRAnimationLayer::getAttributes()
{
return m_attributes;
}

View File

@@ -0,0 +1,97 @@
//
// KRAnimationLayer.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KRContextObject.h"
#include "KREngine-common.h"
#include "KRAnimationAttribute.h"
namespace tinyxml2 {
class XMLNode;
class XMLAttribute;
}
class KRAnimationLayer : public KRContextObject
{
public:
KRAnimationLayer(KRContext& context);
~KRAnimationLayer();
tinyxml2::XMLElement* saveXML(tinyxml2::XMLNode* parent);
void loadXML(tinyxml2::XMLElement* e);
std::string getName() const;
void setName(const std::string& name);
float getWeight() const;
void setWeight(float weight);
typedef enum
{
KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE,
KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE,
KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH
} blend_mode_t;
blend_mode_t getBlendMode() const;
void setBlendMode(const blend_mode_t& blend_mode);
typedef enum
{
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER,
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL
} rotation_accumulation_mode_t;
rotation_accumulation_mode_t getRotationAccumulationMode() const;
void setRotationAccumulationMode(const rotation_accumulation_mode_t& rotation_accumulation_mode);
typedef enum
{
KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY,
KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE
} scale_accumulation_mode_t;
scale_accumulation_mode_t getScaleAccumulationMode() const;
void setScaleAccumulationMode(const scale_accumulation_mode_t& scale_accumulation_mode);
void addAttribute(KRAnimationAttribute* attribute);
std::vector<KRAnimationAttribute*>& getAttributes();
private:
std::string m_name;
float m_weight;
blend_mode_t m_blend_mode;
rotation_accumulation_mode_t m_rotation_accumulation_mode;
scale_accumulation_mode_t m_scale_accumulation_mode;
std::vector<KRAnimationAttribute*> m_attributes;
};

View File

@@ -0,0 +1,135 @@
//
// KRAnimationManager.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimationManager.h"
#include "KRAnimation.h"
KRAnimationManager::KRAnimationManager(KRContext& context) : KRResourceManager(context)
{
}
KRAnimationManager::~KRAnimationManager()
{
for (std::set<KRAnimation*>::iterator itr = m_activeAnimations.begin(); itr != m_activeAnimations.end(); itr++) {
KRAnimation* animation = *itr;
animation->_unlockData();
}
for (unordered_map<std::string, KRAnimation*>::iterator itr = m_animations.begin(); itr != m_animations.end(); ++itr) {
delete (*itr).second;
}
}
void KRAnimationManager::startFrame(float deltaTime)
{
for (std::set<KRAnimation*>::iterator itr = m_animationsToUpdate.begin(); itr != m_animationsToUpdate.end(); itr++) {
KRAnimation* animation = *itr;
std::set<KRAnimation*>::iterator active_animations_itr = m_activeAnimations.find(animation);
if (animation->isPlaying()) {
// Add playing animations to the active animations list
if (active_animations_itr == m_activeAnimations.end()) {
m_activeAnimations.insert(animation);
animation->_lockData();
}
} else {
// Remove stopped animations from the active animations list
if (active_animations_itr != m_activeAnimations.end()) {
m_activeAnimations.erase(active_animations_itr);
animation->_unlockData();
}
}
}
m_animationsToUpdate.clear();
for (std::set<KRAnimation*>::iterator active_animations_itr = m_activeAnimations.begin(); active_animations_itr != m_activeAnimations.end(); active_animations_itr++) {
KRAnimation* animation = *active_animations_itr;
animation->update(deltaTime);
}
}
void KRAnimationManager::endFrame(float deltaTime)
{
}
KRResource* KRAnimationManager::loadResource(const std::string& name, const std::string& extension, mimir::Block* data)
{
if (extension.compare("kranimation") == 0) {
return loadAnimation(name.c_str(), data);
}
return nullptr;
}
KRResource* KRAnimationManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("kranimation") == 0) {
return getAnimation(name.c_str());
}
return nullptr;
}
KRAnimation* KRAnimationManager::loadAnimation(const char* szName, mimir::Block* data)
{
KRAnimation* pAnimation = KRAnimation::Load(*m_pContext, szName, data);
addAnimation(pAnimation);
return pAnimation;
}
KRAnimation* KRAnimationManager::getAnimation(const char* szName)
{
return m_animations[szName];
}
unordered_map<std::string, KRAnimation*>& KRAnimationManager::getAnimations()
{
return m_animations;
}
void KRAnimationManager::addAnimation(KRAnimation* new_animation)
{
m_animations[new_animation->getName()] = new_animation;
updateActiveAnimations(new_animation);
}
void KRAnimationManager::updateActiveAnimations(KRAnimation* animation)
{
m_animationsToUpdate.insert(animation);
}
void KRAnimationManager::deleteAnimation(KRAnimation* animation, bool delete_curves)
{
if (delete_curves) {
animation->deleteCurves();
}
m_animations.erase(animation->getName());
delete animation;
}

View File

@@ -0,0 +1,69 @@
//
// KRAnimationManager.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "resources/KRResourceManager.h"
#include "KRAnimation.h"
#include "KRContextObject.h"
#include "block.h"
class KRAnimationManager : public KRResourceManager
{
public:
KRAnimationManager(KRContext& context);
virtual ~KRAnimationManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, mimir::Block* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRAnimation* loadAnimation(const char* szName, mimir::Block* data);
KRAnimation* getAnimation(const char* szName);
void addAnimation(KRAnimation* new_animation);
unordered_map<std::string, KRAnimation*>& getAnimations();
void deleteAnimation(KRAnimation* animation, bool delete_curves);
void startFrame(float deltaTime);
void endFrame(float deltaTime);
void updateActiveAnimations(KRAnimation* animation);
private:
unordered_map<std::string, KRAnimation*> m_animations;
set<KRAnimation*> m_activeAnimations;
set<KRAnimation*> m_animationsToUpdate;
};

View File

@@ -0,0 +1,245 @@
//
// KRAnimationCurve.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRContext.h"
#include "KRAnimationCurve.h"
#include "block.h"
using namespace mimir;
KRAnimationCurve::KRAnimationCurve(KRContext& context, const std::string& name) : KRResource(context, name)
{
m_pData = new Block();
m_pData->expand(sizeof(animation_curve_header));
m_pData->lock();
animation_curve_header* header = (animation_curve_header*)m_pData->getStart();
strcpy(header->szTag, "KRCURVE1.0 ");
header->frame_rate = 30.0f;
header->frame_start = 0;
header->frame_count = 0;
m_pData->unlock();
}
KRAnimationCurve::~KRAnimationCurve()
{
m_pData->unload();
delete m_pData;
}
bool KRAnimationCurve::load(Block* data)
{
m_pData->unload();
delete m_pData;
m_pData = data;
return true;
}
std::string KRAnimationCurve::getExtension()
{
return "kranimationcurve";
}
bool KRAnimationCurve::save(const std::string& path)
{
return m_pData->save(path);
}
bool KRAnimationCurve::save(Block& data)
{
data.append(*m_pData);
return true;
}
KRAnimationCurve* KRAnimationCurve::Load(KRContext& context, const std::string& name, Block* data)
{
KRAnimationCurve* new_animation_curve = new KRAnimationCurve(context, name);
if (new_animation_curve->load(data)) {
return new_animation_curve;
} else {
delete new_animation_curve;
delete data;
return NULL;
}
}
int KRAnimationCurve::getFrameCount()
{
m_pData->lock();
int frame_count = ((animation_curve_header*)m_pData->getStart())->frame_count;
m_pData->unlock();
return frame_count;
}
void KRAnimationCurve::setFrameCount(int frame_count)
{
m_pData->lock();
int prev_frame_count = getFrameCount();
if (frame_count != prev_frame_count) {
float fill_value = 0.0f;
if (prev_frame_count > 0) {
fill_value = getValue(prev_frame_count - 1);
}
m_pData->expand(sizeof(animation_curve_header) + sizeof(float) * frame_count - m_pData->getSize());
float* frame_data = (float*)((char*)m_pData->getStart() + sizeof(animation_curve_header));
for (int frame_number = prev_frame_count; frame_number < frame_count; frame_number++) {
frame_data[frame_number] = fill_value;
}
((animation_curve_header*)m_pData->getStart())->frame_count = frame_count;
}
m_pData->unlock();
}
float KRAnimationCurve::getFrameRate()
{
m_pData->lock();
float frame_rate = ((animation_curve_header*)m_pData->getStart())->frame_rate;
m_pData->unlock();
return frame_rate;
}
void KRAnimationCurve::setFrameRate(float frame_rate)
{
m_pData->lock();
((animation_curve_header*)m_pData->getStart())->frame_rate = frame_rate;
m_pData->unlock();
}
int KRAnimationCurve::getFrameStart()
{
m_pData->lock();
int frame_start = ((animation_curve_header*)m_pData->getStart())->frame_start;
m_pData->unlock();
return frame_start;
}
void KRAnimationCurve::setFrameStart(int frame_number)
{
m_pData->lock();
((animation_curve_header*)m_pData->getStart())->frame_start = frame_number;
m_pData->unlock();
}
float KRAnimationCurve::getValue(int frame_number)
{
m_pData->lock();
//printf("frame_number: %i\n", frame_number);
int clamped_frame = frame_number - getFrameStart();
if (clamped_frame < 0) {
clamped_frame = 0;
} else if (clamped_frame >= getFrameCount()) {
clamped_frame = getFrameCount() - 1;
}
float* frame_data = (float*)((char*)m_pData->getStart() + sizeof(animation_curve_header));
float v = frame_data[clamped_frame];
m_pData->unlock();
return v;
}
void KRAnimationCurve::setValue(int frame_number, float value)
{
m_pData->lock();
int clamped_frame = frame_number - getFrameStart();
if (clamped_frame >= 0 && clamped_frame < getFrameCount()) {
float* frame_data = (float*)((char*)m_pData->getStart() + sizeof(animation_curve_header));
frame_data[clamped_frame] = value;
}
m_pData->unlock();
}
float KRAnimationCurve::getValue(float local_time)
{
// TODO - Need to add interpolation for time values between frames.
// Must consider looping animations when determining which two frames to interpolate between.
m_pData->lock();
float v = getValue((int)(local_time * getFrameRate()));
m_pData->unlock();
return v;
}
bool KRAnimationCurve::valueChanges(float start_time, float duration)
{
m_pData->lock();
bool c = valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
m_pData->unlock();
return c;
}
bool KRAnimationCurve::valueChanges(int start_frame, int frame_count)
{
m_pData->lock();
float first_value = getValue(start_frame);
bool change_found = false;
// Range of frames is not inclusive of last frame
for (int frame_number = start_frame + 1; frame_number < start_frame + frame_count && !change_found; frame_number++) {
if (getValue(frame_number) != first_value) {
change_found = true;
}
}
m_pData->unlock();
return change_found;
}
KRAnimationCurve* KRAnimationCurve::split(const std::string& name, float start_time, float duration)
{
return split(name, (int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
}
KRAnimationCurve* KRAnimationCurve::split(const std::string& name, int start_frame, int frame_count)
{
KRAnimationCurve* new_curve = new KRAnimationCurve(getContext(), name);
new_curve->setFrameRate(getFrameRate());
new_curve->setFrameStart(start_frame);
new_curve->setFrameCount(frame_count);
new_curve->m_pData->lock();
// Range of frames is not inclusive of last frame
for (int frame_number = start_frame; frame_number < start_frame + frame_count; frame_number++) {
new_curve->setValue(frame_number, getValue(frame_number)); // TODO - MEMCPY here?
}
new_curve->m_pData->unlock();
getContext().getAnimationCurveManager()->addAnimationCurve(new_curve);
return new_curve;
}
void KRAnimationCurve::_lockData()
{
m_pData->lock();
}
void KRAnimationCurve::_unlockData()
{
m_pData->unlock();
}

View File

@@ -0,0 +1,85 @@
//
// KRAnimationCurve.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "block.h"
#include "resources/KRResource.h"
class KRAnimationCurve : public KRResource
{
public:
KRAnimationCurve(KRContext& context, const std::string& name);
virtual ~KRAnimationCurve();
virtual std::string getExtension();
virtual bool save(const std::string& path);
virtual bool save(mimir::Block& data);
virtual bool load(mimir::Block* data);
float getFrameRate();
void setFrameRate(float frame_rate);
int getFrameStart();
void setFrameStart(int frame_number);
int getFrameCount();
void setFrameCount(int frame_count);
float getValue(float local_time);
float getValue(int frame_number);
void setValue(int frame_number, float value);
static KRAnimationCurve* Load(KRContext& context, const std::string& name, mimir::Block* data);
bool valueChanges(float start_time, float duration);
bool valueChanges(int start_frame, int frame_count);
KRAnimationCurve* split(const std::string& name, float start_time, float duration);
KRAnimationCurve* split(const std::string& name, int start_frame, int frame_count);
void _lockData();
void _unlockData();
private:
mimir::Block* m_pData;
typedef struct
{
char szTag[16];
float frame_rate;
int32_t frame_start;
int32_t frame_count;
} animation_curve_header;
};

View File

@@ -0,0 +1,97 @@
//
// KRAnimationCurveManager.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimationCurveManager.h"
#include "KRAnimationCurve.h"
KRAnimationCurveManager::KRAnimationCurveManager(KRContext& context) : KRResourceManager(context)
{
}
KRAnimationCurveManager::~KRAnimationCurveManager()
{
for (unordered_map<std::string, KRAnimationCurve*>::iterator itr = m_animationCurves.begin(); itr != m_animationCurves.end(); ++itr) {
delete (*itr).second;
}
}
void KRAnimationCurveManager::deleteAnimationCurve(KRAnimationCurve* curve)
{
m_animationCurves.erase(curve->getName());
delete curve;
}
KRResource* KRAnimationCurveManager::loadResource(const std::string& name, const std::string& extension, mimir::Block* data)
{
if (extension.compare("kranimationcurve") == 0) {
return loadAnimationCurve(name, data);
}
return nullptr;
}
KRResource* KRAnimationCurveManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("kranimationcurve") == 0) {
return getAnimationCurve(name);
}
return nullptr;
}
KRAnimationCurve* KRAnimationCurveManager::loadAnimationCurve(const std::string& name, mimir::Block* data)
{
KRAnimationCurve* pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data);
if (pAnimationCurve) {
m_animationCurves[name] = pAnimationCurve;
}
return pAnimationCurve;
}
KRAnimationCurve* KRAnimationCurveManager::getAnimationCurve(const std::string& name)
{
unordered_map<std::string, KRAnimationCurve*>::iterator itr = m_animationCurves.find(name);
if (itr == m_animationCurves.end()) {
return NULL; // Not found
} else {
return (*itr).second;
}
}
unordered_map<std::string, KRAnimationCurve*>& KRAnimationCurveManager::getAnimationCurves()
{
return m_animationCurves;
}
void KRAnimationCurveManager::addAnimationCurve(KRAnimationCurve* new_animation_curve)
{
assert(new_animation_curve != NULL);
m_animationCurves[new_animation_curve->getName()] = new_animation_curve;
}

View File

@@ -0,0 +1,63 @@
//
// KRAnimationCurveManager.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "resources/KRResourceManager.h"
#include "KRAnimationCurve.h"
#include "KRContextObject.h"
#include "block.h"
using std::map;
class KRAnimationCurveManager : public KRResourceManager
{
public:
KRAnimationCurveManager(KRContext& context);
virtual ~KRAnimationCurveManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, mimir::Block* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRAnimationCurve* loadAnimationCurve(const std::string& name, mimir::Block* data);
KRAnimationCurve* getAnimationCurve(const std::string& name);
void addAnimationCurve(KRAnimationCurve* new_animation_curve);
unordered_map<std::string, KRAnimationCurve*>& getAnimationCurves();
void deleteAnimationCurve(KRAnimationCurve* curve);
private:
unordered_map<std::string, KRAnimationCurve*> m_animationCurves;
};

View File

@@ -0,0 +1,172 @@
//
// KRBundle.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRBundle.h"
#include "KRContext.h"
#include "KREngine-common.h"
using namespace mimir;
const int KRENGINE_KRBUNDLE_HEADER_SIZE = 512;
typedef struct _tar_header
{
char file_name[100];
char file_mode[8];
char owner_id[8]; // Owner's numeric user ID (OCTAL!)
char group_id[8]; // Group's numeric user ID (OCTAL!)
char file_size[12]; // File size in bytes (OCTAL!)
char mod_time[12]; // Last modification time in numeric Unix time format
char checksum[8]; // Checksum for header block
char file_type[1]; // Link indicator (file type)
char linked_file[100]; // Name of linked file
} tar_header_type;
KRBundle::KRBundle(KRContext& context, std::string name, Block* pData) : KRResource(context, name)
{
m_pData = pData;
__int64_t file_pos = 0;
while (file_pos < (__int64_t)m_pData->getSize()) {
tar_header_type file_header;
m_pData->copy(&file_header, (int)file_pos, sizeof(file_header));
size_t file_size = strtol(file_header.file_size, NULL, 8);
file_pos += 512; // Skip past the header to the file contents
if (file_header.file_name[0] != '\0' && file_header.file_name[0] != '.') {
// We ignore the last two records in the tar file, which are zero'ed out tar_header structures
Block* pFileData = pData->getSubBlock((int)file_pos, (int)file_size);
context.loadResource(file_header.file_name, pFileData);
}
file_pos += RoundUpSize(file_size);
}
}
KRBundle::KRBundle(KRContext& context, std::string name) : KRResource(context, name)
{
// Create an empty krbundle (tar) file, initialized with two zero-ed out file headers, which terminate it.
m_pData = new Block();
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE * 2);
m_pData->lock();
memset(m_pData->getStart(), 0, m_pData->getSize());
m_pData->unlock();
}
size_t KRBundle::RoundUpSize(size_t s)
{
// Get amount of padding needed to increase s to a 512 byte alignment
if ((s & 0x01ff) == 0) {
// file size is a multiple of 512 bytes, we can just add it
return s;
} else {
// We would not be on a 512 byte boundary, round up to the next one
return (s + 0x0200) - (s & 0x1ff);
}
}
KRBundle::~KRBundle()
{
delete m_pData;
}
std::string KRBundle::getExtension()
{
return "krbundle";
}
bool KRBundle::save(const std::string& path)
{
return m_pData->save(path);
}
bool KRBundle::save(Block& data)
{
if (m_pData->getSize() > KRENGINE_KRBUNDLE_HEADER_SIZE * 2) {
// Only output krbundles that contain files
data.append(*m_pData);
}
return true;
}
Block* KRBundle::append(KRResource& resource)
{
// Serialize resource to binary representation
Block resource_data;
resource.save(resource_data);
std::string file_name = resource.getName() + "." + resource.getExtension();
// Padding is added at the end of file to align next header to a 512 byte boundary. Padding at the end of the archive includes an additional 1024 bytes -- two zero-ed out file headers that mark the end of the archive
size_t padding_size = RoundUpSize(resource_data.getSize()) - resource_data.getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE * 2;
size_t resource_data_start = m_pData->getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE;
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE + resource_data.getSize() + padding_size - KRENGINE_KRBUNDLE_HEADER_SIZE * 2); // We will overwrite the existing zero-ed out file headers that marked the end of the archive, so we don't have to include their size here
m_pData->lock();
// Get location of file header
tar_header_type* file_header = (tar_header_type*)((unsigned char*)m_pData->getEnd() - padding_size - resource_data.getSize() - KRENGINE_KRBUNDLE_HEADER_SIZE);
// Zero out new file header
memset(file_header, 0, KRENGINE_KRBUNDLE_HEADER_SIZE);
// Copy resource data
resource_data.lock();
memcpy((unsigned char*)m_pData->getEnd() - padding_size - resource_data.getSize(), resource_data.getStart(), resource_data.getSize());
resource_data.unlock();
// Zero out alignment padding and terminating set of file header blocks
memset((unsigned char*)m_pData->getEnd() - padding_size, 0, padding_size);
// Populate new file header fields
strncpy(file_header->file_name, file_name.c_str(), 100);
strcpy(file_header->file_mode, "000644 ");
strcpy(file_header->owner_id, "000000 ");
strcpy(file_header->group_id, "000000 ");
sprintf(file_header->file_size, "%011o", (int)resource_data.getSize());
file_header->file_size[11] = ' '; // Terminate with space rather than '\0'
sprintf(file_header->mod_time, "%011o", (int)time(NULL));
file_header->mod_time[11] = ' '; // Terminate with space rather than '\0'
// Calculate and write checksum for header
memset(file_header->checksum, ' ', 8); // Must be filled with spaces and no null terminator during checksum calculation
int check_sum = 0;
for (int i = 0; i < KRENGINE_KRBUNDLE_HEADER_SIZE; i++) {
unsigned char* byte_ptr = (unsigned char*)file_header;
check_sum += byte_ptr[i];
}
sprintf(file_header->checksum, "%07o", check_sum);
m_pData->unlock();
Block* pFileData = m_pData->getSubBlock((int)resource_data_start, (int)resource_data.getSize());
return pFileData;
}

View File

@@ -0,0 +1,52 @@
//
// KRBundle.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "resources/KRResource.h"
#include "block.h"
class KRBundle : public KRResource
{
public:
KRBundle(KRContext& context, std::string name, mimir::Block* pData);
KRBundle(KRContext& context, std::string name);
virtual ~KRBundle();
virtual std::string getExtension();
virtual bool save(const std::string& path);
virtual bool save(mimir::Block& data);
mimir::Block* append(KRResource& resource);
private:
mimir::Block* m_pData;
static size_t RoundUpSize(size_t s);
};

View File

@@ -0,0 +1,87 @@
//
// KRBundleManager.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRBundleManager.h"
#include "KRBundle.h"
KRBundleManager::KRBundleManager(KRContext& context) : KRResourceManager(context)
{
}
KRBundleManager::~KRBundleManager()
{
for (unordered_map<std::string, KRBundle*>::iterator itr = m_bundles.begin(); itr != m_bundles.end(); ++itr) {
delete (*itr).second;
}
m_bundles.clear();
}
KRResource* KRBundleManager::loadResource(const std::string& name, const std::string& extension, mimir::Block* data)
{
if (extension.compare("krbundle") == 0) {
return loadBundle(name.c_str(), data);
}
return nullptr;
}
KRResource* KRBundleManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("krbundle") == 0) {
return getBundle(name.c_str());
}
return nullptr;
}
KRBundle* KRBundleManager::loadBundle(const char* szName, mimir::Block* pData)
{
KRBundle* pBundle = new KRBundle(*m_pContext, szName, pData);
m_bundles[szName] = pBundle;
return pBundle;
}
KRBundle* KRBundleManager::createBundle(const char* szName)
{
// TODO: Check for name conflicts
KRBundle* pBundle = new KRBundle(*m_pContext, szName);
m_bundles[szName] = pBundle;
return pBundle;
}
KRBundle* KRBundleManager::getBundle(const char* szName)
{
return m_bundles[szName];
}
unordered_map<std::string, KRBundle*> KRBundleManager::getBundles()
{
return m_bundles;
}

View File

@@ -0,0 +1,61 @@
//
// KRBundleManager.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "resources/KRResourceManager.h"
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "block.h"
class KRContext;
class KRBundle;
class KRBundleManager : public KRResourceManager
{
public:
KRBundleManager(KRContext& context);
~KRBundleManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, mimir::Block* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRBundle* loadBundle(const char* szName, mimir::Block* pData);
KRBundle* getBundle(const char* szName);
KRBundle* createBundle(const char* szName);
std::vector<std::string> getBundleNames();
unordered_map<std::string, KRBundle*> getBundles();
private:
unordered_map<std::string, KRBundle*> m_bundles;
};

View File

@@ -0,0 +1,477 @@
//
// KRMaterial.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRMaterial.h"
#include "KRTextureManager.h"
#include "KRRenderPass.h"
#include "KRContext.h"
using namespace mimir;
using namespace hydra;
KRMaterial::KRMaterial(KRContext& context, const char* szName) : KRResource(context, szName)
{
m_name = szName;
m_pAmbientMap = NULL;
m_pDiffuseMap = NULL;
m_pSpecularMap = NULL;
m_pNormalMap = NULL;
m_pReflectionMap = NULL;
m_pReflectionCube = NULL;
m_ambientColor = Vector3::Zero();
m_diffuseColor = Vector3::One();
m_specularColor = Vector3::One();
m_reflectionColor = Vector3::Zero();
m_tr = 1.0f;
m_ns = 0.0f;
m_ambientMap = "";
m_diffuseMap = "";
m_specularMap = "";
m_normalMap = "";
m_reflectionMap = "";
m_reflectionCube = "";
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
m_specularMapScale = Vector2::Create(1.0f, 1.0f);
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
}
KRMaterial::~KRMaterial()
{
}
std::string KRMaterial::getExtension()
{
return "mtl";
}
bool KRMaterial::needsVertexTangents()
{
return m_normalMap.size() > 0;
}
bool KRMaterial::save(Block& data)
{
std::stringstream stream;
stream.precision(std::numeric_limits<long double>::digits10);
stream.setf(std::ios::fixed, std::ios::floatfield);
stream << "newmtl " << m_name;
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
stream << "\nTr " << m_tr;
stream << "\nNs " << m_ns;
if (m_ambientMap.size()) {
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
} else {
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_diffuseMap.size()) {
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
} else {
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_specularMap.size()) {
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
} else {
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_normalMap.size()) {
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
} else {
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_reflectionMap.size()) {
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
} else {
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if (m_reflectionCube.size()) {
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
} else {
stream << "\n# map_ReflectionCube cubemapname";
}
switch (m_alpha_mode) {
case KRMATERIAL_ALPHA_MODE_OPAQUE:
stream << "\nalpha_mode opaque";
break;
case KRMATERIAL_ALPHA_MODE_TEST:
stream << "\nalpha_mode test";
break;
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
stream << "\nalpha_mode blendoneside";
break;
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
stream << "\nalpha_mode blendtwoside";
break;
}
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
stream << "\n";
data.append(stream.str());
return true;
}
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
{
m_ambientMap = texture_name;
m_ambientMapScale = texture_scale;
m_ambientMapOffset = texture_offset;
}
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
{
m_diffuseMap = texture_name;
m_diffuseMapScale = texture_scale;
m_diffuseMapOffset = texture_offset;
}
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
{
m_specularMap = texture_name;
m_specularMapScale = texture_scale;
m_specularMapOffset = texture_offset;
}
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
{
m_normalMap = texture_name;
m_normalMapScale = texture_scale;
m_normalMapOffset = texture_offset;
}
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset)
{
m_reflectionMap = texture_name;
m_reflectionMapScale = texture_scale;
m_reflectionMapOffset = texture_offset;
}
void KRMaterial::setReflectionCube(std::string texture_name)
{
m_reflectionCube = texture_name;
}
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode)
{
m_alpha_mode = alpha_mode;
}
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode()
{
return m_alpha_mode;
}
void KRMaterial::setAmbient(const Vector3& c)
{
m_ambientColor = c;
}
void KRMaterial::setDiffuse(const Vector3& c)
{
m_diffuseColor = c;
}
void KRMaterial::setSpecular(const Vector3& c)
{
m_specularColor = c;
}
void KRMaterial::setReflection(const Vector3& c)
{
m_reflectionColor = c;
}
void KRMaterial::setTransparency(float a)
{
if (a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
}
m_tr = a;
}
void KRMaterial::setShininess(float s)
{
m_ns = s;
}
bool KRMaterial::isTransparent()
{
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
}
void KRMaterial::preStream(float lodCoverage)
{
getTextures();
if (m_pAmbientMap) {
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
}
if (m_pDiffuseMap) {
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
}
if (m_pNormalMap) {
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
}
if (m_pSpecularMap) {
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
}
if (m_pReflectionMap) {
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
}
if (m_pReflectionCube) {
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
}
}
kraken_stream_level KRMaterial::getStreamLevel()
{
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
getTextures();
if (m_pAmbientMap) {
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
}
if (m_pDiffuseMap) {
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
}
if (m_pNormalMap) {
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
}
if (m_pSpecularMap) {
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
}
if (m_pReflectionMap) {
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
}
if (m_pReflectionCube) {
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
}
return stream_level;
}
void KRMaterial::getTextures()
{
if (!m_pAmbientMap && m_ambientMap.size()) {
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
}
if (!m_pDiffuseMap && m_diffuseMap.size()) {
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
}
if (!m_pNormalMap && m_normalMap.size()) {
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
}
if (!m_pSpecularMap && m_specularMap.size()) {
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
}
if (!m_pReflectionMap && m_reflectionMap.size()) {
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
}
if (!m_pReflectionCube && m_reflectionCube.size()) {
m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());
}
}
void KRMaterial::bind(const KRNode::RenderInfo& ri, ModelFormat modelFormat, __uint32_t vertexAttributes, CullMode cullMode, const std::vector<KRBone*>& bones, const std::vector<Matrix4>& bind_poses, const Matrix4& matModel, KRTexture* pLightMap, const Vector3& rim_color, float rim_power, float lod_coverage)
{
bool bLightMap = pLightMap && ri.camera->settings.bEnableLightMap;
getTextures();
Vector2 default_scale = Vector2::One();
Vector2 default_offset = Vector2::Zero();
bool bHasReflection = m_reflectionColor != Vector3::Zero();
bool bDiffuseMap = m_pDiffuseMap != NULL && ri.camera->settings.bEnableDiffuseMap;
bool bNormalMap = m_pNormalMap != NULL && ri.camera->settings.bEnableNormalMap;
bool bSpecMap = m_pSpecularMap != NULL && ri.camera->settings.bEnableSpecMap;
bool bReflectionMap = m_pReflectionMap != NULL && ri.camera->settings.bEnableReflectionMap && ri.camera->settings.bEnableReflection && bHasReflection;
bool bReflectionCubeMap = m_pReflectionCube != NULL && ri.camera->settings.bEnableReflection && bHasReflection;
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
PipelineInfo info{};
std::string shader_name("ObjectShader");
info.shader_name = &shader_name;
info.pCamera = ri.camera;
info.point_lights = &ri.point_lights;
info.directional_lights = &ri.directional_lights;
info.spot_lights = &ri.spot_lights;
info.bone_count = (int)bones.size();
info.renderPass = ri.renderPass;
info.bDiffuseMap = bDiffuseMap;
info.bNormalMap = bNormalMap;
info.bSpecMap = bSpecMap;
info.bReflectionMap = bReflectionMap;
info.bReflectionCubeMap = bReflectionCubeMap;
info.bLightMap = bLightMap;
info.bDiffuseMapScale = m_diffuseMapScale != default_scale && bDiffuseMap;
info.bSpecMapScale = m_specularMapScale != default_scale && bSpecMap;
info.bNormalMapScale = m_normalMapScale != default_scale && bNormalMap;
info.bReflectionMapScale = m_reflectionMapScale != default_scale && bReflectionMap;
info.bDiffuseMapOffset = m_diffuseMapOffset != default_offset && bDiffuseMap;
info.bSpecMapOffset = m_specularMapOffset != default_offset && bSpecMap;
info.bNormalMapOffset = m_normalMapOffset != default_offset && bNormalMap;
info.bReflectionMapOffset = m_reflectionMapOffset != default_offset && bReflectionMap;
info.bAlphaTest = bAlphaTest;
info.rasterMode = bAlphaBlend ? RasterMode::kAlphaBlend : RasterMode::kOpaque;
info.bRimColor = rim_power != 0.0f;
info.renderPass = ri.renderPass;
info.modelFormat = modelFormat;
info.vertexAttributes = vertexAttributes;
info.cullMode = cullMode;
KRPipeline* pShader = getContext().getPipelineManager()->getPipeline(*ri.surface, info);
// Rim highlighting parameters
pShader->setPushConstant(KRPipeline::PushConstant::rim_color, rim_color);
pShader->setPushConstant(KRPipeline::PushConstant::rim_power, rim_power);
// Bind bones
if (pShader->hasPushConstant(KRPipeline::PushConstant::bone_transforms)) {
float bone_mats[256 * 16];
float* bone_mat_component = bone_mats;
for (int bone_index = 0; bone_index < bones.size(); bone_index++) {
KRBone* bone = bones[bone_index];
// Vector3 initialRotation = bone->getInitialLocalRotation();
// Vector3 rotation = bone->getLocalRotation();
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
// Vector3 translation = bone->getLocalTranslation();
// Vector3 initialScale = bone->getInitialLocalScale();
// Vector3 scale = bone->getLocalScale();
//
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
Matrix4 active_mat = bone->getActivePoseMatrix();
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
Matrix4 t = (inv_bind_mat * active_mat);
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
for (int i = 0; i < 16; i++) {
*bone_mat_component++ = t[i];
}
}
if (pShader->hasPushConstant(KRPipeline::PushConstant::bone_transforms)) {
pShader->setPushConstant(KRPipeline::PushConstant::bone_transforms, (Matrix4*)bone_mats, bones.size());
}
}
pShader->setPushConstant(KRPipeline::PushConstant::material_ambient, m_ambientColor + ri.camera->settings.ambient_intensity);
if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer
pShader->setPushConstant(KRPipeline::PushConstant::material_diffuse, Vector3::Create(m_diffuseColor.x * ri.camera->settings.light_intensity.x, m_diffuseColor.y * ri.camera->settings.light_intensity.y, m_diffuseColor.z * ri.camera->settings.light_intensity.z));
} else {
pShader->setPushConstant(KRPipeline::PushConstant::material_diffuse, m_diffuseColor);
}
if (ri.renderPass->getType() == RenderPassType::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer
pShader->setPushConstant(KRPipeline::PushConstant::material_specular, Vector3::Create(m_specularColor.x * ri.camera->settings.light_intensity.x, m_specularColor.y * ri.camera->settings.light_intensity.y, m_specularColor.z * ri.camera->settings.light_intensity.z));
} else {
pShader->setPushConstant(KRPipeline::PushConstant::material_specular, m_specularColor);
}
pShader->setPushConstant(KRPipeline::PushConstant::material_shininess, m_ns);
pShader->setPushConstant(KRPipeline::PushConstant::material_reflection, m_reflectionColor);
pShader->setPushConstant(KRPipeline::PushConstant::diffusetexture_scale, m_diffuseMapScale);
pShader->setPushConstant(KRPipeline::PushConstant::speculartexture_scale, m_specularMapScale);
pShader->setPushConstant(KRPipeline::PushConstant::reflectiontexture_scale, m_reflectionMapScale);
pShader->setPushConstant(KRPipeline::PushConstant::normaltexture_scale, m_normalMapScale);
pShader->setPushConstant(KRPipeline::PushConstant::diffusetexture_offset, m_diffuseMapOffset);
pShader->setPushConstant(KRPipeline::PushConstant::speculartexture_offset, m_specularMapOffset);
pShader->setPushConstant(KRPipeline::PushConstant::reflectiontexture_offset, m_reflectionMapOffset);
pShader->setPushConstant(KRPipeline::PushConstant::normaltexture_offset, m_normalMapOffset);
pShader->setPushConstant(KRPipeline::PushConstant::material_alpha, m_tr);
if (bDiffuseMap) {
m_pDiffuseMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
pShader->setImageBinding("diffuseTexture", m_pDiffuseMap, getContext().getSamplerManager()->DEFAULT_WRAPPING_SAMPLER);
}
if (bSpecMap) {
m_pSpecularMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
pShader->setImageBinding("specularTexture", m_pDiffuseMap, getContext().getSamplerManager()->DEFAULT_WRAPPING_SAMPLER);
}
if (bNormalMap) {
m_pNormalMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
pShader->setImageBinding("normalTexture", m_pNormalMap, getContext().getSamplerManager()->DEFAULT_WRAPPING_SAMPLER);
}
if (bReflectionCubeMap) {
m_pReflectionCube->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
pShader->setImageBinding("reflectionCubeTexture", m_pReflectionCube, getContext().getSamplerManager()->DEFAULT_CLAMPED_SAMPLER);
}
if (bReflectionMap) {
m_pReflectionMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
pShader->setImageBinding("reflectionTexture", m_pReflectionMap, getContext().getSamplerManager()->DEFAULT_CLAMPED_SAMPLER);
}
pShader->bind(ri.commandBuffer, *ri.camera, ri.viewport, matModel, &ri.point_lights, &ri.directional_lights, &ri.spot_lights, ri.renderPass);
}
const std::string& KRMaterial::getName() const
{
return m_name;
}

View File

@@ -0,0 +1,140 @@
//
// KRMaterial.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "KRTexture.h"
#include "KRPipelineManager.h"
#include "KRPipeline.h"
#include "KRCamera.h"
#include "resources/KRResource.h"
#include "KRScene.h"
#include "KRBone.h"
enum class CullMode : __uint32_t;
enum class ModelFormat : __uint8_t;
class KRTextureManager;
class KRContext;
class KRSurface;
class KRMaterial : public KRResource
{
public:
typedef enum
{
KRMATERIAL_ALPHA_MODE_OPAQUE, // Non-transparent materials
KRMATERIAL_ALPHA_MODE_TEST, // Alpha in diffuse texture is interpreted as punch-through when < 0.5
KRMATERIAL_ALPHA_MODE_BLENDONESIDE, // Blended alpha with backface culling
KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces.
} alpha_mode_type;
KRMaterial(KRContext& context, const char* szName);
virtual ~KRMaterial();
virtual std::string getExtension();
virtual bool save(mimir::Block& data);
void setAmbientMap(std::string texture_name, hydra::Vector2 texture_scale, hydra::Vector2 texture_offset);
void setDiffuseMap(std::string texture_name, hydra::Vector2 texture_scale, hydra::Vector2 texture_offset);
void setSpecularMap(std::string texture_name, hydra::Vector2 texture_scale, hydra::Vector2 texture_offset);
void setReflectionMap(std::string texture_name, hydra::Vector2 texture_scale, hydra::Vector2 texture_offset);
void setReflectionCube(std::string texture_name);
void setNormalMap(std::string texture_name, hydra::Vector2 texture_scale, hydra::Vector2 texture_offset);
void setAmbient(const hydra::Vector3& c);
void setDiffuse(const hydra::Vector3& c);
void setSpecular(const hydra::Vector3& c);
void setReflection(const hydra::Vector3& c);
void setTransparency(float a);
void setShininess(float s);
void setAlphaMode(alpha_mode_type blend_mode);
alpha_mode_type getAlphaMode();
bool isTransparent();
const std::string& getName() const;
void bind(const KRNode::RenderInfo& ri, ModelFormat modelFormat, __uint32_t vertexAttributes, CullMode cullMode, const std::vector<KRBone*>& bones, const std::vector<hydra::Matrix4>& bind_poses, const hydra::Matrix4& matModel, KRTexture* pLightMap, const hydra::Vector3& rim_color, float rim_power, float lod_coverage = 0.0f);
bool needsVertexTangents();
kraken_stream_level getStreamLevel();
void preStream(float lodCoverage);
private:
std::string m_name;
KRTexture* m_pAmbientMap; // mtl map_Ka value
KRTexture* m_pDiffuseMap; // mtl map_Kd value
KRTexture* m_pSpecularMap; // mtl map_Ks value
KRTexture* m_pReflectionMap; // mtl refl value
KRTexture* m_pReflectionCube;
KRTexture* m_pNormalMap; // mtl map_Normal value
std::string m_ambientMap;
std::string m_diffuseMap;
std::string m_specularMap;
std::string m_reflectionMap;
std::string m_reflectionCube;
std::string m_normalMap;
hydra::Vector2 m_ambientMapScale;
hydra::Vector2 m_ambientMapOffset;
hydra::Vector2 m_diffuseMapScale;
hydra::Vector2 m_diffuseMapOffset;
hydra::Vector2 m_specularMapScale;
hydra::Vector2 m_specularMapOffset;
hydra::Vector2 m_reflectionMapScale;
hydra::Vector2 m_reflectionMapOffset;
hydra::Vector2 m_normalMapScale;
hydra::Vector2 m_normalMapOffset;
hydra::Vector3 m_ambientColor; // Ambient rgb
hydra::Vector3 m_diffuseColor; // Diffuse rgb
hydra::Vector3 m_specularColor; // Specular rgb
hydra::Vector3 m_reflectionColor; // Reflection rgb
//float m_ka_r, m_ka_g, m_ka_b; // Ambient rgb
//float m_kd_r, m_kd_g, m_kd_b; // Diffuse rgb
//float m_ks_r, m_ks_g, m_ks_b; // Specular rgb
//float m_kr_r, m_kr_g, m_kr_b; // Reflection rgb
float m_tr; // Transparency
float m_ns; // Shininess
alpha_mode_type m_alpha_mode;
void getTextures();
};

View File

@@ -0,0 +1,289 @@
//
// KRMaterialManager.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRMaterialManager.h"
using namespace mimir;
using namespace hydra;
KRMaterialManager::KRMaterialManager(KRContext& context, KRTextureManager* pTextureManager, KRPipelineManager* pPipelineManager) : KRResourceManager(context)
{
m_pTextureManager = pTextureManager;
m_pPipelineManager = pPipelineManager;
}
KRMaterialManager::~KRMaterialManager()
{
}
KRResource* KRMaterialManager::loadResource(const std::string& name, const std::string& extension, Block* data)
{
if (extension.compare("mtl") == 0) {
return load(name.c_str(), data);
}
return nullptr;
}
KRResource* KRMaterialManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("mtl") == 0) {
// TODO - This is not correct -- there are multiple materials emitted in a single mtl file.
// We should treat "mtl" files as source files, managed by KRSource, which output
// material resources when compiled.
return m_materials[name];
}
return nullptr;
}
unordered_map<std::string, KRMaterial*>& KRMaterialManager::getMaterials()
{
return m_materials;
}
KRMaterial* KRMaterialManager::getMaterial(const std::string& name)
{
std::string lowerName = name;
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
unordered_map<std::string, KRMaterial*>::iterator itr = m_materials.find(lowerName);
if (itr == m_materials.end()) {
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
// Not found
return NULL;
} else {
return (*itr).second;
}
}
void KRMaterialManager::add(KRMaterial* new_material)
{
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
std::string lowerName = new_material->getName();
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
m_materials[lowerName] = new_material;
}
KRMaterial* KRMaterialManager::load(const char* szName, Block* data)
{
KRMaterial* pMaterial = NULL;
char szSymbol[16][256];
data->lock();
char* pScan = (char*)data->getStart();
char* pEnd = (char*)data->getEnd();
while (pScan < pEnd) {
// Scan through whitespace
while (pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++;
}
if (*pScan == '#') {
// Line is a comment line
// Scan to the end of the line
while (pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++;
}
} else {
int cSymbols = 0;
while (pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char* pDest = szSymbol[cSymbols++];
while (pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
if (*pScan >= 'A' && *pScan <= 'Z') {
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
} else {
*pDest++ = *pScan++;
}
}
*pDest = '\0';
// Scan through whitespace, but don't advance to next line
while (pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++;
}
}
if (cSymbols > 0) {
if (strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
m_materials[szSymbol[1]] = pMaterial;
}
if (pMaterial != NULL) {
if (strcmp(szSymbol[0], "alpha_mode") == 0) {
if (cSymbols == 2) {
if (strcmp(szSymbol[1], "test") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
} else if (strcmp(szSymbol[1], "blendoneside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
} else if (strcmp(szSymbol[1], "blendtwoside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
} else {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
}
}
} else if (strcmp(szSymbol[0], "ka") == 0) {
char* pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if (cSymbols == 2) {
pMaterial->setAmbient(Vector3::Create(r, r, r));
} else if (cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setAmbient(Vector3::Create(r, g, b));
}
} else if (strcmp(szSymbol[0], "kd") == 0) {
char* pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if (cSymbols == 2) {
pMaterial->setDiffuse(Vector3::Create(r, r, r));
} else if (cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setDiffuse(Vector3::Create(r, g, b));
}
} else if (strcmp(szSymbol[0], "ks") == 0) {
char* pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if (cSymbols == 2) {
pMaterial->setSpecular(Vector3::Create(r, r, r));
} else if (cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setSpecular(Vector3::Create(r, g, b));
}
} else if (strcmp(szSymbol[0], "kr") == 0) {
char* pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if (cSymbols == 2) {
pMaterial->setReflection(Vector3::Create(r, r, r));
} else if (cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setReflection(Vector3::Create(r, g, b));
}
} else if (strcmp(szSymbol[0], "tr") == 0) {
char* pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
pMaterial->setTransparency(a);
} else if (strcmp(szSymbol[0], "ns") == 0) {
char* pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
pMaterial->setShininess(a);
} else if (strncmp(szSymbol[0], "map", 3) == 0) {
// Truncate file extension
char* pScan2 = szSymbol[1];
char* pLastPeriod = NULL;
while (*pScan2 != '\0') {
if (*pScan2 == '.') {
pLastPeriod = pScan2;
}
pScan2++;
}
if (pLastPeriod) {
*pLastPeriod = '\0';
}
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
int iScanSymbol = 2;
int iScaleParam = -1;
int iOffsetParam = -1;
while (iScanSymbol < cSymbols) {
if (strcmp(szSymbol[iScanSymbol], "-s") == 0) {
// Scale
iScaleParam = 0;
iOffsetParam = -1;
} else if (strcmp(szSymbol[iScanSymbol], "-o") == 0) {
// Offset
iOffsetParam = 0;
iScaleParam = -1;
} else {
char* pScan3 = szSymbol[iScanSymbol];
float v = strtof(pScan3, &pScan3);
if (iScaleParam == 0) {
texture_scale.x = v;
iScaleParam++;
} else if (iScaleParam == 1) {
texture_scale.y = v;
iScaleParam++;
} else if (iOffsetParam == 0) {
texture_offset.x = v;
iOffsetParam++;
} else if (iOffsetParam == 1) {
texture_offset.y = v;
iOffsetParam++;
}
}
iScanSymbol++;
}
if (strcmp(szSymbol[0], "map_ka") == 0) {
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_kd") == 0) {
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_ks") == 0) {
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_normal") == 0) {
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_reflection") == 0) {
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
} else if (strcmp(szSymbol[0], "map_reflectioncube") == 0) {
pMaterial->setReflectionCube(szSymbol[1]);
}
}
}
}
}
}
data->unlock();
delete data;
return pMaterial;
}

View File

@@ -0,0 +1,66 @@
//
// KRMaterialManager.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "resources/KRResourceManager.h"
#include "KRMaterial.h"
#include "KRTextureManager.h"
#include "KRMaterialManager.h"
class KRMaterial;
using std::map;
class KRMaterialManager : public KRResourceManager
{
public:
KRMaterialManager(KRContext& context, KRTextureManager* pTextureManager, KRPipelineManager* pPipelineManager);
virtual ~KRMaterialManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, mimir::Block* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRMaterial* load(const char* szName, mimir::Block* data);
void add(KRMaterial* new_material);
KRMaterial* getMaterial(const std::string& name);
unordered_map<std::string, KRMaterial*>& getMaterials();
private:
unordered_map<std::string, KRMaterial*> m_materials;
KRTextureManager* m_pTextureManager;
KRPipelineManager* m_pPipelineManager;
};

View File

@@ -0,0 +1,67 @@
//
// KRSource.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRSource.h"
using namespace mimir;
KRSource::KRSource(KRContext& context, std::string name, std::string extension) : KRResource(context, name)
{
m_pData = new Block();
m_extension = extension;
}
KRSource::KRSource(KRContext& context, std::string name, std::string extension, Block* data) : KRResource(context, name)
{
m_pData = data;
m_extension = extension;
}
KRSource::~KRSource()
{
delete m_pData;
}
std::string KRSource::getExtension()
{
return m_extension;
}
bool KRSource::save(Block& data)
{
data.append(*m_pData);
return true;
}
Block* KRSource::getData()
{
return m_pData;
}

View File

@@ -0,0 +1,57 @@
//
// KRSource.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "block.h"
#include "resources/KRResource.h"
class KRSource : public KRResource
{
public:
KRSource(KRContext& context, std::string name, std::string extension);
KRSource(KRContext& context, std::string name, std::string extension, mimir::Block* data);
virtual ~KRSource();
virtual std::string getExtension();
virtual bool save(mimir::Block& data);
mimir::Block* getData();
private:
std::string m_extension;
mimir::Block* m_pData;
};

View File

@@ -0,0 +1,125 @@
//
// SourceManager.cpp
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRSourceManager.h"
#include "KREngine-common.h"
#include "KRShader.h"
using namespace mimir;
KRSourceManager::KRSourceManager(KRContext& context) : KRResourceManager(context)
{
}
KRSourceManager::~KRSourceManager()
{
for (unordered_map<std::string, unordered_map<std::string, KRSource*> >::iterator extension_itr = m_sources.begin(); extension_itr != m_sources.end(); extension_itr++) {
for (unordered_map<std::string, KRSource*>::iterator name_itr = (*extension_itr).second.begin(); name_itr != (*extension_itr).second.end(); name_itr++) {
delete (*name_itr).second;
}
}
}
unordered_map<std::string, unordered_map<std::string, KRSource*> >& KRSourceManager::getSources()
{
return m_sources;
}
void KRSourceManager::add(KRSource* source)
{
std::string lower_name = source->getName();
std::string lower_extension = source->getExtension();
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
unordered_map<std::string, unordered_map<std::string, KRSource*> >::iterator extension_itr = m_sources.find(lower_extension);
if (extension_itr == m_sources.end()) {
m_sources[lower_extension] = unordered_map<std::string, KRSource*>();
extension_itr = m_sources.find(lower_extension);
}
unordered_map<std::string, KRSource*>::iterator name_itr = (*extension_itr).second.find(lower_name);
if (name_itr != (*extension_itr).second.end()) {
delete (*name_itr).second;
(*name_itr).second = source;
} else {
(*extension_itr).second[lower_name] = source;
}
}
KRResource* KRSourceManager::loadResource(const std::string& name, const std::string& extension, Block* data)
{
if (getShaderStageFromExtension(extension.c_str()) != ShaderStage::Invalid ||
extension.compare("glsl") == 0 ||
extension.compare("options") == 0) {
return load(name, extension, data);
}
return nullptr;
}
KRResource* KRSourceManager::getResource(const std::string& name, const std::string& extension)
{
if (getShaderStageFromExtension(extension.c_str()) != ShaderStage::Invalid ||
extension.compare("glsl") == 0 ||
extension.compare("options") == 0) {
return get(name, extension);
}
return nullptr;
}
KRSource* KRSourceManager::load(const std::string& name, const std::string& extension, Block* data)
{
KRSource* source = new KRSource(getContext(), name, extension, data);
if (source) add(source);
return source;
}
KRSource* KRSourceManager::get(const std::string& name, const std::string& extension)
{
std::string lower_name = name;
std::string lower_extension = extension;
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
return m_sources[lower_extension][lower_name];
}
const unordered_map<std::string, KRSource*>& KRSourceManager::get(const std::string& extension)
{
std::string lower_extension = extension;
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
return m_sources[lower_extension];
}

View File

@@ -0,0 +1,61 @@
//
// SourceManager.h
// Kraken Engine
//
// Copyright 2024 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "resources/KRResourceManager.h"
#include "resources/source/KRSource.h"
#include "KRContextObject.h"
#include "block.h"
class KRSourceManager : public KRResourceManager
{
public:
KRSourceManager(KRContext& context);
virtual ~KRSourceManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, mimir::Block* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
void add(KRSource* source);
KRSource* load(const std::string& name, const std::string& extension, mimir::Block* data);
KRSource* get(const std::string& name, const std::string& extension);
const unordered_map<std::string, KRSource*>& get(const std::string& extension);
unordered_map<std::string, unordered_map<std::string, KRSource*> >& getSources();
private:
unordered_map<std::string, unordered_map<std::string, KRSource*> > m_sources;
};