WIP adding directory structure
This commit is contained in:
1693
kraken/resources/mesh/KRMesh.cpp
Executable file
1693
kraken/resources/mesh/KRMesh.cpp
Executable file
File diff suppressed because it is too large
Load Diff
307
kraken/resources/mesh/KRMesh.h
Executable file
307
kraken/resources/mesh/KRMesh.h
Executable file
@@ -0,0 +1,307 @@
|
||||
//
|
||||
// KRMesh.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 "KRContext.h"
|
||||
#include "KRBone.h"
|
||||
#include "KRMeshManager.h"
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "hydra.h"
|
||||
|
||||
using namespace kraken;
|
||||
|
||||
#define MAX_VBO_SIZE 65535
|
||||
#define KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX 4
|
||||
#define KRENGINE_MAX_NAME_LENGTH 256
|
||||
// MAX_VBO_SIZE must be divisible by 3 so triangles aren't split across VBO objects...
|
||||
|
||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||
|
||||
#include "resources/material/KRMaterialManager.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRViewport.h"
|
||||
|
||||
class KRMaterial;
|
||||
class KRNode;
|
||||
class KRRenderPass;
|
||||
|
||||
enum class ModelFormat : __uint8_t
|
||||
{
|
||||
KRENGINE_MODEL_FORMAT_TRIANGLES = 0,
|
||||
KRENGINE_MODEL_FORMAT_STRIP,
|
||||
KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES,
|
||||
KRENGINE_MODEL_FORMAT_INDEXED_STRIP
|
||||
};
|
||||
|
||||
class KRMesh : public KRResource
|
||||
{
|
||||
|
||||
public:
|
||||
static void parseName(const std::string& name, std::string& lodBaseName, int& lodCoverage);
|
||||
|
||||
KRMesh(KRContext& context, std::string name, mimir::Block* data);
|
||||
KRMesh(KRContext& context, std::string name);
|
||||
virtual ~KRMesh();
|
||||
|
||||
kraken_stream_level getStreamLevel();
|
||||
void preStream(float lodCoverage);
|
||||
|
||||
bool hasTransparency();
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KRENGINE_ATTRIB_VERTEX = 0,
|
||||
KRENGINE_ATTRIB_NORMAL,
|
||||
KRENGINE_ATTRIB_TANGENT,
|
||||
KRENGINE_ATTRIB_TEXUVA,
|
||||
KRENGINE_ATTRIB_TEXUVB,
|
||||
KRENGINE_ATTRIB_BONEINDEXES,
|
||||
KRENGINE_ATTRIB_BONEWEIGHTS,
|
||||
KRENGINE_ATTRIB_VERTEX_SHORT,
|
||||
KRENGINE_ATTRIB_NORMAL_SHORT,
|
||||
KRENGINE_ATTRIB_TANGENT_SHORT,
|
||||
KRENGINE_ATTRIB_TEXUVA_SHORT,
|
||||
KRENGINE_ATTRIB_TEXUVB_SHORT,
|
||||
KRENGINE_NUM_ATTRIBUTES
|
||||
} vertex_attrib_t;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ModelFormat format;
|
||||
std::vector<hydra::Vector3> vertices;
|
||||
std::vector<__uint16_t> vertex_indexes;
|
||||
std::vector<std::pair<int, int> > vertex_index_bases;
|
||||
std::vector<hydra::Vector2> uva;
|
||||
std::vector<hydra::Vector2> uvb;
|
||||
std::vector<hydra::Vector3> normals;
|
||||
std::vector<hydra::Vector3> tangents;
|
||||
std::vector<int> submesh_starts;
|
||||
std::vector<int> submesh_lengths;
|
||||
std::vector<std::string> material_names;
|
||||
std::vector<std::string> bone_names;
|
||||
std::vector<std::vector<int> > bone_indexes;
|
||||
std::vector<hydra::Matrix4> bone_bind_poses;
|
||||
std::vector<std::vector<float> > bone_weights;
|
||||
} mesh_info;
|
||||
|
||||
void render(const KRNode::RenderInfo& ri, const std::string& object_name, const hydra::Matrix4& matModel, KRTexture* pLightMap, const std::vector<KRBone*>& bones, const hydra::Vector3& rim_color, float rim_power, float lod_coverage = 0.0f);
|
||||
|
||||
std::string m_lodBaseName;
|
||||
|
||||
virtual std::string getExtension();
|
||||
virtual bool save(const std::string& path);
|
||||
virtual bool save(mimir::Block& data);
|
||||
|
||||
void LoadData(const mesh_info& mi, bool calculate_normals, bool calculate_tangents);
|
||||
void loadPack(mimir::Block* data);
|
||||
|
||||
void convertToIndexed();
|
||||
void optimize();
|
||||
void optimizeIndexes();
|
||||
|
||||
void renderNoMaterials(VkCommandBuffer& commandBuffer, const KRRenderPass* renderPass, const std::string& object_name, const std::string& material_name, float lodCoverage);
|
||||
bool isReady() const;
|
||||
|
||||
float getMaxDimension();
|
||||
|
||||
hydra::Vector3 getMinPoint() const;
|
||||
hydra::Vector3 getMaxPoint() const;
|
||||
|
||||
class Submesh
|
||||
{
|
||||
public:
|
||||
Submesh()
|
||||
{};
|
||||
~Submesh()
|
||||
{
|
||||
vbo_data_blocks.clear();
|
||||
for (auto itr = vertex_data_blocks.begin(); itr != vertex_data_blocks.end(); itr++) {
|
||||
delete (*itr);
|
||||
}
|
||||
for (auto itr = index_data_blocks.begin(); itr != index_data_blocks.end(); itr++) {
|
||||
delete (*itr);
|
||||
}
|
||||
};
|
||||
|
||||
int start_vertex;
|
||||
int vertex_count;
|
||||
char szMaterialName[KRENGINE_MAX_NAME_LENGTH];
|
||||
vector<mimir::Block*> vertex_data_blocks;
|
||||
vector<mimir::Block*> index_data_blocks;
|
||||
// KRMeshManager depends on the address of KRVBOData's being constant
|
||||
// after allocation, enforced by deleted copy constructors.
|
||||
// As std::vector requires copy constuctors, we wrap these in shared_ptr.
|
||||
vector<shared_ptr<KRMeshManager::KRVBOData>> vbo_data_blocks;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{ // For Indexed triangles / strips
|
||||
uint16_t index_group;
|
||||
uint16_t index_group_offset;
|
||||
};
|
||||
int32_t start_vertex; // For non-indexed trigangles / strips
|
||||
};
|
||||
int32_t vertex_count;
|
||||
char szName[KRENGINE_MAX_NAME_LENGTH];
|
||||
} pack_material;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char szName[KRENGINE_MAX_NAME_LENGTH];
|
||||
float bind_pose[16];
|
||||
} pack_bone;
|
||||
|
||||
int getLODCoverage() const;
|
||||
std::string getLODBaseName() const;
|
||||
|
||||
|
||||
static bool lod_sort_predicate(const KRMesh* m1, const KRMesh* m2);
|
||||
bool has_vertex_attribute(vertex_attrib_t attribute_type) const;
|
||||
static bool has_vertex_attribute(int vertex_attrib_flags, vertex_attrib_t attribute_type);
|
||||
|
||||
int getSubmeshCount() const;
|
||||
int getVertexCount(int submesh) const;
|
||||
__uint32_t getVertexAttributes() const;
|
||||
|
||||
int getTriangleVertexIndex(int submesh, int index) const;
|
||||
hydra::Vector3 getVertexPosition(int index) const;
|
||||
hydra::Vector3 getVertexNormal(int index) const;
|
||||
hydra::Vector3 getVertexTangent(int index) const;
|
||||
hydra::Vector2 getVertexUVA(int index) const;
|
||||
hydra::Vector2 getVertexUVB(int index) const;
|
||||
int getBoneIndex(int index, int weight_index) const;
|
||||
float getBoneWeight(int index, int weight_index) const;
|
||||
|
||||
void setVertexPosition(int index, const hydra::Vector3& v);
|
||||
void setVertexNormal(int index, const hydra::Vector3& v);
|
||||
void setVertexTangent(int index, const hydra::Vector3& v);
|
||||
void setVertexUVA(int index, const hydra::Vector2& v);
|
||||
void setVertexUVB(int index, const hydra::Vector2& v);
|
||||
void setBoneIndex(int index, int weight_index, int bone_index);
|
||||
void setBoneWeight(int index, int weight_index, float bone_weight);
|
||||
|
||||
static size_t VertexSizeForAttributes(__int32_t vertex_attrib_flags);
|
||||
static size_t AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_flags);
|
||||
static VkFormat AttributeVulkanFormat(__int32_t vertex_attrib);
|
||||
|
||||
int getBoneCount();
|
||||
char* getBoneName(int bone_index);
|
||||
hydra::Matrix4 getBoneBindPose(int bone_index);
|
||||
|
||||
|
||||
ModelFormat getModelFormat() const;
|
||||
|
||||
bool lineCast(const hydra::Vector3& v0, const hydra::Vector3& v1, hydra::HitInfo& hitinfo) const;
|
||||
bool rayCast(const hydra::Vector3& v0, const hydra::Vector3& dir, hydra::HitInfo& hitinfo) const;
|
||||
bool sphereCast(const hydra::Matrix4& model_to_world, const hydra::Vector3& v0, const hydra::Vector3& v1, float radius, hydra::HitInfo& hitinfo) const;
|
||||
|
||||
static int GetLODCoverage(const std::string& name);
|
||||
|
||||
protected:
|
||||
bool m_constant; // TRUE if this should be always loaded and should not be passed through the streamer
|
||||
|
||||
private:
|
||||
mimir::Block* m_pData;
|
||||
mimir::Block* m_pMetaData;
|
||||
mimir::Block* m_pIndexBaseData;
|
||||
|
||||
void getSubmeshes();
|
||||
void getMaterials();
|
||||
void renderSubmesh(VkCommandBuffer& commandBuffer, int iSubmesh, const KRRenderPass* renderPass, const std::string& object_name, const std::string& material_name, float lodCoverage);
|
||||
|
||||
static bool rayCast(const hydra::Vector3& start, const hydra::Vector3& dir, const hydra::Triangle3& tri, const hydra::Vector3& tri_n0, const hydra::Vector3& tri_n1, const hydra::Vector3& tri_n2, hydra::HitInfo& hitinfo);
|
||||
static bool sphereCast(const hydra::Matrix4& model_to_world, const hydra::Vector3& v0, const hydra::Vector3& v1, float radius, const hydra::Triangle3& tri, hydra::HitInfo& hitinfo);
|
||||
|
||||
int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model)
|
||||
vector<KRMaterial*> m_materials;
|
||||
set<KRMaterial*> m_uniqueMaterials;
|
||||
|
||||
bool m_hasTransparency;
|
||||
|
||||
|
||||
hydra::Vector3 m_minPoint, m_maxPoint;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char szTag[16];
|
||||
int32_t model_format; // 0 == Triangle list, 1 == Triangle strips, 2 == Indexed triangle list, 3 == Indexed triangle strips, rest are reserved (model_format_t enum)
|
||||
int32_t vertex_attrib_flags;
|
||||
int32_t vertex_count;
|
||||
int32_t submesh_count;
|
||||
int32_t bone_count;
|
||||
float minx, miny, minz, maxx, maxy, maxz; // Axis aligned bounding box, in model's coordinate space
|
||||
int32_t index_count;
|
||||
int32_t index_base_count;
|
||||
unsigned char reserved[444]; // Pad out to 512 bytes
|
||||
} pack_header;
|
||||
|
||||
vector<Submesh> m_submeshes;
|
||||
int m_vertex_attribute_offset[KRENGINE_NUM_ATTRIBUTES];
|
||||
int m_vertex_size;
|
||||
void updateAttributeOffsets();
|
||||
|
||||
void setName(const std::string name);
|
||||
|
||||
|
||||
|
||||
pack_material* getSubmesh(int mesh_index) const;
|
||||
unsigned char* getVertexData() const;
|
||||
size_t getVertexDataOffset() const;
|
||||
unsigned char* getVertexData(int index) const;
|
||||
__uint16_t* getIndexData() const;
|
||||
size_t getIndexDataOffset() const;
|
||||
__uint32_t* getIndexBaseData() const;
|
||||
pack_header* getHeader() const;
|
||||
pack_bone* getBone(int index);
|
||||
|
||||
|
||||
void getIndexedRange(int index_group, int& start_index_offset, int& start_vertex_offset, int& index_count, int& vertex_count) const;
|
||||
|
||||
void releaseData();
|
||||
|
||||
void createDataBlocks(KRMeshManager::KRVBOData::vbo_type t);
|
||||
|
||||
|
||||
};
|
||||
70
kraken/resources/mesh/KRMeshCube.cpp
Executable file
70
kraken/resources/mesh/KRMeshCube.cpp
Executable file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// KRMeshCube.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 "KRMeshCube.h"
|
||||
|
||||
using namespace hydra;
|
||||
|
||||
KRMeshCube::KRMeshCube(KRContext& context) : KRMesh(context, "__cube")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, -1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, -1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, -1.0, -1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, -1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0, -1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, -1.0, 1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, -1.0, -1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, -1.0, -1.0));
|
||||
mi.vertices.push_back(Vector3::Create(1.0, 1.0, -1.0));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, -1.0));
|
||||
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back((int)mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshCube::~KRMeshCube()
|
||||
{
|
||||
|
||||
}
|
||||
43
kraken/resources/mesh/KRMeshCube.h
Executable file
43
kraken/resources/mesh/KRMeshCube.h
Executable file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// KRMeshCube.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 "KRMesh.h"
|
||||
|
||||
class KRMeshCube : public KRMesh
|
||||
{
|
||||
public:
|
||||
KRMeshCube(KRContext& context);
|
||||
virtual ~KRMeshCube();
|
||||
private:
|
||||
};
|
||||
|
||||
715
kraken/resources/mesh/KRMeshManager.cpp
Executable file
715
kraken/resources/mesh/KRMeshManager.cpp
Executable file
@@ -0,0 +1,715 @@
|
||||
//
|
||||
// KRMeshManager.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 "KRMeshManager.h"
|
||||
|
||||
#include "KRMesh.h"
|
||||
#include "KRMeshCube.h"
|
||||
#include "KRMeshQuad.h"
|
||||
#include "KRMeshSphere.h"
|
||||
#include "KRRenderPass.h"
|
||||
|
||||
using namespace mimir;
|
||||
|
||||
KRMeshManager::KRMeshManager(KRContext& context)
|
||||
: KRResourceManager(context)
|
||||
, m_currentVBO(NULL)
|
||||
, m_vboMemUsed(0)
|
||||
, m_memoryTransferredThisFrame(0)
|
||||
, m_streamerComplete(true)
|
||||
, m_draw_call_logging_enabled(false)
|
||||
, m_draw_call_log_used(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void KRMeshManager::init()
|
||||
{
|
||||
addModel(new KRMeshCube(*m_pContext));
|
||||
addModel(new KRMeshQuad(*m_pContext));
|
||||
addModel(new KRMeshSphere(*m_pContext));
|
||||
|
||||
// ---- Initialize stock models ----
|
||||
static const float _KRENGINE_VBO_3D_CUBE_VERTEX_DATA[] = {
|
||||
1.0, 1.0, 1.0,
|
||||
-1.0, 1.0, 1.0,
|
||||
1.0,-1.0, 1.0,
|
||||
-1.0,-1.0, 1.0,
|
||||
-1.0,-1.0,-1.0,
|
||||
-1.0, 1.0, 1.0,
|
||||
-1.0, 1.0,-1.0,
|
||||
1.0, 1.0, 1.0,
|
||||
1.0, 1.0,-1.0,
|
||||
1.0,-1.0, 1.0,
|
||||
1.0,-1.0,-1.0,
|
||||
-1.0,-1.0,-1.0,
|
||||
1.0, 1.0,-1.0,
|
||||
-1.0, 1.0,-1.0
|
||||
};
|
||||
|
||||
KRENGINE_VBO_3D_CUBE_ATTRIBS = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
||||
KRENGINE_VBO_3D_CUBE_VERTICES.expand(sizeof(float) * 3 * 14);
|
||||
KRENGINE_VBO_3D_CUBE_VERTICES.lock();
|
||||
memcpy(KRENGINE_VBO_3D_CUBE_VERTICES.getStart(), _KRENGINE_VBO_3D_CUBE_VERTEX_DATA, sizeof(float) * 3 * 14);
|
||||
KRENGINE_VBO_3D_CUBE_VERTICES.unlock();
|
||||
|
||||
KRENGINE_VBO_DATA_3D_CUBE_VERTICES.init(this, &KRENGINE_VBO_3D_CUBE_VERTICES, nullptr, KRENGINE_VBO_3D_CUBE_ATTRIBS, false, KRVBOData::CONSTANT
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, "Cube Mesh [built-in]"
|
||||
#endif
|
||||
);
|
||||
|
||||
initRandomParticles();
|
||||
initVolumetricLightingVertexes();
|
||||
|
||||
static const float _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA[] = {
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
|
||||
};
|
||||
KRENGINE_VBO_2D_SQUARE_ATTRIBS = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA);
|
||||
KRENGINE_VBO_2D_SQUARE_VERTICES.expand(sizeof(float) * 5 * 4);
|
||||
KRENGINE_VBO_2D_SQUARE_VERTICES.lock();
|
||||
memcpy(KRENGINE_VBO_2D_SQUARE_VERTICES.getStart(), _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA, sizeof(float) * 5 * 4);
|
||||
KRENGINE_VBO_2D_SQUARE_VERTICES.unlock();
|
||||
|
||||
KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.init(this, &KRENGINE_VBO_2D_SQUARE_VERTICES, nullptr, KRENGINE_VBO_2D_SQUARE_ATTRIBS, false, KRVBOData::CONSTANT
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, "Square Mesh [built-in]"
|
||||
#endif
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
KRMeshManager::~KRMeshManager()
|
||||
{
|
||||
for (unordered_multimap<std::string, KRMesh*>::iterator itr = m_models.begin(); itr != m_models.end(); ++itr) {
|
||||
delete (*itr).second;
|
||||
}
|
||||
m_models.clear();
|
||||
}
|
||||
|
||||
KRResource* KRMeshManager::loadResource(const std::string& name, const std::string& extension, Block* data)
|
||||
{
|
||||
if (extension.compare("krmesh") == 0) {
|
||||
return loadModel(name.c_str(), data);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
KRResource* KRMeshManager::getResource(const std::string& name, const std::string& extension)
|
||||
{
|
||||
if (extension.compare("krmesh") == 0) {
|
||||
std::string lodBaseName;
|
||||
int lodCoverage;
|
||||
KRMesh::parseName(name, lodBaseName, lodCoverage);
|
||||
std::vector<KRMesh*> models = getModel(lodBaseName.c_str());
|
||||
for (KRMesh* mesh : models) {
|
||||
if (mesh->getLODCoverage() == lodCoverage) {
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
KRMesh* KRMeshManager::loadModel(const char* szName, Block* pData)
|
||||
{
|
||||
KRMesh* pModel = new KRMesh(*m_pContext, szName, pData);
|
||||
addModel(pModel);
|
||||
return pModel;
|
||||
}
|
||||
|
||||
void KRMeshManager::addModel(KRMesh* model)
|
||||
{
|
||||
std::string lowerName = model->getLODBaseName();
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
m_models.insert(std::pair<std::string, KRMesh*>(lowerName, model));
|
||||
}
|
||||
|
||||
KRMesh* KRMeshManager::getMaxLODModel(const char* szName)
|
||||
{
|
||||
std::vector<KRMesh*> models = getModel(szName);
|
||||
// models are always in order of highest LOD first
|
||||
if (models.size()) {
|
||||
return models[0];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<KRMesh*> KRMeshManager::getModel(const char* szName)
|
||||
{
|
||||
std::string lowerName = szName;
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
|
||||
std::vector<KRMesh*> matching_models;
|
||||
|
||||
std::pair<unordered_multimap<std::string, KRMesh*>::iterator, unordered_multimap<std::string, KRMesh*>::iterator> range = m_models.equal_range(lowerName);
|
||||
for (unordered_multimap<std::string, KRMesh*>::iterator itr_match = range.first; itr_match != range.second; itr_match++) {
|
||||
matching_models.push_back(itr_match->second);
|
||||
}
|
||||
|
||||
std::sort(matching_models.begin(), matching_models.end(), KRMesh::lod_sort_predicate);
|
||||
|
||||
if (matching_models.size() == 0) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_INFORMATION, "Model not found: %s", lowerName.c_str());
|
||||
}
|
||||
|
||||
return matching_models;
|
||||
}
|
||||
|
||||
unordered_multimap<std::string, KRMesh*>& KRMeshManager::getModels()
|
||||
{
|
||||
return m_models;
|
||||
}
|
||||
|
||||
void KRMeshManager::bindVBO(VkCommandBuffer& commandBuffer, KRVBOData* vbo_data, float lodCoverage)
|
||||
{
|
||||
vbo_data->resetPoolExpiry(lodCoverage);
|
||||
|
||||
bool vbo_changed = false;
|
||||
if (m_currentVBO == NULL) {
|
||||
vbo_changed = true;
|
||||
} else if (m_currentVBO->m_data != vbo_data->m_data) {
|
||||
vbo_changed = true;
|
||||
}
|
||||
|
||||
if (vbo_changed) {
|
||||
|
||||
if (m_vbosActive.find(vbo_data->m_data) != m_vbosActive.end()) {
|
||||
m_currentVBO = m_vbosActive[vbo_data->m_data];
|
||||
} else {
|
||||
m_currentVBO = vbo_data;
|
||||
|
||||
m_vbosActive[vbo_data->m_data] = m_currentVBO;
|
||||
}
|
||||
|
||||
m_currentVBO->bind(commandBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void KRMeshManager::startFrame(float deltaTime)
|
||||
{
|
||||
m_memoryTransferredThisFrame = 0;
|
||||
if (m_draw_call_log_used) {
|
||||
// Only log draw calls on the next frame if the draw call log was used on last frame
|
||||
m_draw_call_log_used = false;
|
||||
m_draw_call_logging_enabled = true;
|
||||
}
|
||||
m_draw_calls.clear();
|
||||
|
||||
// TODO - Implement proper double-buffering to reduce copy operations
|
||||
m_streamerFenceMutex.lock();
|
||||
|
||||
if (m_streamerComplete) {
|
||||
assert(m_activeVBOs_streamer_copy.size() == 0); // The streamer should have emptied this if it really did complete
|
||||
|
||||
const long KRENGINE_VBO_EXPIRY_FRAMES = 1;
|
||||
|
||||
std::set<KRVBOData*> expiredVBOs;
|
||||
for (auto itr = m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
|
||||
KRVBOData* activeVBO = (*itr).second;
|
||||
activeVBO->_swapHandles();
|
||||
if (activeVBO->getType() == KRVBOData::CONSTANT) {
|
||||
// Ensure that CONSTANT data is always loaded
|
||||
float priority = std::numeric_limits<float>::max();
|
||||
m_activeVBOs_streamer_copy.push_back(std::pair<float, KRVBOData*>(priority, activeVBO));
|
||||
} else if (activeVBO->getLastFrameUsed() + KRENGINE_VBO_EXPIRY_FRAMES < getContext().getCurrentFrame()) {
|
||||
// Expire VBO's that haven't been used in a long time
|
||||
|
||||
switch (activeVBO->getType()) {
|
||||
case KRVBOData::STREAMING:
|
||||
case KRVBOData::IMMEDIATE:
|
||||
activeVBO->unload();
|
||||
break;
|
||||
case KRVBOData::CONSTANT:
|
||||
// CONSTANT VBO's are not unloaded
|
||||
break;
|
||||
}
|
||||
|
||||
expiredVBOs.insert(activeVBO);
|
||||
} else if (activeVBO->getType() == KRVBOData::STREAMING) {
|
||||
float priority = activeVBO->getStreamPriority();
|
||||
m_activeVBOs_streamer_copy.push_back(std::pair<float, KRVBOData*>(priority, activeVBO));
|
||||
}
|
||||
}
|
||||
for (std::set<KRVBOData*>::iterator itr = expiredVBOs.begin(); itr != expiredVBOs.end(); itr++) {
|
||||
m_vbosActive.erase((*itr)->m_data);
|
||||
}
|
||||
|
||||
if (m_activeVBOs_streamer_copy.size() > 0) {
|
||||
m_streamerComplete = false;
|
||||
}
|
||||
}
|
||||
m_streamerFenceMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
void KRMeshManager::endFrame(float deltaTime)
|
||||
{
|
||||
m_currentVBO = nullptr;
|
||||
}
|
||||
|
||||
void KRMeshManager::doStreaming(long& memoryRemaining, long& memoryRemainingThisFrame)
|
||||
{
|
||||
|
||||
// TODO - Implement proper double-buffering to reduce copy operations
|
||||
m_streamerFenceMutex.lock();
|
||||
m_activeVBOs_streamer = std::move(m_activeVBOs_streamer_copy);
|
||||
m_streamerFenceMutex.unlock();
|
||||
|
||||
if (m_activeVBOs_streamer.size() > 0) {
|
||||
balanceVBOMemory(memoryRemaining, memoryRemainingThisFrame);
|
||||
|
||||
m_streamerFenceMutex.lock();
|
||||
m_streamerComplete = true;
|
||||
m_streamerFenceMutex.unlock();
|
||||
} else {
|
||||
memoryRemaining -= getMemUsed();
|
||||
}
|
||||
}
|
||||
|
||||
void KRMeshManager::balanceVBOMemory(long& memoryRemaining, long& memoryRemainingThisFrame)
|
||||
{
|
||||
std::sort(m_activeVBOs_streamer.begin(), m_activeVBOs_streamer.end(), std::greater<std::pair<float, KRVBOData*>>());
|
||||
|
||||
|
||||
for (auto vbo_itr = m_activeVBOs_streamer.begin(); vbo_itr != m_activeVBOs_streamer.end(); vbo_itr++) {
|
||||
KRVBOData* vbo_data = (*vbo_itr).second;
|
||||
long vbo_size = vbo_data->getSize();
|
||||
if (!vbo_data->isVBOLoaded()) {
|
||||
if (memoryRemainingThisFrame > vbo_size) {
|
||||
vbo_data->load();
|
||||
memoryRemainingThisFrame -= vbo_size;
|
||||
}
|
||||
}
|
||||
memoryRemaining -= vbo_size;
|
||||
}
|
||||
}
|
||||
|
||||
long KRMeshManager::getMemUsed()
|
||||
{
|
||||
return m_vboMemUsed;
|
||||
}
|
||||
|
||||
long KRMeshManager::getMemActive()
|
||||
{
|
||||
long mem_active = 0;
|
||||
for (unordered_map<Block*, KRVBOData*>::iterator itr = m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
|
||||
mem_active += (*itr).second->getSize();
|
||||
}
|
||||
return mem_active;
|
||||
}
|
||||
|
||||
void KRMeshManager::initVolumetricLightingVertexes()
|
||||
{
|
||||
if (m_volumetricLightingVertexData.getSize() == 0) {
|
||||
m_volumetricLightingVertexData.expand(sizeof(VolumetricLightingVertexData) * KRENGINE_MAX_VOLUMETRIC_PLANES * 6);
|
||||
m_volumetricLightingVertexData.lock();
|
||||
VolumetricLightingVertexData* vertex_data = (VolumetricLightingVertexData*)m_volumetricLightingVertexData.getStart();
|
||||
int iVertex = 0;
|
||||
for (int iPlane = 0; iPlane < KRENGINE_MAX_VOLUMETRIC_PLANES; iPlane++) {
|
||||
vertex_data[iVertex].vertex.x = -1.0f;
|
||||
vertex_data[iVertex].vertex.y = -1.0f;
|
||||
vertex_data[iVertex].vertex.z = (float)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = 1.0f;
|
||||
vertex_data[iVertex].vertex.y = -1.0f;
|
||||
vertex_data[iVertex].vertex.z = (float)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = -1.0f;
|
||||
vertex_data[iVertex].vertex.y = 1.0f;
|
||||
vertex_data[iVertex].vertex.z = (float)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = -1.0f;
|
||||
vertex_data[iVertex].vertex.y = 1.0f;
|
||||
vertex_data[iVertex].vertex.z = (float)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = 1.0f;
|
||||
vertex_data[iVertex].vertex.y = -1.0f;
|
||||
vertex_data[iVertex].vertex.z = (float)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = 1.0f;
|
||||
vertex_data[iVertex].vertex.y = 1.0f;
|
||||
vertex_data[iVertex].vertex.z = (float)iPlane;
|
||||
iVertex++;
|
||||
|
||||
}
|
||||
|
||||
KRENGINE_VBO_DATA_VOLUMETRIC_LIGHTING.init(this, &m_volumetricLightingVertexData, nullptr, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), false, KRVBOData::CONSTANT
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, "Volumetric Lighting Planes [built-in]"
|
||||
#endif
|
||||
);
|
||||
|
||||
m_volumetricLightingVertexData.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void KRMeshManager::initRandomParticles()
|
||||
{
|
||||
if (m_randomParticleVertexData.getSize() == 0) {
|
||||
m_randomParticleVertexData.expand(sizeof(RandomParticleVertexData) * KRENGINE_MAX_RANDOM_PARTICLES * 3);
|
||||
m_randomParticleVertexData.lock();
|
||||
RandomParticleVertexData* vertex_data = (RandomParticleVertexData*)m_randomParticleVertexData.getStart();
|
||||
|
||||
// Generate vertices for randomly placed equilateral triangles with a side length of 1 and an origin point centered so that an inscribed circle can be efficiently rendered without wasting fill
|
||||
|
||||
float equilateral_triangle_height = sqrt(3.0f) * 0.5f;
|
||||
float inscribed_circle_radius = 1.0f / (2.0f * sqrt(3.0f));
|
||||
|
||||
int iVertex = 0;
|
||||
for (int iParticle = 0; iParticle < KRENGINE_MAX_RANDOM_PARTICLES; iParticle++) {
|
||||
vertex_data[iVertex].vertex.x = (float)(rand() % 2000) / 1000.0f - 1000.0f;
|
||||
vertex_data[iVertex].vertex.y = (float)(rand() % 2000) / 1000.0f - 1000.0f;
|
||||
vertex_data[iVertex].vertex.z = (float)(rand() % 2000) / 1000.0f - 1000.0f;
|
||||
vertex_data[iVertex].uva.x = -0.5f;
|
||||
vertex_data[iVertex].uva.y = -inscribed_circle_radius;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = vertex_data[iVertex - 1].vertex.x;
|
||||
vertex_data[iVertex].vertex.y = vertex_data[iVertex - 1].vertex.y;
|
||||
vertex_data[iVertex].vertex.z = vertex_data[iVertex - 1].vertex.z;
|
||||
vertex_data[iVertex].uva.x = 0.5f;
|
||||
vertex_data[iVertex].uva.y = -inscribed_circle_radius;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = vertex_data[iVertex - 1].vertex.x;
|
||||
vertex_data[iVertex].vertex.y = vertex_data[iVertex - 1].vertex.y;
|
||||
vertex_data[iVertex].vertex.z = vertex_data[iVertex - 1].vertex.z;
|
||||
vertex_data[iVertex].uva.x = 0.0f;
|
||||
vertex_data[iVertex].uva.y = -inscribed_circle_radius + equilateral_triangle_height;
|
||||
iVertex++;
|
||||
}
|
||||
|
||||
KRENGINE_VBO_DATA_RANDOM_PARTICLES.init(this, &m_randomParticleVertexData, nullptr, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false, KRVBOData::CONSTANT
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, "Random Particles [built-in]"
|
||||
#endif
|
||||
);
|
||||
|
||||
m_randomParticleVertexData.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
long KRMeshManager::getMemoryTransferedThisFrame()
|
||||
{
|
||||
return m_memoryTransferredThisFrame;
|
||||
}
|
||||
|
||||
|
||||
size_t KRMeshManager::getActiveVBOCount()
|
||||
{
|
||||
return m_vbosActive.size();
|
||||
}
|
||||
|
||||
void KRMeshManager::log_draw_call(RenderPassType pass, const std::string& object_name, const std::string& material_name, int vertex_count)
|
||||
{
|
||||
if (m_draw_call_logging_enabled) {
|
||||
draw_call_info info;
|
||||
info.pass = pass;
|
||||
strncpy(info.object_name, object_name.c_str(), 256);
|
||||
strncpy(info.material_name, material_name.c_str(), 256);
|
||||
info.vertex_count = vertex_count;
|
||||
m_draw_calls.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<KRMeshManager::draw_call_info> KRMeshManager::getDrawCalls()
|
||||
{
|
||||
m_draw_call_log_used = true;
|
||||
return m_draw_calls;
|
||||
}
|
||||
|
||||
KRMeshManager::KRVBOData::KRVBOData()
|
||||
{
|
||||
m_debugLabel[0] = '\0';
|
||||
m_is_vbo_loaded = false;
|
||||
m_is_vbo_ready = false;
|
||||
m_manager = NULL;
|
||||
m_type = STREAMING;
|
||||
m_data = NULL;
|
||||
m_index_data = NULL;
|
||||
m_vertex_attrib_flags = 0;
|
||||
m_size = 0;
|
||||
|
||||
m_last_frame_used = 0;
|
||||
m_last_frame_max_lod_coverage = 0.0f;
|
||||
|
||||
memset(m_allocations, 0, sizeof(AllocationInfo) * KRENGINE_MAX_GPU_COUNT);
|
||||
}
|
||||
|
||||
KRMeshManager::KRVBOData::KRVBOData(KRMeshManager* manager, Block* data, Block* index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, const char* debug_label
|
||||
#endif
|
||||
)
|
||||
{
|
||||
m_debugLabel[0] = '\0';
|
||||
memset(m_allocations, 0, sizeof(AllocationInfo) * KRENGINE_MAX_GPU_COUNT);
|
||||
m_is_vbo_loaded = false;
|
||||
m_is_vbo_ready = false;
|
||||
init(manager, data, index_data, vertex_attrib_flags, static_vbo, t
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, debug_label
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void KRMeshManager::KRVBOData::init(KRMeshManager* manager, Block* data, Block* index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, const char* debug_label
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
snprintf(m_debugLabel, KRENGINE_DEBUG_GPU_LABEL_MAX_LEN, debug_label);
|
||||
#endif //KRENGINE_DEBUG_GPU_LABELS
|
||||
m_manager = manager;
|
||||
m_type = t;
|
||||
m_static_vbo = static_vbo;
|
||||
m_data = data;
|
||||
m_index_data = index_data;
|
||||
m_vertex_attrib_flags = vertex_attrib_flags;
|
||||
|
||||
m_size = m_data->getSize();
|
||||
if (m_index_data != NULL) {
|
||||
m_size += m_index_data->getSize();
|
||||
}
|
||||
|
||||
if (t == KRVBOData::CONSTANT) {
|
||||
m_manager->primeVBO(this);
|
||||
}
|
||||
}
|
||||
|
||||
KRMeshManager::KRVBOData::~KRVBOData()
|
||||
{
|
||||
// TODO - This needs to be done by the streamer thread, and asserted here...
|
||||
unload();
|
||||
}
|
||||
|
||||
void KRMeshManager::KRVBOData::load()
|
||||
{
|
||||
// TODO - This is a bit messy. Clean up after Vulkan refactor.
|
||||
VkCommandBuffer noCommandBuffer = VK_NULL_HANDLE;
|
||||
load(noCommandBuffer);
|
||||
}
|
||||
|
||||
void KRMeshManager::KRVBOData::load(VkCommandBuffer& commandBuffer)
|
||||
{
|
||||
// TODO - We should load on each GPU only if there is a surface using the mesh
|
||||
if (isVBOLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
KRDeviceManager* deviceManager = m_manager->getContext().getDeviceManager();
|
||||
int iAllocation = 0;
|
||||
|
||||
for (auto deviceItr = deviceManager->getDevices().begin(); deviceItr != deviceManager->getDevices().end() && iAllocation < KRENGINE_MAX_GPU_COUNT; deviceItr++, iAllocation++) {
|
||||
KRDevice& device = *(*deviceItr).second;
|
||||
KrDeviceHandle deviceHandle = (*deviceItr).first;
|
||||
VmaAllocator allocator = device.getAllocator();
|
||||
AllocationInfo& allocation = m_allocations[iAllocation];
|
||||
allocation.device = deviceHandle;
|
||||
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
char debug_label[KRENGINE_DEBUG_GPU_LABEL_MAX_LEN];
|
||||
|
||||
const char* type_label = "";
|
||||
|
||||
switch (m_type) {
|
||||
case vbo_type::STREAMING:
|
||||
type_label = "Streaming";
|
||||
break;
|
||||
case vbo_type::CONSTANT:
|
||||
type_label = "Constant";
|
||||
break;
|
||||
case vbo_type::IMMEDIATE:
|
||||
type_label = "Immediate";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
snprintf(debug_label, KRENGINE_DEBUG_GPU_LABEL_MAX_LEN, "%s Vertices: %s", type_label, m_debugLabel);
|
||||
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||
|
||||
device.createBuffer(
|
||||
m_data->getSize(),
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
&allocation.vertex_buffer,
|
||||
&allocation.vertex_allocation
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, debug_label
|
||||
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||
);
|
||||
if (m_type == vbo_type::IMMEDIATE) {
|
||||
device.graphicsUpload(commandBuffer, *m_data, allocation.vertex_buffer);
|
||||
} else {
|
||||
device.streamUpload(*m_data, allocation.vertex_buffer);
|
||||
}
|
||||
|
||||
|
||||
if (m_index_data && m_index_data->getSize() > 0) {
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
snprintf(debug_label, KRENGINE_DEBUG_GPU_LABEL_MAX_LEN, "%s Indexes: %s", type_label, m_debugLabel);
|
||||
#endif // KRENGINE_DEBUG_GPU_LABELS
|
||||
device.createBuffer(
|
||||
m_index_data->getSize(),
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
&allocation.index_buffer,
|
||||
&allocation.index_allocation
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, debug_label
|
||||
#endif
|
||||
);
|
||||
if (m_type == vbo_type::IMMEDIATE) {
|
||||
device.graphicsUpload(commandBuffer, *m_index_data, allocation.index_buffer);
|
||||
} else {
|
||||
device.streamUpload(*m_index_data, allocation.index_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_is_vbo_loaded = true;
|
||||
|
||||
m_manager->m_vboMemUsed += getSize();
|
||||
m_manager->m_memoryTransferredThisFrame += getSize();
|
||||
|
||||
if (m_type != STREAMING) {
|
||||
_swapHandles();
|
||||
}
|
||||
}
|
||||
|
||||
void KRMeshManager::KRVBOData::unload()
|
||||
{
|
||||
KRDeviceManager* deviceManager = m_manager->getContext().getDeviceManager();
|
||||
for (int i = 0; i < KRENGINE_MAX_GPU_COUNT; i++) {
|
||||
AllocationInfo& allocation = m_allocations[i];
|
||||
if (allocation.device) {
|
||||
std::unique_ptr<KRDevice>& device = deviceManager->getDevice(allocation.device);
|
||||
if (device) {
|
||||
VmaAllocator allocator = device->getAllocator();
|
||||
vmaDestroyBuffer(allocator, allocation.vertex_buffer, allocation.vertex_allocation);
|
||||
if (allocation.index_buffer) {
|
||||
vmaDestroyBuffer(allocator, allocation.index_buffer, allocation.index_allocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(&allocation, 0, sizeof(AllocationInfo));
|
||||
}
|
||||
|
||||
if (isVBOLoaded()) {
|
||||
m_manager->m_vboMemUsed -= getSize();
|
||||
}
|
||||
|
||||
m_is_vbo_loaded = false;
|
||||
m_is_vbo_ready = false;
|
||||
}
|
||||
|
||||
void KRMeshManager::KRVBOData::bind(VkCommandBuffer& commandBuffer)
|
||||
{
|
||||
VkBuffer vertexBuffers[] = { getVertexBuffer() };
|
||||
VkDeviceSize offsets[] = { 0 };
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
||||
|
||||
if (m_index_data && m_index_data->getSize() > 0) {
|
||||
// TODO - Support 32-bit index buffers
|
||||
vkCmdBindIndexBuffer(commandBuffer, getIndexBuffer(), 0, VK_INDEX_TYPE_UINT16);
|
||||
}
|
||||
}
|
||||
|
||||
void KRMeshManager::KRVBOData::resetPoolExpiry(float lodCoverage)
|
||||
{
|
||||
long current_frame = m_manager->getContext().getCurrentFrame();
|
||||
if (current_frame != m_last_frame_used) {
|
||||
m_last_frame_used = current_frame;
|
||||
m_last_frame_max_lod_coverage = 0.0f;
|
||||
|
||||
m_manager->primeVBO(this);
|
||||
}
|
||||
m_last_frame_max_lod_coverage = KRMAX(lodCoverage, m_last_frame_max_lod_coverage);
|
||||
}
|
||||
|
||||
|
||||
float KRMeshManager::KRVBOData::getStreamPriority()
|
||||
{
|
||||
long current_frame = m_manager->getContext().getCurrentFrame();
|
||||
if (current_frame > m_last_frame_used + 5) {
|
||||
return 1.0f - KRCLAMP((float)(current_frame - m_last_frame_used) / 60.0f, 0.0f, 1.0f);
|
||||
} else {
|
||||
return 10000.0f + m_last_frame_max_lod_coverage * 10.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void KRMeshManager::KRVBOData::_swapHandles()
|
||||
{
|
||||
m_is_vbo_ready = m_is_vbo_loaded;
|
||||
}
|
||||
|
||||
void KRMeshManager::primeVBO(KRVBOData* vbo_data)
|
||||
{
|
||||
if (m_vbosActive.find(vbo_data->m_data) == m_vbosActive.end()) {
|
||||
m_vbosActive[vbo_data->m_data] = vbo_data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VkBuffer& KRMeshManager::KRVBOData::getVertexBuffer()
|
||||
{
|
||||
assert(m_is_vbo_ready);
|
||||
return m_allocations->vertex_buffer;
|
||||
}
|
||||
|
||||
VkBuffer& KRMeshManager::KRVBOData::getIndexBuffer()
|
||||
{
|
||||
assert(m_is_vbo_ready);
|
||||
return m_allocations->index_buffer;
|
||||
}
|
||||
|
||||
|
||||
uint32_t KRMeshManager::KRVBOData::getVertexAttributes()
|
||||
{
|
||||
return m_vertex_attrib_flags;
|
||||
}
|
||||
248
kraken/resources/mesh/KRMeshManager.h
Executable file
248
kraken/resources/mesh/KRMeshManager.h
Executable file
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// KRMeshManager.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 "KRContextObject.h"
|
||||
#include "block.h"
|
||||
#include "KRNode.h"
|
||||
|
||||
class KRContext;
|
||||
class KRMesh;
|
||||
enum RenderPassType : uint8_t;
|
||||
|
||||
class KRMeshManager : public KRResourceManager
|
||||
{
|
||||
public:
|
||||
static const int KRENGINE_MAX_VOLUMETRIC_PLANES = 500;
|
||||
static const int KRENGINE_MAX_RANDOM_PARTICLES = 150000;
|
||||
|
||||
KRMeshManager(KRContext& context);
|
||||
void init();
|
||||
virtual ~KRMeshManager();
|
||||
|
||||
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 startFrame(float deltaTime);
|
||||
void endFrame(float deltaTime);
|
||||
|
||||
KRMesh* loadModel(const char* szName, mimir::Block* pData);
|
||||
std::vector<KRMesh*> getModel(const char* szName);
|
||||
KRMesh* getMaxLODModel(const char* szName);
|
||||
void addModel(KRMesh* model);
|
||||
|
||||
std::vector<std::string> getModelNames();
|
||||
unordered_multimap<std::string, KRMesh*>& getModels();
|
||||
|
||||
class KRVBOData
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STREAMING,
|
||||
// STREAMING data is loaded asynchronously, with transfer queues in the streamer thread.
|
||||
|
||||
CONSTANT,
|
||||
// CONSTANT data is loaded asyncrhronously, with transfer queues in the streamer thread, but is not unloaded.
|
||||
|
||||
IMMEDIATE
|
||||
// IMMEDIATE data is loaded synchronously, with graphics queues in the presentation threads.
|
||||
// IMMEDIATE data is available for use immediately on the same frame it is generated.
|
||||
} vbo_type;
|
||||
|
||||
KRVBOData();
|
||||
KRVBOData(KRMeshManager* manager, mimir::Block* data, mimir::Block* index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, const char* debug_label
|
||||
#endif
|
||||
);
|
||||
void init(KRMeshManager* manager, mimir::Block* data, mimir::Block* index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
, const char* debug_label
|
||||
#endif
|
||||
);
|
||||
~KRVBOData();
|
||||
|
||||
|
||||
mimir::Block* m_data;
|
||||
mimir::Block* m_index_data;
|
||||
|
||||
bool isVBOLoaded()
|
||||
{
|
||||
return m_is_vbo_loaded;
|
||||
}
|
||||
bool isVBOReady() const
|
||||
{
|
||||
return m_is_vbo_ready;
|
||||
}
|
||||
void load();
|
||||
void load(VkCommandBuffer& commandBuffer);
|
||||
void unload();
|
||||
void bind(VkCommandBuffer& commandBuffer);
|
||||
|
||||
// KRMeshManager depends on the address of KRVBOData's being constant
|
||||
// after allocation. This is enforced by deleted copy constructors.
|
||||
KRVBOData(const KRVBOData& o) = delete;
|
||||
KRVBOData& operator=(const KRVBOData& o) = delete;
|
||||
|
||||
long getSize()
|
||||
{
|
||||
return (long)m_size;
|
||||
}
|
||||
|
||||
void resetPoolExpiry(float lodCoverage);
|
||||
long getLastFrameUsed()
|
||||
{
|
||||
return m_last_frame_used;
|
||||
}
|
||||
|
||||
vbo_type getType()
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
float getStreamPriority();
|
||||
|
||||
void _swapHandles();
|
||||
|
||||
VkBuffer& getVertexBuffer();
|
||||
VkBuffer& getIndexBuffer();
|
||||
uint32_t getVertexAttributes();
|
||||
|
||||
private:
|
||||
KRMeshManager* m_manager;
|
||||
int m_vertex_attrib_flags;
|
||||
long m_size;
|
||||
|
||||
long m_last_frame_used;
|
||||
float m_last_frame_max_lod_coverage;
|
||||
vbo_type m_type;
|
||||
bool m_static_vbo;
|
||||
bool m_is_vbo_loaded;
|
||||
bool m_is_vbo_ready;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
KrDeviceHandle device;
|
||||
VkBuffer vertex_buffer;
|
||||
VmaAllocation vertex_allocation;
|
||||
VkBuffer index_buffer;
|
||||
VmaAllocation index_allocation;
|
||||
} AllocationInfo;
|
||||
|
||||
AllocationInfo m_allocations[KRENGINE_MAX_GPU_COUNT];
|
||||
|
||||
#if KRENGINE_DEBUG_GPU_LABELS
|
||||
char m_debugLabel[KRENGINE_DEBUG_GPU_LABEL_MAX_LEN];
|
||||
#endif
|
||||
};
|
||||
|
||||
void bindVBO(VkCommandBuffer& commandBuffer, KRVBOData* vbo_data, float lodCoverage);
|
||||
long getMemUsed();
|
||||
long getMemActive();
|
||||
|
||||
typedef struct
|
||||
{
|
||||
hydra::Vector3 vertex;
|
||||
hydra::Vector2 uva;
|
||||
} RandomParticleVertexData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
hydra::Vector3 vertex;
|
||||
} VolumetricLightingVertexData;
|
||||
|
||||
long getMemoryTransferedThisFrame();
|
||||
|
||||
size_t getActiveVBOCount();
|
||||
|
||||
struct draw_call_info
|
||||
{
|
||||
RenderPassType pass;
|
||||
char object_name[256];
|
||||
char material_name[256];
|
||||
int vertex_count;
|
||||
};
|
||||
|
||||
void log_draw_call(RenderPassType pass, const std::string& object_name, const std::string& material_name, int vertex_count);
|
||||
std::vector<draw_call_info> getDrawCalls();
|
||||
|
||||
|
||||
|
||||
KRVBOData KRENGINE_VBO_DATA_3D_CUBE_VERTICES;
|
||||
KRVBOData KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
|
||||
KRVBOData KRENGINE_VBO_DATA_RANDOM_PARTICLES;
|
||||
KRVBOData KRENGINE_VBO_DATA_VOLUMETRIC_LIGHTING;
|
||||
|
||||
|
||||
void doStreaming(long& memoryRemaining, long& memoryRemainingThisFrame);
|
||||
|
||||
private:
|
||||
mimir::Block KRENGINE_VBO_3D_CUBE_VERTICES;
|
||||
__int32_t KRENGINE_VBO_3D_CUBE_ATTRIBS;
|
||||
mimir::Block KRENGINE_VBO_2D_SQUARE_VERTICES;
|
||||
__int32_t KRENGINE_VBO_2D_SQUARE_ATTRIBS;
|
||||
|
||||
unordered_multimap<std::string, KRMesh*> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
|
||||
|
||||
long m_vboMemUsed;
|
||||
KRVBOData* m_currentVBO;
|
||||
|
||||
unordered_map<mimir::Block*, KRVBOData*> m_vbosActive;
|
||||
std::vector<std::pair<float, KRVBOData*> > m_activeVBOs_streamer;
|
||||
std::vector<std::pair<float, KRVBOData*> > m_activeVBOs_streamer_copy;
|
||||
|
||||
mimir::Block m_randomParticleVertexData;
|
||||
mimir::Block m_volumetricLightingVertexData;
|
||||
|
||||
long m_memoryTransferredThisFrame;
|
||||
|
||||
std::vector<draw_call_info> m_draw_calls;
|
||||
bool m_draw_call_logging_enabled;
|
||||
bool m_draw_call_log_used;
|
||||
|
||||
std::mutex m_streamerFenceMutex;
|
||||
bool m_streamerComplete;
|
||||
|
||||
void balanceVBOMemory(long& memoryRemaining, long& memoryRemainingThisFrame);
|
||||
|
||||
void primeVBO(KRVBOData* vbo_data);
|
||||
|
||||
void initRandomParticles();
|
||||
void initVolumetricLightingVertexes();
|
||||
|
||||
};
|
||||
64
kraken/resources/mesh/KRMeshQuad.cpp
Executable file
64
kraken/resources/mesh/KRMeshQuad.cpp
Executable file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// KRMeshQuad.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 "KRMeshQuad.h"
|
||||
|
||||
using namespace hydra;
|
||||
|
||||
KRMeshQuad::KRMeshQuad(KRContext& context) : KRMesh(context, "__quad")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
mi.vertices.push_back(Vector3::Create(-1.0f, -1.0f, 0.0f));
|
||||
mi.vertices.push_back(Vector3::Create(1.0f, -1.0f, 0.0f));
|
||||
mi.vertices.push_back(Vector3::Create(-1.0f, 1.0f, 0.0f));
|
||||
mi.vertices.push_back(Vector3::Create(1.0f, 1.0f, 0.0f));
|
||||
|
||||
mi.uva.push_back(Vector2::Create(0.0f, 0.0f));
|
||||
mi.uva.push_back(Vector2::Create(1.0f, 0.0f));
|
||||
mi.uva.push_back(Vector2::Create(0.0f, 1.0f));
|
||||
mi.uva.push_back(Vector2::Create(1.0f, 1.0f));
|
||||
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back((int)mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshQuad::~KRMeshQuad()
|
||||
{
|
||||
|
||||
}
|
||||
42
kraken/resources/mesh/KRMeshQuad.h
Executable file
42
kraken/resources/mesh/KRMeshQuad.h
Executable file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// KRMeshQuad.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 "KRMesh.h"
|
||||
|
||||
class KRMeshQuad : public KRMesh
|
||||
{
|
||||
public:
|
||||
KRMeshQuad(KRContext& context);
|
||||
virtual ~KRMeshQuad();
|
||||
private:
|
||||
};
|
||||
129
kraken/resources/mesh/KRMeshSphere.cpp
Executable file
129
kraken/resources/mesh/KRMeshSphere.cpp
Executable file
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// KRMeshSphere.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 "KRMeshSphere.h"
|
||||
|
||||
using namespace hydra;
|
||||
|
||||
KRMeshSphere::KRMeshSphere(KRContext& context) : KRMesh(context, "__sphere")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = (int)(pow(4, iterations) * 8.0f);
|
||||
|
||||
std::vector<Triangle3> f = std::vector<Triangle3>(facet_count);
|
||||
|
||||
int i, it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
Vector3::Create(0,0,1),
|
||||
Vector3::Create(0,0,-1),
|
||||
Vector3::Create(-1,-1,0),
|
||||
Vector3::Create(1,-1,0),
|
||||
Vector3::Create(1,1,0),
|
||||
Vector3::Create(-1,1,0)
|
||||
};
|
||||
|
||||
Vector3 pa, pb, pc;
|
||||
int nt = 0, ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1.0f / sqrtf(2.0f);
|
||||
for (i = 0; i < 6; i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
f[0][0] = p[0]; f[0][1] = p[3]; f[0][2] = p[4];
|
||||
f[1][0] = p[0]; f[1][1] = p[4]; f[1][2] = p[5];
|
||||
f[2][0] = p[0]; f[2][1] = p[5]; f[2][2] = p[2];
|
||||
f[3][0] = p[0]; f[3][1] = p[2]; f[3][2] = p[3];
|
||||
f[4][0] = p[1]; f[4][1] = p[4]; f[4][2] = p[3];
|
||||
f[5][0] = p[1]; f[5][1] = p[5]; f[5][2] = p[4];
|
||||
f[6][0] = p[1]; f[6][1] = p[2]; f[6][2] = p[5];
|
||||
f[7][0] = p[1]; f[7][1] = p[3]; f[7][2] = p[2];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it = 0; it < iterations; it++) {
|
||||
ntold = nt;
|
||||
for (i = 0; i < ntold; i++) {
|
||||
pa.x = (f[i][0].x + f[i][1].x) / 2;
|
||||
pa.y = (f[i][0].y + f[i][1].y) / 2;
|
||||
pa.z = (f[i][0].z + f[i][1].z) / 2;
|
||||
pb.x = (f[i][1].x + f[i][2].x) / 2;
|
||||
pb.y = (f[i][1].y + f[i][2].y) / 2;
|
||||
pb.z = (f[i][1].z + f[i][2].z) / 2;
|
||||
pc.x = (f[i][2].x + f[i][0].x) / 2;
|
||||
pc.y = (f[i][2].y + f[i][0].y) / 2;
|
||||
pc.z = (f[i][2].z + f[i][0].z) / 2;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
f[nt][0] = f[i][0]; f[nt][1] = pa; f[nt][2] = pc; nt++;
|
||||
f[nt][0] = pa; f[nt][1] = f[i][1]; f[nt][2] = pb; nt++;
|
||||
f[nt][0] = pb; f[nt][1] = f[i][2]; f[nt][2] = pc; nt++;
|
||||
f[i][0] = pa;
|
||||
f[i][1] = pb;
|
||||
f[i][2] = pc;
|
||||
}
|
||||
}
|
||||
|
||||
for (int facet_index = 0; facet_index < facet_count; facet_index++) {
|
||||
mi.vertices.push_back(f[facet_index][0]);
|
||||
mi.vertices.push_back(f[facet_index][1]);
|
||||
mi.vertices.push_back(f[facet_index][2]);
|
||||
}
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back((int)mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
|
||||
|
||||
mi.format = ModelFormat::KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
|
||||
// Generate normals pointing away from center of sphere.
|
||||
for (int vertex_index = 0; vertex_index < mi.vertices.size(); vertex_index++) {
|
||||
mi.normals.push_back(Vector3::Normalize(mi.vertices[vertex_index] - Vector3::Zero()));
|
||||
}
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshSphere::~KRMeshSphere()
|
||||
{
|
||||
|
||||
}
|
||||
42
kraken/resources/mesh/KRMeshSphere.h
Executable file
42
kraken/resources/mesh/KRMeshSphere.h
Executable file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// KRMeshSphere.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 "KRMesh.h"
|
||||
|
||||
class KRMeshSphere : public KRMesh
|
||||
{
|
||||
public:
|
||||
KRMeshSphere(KRContext& context);
|
||||
virtual ~KRMeshSphere();
|
||||
private:
|
||||
};
|
||||
Reference in New Issue
Block a user