init commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
|
||||
set(DV_UTILS_INCLUDE_FILES
|
||||
include/dvu_config.h
|
||||
)
|
||||
source_group("include" FILES ${DV_UTILS_INCLUDE_FILES})
|
||||
|
||||
#################
|
||||
# buffer
|
||||
#################
|
||||
set(DV_UTILS_BUFFER_INCLUDE_FILES
|
||||
include/buffer/dvu_dump_buffer.h
|
||||
)
|
||||
source_group("include/buffer" FILES ${DV_UTILS_BUFFER_INCLUDE_FILES})
|
||||
|
||||
set(DV_UTILS_BUFFER_SOURCE_FILES
|
||||
source/buffer/dvu_dump_buffer.cpp
|
||||
)
|
||||
source_group("source/buffer" FILES ${DV_UTILS_BUFFER_SOURCE_FILES})
|
||||
|
||||
#################
|
||||
# scene
|
||||
#################
|
||||
set(DV_UTILS_SCENE_INCLUDE_FILES
|
||||
include/scene/dvu_load_gltf.h
|
||||
)
|
||||
source_group("include/scene" FILES ${DV_UTILS_SCENE_INCLUDE_FILES})
|
||||
|
||||
set(DV_UTILS_SCENE_SOURCE_FILES
|
||||
source/scene/dvu_load_gltf.cpp
|
||||
)
|
||||
source_group("source/scene" FILES ${DV_UTILS_SCENE_SOURCE_FILES})
|
||||
|
||||
include_directories(
|
||||
${DV_AUTO_INCLUDE_PATH}
|
||||
${DV_CORE_INCLUDE_PATH}
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
add_library(dv_utils SHARED
|
||||
${DV_UTILS_INCLUDE_FILES}
|
||||
${DV_UTILS_SCENE_INCLUDE_FILES}
|
||||
${DV_UTILS_SCENE_SOURCE_FILES}
|
||||
${DV_UTILS_BUFFER_INCLUDE_FILES}
|
||||
${DV_UTILS_BUFFER_SOURCE_FILES}
|
||||
)
|
||||
|
||||
target_link_libraries(dv_utils
|
||||
dv_core
|
||||
tinygltf::tinygltf
|
||||
PNG::png_static
|
||||
)
|
||||
|
||||
target_compile_definitions(dv_utils
|
||||
PRIVATE DV_UTILS_EXPORTS
|
||||
)
|
||||
|
||||
#################
|
||||
# copy runtime dll(for debug)
|
||||
#################
|
||||
add_custom_command(
|
||||
TARGET dv_utils POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:dv_utils> ${CMAKE_BINARY_DIR}/source/console/$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>)
|
||||
|
||||
add_custom_command(
|
||||
TARGET dv_utils POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:dv_utils> ${CMAKE_BINARY_DIR}/test/unit/$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>)
|
||||
|
||||
#################
|
||||
# install
|
||||
#################
|
||||
install(DIRECTORY include/
|
||||
DESTINATION include/utils
|
||||
FILES_MATCHING
|
||||
PATTERN "*.h"
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
install(TARGETS dv_utils
|
||||
RUNTIME DESTINATION bin/$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>
|
||||
ARCHIVE DESTINATION lib/$<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>
|
||||
)
|
||||
else(MSVC)
|
||||
install(TARGETS dv_utils
|
||||
RUNTIME DESTINATION bin
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
endif(MSVC)
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvu_config.h"
|
||||
#include "device/dvc_render_target.h"
|
||||
|
||||
DV_UTILS_BEGIN_NAMESPACE
|
||||
|
||||
bool DV_UTILS_API dump_pixel_buffer(const char* filename, int32_t width, int32_t height,
|
||||
const void* pixelData, davinci::PixelFormat pixelFormat);
|
||||
|
||||
bool DV_UTILS_API dump_render_target(const char* baseFilename, const davinci::RenderTarget& renderTarget);
|
||||
|
||||
DV_UTILS_END_NAMESPACE
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "dv_config.h"
|
||||
|
||||
#ifdef DV_UTILS_EXPORTS
|
||||
#define DV_UTILS_API __declspec(dllexport)
|
||||
#else
|
||||
#define DV_UTILS_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
//utils namespace
|
||||
#define DV_UTILS_BEGIN_NAMESPACE namespace davinci_utils {
|
||||
#define DV_UTILS_END_NAMESPACE }
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvu_config.h"
|
||||
#include "scene/dvc_scene.h"
|
||||
|
||||
DV_UTILS_BEGIN_NAMESPACE
|
||||
|
||||
bool DV_UTILS_API load_scene_from_gltf(const char* szSceneFiles, davinci::Scene& scene);
|
||||
|
||||
bool DV_UTILS_API export_mesh_to_obj(const davinci::Scene& scene);
|
||||
|
||||
DV_UTILS_END_NAMESPACE
|
||||
@@ -0,0 +1,174 @@
|
||||
#include "buffer/dvu_dump_buffer.h"
|
||||
#include "math/dvc_vector3.h"
|
||||
#include "math/dvc_math_util.h"
|
||||
|
||||
#include <png.h>
|
||||
|
||||
DV_UTILS_BEGIN_NAMESPACE
|
||||
|
||||
bool dump_pixel_buffer(const char* filename, int32_t width, int32_t height,
|
||||
const void* pixelData, davinci::PixelFormat pixelFormat)
|
||||
{
|
||||
int32_t bit_depth = 8;
|
||||
|
||||
int32_t color_type;
|
||||
switch (pixelFormat) {
|
||||
case davinci::PF_FLOAT32_RGBA:
|
||||
case davinci::PF_UINT8_RGBA:
|
||||
color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
|
||||
case davinci::PF_FLOAT32_RGB:
|
||||
color_type = PNG_COLOR_TYPE_RGB; break;
|
||||
case davinci::PF_FLOAT32_R:
|
||||
color_type = PNG_COLOR_TYPE_GRAY; break;
|
||||
default:
|
||||
//not support yet!
|
||||
return false;
|
||||
}
|
||||
|
||||
//create png_struct
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
|
||||
if (png_ptr == 0) return false;
|
||||
|
||||
//create png info
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (png_ptr == 0) {
|
||||
png_destroy_write_struct(&png_ptr, 0);
|
||||
return false;
|
||||
}
|
||||
//set default error function
|
||||
setjmp(png_jmpbuf(png_ptr));
|
||||
|
||||
FILE* fp = fopen(filename, "wb");
|
||||
if (fp == 0) {
|
||||
png_destroy_write_struct(&png_ptr, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
//init write io
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
//write png head info
|
||||
png_set_IHDR(png_ptr, info_ptr, (png_uint_32)width, (png_uint_32)height,
|
||||
bit_depth, color_type, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
//integer pixelformat
|
||||
if (davinci::PF_UINT8_RGBA == pixelFormat) {
|
||||
for (int32_t y = 0; y < height; y++) {
|
||||
const uint32_t* p = (const uint32_t*)pixelData + (height - 1 - y) * width;
|
||||
png_write_rows(png_ptr, (png_bytepp)&p, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//write rows
|
||||
png_size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
png_byte* row = (png_byte*)malloc(row_bytes);
|
||||
|
||||
switch (color_type) {
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
{
|
||||
for (int32_t y = 0; y < height; y++) {
|
||||
const davinci::fVector3* p = (const davinci::fVector3*)pixelData + (height - 1 - y) * width;
|
||||
for (int32_t x = 0; x < width; x++) {
|
||||
row[x * 3 + 0] = (uint8_t)(p->x * 255);
|
||||
row[x * 3 + 1] = (uint8_t)(p->y * 255);
|
||||
row[x * 3 + 2] = (uint8_t)(p->z * 255);
|
||||
|
||||
p++;
|
||||
}
|
||||
png_write_rows(png_ptr, &row, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
{
|
||||
for (int32_t y = 0; y < height; y++) {
|
||||
const davinci::fVector4* p = (const davinci::fVector4*)pixelData + (height - 1 - y) * width;
|
||||
for (int32_t x = 0; x < width; x++) {
|
||||
row[x * 4 + 0] = (uint8_t)(p->x * 255);
|
||||
row[x * 4 + 1] = (uint8_t)(p->y * 255);
|
||||
row[x * 4 + 2] = (uint8_t)(p->z * 255);
|
||||
row[x * 4 + 3] = (uint8_t)(p->w * 255);
|
||||
|
||||
p++;
|
||||
}
|
||||
png_write_rows(png_ptr, &row, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
{
|
||||
for (int32_t y = 0; y < height; y++) {
|
||||
const float* p = (const float*)pixelData + (height - 1 - y) * width;
|
||||
for (int32_t x = 0; x < width; x++) {
|
||||
row[x] = (uint8_t)((*p) * 255);
|
||||
p++;
|
||||
}
|
||||
png_write_rows(png_ptr, &row, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(row);
|
||||
}
|
||||
png_write_end(png_ptr, NULL);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dump_render_target(const char* baseFilename, const davinci::RenderTarget& renderTarget)
|
||||
{
|
||||
char szFileName[256] = { 0 };
|
||||
_snprintf(szFileName, 256, "%s_color.png", baseFilename);
|
||||
|
||||
//save rgba
|
||||
dump_pixel_buffer(szFileName,
|
||||
renderTarget.getWidth(), renderTarget.getHeight(),
|
||||
renderTarget.getColorBuffer().ptr(), davinci::PF_FLOAT32_RGBA
|
||||
);
|
||||
|
||||
//save depth
|
||||
float32_t depth_min = std::numeric_limits<float32_t>::max();
|
||||
float32_t depth_max = -std::numeric_limits<float32_t>::max();
|
||||
|
||||
std::vector<float> depth_data((size_t)(renderTarget.getWidth() * renderTarget.getHeight()));
|
||||
const float* p = renderTarget.getDepthBuffer().ptr();
|
||||
|
||||
for (size_t i = 0; i < (size_t)(renderTarget.getWidth() * renderTarget.getHeight()); i++)
|
||||
{
|
||||
depth_data[i] = davinci::MathUtil::saturate(*p++);
|
||||
// depth_data[i] = *p++;
|
||||
if (depth_data[i] > depth_max)
|
||||
{
|
||||
depth_max = depth_data[i];
|
||||
}
|
||||
if (depth_data[i] < depth_min)
|
||||
{
|
||||
depth_min = depth_data[i];
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (depth_max - depth_min > 0.001)
|
||||
{
|
||||
for (size_t i = 0; i < (size_t)(renderTarget.getWidth() * renderTarget.getHeight()); i++)
|
||||
{
|
||||
//depth_data[i] = davinci::MathUtil::saturate(*p++);
|
||||
depth_data[i] = (depth_data[i] - depth_min) / (depth_max - depth_min) + depth_min;
|
||||
}
|
||||
}
|
||||
*/
|
||||
_snprintf(szFileName, 256, "%s_depth.png", baseFilename);
|
||||
dump_pixel_buffer(szFileName,
|
||||
renderTarget.getWidth(), renderTarget.getHeight(),
|
||||
&(depth_data[0]), davinci::PF_FLOAT32_R
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DV_UTILS_END_NAMESPACE
|
||||
@@ -0,0 +1,665 @@
|
||||
#include "scene/dvu_load_gltf.h"
|
||||
#include "scene/dvc_scene.h"
|
||||
#include "scene/dvc_scene_node.h"
|
||||
#include "scene/component/dvc_mesh_component.h"
|
||||
#include "scene/component/dvc_camera_component.h"
|
||||
#include "scene/component/dvc_light_component.h"
|
||||
#include "device/dvc_buffer_accessor.h"
|
||||
#include "asset/dvc_mesh.h"
|
||||
#include "math/dvc_vector3.h"
|
||||
#include "math/dvc_vector4.h"
|
||||
|
||||
#include <tiny_gltf.h>
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
DV_UTILS_BEGIN_NAMESPACE
|
||||
|
||||
//from TINYGLTF_COMPONENT_TYPE_*** to CT_***
|
||||
davinci::ComponentType _getComponentTypeFromGltf(int gltfComponentType)
|
||||
{
|
||||
switch (gltfComponentType)
|
||||
{
|
||||
case TINYGLTF_COMPONENT_TYPE_BYTE:
|
||||
return davinci::CT_Int8;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
|
||||
return davinci::CT_Uint8;
|
||||
case TINYGLTF_COMPONENT_TYPE_SHORT:
|
||||
return davinci::CT_Int16;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
|
||||
return davinci::CT_Uint16;
|
||||
case TINYGLTF_COMPONENT_TYPE_INT:
|
||||
return davinci::CT_Int32;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
|
||||
return davinci::CT_Uint32;
|
||||
case TINYGLTF_COMPONENT_TYPE_FLOAT:
|
||||
return davinci::CT_Float32;
|
||||
case TINYGLTF_COMPONENT_TYPE_DOUBLE:
|
||||
return davinci::CT_Float64;
|
||||
default:
|
||||
return davinci::CT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
//from TINYGLTF_TYPE_*** to DT_***
|
||||
davinci::DataType _getDataTypeFromGltf(int gltfDataType)
|
||||
{
|
||||
switch (gltfDataType)
|
||||
{
|
||||
case TINYGLTF_TYPE_SCALAR:
|
||||
return davinci::DT_Scalar;
|
||||
case TINYGLTF_TYPE_VEC2:
|
||||
return davinci::DT_Vec2;
|
||||
case TINYGLTF_TYPE_VEC3:
|
||||
return davinci::DT_Vec3;
|
||||
case TINYGLTF_TYPE_VEC4:
|
||||
return davinci::DT_Vec4;
|
||||
case TINYGLTF_TYPE_MAT2:
|
||||
return davinci::DT_Matrix2;
|
||||
case TINYGLTF_TYPE_MAT3:
|
||||
return davinci::DT_Matrix3;
|
||||
case TINYGLTF_TYPE_MAT4:
|
||||
return davinci::DT_Matrix4;
|
||||
default:
|
||||
return davinci::DT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
//from TINYGLTF_MODE_*** to PT_***
|
||||
davinci::PrimitiveType _getPrimitiveTypeFromGltf(int gltfModelType)
|
||||
{
|
||||
switch (gltfModelType)
|
||||
{
|
||||
case TINYGLTF_MODE_POINTS:
|
||||
return davinci::PT_POINT_LIST;
|
||||
case TINYGLTF_MODE_LINE:
|
||||
return davinci::PT_LINE_LIST;
|
||||
case TINYGLTF_MODE_LINE_LOOP:
|
||||
return davinci::PT_LINE_LOOP;
|
||||
case TINYGLTF_MODE_LINE_STRIP:
|
||||
return davinci::PT_LINE_STRIP;
|
||||
case TINYGLTF_MODE_TRIANGLES:
|
||||
return davinci::PT_TRIANGLE_LIST;
|
||||
case TINYGLTF_MODE_TRIANGLE_STRIP:
|
||||
return davinci::PT_TRIANGLE_STRIP;
|
||||
case TINYGLTF_MODE_TRIANGLE_FAN:
|
||||
return davinci::PT_TRIANGLE_FAN;
|
||||
default:
|
||||
return davinci::PT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
//from "POSITION/NORMAL/..." to VET_***
|
||||
davinci::VertexElementType _getElementTypeFromGltf(const std::string& gltfElementType)
|
||||
{
|
||||
#define IS_MATCH_RANGE_TYPE(Prefix, PrefixLength, FirstValue, LastValue) \
|
||||
else if (gltfElementType.length() == PrefixLength + 1 && gltfElementType.rfind(Prefix, 0) == 0) \
|
||||
{ \
|
||||
int32_t index = gltfElementType[PrefixLength] - '0'; \
|
||||
if (index<0 || index>(LastValue - FirstValue)) \
|
||||
{ \
|
||||
return davinci::VET_UNKNOWN; \
|
||||
} \
|
||||
return static_cast<davinci::VertexElementType>(static_cast<int32_t>(FirstValue) + index); \
|
||||
}
|
||||
|
||||
if (gltfElementType == "POSITION")
|
||||
{
|
||||
return davinci::VET_POSITION;
|
||||
}
|
||||
else if(gltfElementType == "NORMAL")
|
||||
{
|
||||
return davinci::VET_NORMAL;
|
||||
}
|
||||
else if (gltfElementType == "TANGENT")
|
||||
{
|
||||
return davinci::VET_TANGENT;
|
||||
}
|
||||
else if (gltfElementType == "BINORMAL")
|
||||
{
|
||||
return davinci::VET_BINORMAL;
|
||||
}
|
||||
IS_MATCH_RANGE_TYPE("COLOR_", 6, davinci::VET_COLOR_0, davinci::VET_COLOR_LAST)
|
||||
IS_MATCH_RANGE_TYPE("TEXCOORD_", 9, davinci::VET_TEXCOORD_0, davinci::VET_TEXCOORD_LAST)
|
||||
IS_MATCH_RANGE_TYPE("JOINTS_", 7, davinci::VET_JOINTS_0, davinci::VET_JOINTS_LAST)
|
||||
IS_MATCH_RANGE_TYPE("WEIGHTS_", 8, davinci::VET_WEIGHTS_0, davinci::VET_WEIGHTS_LAST)
|
||||
|
||||
return davinci::VET_UNKNOWN;
|
||||
}
|
||||
|
||||
bool _loadDeviceBuffer(const tinygltf::Model& gltfModel, davinci::Scene& scene)
|
||||
{
|
||||
for (size_t i = 0; i < gltfModel.buffers.size(); i++)
|
||||
{
|
||||
const tinygltf::Buffer& gltfBuffer = gltfModel.buffers[i];
|
||||
|
||||
davinci::DeviceBufferPtr deviceBufferPtr = scene.newDeviceBuffer();
|
||||
deviceBufferPtr->init(gltfBuffer.data.size());
|
||||
|
||||
//fill data
|
||||
memcpy(deviceBufferPtr->ptr(0), gltfBuffer.data.data(), gltfBuffer.data.size());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _loadBufferView(const tinygltf::Model& gltfModel, davinci::Scene& scene)
|
||||
{
|
||||
for (size_t i = 0; i < gltfModel.bufferViews.size(); i++)
|
||||
{
|
||||
const tinygltf::BufferView& gltfBufferView = gltfModel.bufferViews[i];
|
||||
int32_t bufferIndex = gltfBufferView.buffer;
|
||||
davinci::DeviceBufferConstPtr deviceBufferPtr = scene.getDeviceBuffer(bufferIndex);
|
||||
if (deviceBufferPtr == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
davinci::DeviceBufferViewPtr bufferViewPtr = scene.newDeviceBufferView(
|
||||
deviceBufferPtr, gltfBufferView.byteOffset, gltfBufferView.byteLength, gltfBufferView.byteStride);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _loadBufferAccessor(const tinygltf::Model& gltfModel, davinci::Scene& scene)
|
||||
{
|
||||
for (size_t i = 0; i < gltfModel.accessors.size(); i++)
|
||||
{
|
||||
const tinygltf::Accessor& gltfAccessor = gltfModel.accessors[i];
|
||||
|
||||
int32_t bufferViewIndex = gltfAccessor.bufferView;
|
||||
davinci::DeviceBufferViewPtr deviceBufferView = scene.getDeviceBufferView(bufferViewIndex);
|
||||
if (deviceBufferView==nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
davinci::ComponentType componentType = _getComponentTypeFromGltf(gltfAccessor.componentType);
|
||||
if (componentType == davinci::CT_UNKNOWN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
davinci::DataType dataType = _getDataTypeFromGltf(gltfAccessor.type);
|
||||
if (dataType == davinci::DT_UNKNOWN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
davinci::DeviceBufferAccessorPtr bufferAccessor = scene.newDeviceBufferAccessor(
|
||||
deviceBufferView, gltfAccessor.byteOffset, gltfAccessor.count, componentType, dataType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _loadMesh(const tinygltf::Model& gltfModel, davinci::Scene& scene)
|
||||
{
|
||||
for (size_t i=0; i<gltfModel.meshes.size(); i++)
|
||||
{
|
||||
const tinygltf::Mesh& gltfMesh = gltfModel.meshes[i];
|
||||
|
||||
davinci::MeshPtr mesh = std::make_shared<davinci::Mesh>(gltfMesh.name);
|
||||
|
||||
for (size_t j=0; j<gltfMesh.primitives.size(); j++)
|
||||
{
|
||||
const tinygltf::Primitive& gltfPrimitive = gltfMesh.primitives[j];
|
||||
|
||||
davinci::Mesh::PrimitivePtr primitive = mesh->newPrimitive();
|
||||
primitive->type = _getPrimitiveTypeFromGltf(gltfPrimitive.mode);
|
||||
|
||||
std::map<std::string, int>::const_iterator it(gltfPrimitive.attributes.begin());
|
||||
std::map<std::string, int>::const_iterator itEnd(gltfPrimitive.attributes.end());
|
||||
for (; it != itEnd; it++)
|
||||
{
|
||||
davinci::VertexElementType vetype = _getElementTypeFromGltf(it->first);
|
||||
|
||||
int32_t gltfAccessor = it->second;
|
||||
davinci::DeviceBufferAccessorPtr deviceBufferAccessor = scene.getDeviceBufferAccessor(gltfAccessor);
|
||||
if (deviceBufferAccessor ==nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
primitive->attributes.insert(std::make_pair(vetype, deviceBufferAccessor));
|
||||
}
|
||||
|
||||
davinci::DeviceBufferAccessorPtr indicesBufferAccessor = scene.getDeviceBufferAccessor(gltfPrimitive.indices);
|
||||
if (indicesBufferAccessor == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
primitive->indices = indicesBufferAccessor;
|
||||
}
|
||||
|
||||
scene.pushNewMeshAsset(mesh);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _loadLightExternsion(const tinygltf::Model& gltfModel, std::vector<davinci::LightComponent::LightDefine>& lightDefineArray)
|
||||
{
|
||||
lightDefineArray.clear();
|
||||
|
||||
//read lights define from externsions
|
||||
tinygltf::Value lightsArray;
|
||||
auto lightExternsions = gltfModel.extensions.find("KHR_lights_punctual");
|
||||
if (lightExternsions == gltfModel.extensions.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
lightsArray = lightExternsions->second.Get("lights");
|
||||
if (!lightsArray.IsArray())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t lightCounts = lightsArray.ArrayLen();
|
||||
for (size_t i = 0; i < lightCounts; i++)
|
||||
{
|
||||
auto lightObj = lightsArray.Get(i);
|
||||
|
||||
davinci::LightComponent::LightDefine lightDefine;
|
||||
|
||||
auto lightType = lightObj.Get("type");
|
||||
if (!lightType.IsString()) {
|
||||
lightDefineArray.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string lightTypeString = lightType.Get<std::string>();
|
||||
if (lightTypeString == "point") {
|
||||
lightDefine.type = davinci::LightComponent::LT_Point;
|
||||
}
|
||||
else if (lightTypeString == "directional") {
|
||||
lightDefine.type = davinci::LightComponent::LT_Directional;
|
||||
}
|
||||
else if (lightTypeString == "spot") {
|
||||
lightDefine.type = davinci::LightComponent::LT_Spot;
|
||||
}
|
||||
else {
|
||||
//unknown type?
|
||||
lightDefineArray.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: read other defines...
|
||||
lightDefine.color = davinci::fVector3(1.0, 1.0, 1.0);
|
||||
lightDefine.intensity = 1.0f;
|
||||
lightDefine.range = -1.0f;
|
||||
|
||||
lightDefineArray.push_back(lightDefine);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool _loadSceneNodes(const tinygltf::Model& gltfModel, davinci::Scene& scene, const std::vector<davinci::LightComponent::LightDefine>& lightsArray)
|
||||
{
|
||||
std::vector<std::pair<bool, davinci::SceneNodePtr>> sceneNodeArray;
|
||||
|
||||
//read scene nodes
|
||||
for (size_t i = 0; i < gltfModel.nodes.size(); i++)
|
||||
{
|
||||
const tinygltf::Node& gltfNode = gltfModel.nodes[i];
|
||||
|
||||
davinci::SceneNodePtr sceneNode = scene.newSceneNode(gltfNode.name);
|
||||
davinci::fMatrix4 transform = davinci::fMatrix4::IDENTITY;
|
||||
|
||||
if (!gltfNode.scale.empty())
|
||||
{
|
||||
transform =
|
||||
davinci::fMatrix4::makeScale(gltfNode.scale[0], gltfNode.scale[1], gltfNode.scale[2]) * transform;
|
||||
}
|
||||
if (!gltfNode.rotation.empty())
|
||||
{
|
||||
davinci::fVector4 quaternion(gltfNode.rotation[0], gltfNode.rotation[1], gltfNode.rotation[2], gltfNode.rotation[3]);
|
||||
transform = davinci::fMatrix4::makeRotate(quaternion) * transform;
|
||||
}
|
||||
if (!gltfNode.translation.empty())
|
||||
{
|
||||
transform = davinci::fMatrix4::makeTrans(gltfNode.translation[0], gltfNode.translation[1], gltfNode.translation[2]) * transform;
|
||||
}
|
||||
sceneNode->setTransform(transform);
|
||||
|
||||
//add mesh component
|
||||
if (gltfNode.mesh != -1)
|
||||
{
|
||||
davinci::MeshConstPtr meshPtr = scene.getMesh(gltfNode.mesh);
|
||||
if (meshPtr)
|
||||
{
|
||||
davinci::MeshComponentPtr meshComponet = std::make_shared<davinci::MeshComponent>(sceneNode);
|
||||
|
||||
meshComponet->setMesh(meshPtr);
|
||||
|
||||
sceneNode->addComponent(std::dynamic_pointer_cast<davinci::SceneComponent>(meshComponet));
|
||||
}
|
||||
}
|
||||
//add camera component
|
||||
if (gltfNode.camera != -1)
|
||||
{
|
||||
const tinygltf::Camera& gltfCamera = gltfModel.cameras[gltfNode.camera];
|
||||
if (gltfCamera.type == "perspective")
|
||||
{
|
||||
davinci::CameraComponentPtr cameraComponent = std::make_shared<davinci::CameraComponent>(sceneNode);
|
||||
|
||||
davinci::CameraComponent::CameraDefine cameraDefine;
|
||||
cameraDefine.aspect = gltfCamera.perspective.aspectRatio;
|
||||
cameraDefine.fov = gltfCamera.perspective.yfov;
|
||||
cameraDefine.nearClip = gltfCamera.perspective.znear;
|
||||
cameraDefine.farClip = gltfCamera.perspective.zfar;
|
||||
cameraComponent->setCameraDefine(cameraDefine);
|
||||
|
||||
sceneNode->addComponent(std::dynamic_pointer_cast<davinci::SceneComponent>(cameraComponent));
|
||||
}
|
||||
}
|
||||
|
||||
//add light component(KHR_lights_punctual)
|
||||
do
|
||||
{
|
||||
auto node_light_it = gltfNode.extensions.find("KHR_lights_punctual");
|
||||
if (node_light_it == gltfNode.extensions.end()) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto lightValue = node_light_it->second.Get("light");
|
||||
if (!lightValue.IsNumber()) {
|
||||
break;
|
||||
}
|
||||
|
||||
int32_t lightIndex = lightValue.GetNumberAsInt();
|
||||
if (lightIndex < 0 || lightIndex >= lightsArray.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
davinci::LightComponentPtr lightComponent = std::make_shared<davinci::LightComponent>(sceneNode);
|
||||
lightComponent->setLightDefine(lightsArray[lightIndex]);
|
||||
sceneNode->addComponent(std::dynamic_pointer_cast<davinci::SceneComponent>(lightComponent));
|
||||
|
||||
} while (false);
|
||||
|
||||
sceneNodeArray.push_back(std::make_pair(true, sceneNode));
|
||||
}
|
||||
|
||||
assert(sceneNodeArray.size() == gltfModel.nodes.size());
|
||||
|
||||
for (size_t i = 0; i < gltfModel.nodes.size(); i++)
|
||||
{
|
||||
const tinygltf::Node& gltfNode = gltfModel.nodes[i];
|
||||
if (gltfNode.children.empty()) continue;
|
||||
|
||||
//attach children nodes
|
||||
for (size_t j = 0; j < gltfNode.children.size(); j++)
|
||||
{
|
||||
int32_t childrenIndex = gltfNode.children[j];
|
||||
if (childrenIndex < 0 || childrenIndex >= gltfModel.nodes.size())
|
||||
{
|
||||
//error!
|
||||
continue;
|
||||
}
|
||||
if (!(sceneNodeArray[childrenIndex].first)) //already attached?
|
||||
{
|
||||
//error!
|
||||
continue;
|
||||
}
|
||||
sceneNodeArray[childrenIndex].first = false;
|
||||
sceneNodeArray[i].second->addChild(sceneNodeArray[childrenIndex].second);
|
||||
}
|
||||
}
|
||||
|
||||
//add root node
|
||||
for (size_t i = 0; i < gltfModel.scenes.size(); i++)
|
||||
{
|
||||
const tinygltf::Scene& gltfScene = gltfModel.scenes[i];
|
||||
for (size_t j = 0; j < gltfScene.nodes.size(); j++)
|
||||
{
|
||||
int sceneNodeIndex = gltfScene.nodes[j];
|
||||
if(sceneNodeIndex<0 || sceneNodeIndex>= gltfModel.nodes.size())
|
||||
{
|
||||
//error!
|
||||
continue;
|
||||
}
|
||||
if (!(sceneNodeArray[sceneNodeIndex].first)) //already attached?
|
||||
{
|
||||
//error!
|
||||
continue;
|
||||
}
|
||||
scene.getRootSceneNode()->addChild(sceneNodeArray[sceneNodeIndex].second);
|
||||
}
|
||||
}
|
||||
|
||||
//clear temp scene node
|
||||
sceneNodeArray.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_scene_from_gltf(const char* szSceneFiles, davinci::Scene& scene)
|
||||
{
|
||||
std::filesystem::path sceneFilePath = std::filesystem::path(szSceneFiles);
|
||||
|
||||
//is file exist?
|
||||
if (!std::filesystem::exists(std::string(szSceneFiles)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tinygltf::Model gltfModel;
|
||||
tinygltf::TinyGLTF gltf_ctx;
|
||||
std::string err;
|
||||
std::string warn;
|
||||
bool ret = false;
|
||||
|
||||
//get file ext
|
||||
std::filesystem::path ext = sceneFilePath.extension();
|
||||
|
||||
scene.init();
|
||||
|
||||
//--------------------------
|
||||
//load gltf
|
||||
if (ext == ".glb")
|
||||
{
|
||||
//binary file
|
||||
ret = gltf_ctx.LoadBinaryFromFile(&gltfModel, &err, &warn, szSceneFiles);
|
||||
}
|
||||
else
|
||||
{
|
||||
//text file
|
||||
ret = gltf_ctx.LoadASCIIFromFile(&gltfModel, &err, &warn, szSceneFiles);
|
||||
}
|
||||
|
||||
//error
|
||||
if (!ret)
|
||||
{
|
||||
//TODO: log something
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------
|
||||
//dump to davinci scene
|
||||
|
||||
//load device buffer
|
||||
if (!_loadDeviceBuffer(gltfModel, scene))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//load buffer view
|
||||
if (!_loadBufferView(gltfModel, scene))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//load buffer accessor
|
||||
if (!_loadBufferAccessor(gltfModel, scene))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//load mesh
|
||||
if (!_loadMesh(gltfModel, scene))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//load light externsion
|
||||
std::vector<davinci::LightComponent::LightDefine> lightDefine;
|
||||
if (!_loadLightExternsion(gltfModel, lightDefine))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//load scene nodes
|
||||
if (!_loadSceneNodes(gltfModel, scene, lightDefine))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool export_mesh_to_obj(const davinci::Scene& scene)
|
||||
{
|
||||
|
||||
int32_t meshCounts = scene.getMeshCounts();
|
||||
for (int32_t meshIndex = 0; meshIndex < meshCounts; meshIndex++)
|
||||
{
|
||||
davinci::MeshConstPtr mesh = scene.getMesh(meshIndex);
|
||||
|
||||
const std::string& meshName = mesh->getName();
|
||||
if (meshName.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char szTemp[32] = { 0 };
|
||||
_snprintf(szTemp, 32, "d:\\%s.obj", meshName.c_str());
|
||||
|
||||
FILE* fp = fopen(szTemp, "w");
|
||||
fprintf(fp, "o %s\n", meshName.c_str());
|
||||
|
||||
int32_t primitiveCounts = mesh->getPrimitiveCounts();
|
||||
for (int32_t primitiveIndex = 0; primitiveIndex < primitiveCounts; primitiveIndex++)
|
||||
{
|
||||
davinci::Mesh::PrimitiveConstPtr primitive = mesh->getPrimitive(primitiveIndex);
|
||||
|
||||
//Output "POSITION"
|
||||
davinci::Mesh::PrimitiveAttributes::const_iterator posAttribute = primitive->attributes.find(davinci::VET_POSITION);
|
||||
if (posAttribute != primitive->attributes.end())
|
||||
{
|
||||
davinci::DeviceBufferAccessorConstPtr posBuffer = posAttribute->second;
|
||||
posBuffer->walk([=](const uint8_t* ptr, size_t index) {
|
||||
const float32_t* pPos = (const float32_t*)ptr;
|
||||
|
||||
fprintf(fp, "v %f %f %f\n", pPos[0], pPos[1], pPos[2]);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
//Output "NORMAL"
|
||||
davinci::Mesh::PrimitiveAttributes::const_iterator normalAttribute = primitive->attributes.find(davinci::VET_NORMAL);
|
||||
bool bHasNormal = (normalAttribute != primitive->attributes.end());
|
||||
if (bHasNormal)
|
||||
{
|
||||
davinci::DeviceBufferAccessorConstPtr normalBuffer = normalAttribute->second;
|
||||
normalBuffer->walk([=](const uint8_t* ptr, size_t index) {
|
||||
const float32_t* pNormal = (const float32_t*)ptr;
|
||||
|
||||
fprintf(fp, "vn %f %f %f\n", pNormal[0], pNormal[1], pNormal[2]);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
//Output "TEXCOORD_0"
|
||||
davinci::Mesh::PrimitiveAttributes::const_iterator tex0Attribute = primitive->attributes.find(davinci::VET_TEXCOORD_0);
|
||||
bool bHasTex0 = (tex0Attribute != primitive->attributes.end());
|
||||
if (bHasTex0)
|
||||
{
|
||||
davinci::DeviceBufferAccessorConstPtr tex0Buffer = tex0Attribute->second;
|
||||
tex0Buffer->walk([=](const uint8_t* ptr, size_t index) {
|
||||
const float32_t* pTex0 = (const float32_t*)ptr;
|
||||
|
||||
fprintf(fp, "vt %f %f\n", pTex0[0], pTex0[1]);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
//fprintf(fp, "TYPE:%d\n", primitive->type);
|
||||
|
||||
davinci::DeviceBufferAccessorConstPtr indexBufferAccessor = primitive->indices;
|
||||
indexBufferAccessor->walk3([=](const uint8_t* ptr0, const uint8_t* ptr1, const uint8_t* ptr2, size_t index) {
|
||||
|
||||
uint32_t indice0, indice1, indice2;
|
||||
if (indexBufferAccessor->getComponentType() == davinci::CT_Uint16)
|
||||
{
|
||||
indice0 = *((uint16_t*)ptr0) + 1;
|
||||
indice1 = *((uint16_t*)ptr1) + 1;
|
||||
indice2 = *((uint16_t*)ptr2) + 1;
|
||||
}
|
||||
else if (indexBufferAccessor->getComponentType() == davinci::CT_Uint32)
|
||||
{
|
||||
indice0 = *((uint32_t*)ptr0) + 1;
|
||||
indice1 = *((uint32_t*)ptr1) + 1;
|
||||
indice2 = *((uint32_t*)ptr2) + 1;
|
||||
}
|
||||
else if (indexBufferAccessor->getComponentType() == davinci::CT_Uint8)
|
||||
{
|
||||
indice0 = *((uint8_t*)ptr0) + 1;
|
||||
indice1 = *((uint8_t*)ptr1) + 1;
|
||||
indice2 = *((uint8_t*)ptr2) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//error
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bHasTex0)
|
||||
{
|
||||
if (bHasNormal)
|
||||
{
|
||||
fprintf(fp, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
|
||||
indice0, indice0, indice0,
|
||||
indice1, indice1, indice1,
|
||||
indice2, indice2, indice2
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fp, "f %d/%d %d/%d %d/%d\n",
|
||||
indice0, indice0,
|
||||
indice1, indice1,
|
||||
indice2, indice2
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bHasNormal)
|
||||
{
|
||||
fprintf(fp, "f %d//%d %d//%d %d//%d\n",
|
||||
indice0, indice0,
|
||||
indice1, indice1,
|
||||
indice2, indice2
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fp, "f %d %d %d\n",
|
||||
indice0,
|
||||
indice1,
|
||||
indice2
|
||||
);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DV_UTILS_END_NAMESPACE
|
||||
Reference in New Issue
Block a user