Compare commits
2 Commits
946c9e0027
...
5d0741635c
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d0741635c | |||
| 041853a4a0 |
92
Deer/Include/DeerCore/Voxel.h
Normal file
92
Deer/Include/DeerCore/Voxel.h
Normal file
@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#define CHUNK_VOXEL_SIZE 16
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
#include "DeerRender/Resource.h"
|
||||
namespace Deer {
|
||||
class VoxelBuilder;
|
||||
class GPUMesh;
|
||||
} // namespace Deer
|
||||
#endif
|
||||
|
||||
namespace Deer {
|
||||
struct VoxelType {
|
||||
std::string id;
|
||||
};
|
||||
|
||||
struct Chunk {
|
||||
Chunk() {
|
||||
Voxel voxel = {.voxelTypeId = 0};
|
||||
voxels_list.push_back(voxel);
|
||||
voxels_reference_map[voxel] = 0;
|
||||
}
|
||||
|
||||
struct Voxel {
|
||||
uint32_t voxelTypeId;
|
||||
|
||||
bool operator==(const Voxel& other) const noexcept {
|
||||
return voxelTypeId == other.voxelTypeId;
|
||||
}
|
||||
};
|
||||
|
||||
struct VoxelHasher {
|
||||
std::size_t operator()(const Voxel& v) const noexcept {
|
||||
return std::hash<uint32_t>{}(v.voxelTypeId);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<Chunk::Voxel> voxels_list;
|
||||
std::unordered_map<Chunk::Voxel, uint16_t, VoxelHasher> voxels_reference_map;
|
||||
uint16_t reference_matrix[CHUNK_VOXEL_SIZE][CHUNK_VOXEL_SIZE][CHUNK_VOXEL_SIZE];
|
||||
|
||||
uint16_t getOrCreateVoxelReference(const Voxel& voxel);
|
||||
Voxel getVoxel(uint16_t voxelReference);
|
||||
};
|
||||
|
||||
class VoxelEnvironment {
|
||||
public:
|
||||
VoxelEnvironment();
|
||||
|
||||
void modifyVoxel(uint32_t voxelId, int x, int y, int z);
|
||||
uint32_t getVoxel(int x, int y, int z);
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
public:
|
||||
Resource<GPUMesh> buildChunk(int x, int y, int z);
|
||||
Scope<VoxelBuilder> voxelBuilder;
|
||||
#endif
|
||||
private:
|
||||
struct ChunkID {
|
||||
int x, y, z;
|
||||
|
||||
bool operator==(const ChunkID& other) const noexcept {
|
||||
return x == other.x &&
|
||||
y == other.y &&
|
||||
z == other.z;
|
||||
}
|
||||
};
|
||||
|
||||
struct ChunkIDHasher {
|
||||
std::size_t operator()(const ChunkID& c) const noexcept {
|
||||
std::size_t h = 0;
|
||||
h ^= std::hash<int>{}(c.x) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||
h ^= std::hash<int>{}(c.y) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||
h ^= std::hash<int>{}(c.z) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
Chunk* getOrCreateChunk(int x, int y, int z);
|
||||
Chunk* tryGetChunk(int x, int y, int z);
|
||||
|
||||
std::vector<Scope<Chunk>> chunk_list;
|
||||
std::unordered_map<ChunkID, Chunk*, ChunkIDHasher> chunk_map;
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -24,6 +24,12 @@ namespace Deer {
|
||||
VertexUV(float _u, float _v) : u(_u), v(_v) {}
|
||||
};
|
||||
|
||||
struct VertexLight {
|
||||
uint8_t light;
|
||||
|
||||
VertexLight() = default;
|
||||
VertexLight(int8_t _u) : light(_u) {}
|
||||
};
|
||||
// Vertex normal is represented with a number fromn [-64,64], and then its
|
||||
// divided by 64 to know the decimal number
|
||||
struct VertexNormal {
|
||||
@ -43,6 +49,7 @@ namespace Deer {
|
||||
vertexCount = count;
|
||||
}
|
||||
void createUVData() { vertexUVData = MakeScope<VertexUV[]>(vertexCount); }
|
||||
void createLightData() { vertexLightData = MakeScope<VertexLight[]>(vertexCount); }
|
||||
void createIndices(uint32_t count) {
|
||||
indexData = MakeScope<uint32_t[]>(count);
|
||||
indexCount = count;
|
||||
@ -51,6 +58,7 @@ namespace Deer {
|
||||
inline VertexPosition* getVertexPosition() const { return vertexPositionsData.get(); }
|
||||
inline VertexNormal* getVertexNormal() const { return vertexNormalData.get(); }
|
||||
inline VertexUV* getVertexUV() const { return vertexUVData.get(); }
|
||||
inline VertexLight* getVertexLight() const { return vertexLightData.get(); }
|
||||
inline uint32_t* getIndexData() const { return indexData.get(); }
|
||||
|
||||
inline uint32_t getVertexCount() const { return vertexCount; }
|
||||
@ -61,6 +69,7 @@ namespace Deer {
|
||||
Scope<VertexPosition[]> vertexPositionsData;
|
||||
Scope<VertexNormal[]> vertexNormalData;
|
||||
Scope<VertexUV[]> vertexUVData;
|
||||
Scope<VertexLight[]> vertexLightData;
|
||||
|
||||
uint32_t indexCount = 0;
|
||||
Scope<uint32_t[]> indexData;
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
#include "DeerRender/EntityEnviroment.h"
|
||||
#include "DeerRender/Render/FrameBuffer.h"
|
||||
#include "DeerRender/Tools/Memory.h"
|
||||
|
||||
namespace Deer {
|
||||
class RenderPiperline {
|
||||
public:
|
||||
RenderPiperline(RenderPiperline&) = delete;
|
||||
RenderPiperline(PiperlineOptions);
|
||||
|
||||
void render(const EntityEnvironment&);
|
||||
|
||||
private:
|
||||
Scope<FrameBuffer> resultImage;
|
||||
PiperlineOptions options;
|
||||
};
|
||||
|
||||
struct PiperlineOptions {
|
||||
int width = 100;
|
||||
int height = 100;
|
||||
};
|
||||
} // namespace Deer
|
||||
78
Deer/Include/DeerRender/Voxel.h
Normal file
78
Deer/Include/DeerRender/Voxel.h
Normal file
@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Voxel.h"
|
||||
|
||||
#include "DeerRender/Mesh.h"
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
struct VoxelVertex {
|
||||
VoxelVertex() = default;
|
||||
VoxelVertex(glm::vec3 _position) : position(_position) {}
|
||||
|
||||
glm::vec3 position;
|
||||
};
|
||||
|
||||
struct VoxelFaceData {
|
||||
// Basic construction
|
||||
std::vector<VoxelVertex> vertices;
|
||||
std::vector<uint32_t> triangles;
|
||||
|
||||
std::array<std::vector<uint32_t>, 4> connections;
|
||||
std::array<uint32_t, 4> edges;
|
||||
};
|
||||
|
||||
class VoxelBuilder {
|
||||
public:
|
||||
Resource<GPUMesh> buildChunk(int x, int y, int z);
|
||||
|
||||
VoxelBuilder(VoxelEnvironment* env) : environment(env) {}
|
||||
|
||||
private:
|
||||
struct VoxelData {
|
||||
int16_t vertexIndexFace[6] = {-1, -1, -1, -1, -1, -1};
|
||||
};
|
||||
|
||||
struct VertexData {
|
||||
glm::vec3 position;
|
||||
glm::vec3 normal;
|
||||
float extrussion;
|
||||
float light;
|
||||
};
|
||||
|
||||
private:
|
||||
void addFace(VoxelFaceData& data, glm::vec3 origin, glm::vec3 up, glm::vec3 right);
|
||||
void calculateNormals();
|
||||
|
||||
void buildVertices();
|
||||
void buildFaceVertices(int x, int y, int z, int face);
|
||||
|
||||
void buildConnections();
|
||||
void buildAxisConnections(int x, int y, int z);
|
||||
void connectVertices(VoxelFaceData& face1, int edgeIndex1, int face1VertexOffset, VoxelFaceData& face2, int edgeIndex2, int face2VertexOffset);
|
||||
|
||||
void buildMarchingCubesCorners();
|
||||
void buildMarchingVoxel(int x, int y, int z, uint8_t marchingCubeId);
|
||||
int getVertexIdCorner(int x, int y, int z, int edge);
|
||||
|
||||
VoxelData& getVoxelData(int x, int y, int z);
|
||||
void clearVoxelData();
|
||||
|
||||
bool hasBlock(int x, int y, int z);
|
||||
float calculateVertexSunLight(int x, int y, int z);
|
||||
|
||||
std::vector<VertexData> vertices;
|
||||
std::vector<u_int32_t> indices;
|
||||
|
||||
int voxelXOffset;
|
||||
int voxelYOffset;
|
||||
int voxelZOffset;
|
||||
|
||||
VoxelEnvironment* environment;
|
||||
VoxelData voxelData[CHUNK_VOXEL_SIZE + 2][CHUNK_VOXEL_SIZE + 2][CHUNK_VOXEL_SIZE + 2];
|
||||
|
||||
friend VoxelEnvironment;
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -67,6 +67,11 @@ namespace Deer {
|
||||
getContextEntity(handle).destroy();
|
||||
}
|
||||
|
||||
glm::mat4 Scripting::entity_getWorldMatrix(EntityHandle& handle) {
|
||||
Entity& entity = getContextEntity(handle);
|
||||
return entity.getWorldMatrix();
|
||||
}
|
||||
|
||||
int Scripting::entity_getNetworkBehaviour(EntityHandle& handle) {
|
||||
return (int)getContextEntityComponent<TagComponent>(handle).networkBehaviour;
|
||||
}
|
||||
|
||||
@ -32,6 +32,8 @@ namespace Deer {
|
||||
void entity_destroy(EntityHandle&);
|
||||
CScriptArray* entity_getChildrens(EntityHandle&);
|
||||
|
||||
glm::mat4 entity_getWorldMatrix(EntityHandle&);
|
||||
|
||||
int entity_getNetworkBehaviour(EntityHandle&);
|
||||
void entity_setNetworkBehaviour(int, EntityHandle&);
|
||||
int entity_getForcedNetworkBehaviour(EntityHandle&);
|
||||
|
||||
@ -7,6 +7,18 @@ namespace Deer {
|
||||
new (mem) glm::vec3();
|
||||
}
|
||||
|
||||
void mat4_constructor(void* mem) {
|
||||
new (mem) glm::mat4(1.0f);
|
||||
}
|
||||
|
||||
glm::mat4 mat4_getRelativeMatrix(glm::mat4& other, glm::mat4& self) {
|
||||
return glm::inverse(other) * self;
|
||||
}
|
||||
|
||||
glm::vec3 mat4_getPosition(glm::mat4& matrix) {
|
||||
return glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]);
|
||||
}
|
||||
|
||||
void vec3_constructor_params(float x, float y, float z, void* mem) {
|
||||
new (mem) glm::vec3(x, y, z);
|
||||
}
|
||||
|
||||
@ -10,6 +10,10 @@ namespace Deer {
|
||||
void vec3_constructor(void*);
|
||||
void vec3_constructor_params(float, float, float, void*);
|
||||
|
||||
void mat4_constructor(void*);
|
||||
glm::mat4 mat4_getRelativeMatrix(glm::mat4&, glm::mat4&);
|
||||
glm::vec3 mat4_getPosition(glm::mat4&);
|
||||
|
||||
glm::vec3 vec3_add(glm::vec3&, glm::vec3&);
|
||||
glm::vec3 vec3_sub(const glm::vec3&, glm::vec3&);
|
||||
glm::vec3 vec3_neg(glm::vec3&);
|
||||
|
||||
@ -31,6 +31,8 @@ namespace Deer {
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "Entity", "bool opEquals(const Entity &in) const", entity_opEquals);
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "Entity", "array<Entity>@ getChildrens()", entity_getChildrens);
|
||||
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "Entity", "mat4 getWorldMatrix()", entity_getWorldMatrix);
|
||||
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "Entity", "EntityNetworkBehaviour get_networkBehaviour() const property", entity_getNetworkBehaviour);
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "Entity", "void set_networkBehaviour(EntityNetworkBehaviour) property", entity_setNetworkBehaviour);
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "Entity", "EntityNetworkBehaviour getForcedNetworkBehaviour()", entity_getForcedNetworkBehaviour);
|
||||
|
||||
@ -20,6 +20,9 @@ namespace Deer {
|
||||
REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, "vec3", "void f()", vec3_constructor);
|
||||
REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, "vec3", "void f(float, float = 0, float = 0)", vec3_constructor_params);
|
||||
|
||||
scriptEngine->RegisterObjectType("mat4", sizeof(glm::mat4), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<glm::mat4>() | asOBJ_APP_CLASS_ALLFLOATS | asOBJ_APP_CLASS_MORE_CONSTRUCTORS);
|
||||
REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, "mat4", "void f()", mat4_constructor);
|
||||
|
||||
scriptEngine->RegisterObjectType("quat", sizeof(glm::quat), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<glm::quat>() | asOBJ_APP_CLASS_ALLFLOATS | asOBJ_APP_CLASS_MORE_CONSTRUCTORS);
|
||||
scriptEngine->RegisterObjectProperty("quat", "float x", asOFFSET(glm::quat, x));
|
||||
scriptEngine->RegisterObjectProperty("quat", "float y", asOFFSET(glm::quat, y));
|
||||
@ -58,6 +61,9 @@ namespace Deer {
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "quat", "void setEuler(vec3)", quat_setEuler);
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "quat", "vec3 getEuler() const", quat_getEuler);
|
||||
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "mat4", "mat4 getRelativeMatrix(mat4&in) const", mat4_getRelativeMatrix);
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "mat4", "vec3 getPosition() const", mat4_getPosition);
|
||||
|
||||
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "Transform", "vec3 relative(vec3)", transform_relative);
|
||||
}
|
||||
|
||||
|
||||
16
Deer/src/DeerCore/Voxel/Chunk.cpp
Normal file
16
Deer/src/DeerCore/Voxel/Chunk.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "DeerCore/Voxel.h"
|
||||
|
||||
namespace Deer {
|
||||
uint16_t Chunk::getOrCreateVoxelReference(const Voxel& voxel) {
|
||||
if (voxels_reference_map.contains(voxel))
|
||||
return voxels_reference_map[voxel];
|
||||
|
||||
voxels_list.push_back(voxel);
|
||||
voxels_reference_map[voxel] = voxels_list.size() - 1;
|
||||
return voxels_list.size() - 1;
|
||||
}
|
||||
|
||||
Chunk::Voxel Chunk::getVoxel(uint16_t voxelReference) {
|
||||
return voxels_list[voxelReference];
|
||||
}
|
||||
} // namespace Deer
|
||||
91
Deer/src/DeerCore/Voxel/VoxelEnvironment.cpp
Normal file
91
Deer/src/DeerCore/Voxel/VoxelEnvironment.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "DeerCore/Voxel.h"
|
||||
|
||||
namespace Deer {
|
||||
namespace Voxel {
|
||||
int getChunk(int id) {
|
||||
int chunk = id / CHUNK_VOXEL_SIZE;
|
||||
|
||||
// Fix truncation toward zero for negatives
|
||||
if (id < 0 && id % CHUNK_VOXEL_SIZE != 0)
|
||||
--chunk;
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
int getBlock(int id) {
|
||||
int block = id % CHUNK_VOXEL_SIZE;
|
||||
|
||||
// Make remainder positive
|
||||
if (block < 0)
|
||||
block += CHUNK_VOXEL_SIZE;
|
||||
|
||||
return block;
|
||||
}
|
||||
} // namespace Voxel
|
||||
|
||||
Chunk* VoxelEnvironment::getOrCreateChunk(int x, int y, int z) {
|
||||
ChunkID chunkId = {
|
||||
.x = Voxel::getChunk(x),
|
||||
.y = Voxel::getChunk(y),
|
||||
.z = Voxel::getChunk(z)};
|
||||
|
||||
if (chunk_map.contains(chunkId))
|
||||
return chunk_map[chunkId];
|
||||
|
||||
// Should do stuff but we relax for the moment
|
||||
chunk_list.push_back(MakeScope<Chunk>());
|
||||
Chunk* chunk = chunk_list.back().get();
|
||||
chunk_map[chunkId] = chunk;
|
||||
|
||||
for (int x = 0; x < CHUNK_VOXEL_SIZE; x++) {
|
||||
for (int y = 0; y < CHUNK_VOXEL_SIZE; y++) {
|
||||
for (int z = 0; z < CHUNK_VOXEL_SIZE; z++) {
|
||||
chunk->reference_matrix[x][y][z] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
Chunk* VoxelEnvironment::tryGetChunk(int x, int y, int z) {
|
||||
ChunkID chunkId = {
|
||||
.x = Voxel::getChunk(x),
|
||||
.y = Voxel::getChunk(y),
|
||||
.z = Voxel::getChunk(z)};
|
||||
|
||||
if (chunk_map.contains(chunkId))
|
||||
return chunk_map[chunkId];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VoxelEnvironment::modifyVoxel(uint32_t voxelId, int x, int y, int z) {
|
||||
Chunk* chunk = getOrCreateChunk(x, y, z);
|
||||
|
||||
Chunk::Voxel voxel = {.voxelTypeId = voxelId};
|
||||
|
||||
uint16_t voxelRef = chunk->getOrCreateVoxelReference(voxel);
|
||||
|
||||
int posX = Voxel::getBlock(x);
|
||||
int posY = Voxel::getBlock(y);
|
||||
int posZ = Voxel::getBlock(z);
|
||||
|
||||
chunk->reference_matrix[posX][posY][posZ] = voxelRef;
|
||||
}
|
||||
|
||||
uint32_t VoxelEnvironment::getVoxel(int x, int y, int z) {
|
||||
Chunk* chunk = tryGetChunk(x, y, z);
|
||||
|
||||
if (!chunk)
|
||||
return 0;
|
||||
|
||||
int posX = Voxel::getBlock(x);
|
||||
int posY = Voxel::getBlock(y);
|
||||
int posZ = Voxel::getBlock(z);
|
||||
|
||||
uint16_t voxelRef = chunk->reference_matrix[posX][posY][posZ];
|
||||
return chunk->getVoxel(voxelRef).voxelTypeId;
|
||||
}
|
||||
|
||||
} // namespace Deer
|
||||
@ -7,6 +7,7 @@
|
||||
#include "DeerRender/Universe.h"
|
||||
#include "DeerRender/Window.h"
|
||||
#include "DeerRender/World.h"
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
#include "DeerRender/Render/RenderCommand.h"
|
||||
|
||||
@ -1,23 +1,20 @@
|
||||
#include "DeerRender/FrameBuffer.h"
|
||||
|
||||
namespace Deer {
|
||||
Scope<FrameBuffer> ResourceBuilder<FrameBuffer>::buildResource(const FrameBufferData& baseData) {
|
||||
TextureBufferType tbt;
|
||||
switch (baseData.frameBufferType)
|
||||
{
|
||||
case FrameBufferData::FrameBufferType::RGBA8 :
|
||||
tbt = TextureBufferType::RGBA8;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Scope<FrameBuffer> ResourceBuilder<FrameBuffer>::buildResource(const FrameBufferData& baseData) {
|
||||
TextureBufferType tbt;
|
||||
switch (baseData.frameBufferType) {
|
||||
case FrameBufferData::FrameBufferType::RGBA8:
|
||||
tbt = TextureBufferType::RGBA8;
|
||||
break;
|
||||
|
||||
FrameBufferSpecification spec(baseData.sizeX, baseData.sizeY, {tbt}, baseData.samples);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Scope<FrameBuffer> frameBuffer = Scope<FrameBuffer>(FrameBuffer::create(spec));
|
||||
return frameBuffer;
|
||||
FrameBufferSpecification spec(baseData.sizeX, baseData.sizeY, {tbt}, baseData.samples);
|
||||
|
||||
}
|
||||
}
|
||||
Scope<FrameBuffer> frameBuffer = Scope<FrameBuffer>(FrameBuffer::create(spec));
|
||||
return frameBuffer;
|
||||
}
|
||||
} // namespace Deer
|
||||
@ -105,7 +105,7 @@ namespace Deer {
|
||||
}
|
||||
|
||||
void ImGuiLayer::shutdown() {
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGuiLayer::onKeyPressedEvent(KeyPressedEvent& e) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@ -127,7 +127,6 @@ namespace Deer {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddKeyEvent((ImGuiKey)e.getKeyCode(),
|
||||
ImGui::IsKeyPressed(ImGuiKey_LeftSuper) || ImGui::IsKeyPressed(ImGuiKey_RightSuper));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,15 @@ namespace Deer {
|
||||
vertexNormalBuffer->setLayout(normalLayout);
|
||||
vertexArray->addVertexBuffer(vertexNormalBuffer);
|
||||
|
||||
if (data.getVertexPosition()) {
|
||||
if (data.getVertexLight()) {
|
||||
BufferLayout lightLayout({{"v_Light", DataType::Unsigned_Byte, ShaderDataType::FloatingPoint}}, sizeof(VertexLight));
|
||||
Ref<VertexBuffer> vertexLightBuffer = VertexBuffer::create(data.getVertexLight(), data.getVertexCount() * sizeof(VertexLight));
|
||||
vertexLightBuffer->bind();
|
||||
vertexLightBuffer->setLayout(lightLayout);
|
||||
vertexArray->addVertexBuffer(vertexLightBuffer);
|
||||
}
|
||||
|
||||
if (data.getVertexUV()) {
|
||||
BufferLayout uvLayout({{"v_UV", DataType::Float2, ShaderDataType::FloatingPoint}}, sizeof(VertexUV));
|
||||
Ref<VertexBuffer> vertexUVBuffer = VertexBuffer::create(data.getVertexUV(), data.getVertexCount() * sizeof(VertexUV));
|
||||
vertexUVBuffer->bind();
|
||||
|
||||
@ -75,6 +75,10 @@ namespace Deer {
|
||||
REGISTER_GLOBAL_FUNC(scriptEngine, "void drawFrameBuffer(FrameBuffer texture, int, int)", Scripting::drawFrameBuffer);
|
||||
REGISTER_GLOBAL_FUNC(scriptEngine, "void drawFrameBufferCentered(FrameBuffer texture, int, int)", Scripting::drawFrameBufferCentered);
|
||||
|
||||
REGISTER_GLOBAL_FUNC(scriptEngine, "bool manipulationTransform(WorldCamera&in, mat4&in, mat4&out, bool local)", Scripting::manipulationTransform);
|
||||
REGISTER_GLOBAL_FUNC(scriptEngine, "bool manipulationRotation(WorldCamera&in, mat4&in, mat4&out, bool local)", Scripting::manipulationRotation);
|
||||
REGISTER_GLOBAL_FUNC(scriptEngine, "bool manipulationScale(WorldCamera&in, mat4&in, mat4&out, bool local)", Scripting::manipulationScale);
|
||||
|
||||
// Input state
|
||||
REGISTER_GLOBAL_FUNC(scriptEngine, "bool isKeyDown(key)", Scripting::isKeyDown);
|
||||
REGISTER_GLOBAL_FUNC(scriptEngine, "bool isKeyPressed(key)", Scripting::isKeyPressed);
|
||||
|
||||
@ -3,14 +3,18 @@
|
||||
|
||||
#include "DeerCore/Scripting/Helpers.h"
|
||||
#include "DeerRender/Texture.h"
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
#include "DeerRender/ImGuiLayer.h"
|
||||
#include "DeerRender/Scripting/InternalAPI/ImGUI.h"
|
||||
#include "DeerRender/World.h"
|
||||
|
||||
#include "angelscript.h"
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
#include "imgui.h"
|
||||
#include "scriptany.h"
|
||||
|
||||
#include "ImGuizmo.h"
|
||||
#include <string>
|
||||
|
||||
namespace Deer {
|
||||
@ -299,6 +303,69 @@ namespace Deer {
|
||||
ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
|
||||
bool manipulationTransform(WorldCamera& camera, glm::mat4& objMatrix, glm::mat4& outMatrix, bool local) {
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::SetDrawlist();
|
||||
|
||||
ImVec2 window_pos = ImGui::GetItemRectMin();
|
||||
ImVec2 window_size = ImGui::GetItemRectSize();
|
||||
ImGuizmo::SetRect(window_pos.x, window_pos.y, window_size.x, window_size.y);
|
||||
|
||||
glm::mat4 cameraProjection = camera.camera.getMatrix();
|
||||
cameraProjection[2][2] *= -1.0f;
|
||||
cameraProjection[2][3] *= -1.0f;
|
||||
|
||||
glm::mat4 cameraView = glm::inverse(camera.transform.getMatrix());
|
||||
outMatrix = objMatrix;
|
||||
|
||||
ImGuizmo::MODE mode = local ? ImGuizmo::MODE::LOCAL : ImGuizmo::MODE::WORLD;
|
||||
ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(cameraProjection), ImGuizmo::OPERATION::TRANSLATE, mode, glm::value_ptr(outMatrix));
|
||||
|
||||
return ImGuizmo::IsUsing();
|
||||
}
|
||||
|
||||
bool manipulationScale(WorldCamera& camera, glm::mat4& objMatrix, glm::mat4& outMatrix, bool local) {
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::SetDrawlist();
|
||||
|
||||
ImVec2 window_pos = ImGui::GetItemRectMin();
|
||||
ImVec2 window_size = ImGui::GetItemRectSize();
|
||||
ImGuizmo::SetRect(window_pos.x, window_pos.y, window_size.x, window_size.y);
|
||||
|
||||
glm::mat4 cameraProjection = camera.camera.getMatrix();
|
||||
cameraProjection[2][2] *= -1.0f;
|
||||
cameraProjection[2][3] *= -1.0f;
|
||||
|
||||
glm::mat4 cameraView = glm::inverse(camera.transform.getMatrix());
|
||||
outMatrix = objMatrix;
|
||||
|
||||
ImGuizmo::MODE mode = local ? ImGuizmo::MODE::LOCAL : ImGuizmo::MODE::WORLD;
|
||||
ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(cameraProjection), ImGuizmo::OPERATION::SCALE, mode, glm::value_ptr(outMatrix));
|
||||
|
||||
return ImGuizmo::IsUsing();
|
||||
}
|
||||
|
||||
bool manipulationRotation(WorldCamera& camera, glm::mat4& objMatrix, glm::mat4& outMatrix, bool local) {
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::SetDrawlist();
|
||||
|
||||
ImVec2 window_pos = ImGui::GetItemRectMin();
|
||||
ImVec2 window_size = ImGui::GetItemRectSize();
|
||||
ImGuizmo::SetRect(window_pos.x, window_pos.y, window_size.x, window_size.y);
|
||||
|
||||
glm::mat4 cameraProjection = camera.camera.getMatrix();
|
||||
cameraProjection[2][2] *= -1.0f;
|
||||
cameraProjection[2][3] *= -1.0f;
|
||||
|
||||
glm::mat4 cameraView = glm::inverse(camera.transform.getMatrix());
|
||||
outMatrix = objMatrix;
|
||||
|
||||
ImGuizmo::MODE mode = local ? ImGuizmo::MODE::LOCAL : ImGuizmo::MODE::WORLD;
|
||||
ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(cameraProjection), ImGuizmo::OPERATION::ROTATE, mode, glm::value_ptr(outMatrix));
|
||||
|
||||
return ImGuizmo::IsUsing();
|
||||
}
|
||||
|
||||
void drawIconCentered(Resource<Texture> texture, int size) {
|
||||
if (!texture.isValid()) {
|
||||
ImGui::TextColored(ImVec4(0.5, 0, 0, 1), "Invalid texture");
|
||||
|
||||
@ -9,6 +9,7 @@ class asIScriptFunction;
|
||||
class CScriptAny;
|
||||
|
||||
namespace Deer {
|
||||
struct WorldCamera;
|
||||
|
||||
namespace Scripting {
|
||||
namespace DragDropPayload {
|
||||
@ -42,6 +43,10 @@ namespace Deer {
|
||||
void drawFrameBuffer(Resource<FrameBuffer> frameBuffer, int sizeX, int sizeY);
|
||||
void drawFrameBufferCentered(Resource<FrameBuffer> frameBuffer, int sizeX, int sizeY);
|
||||
|
||||
bool manipulationTransform(WorldCamera&, glm::mat4&, glm::mat4&, bool local);
|
||||
bool manipulationScale(WorldCamera&, glm::mat4&, glm::mat4&, bool local);
|
||||
bool manipulationRotation(WorldCamera&, glm::mat4&, glm::mat4&, bool local);
|
||||
|
||||
int getIconId(const std::string& name);
|
||||
|
||||
// Layout & panel
|
||||
@ -117,5 +122,6 @@ namespace Deer {
|
||||
|
||||
void openPopup(std::string&, CScriptAny*);
|
||||
void closePopup();
|
||||
|
||||
} // namespace Scripting
|
||||
} // namespace Deer
|
||||
|
||||
@ -9,11 +9,11 @@
|
||||
#include "scriptarray.h"
|
||||
#include "scriptstdstring.h"
|
||||
|
||||
#include "DeerRender/Shader.h"
|
||||
#include "DeerRender/Components.h"
|
||||
#include "DeerRender/Mesh.h"
|
||||
#include "DeerRender/Render/Render.h"
|
||||
#include "DeerRender/Render/RenderUtils.h"
|
||||
#include "DeerRender/Components.h"
|
||||
#include "DeerRender/Shader.h"
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/matrix.hpp"
|
||||
@ -97,8 +97,8 @@ namespace Deer {
|
||||
return frameBuffer.getData().getSpecification().height;
|
||||
}
|
||||
void frameBuffer_clearRGBA(int r, int g, int b, int a, Resource<FrameBuffer>& frameBuffer) {
|
||||
int data[] = {r, g, b, a};
|
||||
frameBuffer.getData().clear();
|
||||
uint8_t data[] = {(uint8_t)r, (uint8_t)g, (uint8_t)b, (uint8_t)a};
|
||||
frameBuffer.getData().clearBuffer(0, data);
|
||||
}
|
||||
bool frameBuffer_isValid(Resource<FrameBuffer>& frameBuffer) {
|
||||
|
||||
428
Deer/src/DeerRender/Voxel/VoxelBuilder.cpp
Normal file
428
Deer/src/DeerRender/Voxel/VoxelBuilder.cpp
Normal file
@ -0,0 +1,428 @@
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerRender/Voxel.h"
|
||||
#include "DeerRender/Voxel/VoxelData.h"
|
||||
#include <random>
|
||||
|
||||
namespace Deer {
|
||||
|
||||
VoxelFaceData testFaceData = {
|
||||
.vertices = {
|
||||
VoxelVertex(glm::vec3(0.1f, 0.90f, 0.1f)), // 0
|
||||
VoxelVertex(glm::vec3(0.5f, 0.90f, 0.1f)), // 1
|
||||
VoxelVertex(glm::vec3(0.9f, 0.90f, 0.1f)), // 2
|
||||
VoxelVertex(glm::vec3(0.1f, 0.6f, 0.2f)), // 3
|
||||
VoxelVertex(glm::vec3(0.5f, 0.35f, 0.2f)), // 4
|
||||
VoxelVertex(glm::vec3(0.9f, 0.6f, 0.2f)), // 5
|
||||
VoxelVertex(glm::vec3(0.1f, 0.55f, 0)), // 3
|
||||
VoxelVertex(glm::vec3(0.5f, 0.3f, 0)), // 4
|
||||
VoxelVertex(glm::vec3(0.9f, 0.55f, 0)), // 5
|
||||
VoxelVertex(glm::vec3(0.1f, 0.1f, 0)), // 6
|
||||
VoxelVertex(glm::vec3(0.5f, 0.1f, 0)), // 7
|
||||
VoxelVertex(glm::vec3(0.9f, 0.1f, 0)), // 8
|
||||
},
|
||||
.triangles = {0, 1, 3, 3, 1, 4, 5, 1, 2, 1, 5, 4, 3, 4, 7, 3, 7, 6, 5, 8, 4, 4, 8, 7, 6, 7, 9, 7, 10, 9, 8, 11, 7, 7, 11, 10},
|
||||
.connections = {
|
||||
std::vector<uint32_t>{9, 6, 3, 0}, // [0]
|
||||
std::vector<uint32_t>{2, 5, 8, 11}, // [1]
|
||||
std::vector<uint32_t>{11, 10, 9}, // [2]
|
||||
std::vector<uint32_t>{0, 1, 2} // [3]
|
||||
},
|
||||
.edges = {9, 11, 0, 2}};
|
||||
|
||||
VoxelFaceData flatFaceData = {
|
||||
.vertices = {
|
||||
VoxelVertex(glm::vec3(0.3f, 0.3f, 0)),
|
||||
VoxelVertex(glm::vec3(0.7f, 0.3f, 0)),
|
||||
VoxelVertex(glm::vec3(0.3f, 0.7f, 0)),
|
||||
VoxelVertex(glm::vec3(0.7f, 0.7f, 0)),
|
||||
},
|
||||
.triangles = {0, 2, 1, 1, 2, 3},
|
||||
.connections = {
|
||||
std::vector<uint32_t>{0, 2}, // [0]
|
||||
std::vector<uint32_t>{3, 1}, // [1]
|
||||
std::vector<uint32_t>{1, 0}, // [2]
|
||||
std::vector<uint32_t>{2, 3} // [3]
|
||||
},
|
||||
.edges = {0, 1, 2, 3}};
|
||||
/*
|
||||
VoxelFaceData testFaceData = {
|
||||
.vertices = {
|
||||
VoxelVertex(glm::vec2(0.1f, 0.95f)), // 0
|
||||
VoxelVertex(glm::vec2(0.4f, 0.8f)), // 1
|
||||
VoxelVertex(glm::vec2(0.9f, 0.95f)), // 2
|
||||
VoxelVertex(glm::vec2(0.2f, 0.5f)), // 3
|
||||
VoxelVertex(glm::vec2(0.5f, 0.6f)), // 4
|
||||
VoxelVertex(glm::vec2(0.8f, 0.4f)), // 5
|
||||
VoxelVertex(glm::vec2(0.1f, 0.1f)), // 6
|
||||
VoxelVertex(glm::vec2(0.6f, 0.1f)), // 7
|
||||
VoxelVertex(glm::vec2(0.9f, 0.1f)), // 8
|
||||
},
|
||||
.triangles = {0, 1, 3, 1, 4, 3, 1, 2, 5, 1, 5, 4, 6, 3, 4, 6, 4, 7, 4, 5, 7, 7, 5, 8},
|
||||
.connections = {
|
||||
std::vector<uint32_t>{6, 3, 0}, // [0]
|
||||
std::vector<uint32_t>{2, 5, 8}, // [1]
|
||||
std::vector<uint32_t>{8, 7, 6}, // [2]
|
||||
std::vector<uint32_t>{0, 1, 2} // [3]
|
||||
},
|
||||
.edges = {6, 8, 0, 2}};
|
||||
|
||||
VoxelFaceData testFaceData = {
|
||||
.vertices = {
|
||||
VoxelVertex(glm::vec2(0.1f, 0.1f)),
|
||||
VoxelVertex(glm::vec2(0.9f, 0.1f)),
|
||||
VoxelVertex(glm::vec2(0.1f, 0.9f)),
|
||||
VoxelVertex(glm::vec2(0.9f, 0.9f)),
|
||||
},
|
||||
.triangles = {0, 2, 1, 1, 2, 3},
|
||||
.connections = {
|
||||
std::vector<uint32_t>{0, 2}, // [0]
|
||||
std::vector<uint32_t>{3, 1}, // [1]
|
||||
std::vector<uint32_t>{1, 0}, // [2]
|
||||
std::vector<uint32_t>{2, 3} // [3]
|
||||
},
|
||||
.edges = {0, 1, 2, 3}};
|
||||
*/
|
||||
|
||||
void VoxelBuilder::calculateNormals() {
|
||||
for (uint32_t indexId = 0; indexId < indices.size(); indexId += 3) {
|
||||
glm::vec3 startIndex = vertices[indices[indexId + 0]].position;
|
||||
glm::vec3 direction1 = vertices[indices[indexId + 1]].position - startIndex;
|
||||
glm::vec3 direction2 = vertices[indices[indexId + 2]].position - startIndex;
|
||||
|
||||
glm::vec3 normal = glm::cross(direction1, direction2);
|
||||
vertices[indices[indexId + 0]].normal += normal;
|
||||
vertices[indices[indexId + 1]].normal += normal;
|
||||
vertices[indices[indexId + 2]].normal += normal;
|
||||
}
|
||||
}
|
||||
|
||||
Resource<GPUMesh> VoxelBuilder::buildChunk(int x, int y, int z) {
|
||||
voxelXOffset = x;
|
||||
voxelYOffset = y;
|
||||
voxelZOffset = z;
|
||||
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
clearVoxelData();
|
||||
|
||||
buildVertices();
|
||||
buildConnections();
|
||||
buildMarchingCubesCorners();
|
||||
|
||||
calculateNormals();
|
||||
|
||||
for (size_t i = 0; i < vertices.size(); i++) {
|
||||
float randomValue = (float)(rand() % 1000) / 10000.0f - 0.05f;
|
||||
randomValue = 0;
|
||||
glm::vec3 normal = glm::normalize(vertices[i].normal);
|
||||
vertices[i].position += normal * randomValue + normal * vertices[i].extrussion;
|
||||
}
|
||||
|
||||
calculateNormals();
|
||||
|
||||
MeshData meshData;
|
||||
meshData.createVertices(vertices.size());
|
||||
meshData.createIndices(indices.size());
|
||||
meshData.createLightData();
|
||||
|
||||
DEER_CORE_TRACE("{} , {}", meshData.getVertexCount(), meshData.getIndexCount());
|
||||
for (size_t i = 0; i < meshData.getVertexCount(); i++) {
|
||||
meshData.getVertexPosition()[i].x = vertices[i].position.x;
|
||||
meshData.getVertexPosition()[i].y = vertices[i].position.y;
|
||||
meshData.getVertexPosition()[i].z = vertices[i].position.z;
|
||||
|
||||
glm::vec3 normal = glm::normalize(vertices[i].normal);
|
||||
meshData.getVertexNormal()[i].x = (uint8_t)(normal.x * 64);
|
||||
meshData.getVertexNormal()[i].y = (uint8_t)(normal.y * 64);
|
||||
meshData.getVertexNormal()[i].z = (uint8_t)(normal.z * 64);
|
||||
|
||||
meshData.getVertexLight()[i].light = (uint8_t)(vertices[i].light * 255.0f);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < meshData.getIndexCount(); i++) {
|
||||
meshData.getIndexData()[i] = indices[i];
|
||||
}
|
||||
|
||||
return ResourceManager<GPUMesh>::loadResourceFromData(meshData, "tmp&&");
|
||||
}
|
||||
|
||||
VoxelBuilder::VoxelData& VoxelBuilder::getVoxelData(int x, int y, int z) {
|
||||
return voxelData[x + 1][y + 1][z + 1];
|
||||
}
|
||||
|
||||
void VoxelBuilder::clearVoxelData() {
|
||||
for (int x = 0; x < CHUNK_VOXEL_SIZE + 2; x++) {
|
||||
for (int y = 0; y < CHUNK_VOXEL_SIZE + 2; y++) {
|
||||
for (int z = 0; z < CHUNK_VOXEL_SIZE + 2; z++) {
|
||||
voxelData[x][y][z] = VoxelData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VoxelBuilder::hasBlock(int x, int y, int z) {
|
||||
uint32_t voxelId = environment->getVoxel(x, y, z);
|
||||
return voxelId > 0;
|
||||
}
|
||||
|
||||
float VoxelBuilder::calculateVertexSunLight(int x, int y, int z) {
|
||||
float acumulatedLight = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (!hasBlock(x + Voxel::voxelCheckOrder[i][0],
|
||||
y + Voxel::voxelCheckOrder[i][1],
|
||||
z + Voxel::voxelCheckOrder[i][2]))
|
||||
acumulatedLight += 1.0f / 4.0f;
|
||||
}
|
||||
if (acumulatedLight < 1)
|
||||
return acumulatedLight;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void VoxelBuilder::buildVertices() {
|
||||
for (int x = 0; x < CHUNK_VOXEL_SIZE; x++) {
|
||||
for (int y = 0; y < CHUNK_VOXEL_SIZE; y++) {
|
||||
for (int z = 0; z < CHUNK_VOXEL_SIZE; z++) {
|
||||
if (!hasBlock(x, y, z))
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (!hasBlock(
|
||||
x + Voxel::faceNeighborOffset[i][0],
|
||||
y + Voxel::faceNeighborOffset[i][1],
|
||||
z + Voxel::faceNeighborOffset[i][2])) {
|
||||
buildFaceVertices(x, y, z, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBuilder::buildFaceVertices(int x, int y, int z, int face) {
|
||||
uint32_t startIndex = vertices.size();
|
||||
getVoxelData(x, y, z).vertexIndexFace[face] = startIndex;
|
||||
|
||||
VoxelFaceData* faceData = &testFaceData;
|
||||
if (face == 2 || face == 3)
|
||||
faceData = &flatFaceData;
|
||||
|
||||
float cornersLight[4];
|
||||
cornersLight[0] = calculateVertexSunLight(x + Voxel::faceOriginVectorInt[face][0],
|
||||
y + Voxel::faceOriginVectorInt[face][1],
|
||||
z + Voxel::faceOriginVectorInt[face][2]);
|
||||
cornersLight[1] = calculateVertexSunLight(x + Voxel::faceOriginVectorInt[face][0] + Voxel::faceRightVector[face][0],
|
||||
y + Voxel::faceOriginVectorInt[face][1] + Voxel::faceRightVector[face][1],
|
||||
z + Voxel::faceOriginVectorInt[face][2] + Voxel::faceRightVector[face][2]);
|
||||
cornersLight[2] = calculateVertexSunLight(x + Voxel::faceOriginVectorInt[face][0] + Voxel::faceUpVectorInt[face][0],
|
||||
y + Voxel::faceOriginVectorInt[face][1] + Voxel::faceUpVectorInt[face][1],
|
||||
z + Voxel::faceOriginVectorInt[face][2] + Voxel::faceUpVectorInt[face][2]);
|
||||
cornersLight[3] = calculateVertexSunLight(x + Voxel::faceOriginVectorInt[face][0] + Voxel::faceUpVectorInt[face][0] + Voxel::faceRightVector[face][0],
|
||||
y + Voxel::faceOriginVectorInt[face][1] + Voxel::faceUpVectorInt[face][1] + Voxel::faceRightVector[face][1],
|
||||
z + Voxel::faceOriginVectorInt[face][2] + Voxel::faceUpVectorInt[face][2] + Voxel::faceRightVector[face][2]);
|
||||
|
||||
for (VoxelVertex& voxelVertex : faceData->vertices) {
|
||||
glm::vec3 vertexPosition = glm::vec3(x, y, z) + Voxel::faceOriginVector[face];
|
||||
glm::vec3 up = Voxel::faceUpVector[face];
|
||||
glm::vec3 right = Voxel::faceRightVector[face];
|
||||
|
||||
vertexPosition += up * voxelVertex.position.y;
|
||||
vertexPosition += right * voxelVertex.position.x;
|
||||
|
||||
glm::vec3 perpendicular = glm::cross(up, right);
|
||||
|
||||
float topLight = Voxel::lerp(voxelVertex.position.x, cornersLight[3], cornersLight[2]);
|
||||
float bottomLight = Voxel::lerp(voxelVertex.position.x, cornersLight[1], cornersLight[0]);
|
||||
|
||||
vertices.push_back({});
|
||||
VertexData& vv = vertices.back();
|
||||
vv.position = vertexPosition;
|
||||
vv.extrussion = voxelVertex.position.z;
|
||||
vv.light = Voxel::lerp(voxelVertex.position.y, topLight, bottomLight);
|
||||
}
|
||||
|
||||
for (uint32_t index : faceData->triangles) {
|
||||
indices.push_back(index + startIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// This function goes foreach edge, from (0, 0, 0) to (33, 33, 33) then check each edge
|
||||
void VoxelBuilder::buildConnections() {
|
||||
for (int x = 0; x < CHUNK_VOXEL_SIZE + 1; x++) {
|
||||
for (int y = 0; y < CHUNK_VOXEL_SIZE + 1; y++) {
|
||||
for (int z = 0; z < CHUNK_VOXEL_SIZE + 1; z++) {
|
||||
buildAxisConnections(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBuilder::buildAxisConnections(int x, int y, int z) {
|
||||
for (int axis = 0; axis < AXIS_NUMBER; axis++) {
|
||||
uint8_t edgeCheckBitmask = 0;
|
||||
for (int edge = 0; edge < EDGE_PER_AXIS; edge++) {
|
||||
uint8_t currentEdgeBitmask = 1 << edge;
|
||||
if (edgeCheckBitmask & currentEdgeBitmask)
|
||||
continue;
|
||||
|
||||
Voxel::VoxelEdge& voxelEdge = Voxel::edgesPerAxis[axis][edge];
|
||||
VoxelData& voxel = getVoxelData(x + voxelEdge.voxelOffset[0],
|
||||
y + voxelEdge.voxelOffset[1],
|
||||
z + voxelEdge.voxelOffset[2]);
|
||||
bool existsFace = voxel.vertexIndexFace[voxelEdge.faceIndex] >= 0;
|
||||
|
||||
edgeCheckBitmask |= currentEdgeBitmask;
|
||||
if (!existsFace)
|
||||
continue;
|
||||
|
||||
int edgeCheckIndex = edge;
|
||||
for (int safeCheck = 0; safeCheck < EDGE_PER_AXIS - 1; safeCheck++) {
|
||||
edgeCheckIndex += voxelEdge.isClockwiseOrder ? 1 : -1;
|
||||
|
||||
if (edgeCheckIndex >= EDGE_PER_AXIS)
|
||||
edgeCheckIndex -= EDGE_PER_AXIS;
|
||||
|
||||
if (edgeCheckIndex < 0)
|
||||
edgeCheckIndex += EDGE_PER_AXIS;
|
||||
|
||||
uint8_t nextEdgeBitmask = 1 << edgeCheckIndex;
|
||||
if (nextEdgeBitmask & edgeCheckBitmask)
|
||||
continue;
|
||||
|
||||
edgeCheckBitmask |= nextEdgeBitmask;
|
||||
|
||||
Voxel::VoxelEdge& nextVoxelEdge = Voxel::edgesPerAxis[axis][edgeCheckIndex];
|
||||
VoxelData& nextVoxel = getVoxelData(x + nextVoxelEdge.voxelOffset[0],
|
||||
y + nextVoxelEdge.voxelOffset[1],
|
||||
z + nextVoxelEdge.voxelOffset[2]);
|
||||
|
||||
bool nextEdgeExist = nextVoxel.vertexIndexFace[nextVoxelEdge.faceIndex] >= 0;
|
||||
if (nextEdgeExist) {
|
||||
|
||||
VoxelFaceData* faceData1 = &testFaceData;
|
||||
if (voxelEdge.faceIndex == 2 || voxelEdge.faceIndex == 3)
|
||||
faceData1 = &flatFaceData;
|
||||
|
||||
VoxelFaceData* faceData2 = &testFaceData;
|
||||
if (nextVoxelEdge.faceIndex == 2 || nextVoxelEdge.faceIndex == 3)
|
||||
faceData2 = &flatFaceData;
|
||||
|
||||
connectVertices(*faceData1, voxelEdge.edgeIndex, voxel.vertexIndexFace[voxelEdge.faceIndex],
|
||||
*faceData2, nextVoxelEdge.edgeIndex, nextVoxel.vertexIndexFace[nextVoxelEdge.faceIndex]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBuilder::connectVertices(VoxelFaceData& face1, int edgeIndex1, int face1VertexOffset, VoxelFaceData& face2, int edgeIndex2, int face2VertexOffset) {
|
||||
int edge1Index = 0;
|
||||
int edge2Index = face2.connections[edgeIndex2].size() - 1;
|
||||
|
||||
int triangleCount = 0;
|
||||
while (edge1Index < face1.connections[edgeIndex1].size() - 1 || edge2Index > 0) {
|
||||
triangleCount++;
|
||||
if (edge1Index == face1.connections[edgeIndex1].size() - 1) {
|
||||
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index]);
|
||||
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index]);
|
||||
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index - 1]);
|
||||
|
||||
edge2Index--;
|
||||
} else if (edge2Index == 0) {
|
||||
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index]);
|
||||
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index + 1]);
|
||||
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index]);
|
||||
|
||||
edge1Index++;
|
||||
} else {
|
||||
glm::vec3 firstEdgeVertex = vertices[face1.connections[edgeIndex1][edge1Index] + face1VertexOffset].position;
|
||||
glm::vec3 secondEdgeVertex = vertices[face2.connections[edgeIndex2][edge2Index] + face2VertexOffset].position;
|
||||
|
||||
glm::vec3 midPoint = (firstEdgeVertex + secondEdgeVertex) * 0.5f;
|
||||
|
||||
glm::vec3 FED = vertices[face1.connections[edgeIndex1][edge1Index + 1] + face1VertexOffset].position - midPoint;
|
||||
glm::vec3 SED = vertices[face2.connections[edgeIndex2][edge2Index - 1] + face2VertexOffset].position - midPoint;
|
||||
|
||||
float firstDistanceNext = FED.x * FED.x + FED.y * FED.y + FED.z * FED.z;
|
||||
float secondDistanceNext = SED.x * SED.x + SED.y * SED.y + SED.z * SED.z;
|
||||
|
||||
if (firstDistanceNext > secondDistanceNext) {
|
||||
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index]);
|
||||
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index]);
|
||||
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index - 1]);
|
||||
|
||||
edge2Index--;
|
||||
} else {
|
||||
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index]);
|
||||
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index]);
|
||||
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index + 1]);
|
||||
|
||||
edge1Index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBuilder::buildMarchingCubesCorners() {
|
||||
for (int x = 0; x < CHUNK_VOXEL_SIZE + 1; x++) {
|
||||
for (int y = 0; y < CHUNK_VOXEL_SIZE + 1; y++) {
|
||||
for (int z = 0; z < CHUNK_VOXEL_SIZE + 1; z++) {
|
||||
uint8_t marchingCubeId = 0;
|
||||
for (int side = 0; side < CUBE_SIDES; side++) {
|
||||
bool hasVoxel = hasBlock(x + Voxel::voxelCheckOrder[side][0],
|
||||
y + Voxel::voxelCheckOrder[side][1],
|
||||
z + Voxel::voxelCheckOrder[side][2]);
|
||||
|
||||
if (hasVoxel)
|
||||
marchingCubeId |= 1 << side;
|
||||
}
|
||||
|
||||
if (marchingCubeId == 0)
|
||||
continue;
|
||||
|
||||
buildMarchingVoxel(x, y, z, marchingCubeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelBuilder::buildMarchingVoxel(int x, int y, int z, uint8_t marchingCubeId) {
|
||||
for (int safeStop = 0; safeStop < 16; safeStop += 3) {
|
||||
int nextMarchingCubesedgeIndex = Voxel::marchingCubesTriTable[marchingCubeId][safeStop];
|
||||
if (nextMarchingCubesedgeIndex == -1)
|
||||
return;
|
||||
|
||||
int vertices[3] = {
|
||||
getVertexIdCorner(x, y, z, nextMarchingCubesedgeIndex),
|
||||
getVertexIdCorner(x, y, z, Voxel::marchingCubesTriTable[marchingCubeId][safeStop + 1]),
|
||||
getVertexIdCorner(x, y, z, Voxel::marchingCubesTriTable[marchingCubeId][safeStop + 2]),
|
||||
};
|
||||
|
||||
if (vertices[0] != -1 && vertices[1] != -1 && vertices[2] != -1) {
|
||||
indices.push_back(vertices[0]);
|
||||
indices.push_back(vertices[1]);
|
||||
indices.push_back(vertices[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int VoxelBuilder::getVertexIdCorner(int x, int y, int z, int edge) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
Voxel::VoxelCorner& option = Voxel::marchingCubesEdgeCornerPairs[edge][i];
|
||||
|
||||
VoxelData& _voxelData = getVoxelData(x + option.voxelOffset[0],
|
||||
y + option.voxelOffset[1],
|
||||
z + option.voxelOffset[2]);
|
||||
|
||||
VoxelFaceData* faceData = &testFaceData;
|
||||
if (option.faceIndex == 2 || option.faceIndex == 3)
|
||||
faceData = &flatFaceData;
|
||||
|
||||
int voxelDataFaceOffset = _voxelData.vertexIndexFace[option.faceIndex];
|
||||
if (voxelDataFaceOffset >= 0)
|
||||
return faceData->edges[option.localCornerIndex] + voxelDataFaceOffset;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
} // namespace Deer
|
||||
50
Deer/src/DeerRender/Voxel/VoxelData.h
Normal file
50
Deer/src/DeerRender/Voxel/VoxelData.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
#define EDGE_PER_AXIS 8
|
||||
#define AXIS_NUMBER 3
|
||||
#define CUBE_SIDES 8
|
||||
|
||||
namespace Deer {
|
||||
namespace Voxel {
|
||||
// Represents an edge of a voxel along a specific axis
|
||||
struct VoxelEdge {
|
||||
int voxelOffset[3];
|
||||
int faceIndex;
|
||||
int edgeIndex;
|
||||
bool isClockwiseOrder;
|
||||
};
|
||||
|
||||
struct VoxelCorner {
|
||||
int voxelOffset[3];
|
||||
int faceIndex;
|
||||
int localCornerIndex;
|
||||
};
|
||||
|
||||
inline float lerp(float v, float a, float b) {
|
||||
return b + (a - b) * v;
|
||||
}
|
||||
|
||||
// Direction vectors for checking neighboring voxels along each face
|
||||
extern int faceNeighborOffset[6][3];
|
||||
|
||||
// Local "up" vector for each face of the voxel
|
||||
extern glm::vec3 faceUpVector[6];
|
||||
extern int faceUpVectorInt[6][3];
|
||||
|
||||
// Local "right" vector for each face of the voxel
|
||||
extern glm::vec3 faceRightVector[6];
|
||||
extern int faceRightVectorInt[6][3];
|
||||
|
||||
// Offset to the voxel face position relative to voxel center
|
||||
extern glm::vec3 faceOriginVector[6];
|
||||
extern int faceOriginVectorInt[6][3];
|
||||
|
||||
extern VoxelEdge edgesPerAxis[AXIS_NUMBER][EDGE_PER_AXIS];
|
||||
extern int marchingCubesTriTable[256][16];
|
||||
|
||||
extern VoxelCorner marchingCubesEdgeCornerPairs[12][2];
|
||||
|
||||
extern int voxelCheckOrder[CUBE_SIDES][3];
|
||||
} // namespace Voxel
|
||||
} // namespace Deer
|
||||
7
Deer/src/DeerRender/Voxel/VoxelEnvironment.cpp
Normal file
7
Deer/src/DeerRender/Voxel/VoxelEnvironment.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "DeerRender/Voxel.h"
|
||||
|
||||
namespace Deer {
|
||||
VoxelEnvironment::VoxelEnvironment() {
|
||||
voxelBuilder = MakeScope<VoxelBuilder>(this);
|
||||
}
|
||||
} // namespace Deer
|
||||
534
Deer/src/DeerRender/Voxel/VoxelGenerationData.cpp
Normal file
534
Deer/src/DeerRender/Voxel/VoxelGenerationData.cpp
Normal file
@ -0,0 +1,534 @@
|
||||
#include "DeerRender/Voxel/VoxelData.h"
|
||||
|
||||
namespace Deer {
|
||||
namespace Voxel {
|
||||
// Direction vectors for checking neighboring voxels along each face
|
||||
int faceNeighborOffset[6][3] = {
|
||||
{-1, 0, 0}, // Left
|
||||
{1, 0, 0}, // Right
|
||||
{0, -1, 0}, // Bottom
|
||||
{0, 1, 0}, // Top
|
||||
{0, 0, -1}, // Back
|
||||
{0, 0, 1} // Front
|
||||
};
|
||||
|
||||
// Local "up" vector for each face of the voxel
|
||||
glm::vec3 faceUpVector[6] = {
|
||||
glm::vec3(0, 1, 0), // Left
|
||||
glm::vec3(0, 1, 0), // Right
|
||||
glm::vec3(0, 0, -1), // Bottom
|
||||
glm::vec3(0, 0, 1), // Top
|
||||
glm::vec3(0, 1, 0), // Back
|
||||
glm::vec3(0, 1, 0) // Front
|
||||
};
|
||||
int faceUpVectorInt[6][3] = {
|
||||
{0, 1, 0},
|
||||
{0, 1, 0}, // Right
|
||||
{0, 0, -1}, // Bottom
|
||||
{0, 0, 1}, // Top
|
||||
{0, 1, 0}, // Back
|
||||
{0, 1, 0} // Front
|
||||
};
|
||||
|
||||
// Local "right" vector for each face of the voxel
|
||||
glm::vec3 faceRightVector[6] = {
|
||||
glm::vec3(0, 0, -1), // Left
|
||||
glm::vec3(0, 0, 1), // Right
|
||||
glm::vec3(1, 0, 0), // Bottom
|
||||
glm::vec3(1, 0, 0), // Top
|
||||
glm::vec3(1, 0, 0), // Back
|
||||
glm::vec3(-1, 0, 0) // Front
|
||||
};
|
||||
int faceRightVectorInt[6][3] = {
|
||||
{0, 0, -1}, // Left
|
||||
{0, 0, 1}, // Right
|
||||
{1, 0, 0}, // Bottom
|
||||
{1, 0, 0}, // Top
|
||||
{1, 0, 0}, // Back
|
||||
{-1, 0, 0} // Front
|
||||
};
|
||||
|
||||
// Offset to the voxel face position relative to voxel center
|
||||
glm::vec3 faceOriginVector[6] = {
|
||||
glm::vec3(-0.5f, -0.5f, 0.5f), // Left
|
||||
glm::vec3(0.5f, -0.5f, -0.5f), // Right
|
||||
glm::vec3(-0.5f, -0.5f, 0.5f), // Bottom
|
||||
glm::vec3(-0.5f, 0.5f, -0.5f), // Top
|
||||
glm::vec3(-0.5f, -0.5f, -0.5f), // Back
|
||||
glm::vec3(0.5f, -0.5f, 0.5f) // Front
|
||||
};
|
||||
|
||||
extern int faceOriginVectorInt[6][3] = {
|
||||
{0, 0, 1}, // Left
|
||||
{1, 0, 0}, // Right
|
||||
{0, 0, 1}, // Bottom
|
||||
{0, 1, 0}, // Top
|
||||
{0, 0, 0}, // Back
|
||||
{1, 0, 1} // Front
|
||||
};
|
||||
|
||||
int voxelCheckOrder[CUBE_SIDES][3]{
|
||||
{-1, -1, -1},
|
||||
{0, -1, -1},
|
||||
{-1, 0, -1},
|
||||
{0, 0, -1},
|
||||
{-1, -1, 0},
|
||||
{0, -1, 0},
|
||||
{-1, 0, 0},
|
||||
{0, 0, 0}};
|
||||
|
||||
// For each MC case, a list of triangles, specified as triples of edge indices, terminated by -1
|
||||
int marchingCubesTriTable[256][16] = {
|
||||
{-1},
|
||||
{0, 3, 8, -1},
|
||||
{0, 9, 1, -1},
|
||||
{3, 8, 1, 1, 8, 9, -1},
|
||||
{2, 11, 3, -1},
|
||||
{8, 0, 11, 11, 0, 2, -1},
|
||||
{3, 2, 11, 1, 0, 9, -1},
|
||||
{11, 1, 2, 11, 9, 1, 11, 8, 9, -1},
|
||||
{1, 10, 2, -1},
|
||||
{0, 3, 8, 2, 1, 10, -1},
|
||||
{10, 2, 9, 9, 2, 0, -1},
|
||||
{8, 2, 3, 8, 10, 2, 8, 9, 10, -1},
|
||||
{11, 3, 10, 10, 3, 1, -1},
|
||||
{10, 0, 1, 10, 8, 0, 10, 11, 8, -1},
|
||||
{9, 3, 0, 9, 11, 3, 9, 10, 11, -1},
|
||||
{8, 9, 11, 11, 9, 10, -1},
|
||||
{4, 8, 7, -1},
|
||||
{7, 4, 3, 3, 4, 0, -1},
|
||||
{4, 8, 7, 0, 9, 1, -1},
|
||||
{1, 4, 9, 1, 7, 4, 1, 3, 7, -1},
|
||||
{8, 7, 4, 11, 3, 2, -1},
|
||||
{4, 11, 7, 4, 2, 11, 4, 0, 2, -1},
|
||||
{0, 9, 1, 8, 7, 4, 11, 3, 2, -1},
|
||||
{7, 4, 11, 11, 4, 2, 2, 4, 9, 2, 9, 1, -1},
|
||||
{4, 8, 7, 2, 1, 10, -1},
|
||||
{7, 4, 3, 3, 4, 0, 10, 2, 1, -1},
|
||||
{10, 2, 9, 9, 2, 0, 7, 4, 8, -1},
|
||||
{10, 2, 3, 10, 3, 4, 3, 7, 4, 9, 10, 4, -1},
|
||||
{1, 10, 3, 3, 10, 11, 4, 8, 7, -1},
|
||||
{10, 11, 1, 11, 7, 4, 1, 11, 4, 1, 4, 0, -1},
|
||||
{7, 4, 8, 9, 3, 0, 9, 11, 3, 9, 10, 11, -1},
|
||||
{7, 4, 11, 4, 9, 11, 9, 10, 11, -1},
|
||||
{9, 4, 5, -1},
|
||||
{9, 4, 5, 8, 0, 3, -1},
|
||||
{4, 5, 0, 0, 5, 1, -1},
|
||||
{5, 8, 4, 5, 3, 8, 5, 1, 3, -1},
|
||||
{9, 4, 5, 11, 3, 2, -1},
|
||||
{2, 11, 0, 0, 11, 8, 5, 9, 4, -1},
|
||||
{4, 5, 0, 0, 5, 1, 11, 3, 2, -1},
|
||||
{5, 1, 4, 1, 2, 11, 4, 1, 11, 4, 11, 8, -1},
|
||||
{1, 10, 2, 5, 9, 4, -1},
|
||||
{9, 4, 5, 0, 3, 8, 2, 1, 10, -1},
|
||||
{2, 5, 10, 2, 4, 5, 2, 0, 4, -1},
|
||||
{10, 2, 5, 5, 2, 4, 4, 2, 3, 4, 3, 8, -1},
|
||||
{11, 3, 10, 10, 3, 1, 4, 5, 9, -1},
|
||||
{4, 5, 9, 10, 0, 1, 10, 8, 0, 10, 11, 8, -1},
|
||||
{11, 3, 0, 11, 0, 5, 0, 4, 5, 10, 11, 5, -1},
|
||||
{4, 5, 8, 5, 10, 8, 10, 11, 8, -1},
|
||||
{8, 7, 9, 9, 7, 5, -1},
|
||||
{3, 9, 0, 3, 5, 9, 3, 7, 5, -1},
|
||||
{7, 0, 8, 7, 1, 0, 7, 5, 1, -1},
|
||||
{7, 5, 3, 3, 5, 1, -1},
|
||||
{5, 9, 7, 7, 9, 8, 2, 11, 3, -1},
|
||||
{2, 11, 7, 2, 7, 9, 7, 5, 9, 0, 2, 9, -1},
|
||||
{2, 11, 3, 7, 0, 8, 7, 1, 0, 7, 5, 1, -1},
|
||||
{2, 11, 1, 11, 7, 1, 7, 5, 1, -1},
|
||||
{8, 7, 9, 9, 7, 5, 2, 1, 10, -1},
|
||||
{10, 2, 1, 3, 9, 0, 3, 5, 9, 3, 7, 5, -1},
|
||||
{7, 5, 8, 5, 10, 2, 8, 5, 2, 8, 2, 0, -1},
|
||||
{10, 2, 5, 2, 3, 5, 3, 7, 5, -1},
|
||||
{8, 7, 5, 8, 5, 9, 11, 3, 10, 3, 1, 10, -1},
|
||||
{5, 11, 7, 10, 11, 5, 1, 9, 0, -1},
|
||||
{11, 5, 10, 7, 5, 11, 8, 3, 0, -1},
|
||||
{5, 11, 7, 10, 11, 5, -1},
|
||||
{6, 7, 11, -1},
|
||||
{7, 11, 6, 3, 8, 0, -1},
|
||||
{6, 7, 11, 0, 9, 1, -1},
|
||||
{9, 1, 8, 8, 1, 3, 6, 7, 11, -1},
|
||||
{3, 2, 7, 7, 2, 6, -1},
|
||||
{0, 7, 8, 0, 6, 7, 0, 2, 6, -1},
|
||||
{6, 7, 2, 2, 7, 3, 9, 1, 0, -1},
|
||||
{6, 7, 8, 6, 8, 1, 8, 9, 1, 2, 6, 1, -1},
|
||||
{11, 6, 7, 10, 2, 1, -1},
|
||||
{3, 8, 0, 11, 6, 7, 10, 2, 1, -1},
|
||||
{0, 9, 2, 2, 9, 10, 7, 11, 6, -1},
|
||||
{6, 7, 11, 8, 2, 3, 8, 10, 2, 8, 9, 10, -1},
|
||||
{7, 10, 6, 7, 1, 10, 7, 3, 1, -1},
|
||||
{8, 0, 7, 7, 0, 6, 6, 0, 1, 6, 1, 10, -1},
|
||||
{7, 3, 6, 3, 0, 9, 6, 3, 9, 6, 9, 10, -1},
|
||||
{6, 7, 10, 7, 8, 10, 8, 9, 10, -1},
|
||||
{11, 6, 8, 8, 6, 4, -1},
|
||||
{6, 3, 11, 6, 0, 3, 6, 4, 0, -1},
|
||||
{11, 6, 8, 8, 6, 4, 1, 0, 9, -1},
|
||||
{1, 3, 9, 3, 11, 6, 9, 3, 6, 9, 6, 4, -1},
|
||||
{2, 8, 3, 2, 4, 8, 2, 6, 4, -1},
|
||||
{4, 0, 6, 6, 0, 2, -1},
|
||||
{9, 1, 0, 2, 8, 3, 2, 4, 8, 2, 6, 4, -1},
|
||||
{9, 1, 4, 1, 2, 4, 2, 6, 4, -1},
|
||||
{4, 8, 6, 6, 8, 11, 1, 10, 2, -1},
|
||||
{1, 10, 2, 6, 3, 11, 6, 0, 3, 6, 4, 0, -1},
|
||||
{11, 6, 4, 11, 4, 8, 10, 2, 9, 2, 0, 9, -1},
|
||||
{10, 4, 9, 6, 4, 10, 11, 2, 3, -1},
|
||||
{4, 8, 3, 4, 3, 10, 3, 1, 10, 6, 4, 10, -1},
|
||||
{1, 10, 0, 10, 6, 0, 6, 4, 0, -1},
|
||||
{4, 10, 6, 9, 10, 4, 0, 8, 3, -1},
|
||||
{4, 10, 6, 9, 10, 4, -1},
|
||||
{6, 7, 11, 4, 5, 9, -1},
|
||||
{4, 5, 9, 7, 11, 6, 3, 8, 0, -1},
|
||||
{1, 0, 5, 5, 0, 4, 11, 6, 7, -1},
|
||||
{11, 6, 7, 5, 8, 4, 5, 3, 8, 5, 1, 3, -1},
|
||||
{3, 2, 7, 7, 2, 6, 9, 4, 5, -1},
|
||||
{5, 9, 4, 0, 7, 8, 0, 6, 7, 0, 2, 6, -1},
|
||||
{3, 2, 6, 3, 6, 7, 1, 0, 5, 0, 4, 5, -1},
|
||||
{6, 1, 2, 5, 1, 6, 4, 7, 8, -1},
|
||||
{10, 2, 1, 6, 7, 11, 4, 5, 9, -1},
|
||||
{0, 3, 8, 4, 5, 9, 11, 6, 7, 10, 2, 1, -1},
|
||||
{7, 11, 6, 2, 5, 10, 2, 4, 5, 2, 0, 4, -1},
|
||||
{8, 4, 7, 5, 10, 6, 3, 11, 2, -1},
|
||||
{9, 4, 5, 7, 10, 6, 7, 1, 10, 7, 3, 1, -1},
|
||||
{10, 6, 5, 7, 8, 4, 1, 9, 0, -1},
|
||||
{4, 3, 0, 7, 3, 4, 6, 5, 10, -1},
|
||||
{10, 6, 5, 8, 4, 7, -1},
|
||||
{9, 6, 5, 9, 11, 6, 9, 8, 11, -1},
|
||||
{11, 6, 3, 3, 6, 0, 0, 6, 5, 0, 5, 9, -1},
|
||||
{11, 6, 5, 11, 5, 0, 5, 1, 0, 8, 11, 0, -1},
|
||||
{11, 6, 3, 6, 5, 3, 5, 1, 3, -1},
|
||||
{9, 8, 5, 8, 3, 2, 5, 8, 2, 5, 2, 6, -1},
|
||||
{5, 9, 6, 9, 0, 6, 0, 2, 6, -1},
|
||||
{1, 6, 5, 2, 6, 1, 3, 0, 8, -1},
|
||||
{1, 6, 5, 2, 6, 1, -1},
|
||||
{2, 1, 10, 9, 6, 5, 9, 11, 6, 9, 8, 11, -1},
|
||||
{9, 0, 1, 3, 11, 2, 5, 10, 6, -1},
|
||||
{11, 0, 8, 2, 0, 11, 10, 6, 5, -1},
|
||||
{3, 11, 2, 5, 10, 6, 2, 11, 6, 6, 10, 2, -1},
|
||||
{1, 8, 3, 9, 8, 1, 5, 10, 6, -1},
|
||||
{6, 5, 10, 0, 1, 9, -1},
|
||||
{8, 3, 0, 5, 10, 6, -1},
|
||||
{6, 5, 10, -1},
|
||||
{10, 5, 6, -1},
|
||||
{0, 3, 8, 6, 10, 5, -1},
|
||||
{10, 5, 6, 9, 1, 0, -1},
|
||||
{3, 8, 1, 1, 8, 9, 6, 10, 5, -1},
|
||||
{2, 11, 3, 6, 10, 5, -1},
|
||||
{8, 0, 11, 11, 0, 2, 5, 6, 10, -1},
|
||||
{1, 0, 9, 2, 11, 3, 6, 10, 5, -1},
|
||||
{5, 6, 10, 11, 1, 2, 11, 9, 1, 11, 8, 9, -1},
|
||||
{5, 6, 1, 1, 6, 2, -1},
|
||||
{5, 6, 1, 1, 6, 2, 8, 0, 3, -1},
|
||||
{6, 9, 5, 6, 0, 9, 6, 2, 0, -1},
|
||||
{6, 2, 5, 2, 3, 8, 5, 2, 8, 5, 8, 9, -1},
|
||||
{3, 6, 11, 3, 5, 6, 3, 1, 5, -1},
|
||||
{8, 0, 1, 8, 1, 6, 1, 5, 6, 11, 8, 6, -1},
|
||||
{11, 3, 6, 6, 3, 5, 5, 3, 0, 5, 0, 9, -1},
|
||||
{5, 6, 9, 6, 11, 9, 11, 8, 9, -1},
|
||||
{5, 6, 10, 7, 4, 8, -1},
|
||||
{0, 3, 4, 4, 3, 7, 10, 5, 6, -1},
|
||||
{5, 6, 10, 4, 8, 7, 0, 9, 1, -1},
|
||||
{6, 10, 5, 1, 4, 9, 1, 7, 4, 1, 3, 7, -1},
|
||||
{7, 4, 8, 6, 10, 5, 2, 11, 3, -1},
|
||||
{10, 5, 6, 4, 11, 7, 4, 2, 11, 4, 0, 2, -1},
|
||||
{4, 8, 7, 6, 10, 5, 3, 2, 11, 1, 0, 9, -1},
|
||||
{1, 2, 10, 11, 7, 6, 9, 5, 4, -1},
|
||||
{2, 1, 6, 6, 1, 5, 8, 7, 4, -1},
|
||||
{0, 3, 7, 0, 7, 4, 2, 1, 6, 1, 5, 6, -1},
|
||||
{8, 7, 4, 6, 9, 5, 6, 0, 9, 6, 2, 0, -1},
|
||||
{7, 2, 3, 6, 2, 7, 5, 4, 9, -1},
|
||||
{4, 8, 7, 3, 6, 11, 3, 5, 6, 3, 1, 5, -1},
|
||||
{5, 0, 1, 4, 0, 5, 7, 6, 11, -1},
|
||||
{9, 5, 4, 6, 11, 7, 0, 8, 3, -1},
|
||||
{11, 7, 6, 9, 5, 4, -1},
|
||||
{6, 10, 4, 4, 10, 9, -1},
|
||||
{6, 10, 4, 4, 10, 9, 3, 8, 0, -1},
|
||||
{0, 10, 1, 0, 6, 10, 0, 4, 6, -1},
|
||||
{6, 10, 1, 6, 1, 8, 1, 3, 8, 4, 6, 8, -1},
|
||||
{9, 4, 10, 10, 4, 6, 3, 2, 11, -1},
|
||||
{2, 11, 8, 2, 8, 0, 6, 10, 4, 10, 9, 4, -1},
|
||||
{11, 3, 2, 0, 10, 1, 0, 6, 10, 0, 4, 6, -1},
|
||||
{6, 8, 4, 11, 8, 6, 2, 10, 1, -1},
|
||||
{4, 1, 9, 4, 2, 1, 4, 6, 2, -1},
|
||||
{3, 8, 0, 4, 1, 9, 4, 2, 1, 4, 6, 2, -1},
|
||||
{6, 2, 4, 4, 2, 0, -1},
|
||||
{3, 8, 2, 8, 4, 2, 4, 6, 2, -1},
|
||||
{4, 6, 9, 6, 11, 3, 9, 6, 3, 9, 3, 1, -1},
|
||||
{8, 6, 11, 4, 6, 8, 9, 0, 1, -1},
|
||||
{11, 3, 6, 3, 0, 6, 0, 4, 6, -1},
|
||||
{8, 6, 11, 4, 6, 8, -1},
|
||||
{10, 7, 6, 10, 8, 7, 10, 9, 8, -1},
|
||||
{3, 7, 0, 7, 6, 10, 0, 7, 10, 0, 10, 9, -1},
|
||||
{6, 10, 7, 7, 10, 8, 8, 10, 1, 8, 1, 0, -1},
|
||||
{6, 10, 7, 10, 1, 7, 1, 3, 7, -1},
|
||||
{3, 2, 11, 10, 7, 6, 10, 8, 7, 10, 9, 8, -1},
|
||||
{2, 9, 0, 10, 9, 2, 6, 11, 7, -1},
|
||||
{0, 8, 3, 7, 6, 11, 1, 2, 10, -1},
|
||||
{7, 6, 11, 1, 2, 10, 11, 6, 2, 2, 6, 10, -1},
|
||||
{2, 1, 9, 2, 9, 7, 9, 8, 7, 6, 2, 7, -1},
|
||||
{2, 7, 6, 3, 7, 2, 0, 1, 9, -1},
|
||||
{8, 7, 0, 7, 6, 0, 6, 2, 0, -1},
|
||||
{7, 2, 3, 6, 2, 7, -1},
|
||||
{8, 1, 9, 3, 1, 8, 11, 7, 6, -1},
|
||||
{11, 7, 6, 1, 9, 0, -1},
|
||||
{6, 11, 7, 0, 8, 3, -1},
|
||||
{11, 7, 6, -1},
|
||||
{7, 11, 5, 5, 11, 10, -1},
|
||||
{10, 5, 11, 11, 5, 7, 0, 3, 8, -1},
|
||||
{7, 11, 5, 5, 11, 10, 0, 9, 1, -1},
|
||||
{7, 11, 10, 7, 10, 5, 3, 8, 1, 8, 9, 1, -1},
|
||||
{5, 2, 10, 5, 3, 2, 5, 7, 3, -1},
|
||||
{5, 7, 10, 7, 8, 0, 10, 7, 0, 10, 0, 2, -1},
|
||||
{0, 9, 1, 5, 2, 10, 5, 3, 2, 5, 7, 3, -1},
|
||||
{9, 7, 8, 5, 7, 9, 10, 1, 2, -1},
|
||||
{1, 11, 2, 1, 7, 11, 1, 5, 7, -1},
|
||||
{8, 0, 3, 1, 11, 2, 1, 7, 11, 1, 5, 7, -1},
|
||||
{7, 11, 2, 7, 2, 9, 2, 0, 9, 5, 7, 9, -1},
|
||||
{7, 9, 5, 8, 9, 7, 3, 11, 2, -1},
|
||||
{3, 1, 7, 7, 1, 5, -1},
|
||||
{8, 0, 7, 0, 1, 7, 1, 5, 7, -1},
|
||||
{0, 9, 3, 9, 5, 3, 5, 7, 3, -1},
|
||||
{9, 7, 8, 5, 7, 9, -1},
|
||||
{8, 5, 4, 8, 10, 5, 8, 11, 10, -1},
|
||||
{0, 3, 11, 0, 11, 5, 11, 10, 5, 4, 0, 5, -1},
|
||||
{1, 0, 9, 8, 5, 4, 8, 10, 5, 8, 11, 10, -1},
|
||||
{10, 3, 11, 1, 3, 10, 9, 5, 4, -1},
|
||||
{3, 2, 8, 8, 2, 4, 4, 2, 10, 4, 10, 5, -1},
|
||||
{10, 5, 2, 5, 4, 2, 4, 0, 2, -1},
|
||||
{5, 4, 9, 8, 3, 0, 10, 1, 2, -1},
|
||||
{2, 10, 1, 4, 9, 5, -1},
|
||||
{8, 11, 4, 11, 2, 1, 4, 11, 1, 4, 1, 5, -1},
|
||||
{0, 5, 4, 1, 5, 0, 2, 3, 11, -1},
|
||||
{0, 11, 2, 8, 11, 0, 4, 9, 5, -1},
|
||||
{5, 4, 9, 2, 3, 11, -1},
|
||||
{4, 8, 5, 8, 3, 5, 3, 1, 5, -1},
|
||||
{0, 5, 4, 1, 5, 0, -1},
|
||||
{5, 4, 9, 3, 0, 8, -1},
|
||||
{5, 4, 9, -1},
|
||||
{11, 4, 7, 11, 9, 4, 11, 10, 9, -1},
|
||||
{0, 3, 8, 11, 4, 7, 11, 9, 4, 11, 10, 9, -1},
|
||||
{11, 10, 7, 10, 1, 0, 7, 10, 0, 7, 0, 4, -1},
|
||||
{3, 10, 1, 11, 10, 3, 7, 8, 4, -1},
|
||||
{3, 2, 10, 3, 10, 4, 10, 9, 4, 7, 3, 4, -1},
|
||||
{9, 2, 10, 0, 2, 9, 8, 4, 7, -1},
|
||||
{3, 4, 7, 0, 4, 3, 1, 2, 10, -1},
|
||||
{7, 8, 4, 10, 1, 2, -1},
|
||||
{7, 11, 4, 4, 11, 9, 9, 11, 2, 9, 2, 1, -1},
|
||||
{1, 9, 0, 4, 7, 8, 2, 3, 11, -1},
|
||||
{7, 11, 4, 11, 2, 4, 2, 0, 4, -1},
|
||||
{4, 7, 8, 2, 3, 11, -1},
|
||||
{9, 4, 1, 4, 7, 1, 7, 3, 1, -1},
|
||||
{7, 8, 4, 1, 9, 0, -1},
|
||||
{3, 4, 7, 0, 4, 3, -1},
|
||||
{7, 8, 4, -1},
|
||||
{11, 10, 8, 8, 10, 9, -1},
|
||||
{0, 3, 9, 3, 11, 9, 11, 10, 9, -1},
|
||||
{1, 0, 10, 0, 8, 10, 8, 11, 10, -1},
|
||||
{10, 3, 11, 1, 3, 10, -1},
|
||||
{3, 2, 8, 2, 10, 8, 10, 9, 8, -1},
|
||||
{9, 2, 10, 0, 2, 9, -1},
|
||||
{8, 3, 0, 10, 1, 2, -1},
|
||||
{2, 10, 1, -1},
|
||||
{2, 1, 11, 1, 9, 11, 9, 8, 11, -1},
|
||||
{11, 2, 3, 9, 0, 1, -1},
|
||||
{11, 0, 8, 2, 0, 11, -1},
|
||||
{3, 11, 2, -1},
|
||||
{1, 8, 3, 9, 8, 1, -1},
|
||||
{1, 9, 0, -1},
|
||||
{8, 3, 0, -1},
|
||||
{-1},
|
||||
};
|
||||
|
||||
extern VoxelCorner marchingCubesEdgeCornerPairs[12][2] = {
|
||||
{// 0
|
||||
{.voxelOffset = {-1, -1, -1},
|
||||
.faceIndex = 1,
|
||||
.localCornerIndex = 3},
|
||||
{.voxelOffset = {0, -1, -1},
|
||||
.faceIndex = 0,
|
||||
.localCornerIndex = 2}},
|
||||
{// 1
|
||||
{.voxelOffset = {0, -1, -1},
|
||||
.faceIndex = 3,
|
||||
.localCornerIndex = 2},
|
||||
{.voxelOffset = {0, 0, -1},
|
||||
.faceIndex = 2,
|
||||
.localCornerIndex = 0}},
|
||||
{// 2
|
||||
{.voxelOffset = {0, 0, -1},
|
||||
.faceIndex = 0,
|
||||
.localCornerIndex = 0},
|
||||
{.voxelOffset = {-1, 0, -1},
|
||||
.faceIndex = 1,
|
||||
.localCornerIndex = 1}},
|
||||
{// 3
|
||||
{.voxelOffset = {-1, 0, -1},
|
||||
.faceIndex = 2,
|
||||
.localCornerIndex = 1},
|
||||
{.voxelOffset = {-1, -1, -1},
|
||||
.faceIndex = 3,
|
||||
.localCornerIndex = 3}},
|
||||
{// 4
|
||||
{.voxelOffset = {-1, -1, 0},
|
||||
.faceIndex = 1,
|
||||
.localCornerIndex = 2},
|
||||
{.voxelOffset = {0, -1, 0},
|
||||
.faceIndex = 0,
|
||||
.localCornerIndex = 3}},
|
||||
{// 5
|
||||
{.voxelOffset = {0, -1, 0},
|
||||
.faceIndex = 3,
|
||||
.localCornerIndex = 0},
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.faceIndex = 2,
|
||||
.localCornerIndex = 2}},
|
||||
{// 6
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.faceIndex = 0,
|
||||
.localCornerIndex = 1},
|
||||
{.voxelOffset = {-1, 0, 0},
|
||||
.faceIndex = 1,
|
||||
.localCornerIndex = 0}},
|
||||
{// 7
|
||||
{.voxelOffset = {-1, 0, 0},
|
||||
.faceIndex = 2,
|
||||
.localCornerIndex = 3},
|
||||
{.voxelOffset = {-1, -1, 0},
|
||||
.faceIndex = 3,
|
||||
.localCornerIndex = 1}},
|
||||
{// 8
|
||||
{.voxelOffset = {-1, -1, -1},
|
||||
.faceIndex = 5,
|
||||
.localCornerIndex = 2},
|
||||
{.voxelOffset = {-1, -1, 0},
|
||||
.faceIndex = 4,
|
||||
.localCornerIndex = 3}},
|
||||
{// 9
|
||||
{.voxelOffset = {0, -1, -1},
|
||||
.faceIndex = 5,
|
||||
.localCornerIndex = 3},
|
||||
{.voxelOffset = {0, -1, 0},
|
||||
.faceIndex = 4,
|
||||
.localCornerIndex = 2}},
|
||||
{// 10
|
||||
{.voxelOffset = {0, 0, -1},
|
||||
.faceIndex = 5,
|
||||
.localCornerIndex = 1},
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.faceIndex = 4,
|
||||
.localCornerIndex = 0}},
|
||||
{// 11
|
||||
{.voxelOffset = {-1, 0, -1},
|
||||
.faceIndex = 5,
|
||||
.localCornerIndex = 0},
|
||||
{.voxelOffset = {-1, 0, 0},
|
||||
.faceIndex = 4,
|
||||
.localCornerIndex = 1}}};
|
||||
|
||||
// Represents the 8 edges along each of the 3 axes for a voxel, axis : (X, Y, Z)
|
||||
VoxelEdge edgesPerAxis[AXIS_NUMBER][EDGE_PER_AXIS] = {
|
||||
{
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 4,
|
||||
.edgeIndex = 2},
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 2,
|
||||
.edgeIndex = 3},
|
||||
|
||||
{.voxelOffset = {0, -1, 0},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 3,
|
||||
.edgeIndex = 2},
|
||||
{.voxelOffset = {0, -1, 0},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 4,
|
||||
.edgeIndex = 3},
|
||||
|
||||
{.voxelOffset = {0, -1, -1},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 5,
|
||||
.edgeIndex = 3},
|
||||
{.voxelOffset = {0, -1, -1},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 3,
|
||||
.edgeIndex = 3},
|
||||
|
||||
{.voxelOffset = {0, 0, -1},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 2,
|
||||
.edgeIndex = 2},
|
||||
{.voxelOffset = {0, 0, -1},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 5,
|
||||
.edgeIndex = 2},
|
||||
}, // X axis
|
||||
{
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 0,
|
||||
.edgeIndex = 1},
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 4,
|
||||
.edgeIndex = 0},
|
||||
{.voxelOffset = {0, 0, -1},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 5,
|
||||
.edgeIndex = 1},
|
||||
{.voxelOffset = {0, 0, -1},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 0,
|
||||
.edgeIndex = 0},
|
||||
{.voxelOffset = {-1, 0, -1},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 1,
|
||||
.edgeIndex = 1},
|
||||
{.voxelOffset = {-1, 0, -1},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 5,
|
||||
.edgeIndex = 0},
|
||||
{.voxelOffset = {-1, 0, 0},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 4,
|
||||
.edgeIndex = 1},
|
||||
{.voxelOffset = {-1, 0, 0},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 1,
|
||||
.edgeIndex = 0}}, // Y axis
|
||||
{
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 0,
|
||||
.edgeIndex = 2},
|
||||
{.voxelOffset = {0, 0, 0},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 2,
|
||||
.edgeIndex = 0},
|
||||
{.voxelOffset = {0, -1, 0},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 3,
|
||||
.edgeIndex = 0},
|
||||
{.voxelOffset = {0, -1, 0},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 0,
|
||||
.edgeIndex = 3},
|
||||
{.voxelOffset = {-1, -1, 0},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 1,
|
||||
.edgeIndex = 3},
|
||||
{.voxelOffset = {-1, -1, 0},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 3,
|
||||
.edgeIndex = 1},
|
||||
{.voxelOffset = {-1, 0, 0},
|
||||
.isClockwiseOrder = true,
|
||||
.faceIndex = 2,
|
||||
.edgeIndex = 1},
|
||||
{.voxelOffset = {-1, 0, 0},
|
||||
.isClockwiseOrder = false,
|
||||
.faceIndex = 1,
|
||||
.edgeIndex = 2},
|
||||
} // Z axis
|
||||
};
|
||||
} // namespace Voxel
|
||||
} // namespace Deer
|
||||
@ -40,7 +40,7 @@ namespace Deer {
|
||||
if (targetRenderTime > 0 && accumulatedRenderTime >= targetRenderTime) {
|
||||
renderDeltaTime = accumulatedRenderTime;
|
||||
worldSettings.renderCallback(*this);
|
||||
accumulatedRenderTime = 0;
|
||||
accumulatedRenderTime -= targetRenderTime;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
#include "DeerRender/World.h"
|
||||
|
||||
// TMP
|
||||
#include "DeerCore/EntityEnviroment.h"
|
||||
#include "DeerRender/Voxel.h"
|
||||
#include "DeerStudio/Fonts.h"
|
||||
#include "DeerStudio/Style.h"
|
||||
// TMP
|
||||
@ -17,6 +19,7 @@ namespace Deer {
|
||||
|
||||
namespace DeerStudio {
|
||||
World* world;
|
||||
VoxelEnvironment env;
|
||||
|
||||
void onUpdate();
|
||||
void onRender();
|
||||
@ -46,6 +49,53 @@ namespace Deer {
|
||||
|
||||
while (world) {
|
||||
StudioPanel::setWorld(world);
|
||||
|
||||
Entity& entity = world->entityEnvironment->createEntity();
|
||||
MeshComponent& mesh = entity.addComponent<MeshComponent>();
|
||||
ShaderComponent& shader = entity.addComponent<ShaderComponent>();
|
||||
|
||||
/*
|
||||
env.modifyVoxel(1, 0, 1, 0);
|
||||
env.modifyVoxel(1, 1, 2, 0);
|
||||
|
||||
env.modifyVoxel(1, 5, 1, 1);
|
||||
env.modifyVoxel(1, 5, 2, 2);
|
||||
env.modifyVoxel(1, 5, 1, 3);
|
||||
|
||||
env.modifyVoxel(1, 15, 1, 15);
|
||||
env.modifyVoxel(1, 14, 1, 16);
|
||||
|
||||
env.modifyVoxel(1, 5, 1, 8);
|
||||
env.modifyVoxel(1, 5, 1, 9);
|
||||
env.modifyVoxel(1, 5, 2, 9);
|
||||
env.modifyVoxel(1, 6, 1, 9);
|
||||
|
||||
env.modifyVoxel(1, 0, 1, 5);
|
||||
env.modifyVoxel(1, 1, 2, 6);
|
||||
|
||||
env.modifyVoxel(1, 4, 1, 5);
|
||||
|
||||
env.modifyVoxel(1, 9, 1, 9);
|
||||
env.modifyVoxel(1, 10, 1, 10);
|
||||
*/
|
||||
for (int x = 0; x < 20; x++)
|
||||
for (int y = 0; y < 20; y++)
|
||||
env.modifyVoxel(1, x, 0, y);
|
||||
|
||||
env.modifyVoxel(1, 5, 1, 5);
|
||||
env.modifyVoxel(1, 5, 2, 5);
|
||||
env.modifyVoxel(1, 4, 2, 5);
|
||||
env.modifyVoxel(1, 4, 2, 4);
|
||||
|
||||
env.modifyVoxel(1, 7, 1, 5);
|
||||
env.modifyVoxel(1, 6, 1, 5);
|
||||
env.modifyVoxel(1, 6, 1, 4);
|
||||
|
||||
DEER_CORE_INFO("{}", env.getVoxel(0, 0, 0));
|
||||
|
||||
shader.shader = Builtin::simpleShader();
|
||||
mesh.mesh = env.voxelBuilder->buildChunk(0, 0, 0);
|
||||
|
||||
world->execute();
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
#include "DeerStudio/DeerStudio.h"
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
namespace Deer {
|
||||
namespace DeerStudio {
|
||||
void onPanelMenuBar() {
|
||||
}
|
||||
|
||||
} // namespace DeerStudio
|
||||
} // namespace Deer
|
||||
@ -11,42 +11,40 @@ class MeshComponentRender {
|
||||
if (!entity.hasComponent<MeshComponent>())
|
||||
return;
|
||||
|
||||
ImGui::title("Mesh Component");
|
||||
ImGui::space(10, 10);
|
||||
ImGui::text("Mesh : ");
|
||||
ImGui::sameline();
|
||||
if (meshComponent.hasMesh) {
|
||||
ImGui::text(meshComponent.meshResource.name);
|
||||
} else {
|
||||
ImGui::text("Empty");
|
||||
}
|
||||
|
||||
// Mesh icon
|
||||
if (meshComponent.hasMesh) {
|
||||
ImGui::drawIcon(StudioAPI::loadIcon("object3d.png"), 32);
|
||||
FrameBuffer frameBuffer = Previewer::getMeshPreview(meshComponent.meshResource);
|
||||
ImGui::drawFrameBufferCentered(frameBuffer, 128, 128);
|
||||
} else {
|
||||
ImGui::drawIcon(StudioAPI::loadIcon("empty.png"), 32);
|
||||
ImGui::drawIconCentered(StudioAPI::loadIcon("empty.png"), 128);
|
||||
}
|
||||
|
||||
ImGui::dragDropTarget("MESH", ReciverFunction(this.setMesh));
|
||||
|
||||
if (meshComponent.hasMesh) {
|
||||
ImGui::sameline();
|
||||
ImGui::space();
|
||||
ImGui::sameline();
|
||||
|
||||
GPUMesh mesh = meshComponent.get_meshResource();
|
||||
ImGui::titleCenterY(mesh.name, 32);
|
||||
ImGui::dragDropTarget("MESH", ReciverFunction(this.setMesh));
|
||||
}
|
||||
|
||||
ImGui::space(0, 20);
|
||||
|
||||
if (ImGui::button("Clear")) {
|
||||
meshComponent.clear();
|
||||
}
|
||||
|
||||
ImGui::sameline();
|
||||
ImGui::space(0, 20);
|
||||
ImGui::sameline();
|
||||
|
||||
bool active = meshComponent.get_isActive();
|
||||
ImGui::space(10, 10);
|
||||
bool active = meshComponent.isActive;
|
||||
if (meshComponent.get_hasMesh()) {
|
||||
active = ImGui::checkbox("Active", active);
|
||||
meshComponent.set_isActive(active);
|
||||
} else {
|
||||
ImGui::checkboxDisabled("Active", active);
|
||||
}
|
||||
|
||||
ImGui::sameline();
|
||||
|
||||
if (ImGui::buttonEnd("Clear")) {
|
||||
meshComponent.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void setMesh(any@ meshData) {
|
||||
|
||||
@ -25,51 +25,30 @@ class ShaderComponentRender {
|
||||
if (!entity.hasComponent<ShaderComponent>())
|
||||
return;
|
||||
|
||||
// Shader icon
|
||||
ImGui::title("Shader Component");
|
||||
ImGui::space(10, 10);
|
||||
ImGui::text("Shader : ");
|
||||
ImGui::sameline();
|
||||
if (shaderComponent.hasShader) {
|
||||
ImGui::drawIcon(StudioAPI::loadIcon("shader.png"), 32);
|
||||
ImGui::text(shaderComponent.shader.name);
|
||||
} else {
|
||||
ImGui::drawIcon(StudioAPI::loadIcon("empty.png"), 32);
|
||||
ImGui::text("Empty");
|
||||
}
|
||||
|
||||
// Mesh icon
|
||||
if (shaderComponent.hasShader) {
|
||||
FrameBuffer frameBuffer = Previewer::getShaderPreview(shaderComponent.shader);
|
||||
ImGui::drawFrameBufferCentered(frameBuffer, 128, 128);
|
||||
} else {
|
||||
ImGui::drawIconCentered(StudioAPI::loadIcon("empty.png"), 128);
|
||||
}
|
||||
|
||||
ImGui::dragDropTarget("SHADER", ReciverFunction(this.setShader));
|
||||
|
||||
if (shaderComponent.hasShader) {
|
||||
ImGui::sameline();
|
||||
ImGui::space();
|
||||
ImGui::sameline();
|
||||
|
||||
Shader shader = shaderComponent.shader;
|
||||
ImGui::titleCenterY(shader.name, 32);
|
||||
ImGui::dragDropTarget("SHADER", ReciverFunction(this.setShader));
|
||||
}
|
||||
|
||||
ImGui::space();
|
||||
|
||||
// Texture icon
|
||||
Texture texture = shaderComponent.texture;
|
||||
if (texture.isValid()) {
|
||||
ImGui::drawIcon(texture, 32);
|
||||
} else {
|
||||
ImGui::drawIcon(StudioAPI::loadIcon("empty.png"), 32);
|
||||
}
|
||||
|
||||
ImGui::dragDropTarget("TEXTURE", ReciverFunction(this.setTexture));
|
||||
|
||||
if (texture.isValid()) {
|
||||
ImGui::sameline();
|
||||
ImGui::space();
|
||||
ImGui::sameline();
|
||||
|
||||
ImGui::titleCenterY(texture.name, 32);
|
||||
ImGui::dragDropTarget("TEXTURE", ReciverFunction(this.setTexture));
|
||||
}
|
||||
|
||||
ImGui::space(0, 20);
|
||||
|
||||
if (ImGui::button("Clear")) {
|
||||
if (ImGui::buttonEnd("Clear")) {
|
||||
shaderComponent.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void remove() {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
namespace Previewer {
|
||||
FrameBuffer getMeshPreview(GPUMesh mesh) {
|
||||
FrameBuffer frame = Resource::createFrameBuffer(mesh.path, 128, 128);
|
||||
frame.clearRGBA(0, 0, 0, 255);
|
||||
frame.clearRGBA(0, 0, 0, 0);
|
||||
|
||||
WorldCamera wcamera;
|
||||
wcamera.transform.position = vec3(0, 1, -3.5);
|
||||
@ -29,4 +29,4 @@ namespace Previewer {
|
||||
frame.drawMesh(mesh, shader, transform, wcamera);
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,10 +5,22 @@ class ViewportPanel : Panel {
|
||||
float pitch = 0;
|
||||
float yaw = 0;
|
||||
|
||||
int frameCounter = 0;
|
||||
float deltaAcomulated = 0;
|
||||
float latestFrameRate;
|
||||
|
||||
void onImGui() {
|
||||
if (!frameBuffer.isValid())
|
||||
return;
|
||||
|
||||
frameCounter++;
|
||||
deltaAcomulated += World::getRenderDeltaTime();
|
||||
if (frameCounter == 50) {
|
||||
latestFrameRate = 50 / deltaAcomulated;
|
||||
frameCounter = 0;
|
||||
deltaAcomulated = 0;
|
||||
}
|
||||
|
||||
float vel = World::getRenderDeltaTime() * 3;
|
||||
|
||||
if (ImGui::isKeyDown(key::LeftShift))
|
||||
@ -21,23 +33,35 @@ class ViewportPanel : Panel {
|
||||
return;
|
||||
|
||||
frameBuffer.resize(x, y);
|
||||
frameBuffer.clearRGBA(0, 0, 0, 255);
|
||||
frameBuffer.clearRGBA(20, 30, 45, 255);
|
||||
|
||||
sceneCamera.camera.aspect = float(x) / y;
|
||||
World::render(frameBuffer, sceneCamera);
|
||||
|
||||
ImGui::drawFrameBufferCentered(frameBuffer, x, y);
|
||||
|
||||
if(ActiveEntity::entity != World::getRoot()) {
|
||||
mat4 entityTransform = ActiveEntity::entity.getWorldMatrix();
|
||||
|
||||
if (ImGui::manipulationTransform(sceneCamera, entityTransform, entityTransform, false)) {
|
||||
mat4 parentTransform = ActiveEntity::entity.parent.getWorldMatrix();
|
||||
|
||||
mat4 relativeMatrix = entityTransform.getRelativeMatrix(parentTransform);
|
||||
ActiveEntity::entity.getComponent<TransformComponent>().position = relativeMatrix.getPosition();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ImGui::isPanelActive())
|
||||
return;
|
||||
|
||||
if (ImGui::isMouseDragging(key::MouseLeft) && !ImGui::isKeyDown(key::MouseMiddle)) {
|
||||
if (ImGui::isMouseDragging(key::MouseRight) && !ImGui::isKeyDown(key::MouseMiddle)) {
|
||||
pitch += ImGui::getMouseDeltaY() * 0.1;
|
||||
yaw += ImGui::getMouseDeltaX() * 0.1;
|
||||
|
||||
sceneCamera.transform.rotation.setEuler(vec3(pitch, yaw, 0));
|
||||
}
|
||||
|
||||
if (ImGui::isMouseDragging(key::MouseMiddle) && !ImGui::isKeyDown(key::MouseLeft)) {
|
||||
if (ImGui::isMouseDragging(key::MouseMiddle) && !ImGui::isKeyDown(key::MouseRight)) {
|
||||
vec3 panDir = vec3();
|
||||
|
||||
panDir.x -= ImGui::getMouseDeltaX();
|
||||
@ -92,7 +116,7 @@ class ViewportPanel : Panel {
|
||||
}
|
||||
|
||||
ImGui::simplePopup("ViewportCameraProps", SimpleFunction(this.viewportCameraProps));
|
||||
ImGui::textColor(0, 0.5f, 0,"" + ceil(1 / World::getRenderDeltaTime()));
|
||||
ImGui::textColor(0, 0.5f, 0,"" + latestFrameRate);
|
||||
}
|
||||
|
||||
void viewportCameraProps() {
|
||||
|
||||
12
Editor/Scripts/VoxelEditor/VoxelEditor.as
Normal file
12
Editor/Scripts/VoxelEditor/VoxelEditor.as
Normal file
@ -0,0 +1,12 @@
|
||||
class VoxelEditor : Panel {
|
||||
FrameBuffer editorBuffer;
|
||||
|
||||
void onInit() {
|
||||
editorBuffer = Resource::createFrameBuffer("VoxelEditor", 620, 620);
|
||||
}
|
||||
|
||||
void onImGui() {
|
||||
editorBuffer.clearRGBA(60, 120, 100, 255);
|
||||
ImGui::drawFrameBufferCentered(editorBuffer, 620, 620);
|
||||
}
|
||||
}
|
||||
83
Resources/normal.glsl
Normal file
83
Resources/normal.glsl
Normal file
@ -0,0 +1,83 @@
|
||||
#type vertex
|
||||
#version 410 core
|
||||
|
||||
// Vertex attributes
|
||||
layout(location = 0) in vec3 v_position;
|
||||
layout(location = 1) in vec3 v_normal;
|
||||
layout(location = 2) in vec2 v_UV;
|
||||
|
||||
// Outputs to fragment shader
|
||||
out vec3 normalWS;
|
||||
out vec3 normalVS;
|
||||
out vec3 positionVS;
|
||||
|
||||
// Uniforms
|
||||
uniform mat4 u_worldMatrix;
|
||||
uniform mat4 u_viewMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_viewMatrix * u_worldMatrix * vec4(v_position, 1.0);
|
||||
positionVS = gl_Position.xyz;
|
||||
|
||||
mat3 normalMatrix = transpose(inverse(mat3(u_worldMatrix)));
|
||||
normalWS = normalize(normalMatrix * v_normal);
|
||||
|
||||
mat3 normalMatrixView = transpose(inverse(mat3(u_viewMatrix * u_worldMatrix)));
|
||||
normalVS = normalize(normalMatrixView * v_normal);
|
||||
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 410 core
|
||||
|
||||
// Fragment outputs
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(location = 1) out int objectID;
|
||||
|
||||
// Inputs from vertex shader
|
||||
in vec3 normalWS;
|
||||
in vec3 normalVS;
|
||||
in vec3 positionVS;
|
||||
|
||||
// Uniforms
|
||||
uniform int u_objectID;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Directional light
|
||||
vec3 lightDir = normalize(vec3(1.0, 7.0, 3.0));
|
||||
|
||||
// Base light intensity
|
||||
float light = clamp(dot(normalize(normalWS), lightDir) * 0.8 + 0.2, 0.0, 1.0);
|
||||
|
||||
// Gradient from purple (dark) to cyan (lit)
|
||||
vec3 gradientColor = mix(
|
||||
vec3(0.9412, 0.4471, 0.7137),
|
||||
vec3(1.0, 0.9725, 0.5255),
|
||||
light
|
||||
);
|
||||
|
||||
// Rim/fresnel effect
|
||||
float rim = 0.5 - dot(normalize(normalWS), normalize(lightDir)) * 0.5;
|
||||
float rimValue = rim * rim * rim * rim;
|
||||
vec3 rimColor = vec3(1.0, 0.8, 0.5) * (rim * rim * rim * rim);
|
||||
|
||||
vec3 mixedColor = mix(
|
||||
gradientColor,
|
||||
vec3(1, 1, 1) ,
|
||||
rimValue
|
||||
);
|
||||
|
||||
//float fresnel = dot(, vec3(0, 0, -1));
|
||||
//fresnel = fresnel * fresnel;
|
||||
|
||||
float fresnel = 1 + dot(normalize(positionVS), normalize(normalVS));
|
||||
fresnel = fresnel * fresnel * fresnel * fresnel;
|
||||
|
||||
// Combine everything
|
||||
fragColor = vec4(normalize(normalWS) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0);
|
||||
|
||||
// Object ID output
|
||||
objectID = u_objectID;
|
||||
}
|
||||
87
Resources/shad.glsl
Normal file
87
Resources/shad.glsl
Normal file
@ -0,0 +1,87 @@
|
||||
#type vertex
|
||||
#version 410 core
|
||||
|
||||
// Vertex attributes
|
||||
layout(location = 0) in vec3 v_position;
|
||||
layout(location = 1) in vec3 v_normal;
|
||||
layout(location = 2) in float v_light;
|
||||
|
||||
// Outputs to fragment shader
|
||||
out vec3 normalWS;
|
||||
out vec3 normalVS;
|
||||
out vec3 positionVS;
|
||||
out float shadow;
|
||||
|
||||
// Uniforms
|
||||
uniform mat4 u_worldMatrix;
|
||||
uniform mat4 u_viewMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_viewMatrix * u_worldMatrix * vec4(v_position, 1.0);
|
||||
positionVS = gl_Position.xyz;
|
||||
|
||||
mat3 normalMatrix = transpose(inverse(mat3(u_worldMatrix)));
|
||||
normalWS = normalize(normalMatrix * v_normal);
|
||||
|
||||
mat3 normalMatrixView = transpose(inverse(mat3(u_viewMatrix * u_worldMatrix)));
|
||||
normalVS = normalize(normalMatrixView * v_normal);
|
||||
|
||||
shadow = v_light;
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 410 core
|
||||
|
||||
// Fragment outputs
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(location = 1) out int objectID;
|
||||
|
||||
// Inputs from vertex shader
|
||||
in vec3 normalWS;
|
||||
in vec3 normalVS;
|
||||
in vec3 positionVS;
|
||||
in float shadow;
|
||||
|
||||
// Uniforms
|
||||
uniform int u_objectID;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Directional light
|
||||
vec3 lightDir = normalize(vec3(1.0, 7.0, 3.0));
|
||||
|
||||
// Base light intensity
|
||||
float light = clamp(dot(normalize(normalWS), lightDir) * 0.8 + 0.2, 0.0, 1.0);
|
||||
|
||||
// Gradient from purple (dark) to cyan (lit)
|
||||
vec3 gradientColor = mix(
|
||||
vec3(0.9412, 0.4471, 0.7137),
|
||||
vec3(1.0, 0.9725, 0.5255),
|
||||
light
|
||||
);
|
||||
|
||||
// Rim/fresnel effect
|
||||
float rim = 0.5 - dot(normalize(normalWS), normalize(lightDir)) * 0.5;
|
||||
float rimValue = rim * rim * rim * rim;
|
||||
vec3 rimColor = vec3(1.0, 0.8, 0.5) * (rim * rim * rim * rim);
|
||||
|
||||
vec3 mixedColor = mix(
|
||||
gradientColor,
|
||||
vec3(1, 1, 1) ,
|
||||
rimValue
|
||||
);
|
||||
|
||||
//float fresnel = dot(, vec3(0, 0, -1));
|
||||
//fresnel = fresnel * fresnel;
|
||||
|
||||
float fresnel = 1 + dot(normalize(positionVS), normalize(normalVS));
|
||||
fresnel = fresnel * fresnel * fresnel * fresnel;
|
||||
|
||||
// Combine everything
|
||||
fragColor = vec4(normalize(normalWS) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0);
|
||||
fragColor = vec4(shadow / 255, shadow / 255, shadow / 255, 1);
|
||||
|
||||
// Object ID output
|
||||
objectID = u_objectID;
|
||||
}
|
||||
26
imgui.ini
26
imgui.ini
@ -10,34 +10,40 @@ Collapsed=0
|
||||
|
||||
[Window][ViewportPanel]
|
||||
Pos=561,26
|
||||
Size=1574,853
|
||||
Size=1348,870
|
||||
Collapsed=0
|
||||
DockId=0x00000005,0
|
||||
|
||||
[Window][PropertiesPanel]
|
||||
Pos=2137,26
|
||||
Size=423,853
|
||||
Pos=1911,26
|
||||
Size=649,870
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][ResourceExplorer]
|
||||
Pos=0,881
|
||||
Size=2560,490
|
||||
Pos=0,898
|
||||
Size=2560,473
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
[Window][TreePanel]
|
||||
Pos=0,26
|
||||
Size=559,853
|
||||
Size=559,870
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
|
||||
[Window][VoxelEditor]
|
||||
Pos=1911,26
|
||||
Size=649,870
|
||||
Collapsed=0
|
||||
DockId=0x00000006,1
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,26 Size=2560,1345 Split=Y
|
||||
DockNode ID=0x00000003 Parent=0x0AC2E849 SizeRef=1920,493 Split=X
|
||||
DockNode ID=0x00000003 Parent=0x0AC2E849 SizeRef=1920,870 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=559,985 Selected=0x16E3C1E7
|
||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1359,985 Split=X
|
||||
DockNode ID=0x00000005 Parent=0x00000002 SizeRef=934,493 CentralNode=1 Selected=0x0F5FFC8C
|
||||
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=423,493 Selected=0x9876A79B
|
||||
DockNode ID=0x00000004 Parent=0x0AC2E849 SizeRef=1920,490 Selected=0x018A0F9B
|
||||
DockNode ID=0x00000005 Parent=0x00000002 SizeRef=1348,493 CentralNode=1 Selected=0x0F5FFC8C
|
||||
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=649,493 Selected=0x9876A79B
|
||||
DockNode ID=0x00000004 Parent=0x0AC2E849 SizeRef=1920,473 Selected=0x018A0F9B
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user