heightmap wip
This commit is contained in:
@@ -393,6 +393,37 @@ namespace Gen
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RayTriangleIntersect(Vec3 l1, Vec3 l2, Vec3 p1, Vec3 p2, Vec3 p3, Vec3& out)
|
||||
{
|
||||
const float EPSILON = 1e-6f;
|
||||
Vec3 dir = l2 - l1; // Ray direction
|
||||
Vec3 edge1 = p2 - p1;
|
||||
Vec3 edge2 = p3 - p1;
|
||||
|
||||
Vec3 h = CrossProduct(dir, edge2);
|
||||
float a = DotProduct(edge1, h);
|
||||
|
||||
if (bx::abs(a) < EPSILON) return false; // Ray is parallel to the triangle
|
||||
|
||||
float f = 1.0f / a;
|
||||
Vec3 s = l1 - p1;
|
||||
float u = f * DotProduct(s, h);
|
||||
if (u < 0.0f || u > 1.0f) return false;
|
||||
|
||||
Vec3 q = CrossProduct(s, edge1);
|
||||
float v = f * DotProduct(dir, q);
|
||||
if (v < 0.0f || u + v > 1.0f) return false;
|
||||
|
||||
float t = f * DotProduct(edge2, q);
|
||||
if (t > EPSILON)
|
||||
{
|
||||
out = l1 + dir * t;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Translate(Transform& trans, Vec3 offset)
|
||||
{
|
||||
trans.Position += Vec3{offset.x, offset.y, offset.z};
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace Gen
|
||||
Vec3 CrossProduct(Vec3 a, Vec3 b);
|
||||
Vec3 CrossProductFromPlane(Vec3 a, Vec3 b, Vec3 c);
|
||||
bool RayPlaneIntersect(Vec3 l1, Vec3 l2, Vec3 p1, Vec3 p2, Vec3 p3, Vec3& out);
|
||||
bool RayTriangleIntersect(Vec3 l1, Vec3 l2, Vec3 p1, Vec3 p2, Vec3 p3, Vec3& out);
|
||||
|
||||
void Translate(Transform& trans, Vec3 offset);
|
||||
void TranslateLocal(Transform& trans, Vec3 offset);
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
#include "bx/filepath.h"
|
||||
#include "bx/hash.h"
|
||||
#include "bx/string.h"
|
||||
#include "bx/timer.h"
|
||||
#include "rendering/Rendering.h"
|
||||
|
||||
#include "Instance.h"
|
||||
#include <cfloat>
|
||||
#include <cstdint>
|
||||
|
||||
#define TINYGLTF_IMPLEMENTATION
|
||||
@@ -61,23 +63,23 @@ namespace Game
|
||||
|
||||
tinygltf::Primitive primitive = model.meshes[0].primitives[0];
|
||||
{
|
||||
tinygltf::Accessor accessor = model.accessors.at(primitive.indices);
|
||||
tinygltf::BufferView bufferView = model.bufferViews.at(accessor.bufferView);
|
||||
tinygltf::Buffer buffer = model.buffers[bufferView.buffer];
|
||||
const bgfx::Memory* ibMem = bgfx::alloc(bufferView.byteLength);
|
||||
bx::memCopy(ibMem->data, &buffer.data.at(bufferView.byteOffset), bufferView.byteLength);
|
||||
tinygltf::Accessor indexAccessor = model.accessors.at(primitive.indices);
|
||||
tinygltf::BufferView indexBufferView = model.bufferViews.at(indexAccessor.bufferView);
|
||||
int32_t indexStride = sizeof(uint16_t);
|
||||
tinygltf::Buffer indexBuffer = model.buffers[indexBufferView.buffer];
|
||||
const bgfx::Memory* ibMem = bgfx::alloc(indexBufferView.byteLength);
|
||||
bx::memCopy(ibMem->data, &indexBuffer.data.at(indexBufferView.byteOffset), indexBufferView.byteLength);
|
||||
mesh.IndexBuffer = bgfx::createIndexBuffer(ibMem);
|
||||
}
|
||||
{
|
||||
|
||||
tinygltf::Accessor posAccessor = model.accessors.at(primitive.attributes.at("POSITION"));
|
||||
tinygltf::Accessor normalAccessor = model.accessors.at(primitive.attributes.at("NORMAL"));
|
||||
tinygltf::Accessor uvAccessor = model.accessors.at(primitive.attributes.at("TEXCOORD_0"));
|
||||
tinygltf::BufferView posBufferView = model.bufferViews[posAccessor.bufferView];
|
||||
tinygltf::BufferView normalBufferView = model.bufferViews[normalAccessor.bufferView];
|
||||
tinygltf::BufferView uvBufferView = model.bufferViews[uvAccessor.bufferView];
|
||||
int posStride = posAccessor.ByteStride(posBufferView);
|
||||
int normalStride = normalAccessor.ByteStride(normalBufferView);
|
||||
int uvStride = uvAccessor.ByteStride(uvBufferView);
|
||||
int32_t posStride = posAccessor.ByteStride(posBufferView);
|
||||
int32_t normalStride = normalAccessor.ByteStride(normalBufferView);
|
||||
int32_t uvStride = uvAccessor.ByteStride(uvBufferView);
|
||||
tinygltf::Buffer posBuffer = model.buffers[posBufferView.buffer];
|
||||
tinygltf::Buffer normalBuffer = model.buffers[normalBufferView.buffer];
|
||||
tinygltf::Buffer uvBuffer = model.buffers[uvBufferView.buffer];
|
||||
@@ -95,15 +97,75 @@ namespace Game
|
||||
bx::memCopy(&v.uv_x, &uvBuffer.data.at(uvBufferView.byteOffset + i * uvStride), uvStride);
|
||||
}
|
||||
mesh.VertexBuffer = bgfx::createVertexBuffer(vbMem, mesh.VertLayout);
|
||||
|
||||
constexpr float SIZE_LIMIT = 1000.0f;
|
||||
mesh.MinPos = {SIZE_LIMIT, SIZE_LIMIT, SIZE_LIMIT};
|
||||
mesh.MaxPos = {-SIZE_LIMIT, -SIZE_LIMIT, -SIZE_LIMIT};
|
||||
|
||||
bx::memSet(mesh.Height.Values, 0, BX_COUNTOF(mesh.Height.Values));
|
||||
|
||||
int64_t startTime = bx::getHPCounter();
|
||||
for (int32_t i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
Gen::Vec3* pos =
|
||||
reinterpret_cast<Gen::Vec3*>(&posBuffer.data[posBufferView.byteOffset + i * posStride]);
|
||||
if (pos->x < mesh.MinPos.x) mesh.MinPos.x = pos->x;
|
||||
if (pos->y < mesh.MinPos.y) mesh.MinPos.y = pos->y;
|
||||
if (pos->z < mesh.MinPos.z) mesh.MinPos.z = pos->z;
|
||||
if (pos->x > mesh.MaxPos.x) mesh.MaxPos.x = pos->x;
|
||||
if (pos->y > mesh.MaxPos.y) mesh.MaxPos.y = pos->y;
|
||||
if (pos->z > mesh.MaxPos.z) mesh.MaxPos.z = pos->z;
|
||||
}
|
||||
LOG("min/max: %lli", bx::getHPCounter() - startTime);
|
||||
|
||||
mesh.Size = mesh.MaxPos - mesh.MinPos;
|
||||
|
||||
startTime = bx::getHPCounter();
|
||||
for (uint32_t v = 0; v < HeightMap::Height; ++v)
|
||||
{
|
||||
float vPos = mesh.MinPos.y + (float)v / HeightMap::Height * mesh.Size.y;
|
||||
|
||||
for (uint32_t u = 0; u < HeightMap::Width; ++u)
|
||||
{
|
||||
float uPos = mesh.MinPos.x + (float)u / HeightMap::Width * mesh.Size.x;
|
||||
|
||||
Gen::Vec3 rayStart = {uPos, vPos, SIZE_LIMIT};
|
||||
Gen::Vec3 rayEnd = {uPos, vPos, -SIZE_LIMIT};
|
||||
Gen::Vec3 ptOut;
|
||||
|
||||
for (int16_t i = 0; i < indexBufferView.byteLength; i += indexStride * 3)
|
||||
{
|
||||
uint16_t* idxA = reinterpret_cast<uint16_t*>(&indexBuffer.data[indexBufferView.byteOffset + i]);
|
||||
uint16_t* idxB = reinterpret_cast<uint16_t*>(
|
||||
&indexBuffer.data[indexBufferView.byteOffset + i + 1 * indexStride]);
|
||||
uint16_t* idxC = reinterpret_cast<uint16_t*>(
|
||||
&indexBuffer.data[indexBufferView.byteOffset + i + 2 * indexStride]);
|
||||
Gen::Vec3* triA =
|
||||
reinterpret_cast<Gen::Vec3*>(&posBuffer.data[posBufferView.byteOffset + *idxA * posStride]);
|
||||
Gen::Vec3* triB =
|
||||
reinterpret_cast<Gen::Vec3*>(&posBuffer.data[posBufferView.byteOffset + *idxB * posStride]);
|
||||
Gen::Vec3* triC =
|
||||
reinterpret_cast<Gen::Vec3*>(&posBuffer.data[posBufferView.byteOffset + *idxC * posStride]);
|
||||
if (Gen::RayTriangleIntersect(rayStart, rayEnd, *triA, *triB, *triC, ptOut))
|
||||
{
|
||||
float len = mesh.MaxPos.z - ptOut.z;
|
||||
uint8_t val = (uint8_t)(len / mesh.Size.z * UINT8_MAX);
|
||||
int32_t idx = v * HeightMap::Width + u;
|
||||
if (mesh.Height.Values[idx] < val)
|
||||
{
|
||||
mesh.Height.Values[idx] = val;
|
||||
}
|
||||
if (len < 0.0f)
|
||||
{
|
||||
LOG_ONCE("%f / %f = %u", len, mesh.Size.z, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG("heightmap: %lli", bx::getHPCounter() - startTime);
|
||||
}
|
||||
|
||||
for (uint32_t y = 0; y < HeightMap::Height; ++y)
|
||||
{
|
||||
for (uint32_t x = 0; x < HeightMap::Width; ++x)
|
||||
{
|
||||
mesh.Height.Values[y * HeightMap::Width + x] = (uint8_t)(((float)x / HeightMap::Width) * UINT8_MAX);
|
||||
}
|
||||
}
|
||||
const bgfx::Memory* mem = bgfx::makeRef(&mesh.Height.Values[0], sizeof(mesh.Height.Values));
|
||||
mesh.HeightMapTexture =
|
||||
bgfx::createTexture2D(HeightMap::Width, HeightMap::Height, false, 1, bgfx::TextureFormat::R8, 0, mem);
|
||||
|
||||
@@ -58,6 +58,9 @@ namespace Game
|
||||
ModelSocket Sockets[MaxSocketCount];
|
||||
HeightMap Height;
|
||||
bgfx::TextureHandle HeightMapTexture = {bgfx::kInvalidHandle};
|
||||
Gen::Vec3 MinPos;
|
||||
Gen::Vec3 MaxPos;
|
||||
Gen::Vec3 Size;
|
||||
char Name[128]{0};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user