summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/examples/common/bgfx_utils.cpp
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-02-01 10:14:17 +0100
committer Miodrag Milanovic <mmicko@gmail.com>2015-02-01 10:14:17 +0100
commitb3303c3a32b94b61f82e739d8d494752047f11c1 (patch)
tree1383c753eaebdfa039f1768f55c96fe800ce020f /3rdparty/bgfx/examples/common/bgfx_utils.cpp
parent09b6ec9869349cf9befd8c3589f1dccb32bacd1a (diff)
Added BGFX latest code to 3rdparty (nw)
Diffstat (limited to '3rdparty/bgfx/examples/common/bgfx_utils.cpp')
-rw-r--r--3rdparty/bgfx/examples/common/bgfx_utils.cpp525
1 files changed, 525 insertions, 0 deletions
diff --git a/3rdparty/bgfx/examples/common/bgfx_utils.cpp b/3rdparty/bgfx/examples/common/bgfx_utils.cpp
new file mode 100644
index 00000000000..a9516af16ee
--- /dev/null
+++ b/3rdparty/bgfx/examples/common/bgfx_utils.cpp
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2011-2015 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include <string.h> // strlen
+
+#include <tinystl/allocator.h>
+#include <tinystl/vector.h>
+#include <tinystl/string.h>
+namespace stl = tinystl;
+
+#include <bgfx.h>
+#include <bx/readerwriter.h>
+#include <bx/fpumath.h>
+#include "entry/entry.h"
+#include <ib-compress/indexbufferdecompression.h>
+
+#include "bgfx_utils.h"
+
+void* load(bx::FileReaderI* _reader, const char* _filePath, uint32_t* _size)
+{
+ if (0 == bx::open(_reader, _filePath) )
+ {
+ uint32_t size = (uint32_t)bx::getSize(_reader);
+ void* data = malloc(size);
+ bx::read(_reader, data, size);
+ bx::close(_reader);
+ if (NULL != _size)
+ {
+ *_size = size;
+ }
+ return data;
+ }
+
+ if (NULL != _size)
+ {
+ *_size = 0;
+ }
+ return NULL;
+}
+
+void* load(const char* _filePath, uint32_t* _size)
+{
+ return load(entry::getFileReader(), _filePath, _size);
+}
+
+static const bgfx::Memory* loadMem(bx::FileReaderI* _reader, const char* _filePath)
+{
+ if (0 == bx::open(_reader, _filePath) )
+ {
+ uint32_t size = (uint32_t)bx::getSize(_reader);
+ const bgfx::Memory* mem = bgfx::alloc(size+1);
+ bx::read(_reader, mem->data, size);
+ bx::close(_reader);
+ mem->data[mem->size-1] = '\0';
+ return mem;
+ }
+
+ return NULL;
+}
+
+static bgfx::ShaderHandle loadShader(bx::FileReaderI* _reader, const char* _name)
+{
+ char filePath[512];
+
+ const char* shaderPath = "shaders/dx9/";
+
+ switch (bgfx::getRendererType() )
+ {
+ case bgfx::RendererType::Direct3D11:
+ shaderPath = "shaders/dx11/";
+ break;
+
+ case bgfx::RendererType::OpenGL:
+ shaderPath = "shaders/glsl/";
+ break;
+
+ case bgfx::RendererType::OpenGLES:
+ shaderPath = "shaders/gles/";
+ break;
+
+ default:
+ break;
+ }
+
+ strcpy(filePath, shaderPath);
+ strcat(filePath, _name);
+ strcat(filePath, ".bin");
+
+ return bgfx::createShader(loadMem(_reader, filePath) );
+}
+
+bgfx::ShaderHandle loadShader(const char* _name)
+{
+ return loadShader(entry::getFileReader(), _name);
+}
+
+bgfx::ProgramHandle loadProgram(bx::FileReaderI* _reader, const char* _vsName, const char* _fsName)
+{
+ bgfx::ShaderHandle vsh = loadShader(_reader, _vsName);
+ bgfx::ShaderHandle fsh = loadShader(_reader, _fsName);
+
+ return bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */);
+}
+
+bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName)
+{
+ return loadProgram(entry::getFileReader(), _vsName, _fsName);
+}
+
+bgfx::TextureHandle loadTexture(bx::FileReaderI* _reader, const char* _name, uint32_t _flags, uint8_t _skip, bgfx::TextureInfo* _info)
+{
+ char filePath[512];
+ strcpy(filePath, "textures/");
+ strcat(filePath, _name);
+
+ const bgfx::Memory* mem = loadMem(_reader, filePath);
+
+ return bgfx::createTexture(mem, _flags, _skip, _info);
+}
+
+bgfx::TextureHandle loadTexture(const char* _name, uint32_t _flags, uint8_t _skip, bgfx::TextureInfo* _info)
+{
+ return loadTexture(entry::getFileReader(), _name, _flags, _skip, _info);
+}
+
+void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl, const uint16_t* _indices, uint32_t _numIndices)
+{
+ struct PosTexcoord
+ {
+ float m_x;
+ float m_y;
+ float m_z;
+ float m_pad0;
+ float m_u;
+ float m_v;
+ float m_pad1;
+ float m_pad2;
+ };
+
+ float* tangents = new float[6*_numVertices];
+ memset(tangents, 0, 6*_numVertices*sizeof(float) );
+
+ PosTexcoord v0;
+ PosTexcoord v1;
+ PosTexcoord v2;
+
+ for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii)
+ {
+ const uint16_t* indices = &_indices[ii*3];
+ uint32_t i0 = indices[0];
+ uint32_t i1 = indices[1];
+ uint32_t i2 = indices[2];
+
+ bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _decl, _vertices, i0);
+ bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i0);
+
+ bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _decl, _vertices, i1);
+ bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i1);
+
+ bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _decl, _vertices, i2);
+ bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i2);
+
+ const float bax = v1.m_x - v0.m_x;
+ const float bay = v1.m_y - v0.m_y;
+ const float baz = v1.m_z - v0.m_z;
+ const float bau = v1.m_u - v0.m_u;
+ const float bav = v1.m_v - v0.m_v;
+
+ const float cax = v2.m_x - v0.m_x;
+ const float cay = v2.m_y - v0.m_y;
+ const float caz = v2.m_z - v0.m_z;
+ const float cau = v2.m_u - v0.m_u;
+ const float cav = v2.m_v - v0.m_v;
+
+ const float det = (bau * cav - bav * cau);
+ const float invDet = 1.0f / det;
+
+ const float tx = (bax * cav - cax * bav) * invDet;
+ const float ty = (bay * cav - cay * bav) * invDet;
+ const float tz = (baz * cav - caz * bav) * invDet;
+
+ const float bx = (cax * bau - bax * cau) * invDet;
+ const float by = (cay * bau - bay * cau) * invDet;
+ const float bz = (caz * bau - baz * cau) * invDet;
+
+ for (uint32_t jj = 0; jj < 3; ++jj)
+ {
+ float* tanu = &tangents[indices[jj]*6];
+ float* tanv = &tanu[3];
+ tanu[0] += tx;
+ tanu[1] += ty;
+ tanu[2] += tz;
+
+ tanv[0] += bx;
+ tanv[1] += by;
+ tanv[2] += bz;
+ }
+ }
+
+ for (uint32_t ii = 0; ii < _numVertices; ++ii)
+ {
+ const float* tanu = &tangents[ii*6];
+ const float* tanv = &tangents[ii*6 + 3];
+
+ float normal[4];
+ bgfx::vertexUnpack(normal, bgfx::Attrib::Normal, _decl, _vertices, ii);
+ float ndt = bx::vec3Dot(normal, tanu);
+
+ float nxt[3];
+ bx::vec3Cross(nxt, normal, tanu);
+
+ float tmp[3];
+ tmp[0] = tanu[0] - normal[0] * ndt;
+ tmp[1] = tanu[1] - normal[1] * ndt;
+ tmp[2] = tanu[2] - normal[2] * ndt;
+
+ float tangent[4];
+ bx::vec3Norm(tangent, tmp);
+
+ tangent[3] = bx::vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
+ bgfx::vertexPack(tangent, true, bgfx::Attrib::Tangent, _decl, _vertices, ii);
+ }
+
+ delete [] tangents;
+}
+
+struct Aabb
+{
+ float m_min[3];
+ float m_max[3];
+};
+
+struct Obb
+{
+ float m_mtx[16];
+};
+
+struct Sphere
+{
+ float m_center[3];
+ float m_radius;
+};
+
+struct Primitive
+{
+ uint32_t m_startIndex;
+ uint32_t m_numIndices;
+ uint32_t m_startVertex;
+ uint32_t m_numVertices;
+
+ Sphere m_sphere;
+ Aabb m_aabb;
+ Obb m_obb;
+};
+
+typedef stl::vector<Primitive> PrimitiveArray;
+
+struct Group
+{
+ Group()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ m_vbh.idx = bgfx::invalidHandle;
+ m_ibh.idx = bgfx::invalidHandle;
+ m_prims.clear();
+ }
+
+ bgfx::VertexBufferHandle m_vbh;
+ bgfx::IndexBufferHandle m_ibh;
+ Sphere m_sphere;
+ Aabb m_aabb;
+ Obb m_obb;
+ PrimitiveArray m_prims;
+};
+
+namespace bgfx
+{
+ int32_t read(bx::ReaderI* _reader, bgfx::VertexDecl& _decl);
+}
+
+struct Mesh
+{
+ void load(bx::ReaderSeekerI* _reader)
+ {
+#define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x1)
+#define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0)
+#define BGFX_CHUNK_MAGIC_IBC BX_MAKEFOURCC('I', 'B', 'C', 0x0)
+#define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
+
+ using namespace bx;
+ using namespace bgfx;
+
+ Group group;
+
+ bx::ReallocatorI* allocator = entry::getAllocator();
+
+ uint32_t chunk;
+ while (4 == bx::read(_reader, chunk) )
+ {
+ switch (chunk)
+ {
+ case BGFX_CHUNK_MAGIC_VB:
+ {
+ read(_reader, group.m_sphere);
+ read(_reader, group.m_aabb);
+ read(_reader, group.m_obb);
+
+ read(_reader, m_decl);
+
+ uint16_t stride = m_decl.getStride();
+
+ uint16_t numVertices;
+ read(_reader, numVertices);
+ const bgfx::Memory* mem = bgfx::alloc(numVertices*stride);
+ read(_reader, mem->data, mem->size);
+
+ group.m_vbh = bgfx::createVertexBuffer(mem, m_decl);
+ }
+ break;
+
+ case BGFX_CHUNK_MAGIC_IB:
+ {
+ uint32_t numIndices;
+ read(_reader, numIndices);
+ const bgfx::Memory* mem = bgfx::alloc(numIndices*2);
+ read(_reader, mem->data, mem->size);
+ group.m_ibh = bgfx::createIndexBuffer(mem);
+ }
+ break;
+
+ case BGFX_CHUNK_MAGIC_IBC:
+ {
+ uint32_t numIndices;
+ bx::read(_reader, numIndices);
+
+ const bgfx::Memory* mem = bgfx::alloc(numIndices*2);
+
+ uint32_t compressedSize;
+ bx::read(_reader, compressedSize);
+
+ void* compressedIndices = BX_ALLOC(allocator, compressedSize);
+
+ bx::read(_reader, compressedIndices, compressedSize);
+
+ ReadBitstream rbs( (const uint8_t*)compressedIndices, compressedSize);
+ DecompressIndexBuffer( (uint16_t*)mem->data, numIndices / 3, rbs);
+
+ BX_FREE(allocator, compressedIndices);
+
+ group.m_ibh = bgfx::createIndexBuffer(mem);
+ }
+ break;
+
+ case BGFX_CHUNK_MAGIC_PRI:
+ {
+ uint16_t len;
+ read(_reader, len);
+
+ stl::string material;
+ material.resize(len);
+ read(_reader, const_cast<char*>(material.c_str() ), len);
+
+ uint16_t num;
+ read(_reader, num);
+
+ for (uint32_t ii = 0; ii < num; ++ii)
+ {
+ read(_reader, len);
+
+ stl::string name;
+ name.resize(len);
+ read(_reader, const_cast<char*>(name.c_str() ), len);
+
+ Primitive prim;
+ read(_reader, prim.m_startIndex);
+ read(_reader, prim.m_numIndices);
+ read(_reader, prim.m_startVertex);
+ read(_reader, prim.m_numVertices);
+ read(_reader, prim.m_sphere);
+ read(_reader, prim.m_aabb);
+ read(_reader, prim.m_obb);
+
+ group.m_prims.push_back(prim);
+ }
+
+ m_groups.push_back(group);
+ group.reset();
+ }
+ break;
+
+ default:
+ DBG("%08x at %d", chunk, bx::skip(_reader, 0) );
+ break;
+ }
+ }
+ }
+
+ void unload()
+ {
+ for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
+ {
+ const Group& group = *it;
+ bgfx::destroyVertexBuffer(group.m_vbh);
+
+ if (bgfx::isValid(group.m_ibh) )
+ {
+ bgfx::destroyIndexBuffer(group.m_ibh);
+ }
+ }
+ m_groups.clear();
+ }
+
+ void submit(uint8_t _id, bgfx::ProgramHandle _program, const float* _mtx, uint64_t _state) const
+ {
+ if (BGFX_STATE_MASK == _state)
+ {
+ _state = 0
+ | BGFX_STATE_RGB_WRITE
+ | BGFX_STATE_ALPHA_WRITE
+ | BGFX_STATE_DEPTH_WRITE
+ | BGFX_STATE_DEPTH_TEST_LESS
+ | BGFX_STATE_CULL_CCW
+ | BGFX_STATE_MSAA
+ ;
+ }
+
+ uint32_t cached = bgfx::setTransform(_mtx);
+
+ for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
+ {
+ const Group& group = *it;
+
+ bgfx::setTransform(cached);
+ bgfx::setProgram(_program);
+ bgfx::setIndexBuffer(group.m_ibh);
+ bgfx::setVertexBuffer(group.m_vbh);
+ bgfx::setState(_state);
+ bgfx::submit(_id);
+ }
+ }
+
+ void submit(const MeshState*const* _state, uint8_t _numPasses, const float* _mtx, uint16_t _numMatrices) const
+ {
+ uint32_t cached = bgfx::setTransform(_mtx, _numMatrices);
+
+ for (uint32_t pass = 0; pass < _numPasses; ++pass)
+ {
+ const MeshState& state = *_state[pass];
+
+ for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
+ {
+ const Group& group = *it;
+
+ bgfx::setTransform(cached, _numMatrices);
+ for (uint8_t tex = 0; tex < state.m_numTextures; ++tex)
+ {
+ const MeshState::Texture& texture = state.m_textures[tex];
+ bgfx::setTexture(texture.m_stage
+ , texture.m_sampler
+ , texture.m_texture
+ , texture.m_flags
+ );
+ }
+ bgfx::setProgram(state.m_program);
+ bgfx::setIndexBuffer(group.m_ibh);
+ bgfx::setVertexBuffer(group.m_vbh);
+ bgfx::setState(state.m_state);
+ bgfx::submit(state.m_viewId);
+ }
+ }
+ }
+
+ bgfx::VertexDecl m_decl;
+ typedef stl::vector<Group> GroupArray;
+ GroupArray m_groups;
+};
+
+Mesh* meshLoad(bx::ReaderSeekerI* _reader)
+{
+ Mesh* mesh = new Mesh;
+ mesh->load(_reader);
+ return mesh;
+}
+
+Mesh* meshLoad(const char* _filePath)
+{
+ bx::FileReaderI* reader = entry::getFileReader();
+ bx::open(reader, _filePath);
+ Mesh* mesh = meshLoad(reader);
+ bx::close(reader);
+ return mesh;
+}
+
+void meshUnload(Mesh* _mesh)
+{
+ _mesh->unload();
+ delete _mesh;
+}
+
+MeshState* meshStateCreate()
+{
+ MeshState* state = (MeshState*)BX_ALLOC(entry::getAllocator(), sizeof(MeshState) );
+ return state;
+}
+
+void meshStateDestroy(MeshState* _meshState)
+{
+ BX_FREE(entry::getAllocator(), _meshState);
+}
+
+void meshSubmit(const Mesh* _mesh, uint8_t _id, bgfx::ProgramHandle _program, const float* _mtx, uint64_t _state)
+{
+ _mesh->submit(_id, _program, _mtx, _state);
+}
+
+void meshSubmit(const Mesh* _mesh, const MeshState*const* _state, uint8_t _numPasses, const float* _mtx, uint16_t _numMatrices)
+{
+ _mesh->submit(_state, _numPasses, _mtx, _numMatrices);
+}