Commit for 2022.01.05 23-01-04.7z

This commit is contained in:
mrq 2022-01-05 23:01:00 -06:00
parent c3d320ce1a
commit 112a061dc8
41 changed files with 585 additions and 650 deletions

View File

@ -3,7 +3,7 @@ CC = $(shell cat "./bin/exe/default.config")
TARGET_NAME = program
TARGET_EXTENSION = exe
TARGET_LIB_EXTENSION = dll
RENDERER = opengl
RENDERER = vulkan
include makefiles/$(ARCH).$(CC).make
@ -33,9 +33,9 @@ EXT_LIB_NAME += ext
#VULKAN_SDK_PATH += /c/VulkanSDK/1.2.182.0/
VULKAN_SDK_PATH += /c/VulkanSDK/1.2.198.1/
#GLSL_VALIDATOR += $(VULKAN_SDK_PATH)/Bin32/glslangValidator
GLSL_VALIDATOR += $(VULKAN_SDK_PATH)/Bin32/glslc
SPV_OPTIMIZER += $(VULKAN_SDK_PATH)/Bin32/spirv-opt
#GLSL_VALIDATOR += $(VULKAN_SDK_PATH)/Bin/glslangValidator
GLSL_VALIDATOR += $(VULKAN_SDK_PATH)/Bin/glslc
SPV_OPTIMIZER += $(VULKAN_SDK_PATH)/Bin/spirv-opt
# Base Engine's DLL
INC_DIR += $(ENGINE_INC_DIR)/$(ARCH)/$(CC)
LIB_DIR += $(ENGINE_LIB_DIR)/$(ARCH)
@ -51,7 +51,7 @@ ifneq (,$(findstring win64,$(ARCH)))
FLAGS +=
DEPS += -lgdi32
else ifneq (,$(findstring dreamcast,$(ARCH)))
REQ_DEPS += opengl gldc json:nlohmann lua reactphysics freetype png zlib ctti ogg openal aldc # bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord
REQ_DEPS += simd opengl gldc json:nlohmann lua reactphysics freetype png zlib ctti ogg openal aldc # bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord
endif
ifneq (,$(findstring vulkan,$(REQ_DEPS)))
FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN
@ -60,7 +60,8 @@ ifneq (,$(findstring vulkan,$(REQ_DEPS)))
LIBS += -L$(VULKAN_SDK_PATH)/Lib
endif
ifneq (,$(findstring opengl,$(REQ_DEPS)))
FLAGS += -DUF_USE_OPENGL -DUF_USE_GLEW -DUF_USE_OPENGL_FIXED_FUNCTION
FLAGS += -DUF_USE_OPENGL -DUF_USE_OPENGL_FIXED_FUNCTION
ifneq (,$(findstring dreamcast,$(ARCH)))
ifneq (,$(findstring gldc,$(REQ_DEPS)))
DEPS += -lGLdc
@ -69,7 +70,13 @@ ifneq (,$(findstring opengl,$(REQ_DEPS)))
DEPS += -lGL
endif
else
DEPS += -lglew32 -lopengl32 -lglu32
ifneq (,$(findstring gldc,$(REQ_DEPS)))
DEPS += -lGLdc -lSDL2
FLAGS += -DUF_USE_OPENGL_GLDC
else
FLAGS += -DUF_USE_GLEW
DEPS += -lglew32 -lopengl32 -lglu32
endif
endif
endif
@ -159,8 +166,11 @@ ifneq (,$(findstring reactphysics,$(REQ_DEPS)))
DEPS += -lreactphysics3d
endif
ifneq (,$(findstring simd,$(REQ_DEPS)))
FLAGS += -DUF_USE_SIMD -DUF_MATRIX_ALIGNED #-DUF_VECTOR_ALIGNED #-march=native
ifneq (,$(findstring dreamcast,$(ARCH)))
FLAGS += -DUF_ENV_DREAMCAST_SIMD
else
FLAGS += -DUF_USE_SIMD -DUF_ALIGN_FOR_SIMD -DUF_MATRIX_ALIGNED #-DUF_VECTOR_ALIGNED #-march=native
endif
endif
ifneq (,$(findstring meshoptimizer,$(REQ_DEPS)))
FLAGS += -DUF_USE_MESHOPTIMIZER

View File

@ -2,7 +2,7 @@
"engine": {
"scenes": {
"start": "SS2",
"meshes": { "interleave": false },
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": true },
"lights": {
"max": 24,

View File

@ -26,7 +26,7 @@
"unwrap": true
},
"baking": {
"enabled": false,
"enabled": true,
"resolution": 8192,
"shadows": 1024,
"trigger": { "mode": "rendered" },

View File

@ -2,6 +2,7 @@
"import": "/model.json",
"assets": [
// { "filename": "./models/tiny_msci.glb", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/tiny_msci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
{ "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" }
@ -28,6 +29,7 @@
},
"tags": {
"worldspawn": { "physics": { "type": "mesh", "static": true } },
"worldspawn_20": { "physics": { "type": "mesh", "static": true } },
// "worldspawn": { "physics": { "type": "bounding boxes", "static": true } },
"info_player_spawn": {
"action": "attach",

View File

@ -3,8 +3,8 @@ layout (constant_id = 0) const uint PASSES = 6;
#include "../common/structs.h"
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec4 inColor;
layout (location = 2) in vec2 inUv;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec4 inColor;
layout (location = 3) in vec2 inSt;
layout (location = 4) in vec3 inNormal;
layout (location = 5) in vec4 inTangent;

View File

@ -2,7 +2,7 @@
"engine": {
"scenes": {
"start": "SS2",
"meshes": { "interleave": false },
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": false },
"lights": {
"max": 8,
@ -63,18 +63,12 @@
"json": "/json.lua"
}
},
"bullet": {
"iterations": 1,
"substeps": 6,
"timescale": 1,
"multithreaded": false,
"pool size": {
"max collision algorithm": 64,
"max persistent manifold": 64
},
"reactphysics": {
"timescale": 0.03333333333,
"debug draw": {
"enabled": false,
"rate": 1.0
// "layer": "Gui",
"rate": 0.0125
}
}
},

View File

@ -109,6 +109,12 @@
#define alignas(X)
#endif
#if UF_ALIGN_FOR_SIMD
#define ALIGN16 alignas(16)
#else
#define ALIGN16
#endif
#include "macros.h"
#include "simd.h"
#include "helpers.inl"

View File

@ -2,23 +2,23 @@ namespace uf {
namespace graph {
namespace mesh {
struct Base {
pod::Vector3f position;
pod::ColorRgba color;
pod::Vector2f uv;
pod::Vector2f st;
pod::Vector3f normal;
pod::Vector3f position{};
pod::Vector2f uv{};
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
pod::Vector2f st{};
pod::Vector3f normal{};
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct Skinned {
pod::Vector3f position;
pod::ColorRgba color;
pod::Vector2f uv;
pod::Vector2f st;
pod::Vector3f normal;
pod::Vector3f tangent;
pod::Vector<uint16_t, 4> joints;
pod::Vector4f weights;
pod::Vector3f position{};
pod::Vector2f uv{};
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
pod::Vector2f st{};
pod::Vector3f normal{};
pod::Vector3f tangent{};
pod::Vector<uint16_t, 4> joints{};
pod::Vector4f weights{};
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};

View File

@ -4,7 +4,7 @@
#if UF_USE_FREETYPE
#if UF_ENV_DREAMCAST
#include <freetype/freetype2/ft2build.h>
#include <ft2build.h>
#else
#include <ft2build.h>
#endif

View File

@ -3,9 +3,15 @@
#include <uf/config.h>
#if UF_USE_OPENAL
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>
#if UF_ENV_DREAMCAST && UF_USE_OPENAL_ALDC
#include <ALdc/al.h>
#include <ALdc/alc.h>
#include <ALdc/alut.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>
#endif
namespace ext {
namespace al {

View File

@ -3,9 +3,15 @@
#include <uf/config.h>
#if UF_USE_OPENAL
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>
#if UF_ENV_DREAMCAST && UF_USE_OPENAL_ALDC
#include <ALdc/al.h>
#include <ALdc/alc.h>
#include <ALdc/alut.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>
#endif
namespace ext {
namespace al {

View File

@ -40,7 +40,7 @@ namespace ext {
namespace Image {
typedef GLenum type_t;
typedef GLenum viewType_t;
#if UF_ENV_DREAMCAST
#if UF_USE_OPENGL_FIXED_FUNCTION
static const type_t TYPE_1D = 100;
static const type_t TYPE_2D = GL_TEXTURE_2D;
static const type_t TYPE_3D = 110;
@ -75,7 +75,7 @@ namespace ext {
}
namespace Shader {
typedef GLenum type_t;
#if UF_ENV_DREAMCAST
#if UF_USE_OPENGL_FIXED_FUNCTION
static const type_t VERTEX = 0x00000001;
static const type_t TESSELLATION_CONTROL = 0x00000002;
static const type_t TESSELLATION_EVALUATION = 0x00000003;
@ -129,7 +129,7 @@ namespace ext {
}
namespace Type {
typedef GLenum type_t;
#if UF_ENV_DREAMCAST
#if UF_USE_OPENGL_FIXED_FUNCTION
static const type_t BYTE = GL_BYTE;
static const type_t UBYTE = GL_UNSIGNED_BYTE;

View File

@ -1,12 +1,25 @@
#pragma once
#include <uf/config.h>
#if defined(UF_ENV_WINDOWS)
#if UF_USE_GLEW
#include <GL/glew.h>
#endif
#if UF_USE_OPENGL_GLDC
#include <GLdc/gl.h>
#include <GLdc/glu.h>
#include <GLdc/glkos.h>
#include <GLdc/glext.h>
#define GL_NONE 0
#define GLsizeiptr GLsizei
#define UF_USE_OPENGL_12 1
#define UF_USE_OPENGL_FIXED_FUNCTION 1
#elif defined(UF_ENV_WINDOWS)
// The Visual C++ version of gl.h uses WINGDIAPI and APIENTRY but doesn't define them
#ifdef _MSC_VER
#include <windows.h>
#endif
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/wglext.h>
@ -18,22 +31,21 @@
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#elif defined(UF_ENV_DREAMCAST)
#if UF_USE_OPENGL_GLDC
#include <GLdc/gl.h>
#include <GLdc/glu.h>
#include <GLdc/glkos.h>
#include <GLdc/glext.h>
#else
#include <GLkos/gl.h>
#include <GLkos/glu.h>
#include <GLkos/glut.h>
#include <GLkos/glext.h>
#define glIsTexture(x) ( x != 0 )
#endif
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glext.h>
#define glIsTexture(x) ( x != 0 )
#define GL_NONE 0
#define GLsizeiptr GLsizei
#define UF_USE_OPENGL_12 1
#define UF_USE_OPENGL_FIXED_FUNCTION 1
#define glClientActiveTexture glClientActiveTextureARB
#define glActiveTexture glActiveTextureARB
#define glCompressedTexImage2DARB glCompressedTexImage2D
#endif
#include <typeinfo>

View File

@ -43,10 +43,8 @@
#include <iomanip>
#endif
// uf::iostream
#define UF_IO_COUT std::cout
// "\n"
#define UF_IO_ENDL std::endl
#define UF_IO_COUT std::cout // uf::iostream
#define UF_IO_ENDL std::endl // "\r\n"
#define UF_MSG(Y, X) UF_IO_COUT << "[" << X << "] " << __FILE__ << ":" << __FUNCTION__ << "@" << __LINE__ << ": " << Y << UF_IO_ENDL;

View File

@ -2,7 +2,12 @@
#include "universal.h"
#if !UF_USE_SFML
#if !UF_USE_OPENGL || UF_USE_OPENGL_GLDC
#include "unknown.h"
namespace spec {
typedef spec::unknown::Context Context;
}
#else
namespace spec {
namespace win32 {
class UF_API_VAR Context : public spec::uni::Context {

View File

@ -21,8 +21,8 @@ namespace pod {
struct Viewports {
struct Matrices{
/*alignas(16)*/ pod::Matrix4f view;
/*alignas(16)*/ pod::Matrix4f projection;
pod::Matrix4f view;
pod::Matrix4f projection;
} matrices[uf::camera::maxViews];
} viewport;
};

View File

@ -9,7 +9,7 @@ namespace pod {
#if UF_MATRIX_ALIGNED
struct /*UF_API*/ alignas(16) Matrix {
#else
struct /*UF_API*/ /*alignas(16)*/ Matrix {
struct /*UF_API*/ Matrix {
#endif
// n-dimensional/unspecialized matrix access
T components[R*C] = {};

View File

@ -47,7 +47,7 @@ const T* pod::Matrix<T,R,C>::operator[](size_t i) const {
*/
template<typename T>
pod::Matrix4t<T> /*UF_API*/ uf::matrix::identity() {
alignas(16) pod::Matrix4t<T> matrix;
ALIGN16 pod::Matrix4t<T> matrix;
#pragma unroll // GCC unroll 4
for ( uint_fast8_t c = 0; c < 4; ++c )
#pragma unroll // GCC unroll 4
@ -57,7 +57,7 @@ pod::Matrix4t<T> /*UF_API*/ uf::matrix::identity() {
}
template<typename T>
pod::Matrix4t<T> /*UF_API*/ uf::matrix::initialize( const T* list ) {
alignas(16) pod::Matrix4t<T> matrix;
ALIGN16 pod::Matrix4t<T> matrix;
// memcpy(&matrix[0], list, sizeof(matrix));
#pragma unroll // GCC unroll 16
for ( uint_fast8_t i = 0; i < 16; ++i )
@ -72,7 +72,7 @@ pod::Matrix4t<T> /*UF_API*/ uf::matrix::initialize( const T* list ) {
}
template<typename T>
pod::Matrix4t<T> /*UF_API*/ uf::matrix::initialize( const uf::stl::vector<T>& list ) {
alignas(16) pod::Matrix4t<T> matrix;
ALIGN16 pod::Matrix4t<T> matrix;
if ( list.size() != 16 ) return matrix;
// memcpy(&matrix[0], &list[0], sizeof(matrix));
#pragma unroll // GCC unroll 16
@ -89,7 +89,7 @@ pod::Matrix4t<T> /*UF_API*/ uf::matrix::initialize( const uf::stl::vector<T>& li
return matrix;
}
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> uf::matrix::identityi(){
alignas(16) pod::Matrix<typename T::type_t, T::columns, T::columns> matrix;
ALIGN16 pod::Matrix<typename T::type_t, T::columns, T::columns> matrix;
#pragma unroll // GCC unroll T::columns
for ( uint_fast8_t c = 0; c < T::columns; ++c )
@ -149,7 +149,7 @@ template<typename T> bool uf::matrix::equals( const T& left, const T& right ) {
// Basic arithmetic
// Multiplies two matrices of same type and size together
template<typename T> pod::Matrix<T,4,4> uf::matrix::multiply( const pod::Matrix<T,4,4>& left, const pod::Matrix<T,4,4>& right ) {
alignas(16) pod::Matrix<T,4,4> res;
ALIGN16 pod::Matrix<T,4,4> res;
#if UF_USE_SIMD
auto row1 = uf::simd::load(&left[0]);
auto row2 = uf::simd::load(&left[4]);
@ -242,7 +242,7 @@ template<typename T> pod::Matrix<T,4,4> uf::matrix::multiply( const pod::Matrix<
#endif
}
template<typename T, typename U> pod::Matrix<typename T::type_t, T::columns, T::columns> uf::matrix::multiply( const T& left, const U& right ) {
alignas(16) pod::Matrix<typename T::type_t,T::rows,T::columns> res;
ALIGN16 pod::Matrix<typename T::type_t,T::rows,T::columns> res;
#if 1
float* dstPtr = &res[0];
const float* leftPtr = &right[0];
@ -280,7 +280,7 @@ template<typename T, typename U> pod::Matrix<typename T::type_t, T::columns, T::
return res;
}
template<typename T> T /*UF_API*/ uf::matrix::multiplyAll( const T& m, typename T::type_t scalar ) {
alignas(16) T matrix;
ALIGN16 T matrix;
#pragma unroll // GCC unroll T::rows * T::columns
for ( uint_fast8_t i = 0; i < T::rows * T::columns; ++i )
matrix[i] = m[i] * scalar;
@ -288,7 +288,7 @@ template<typename T> T /*UF_API*/ uf::matrix::multiplyAll( const T& m, typename
return matrix;
}
template<typename T> T /*UF_API*/ uf::matrix::add( const T& lhs, const T& rhs ) {
alignas(16) T matrix;
ALIGN16 T matrix;
#pragma unroll // GCC unroll T::rows * T::columns
for ( uint_fast8_t i = 0; i < T::rows * T::columns; ++i )
matrix[i] = lhs[i] + rhs[i];
@ -297,7 +297,7 @@ template<typename T> T /*UF_API*/ uf::matrix::add( const T& lhs, const T& rhs )
}
// Transpose matrix
template<typename T> T uf::matrix::transpose( const T& matrix ) {
alignas(16) T transpose;
ALIGN16 T transpose;
#pragma unroll // GCC unroll T::rows
for ( typename T::type_t r = 0; r < T::rows; ++r )
@ -313,7 +313,7 @@ template<typename T> T uf::matrix::inverse( const T& matrix ) {
if ( T::rows != 4 || T::columns != 4 ) return matrix;
const typename T::type_t* m = &matrix[0];
alignas(16) typename T::type_t inv[16];
ALIGN16 typename T::type_t inv[16];
typename T::type_t det;
uint_fast8_t i;
@ -417,7 +417,7 @@ template<typename T> T uf::matrix::inverse( const T& matrix ) {
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
if (det == 0) return matrix;
det = 1.0 / det;
alignas(16) T inverted;
ALIGN16 T inverted;
#pragma unroll // GCC unroll 16
for ( i = 0; i < 16; ++i )
inverted[i] = inv[i] * det;
@ -435,7 +435,7 @@ template<typename T> pod::Vector4t<T> uf::matrix::multiply( const pod::Matrix4t<
if ( div && res.w > 0 ) res /= res.w;
return res;
#else
alignas(16) auto res = pod::Vector4t<T>{
ALIGN16 auto res = pod::Vector4t<T>{
vector[0] * mat[0] + vector[1] * mat[4] + vector[2] * mat[8] + vector[3] * mat[12],
vector[0] * mat[1] + vector[1] * mat[5] + vector[2] * mat[9] + vector[3] * mat[13],
vector[0] * mat[2] + vector[1] * mat[6] + vector[2] * mat[10] + vector[3] * mat[14],
@ -492,14 +492,14 @@ template<typename T> T& uf::matrix::scale_( T& matrix, const pod::Vector3t<typen
}
// Complex arithmetic
template<typename T> T uf::matrix::translate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector ) {
alignas(16) T res = matrix;
ALIGN16 T res = matrix;
res[12] = vector.x;
res[13] = vector.y;
res[14] = vector.z;
return res;
}
template<typename T> T uf::matrix::rotate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector ) {
alignas(16) T res = matrix;
ALIGN16 T res = matrix;
if ( vector.x != 0 ) {
res[5] = cos( vector.x );
res[6] = sin( vector.x );
@ -523,7 +523,7 @@ template<typename T> T uf::matrix::rotate( const T& matrix, const pod::Vector3t<
return res;
}
template<typename T> T uf::matrix::scale( const T& matrix, const pod::Vector3t<typename T::type_t>& vector ) {
alignas(16) T res = matrix;
ALIGN16 T res = matrix;
res[0] = vector.x;
res[5] = vector.y;
res[10] = vector.z;
@ -531,7 +531,7 @@ template<typename T> T uf::matrix::scale( const T& matrix, const pod::Vector3t<t
}
template<typename T>
pod::Matrix4t<T> /*UF_API*/ uf::matrix::orthographic( T l, T r, T b, T t, T f, T n ) {
alignas(16) pod::Matrix4t<T> m = uf::matrix::identity();
ALIGN16 pod::Matrix4t<T> m = uf::matrix::identity();
m[0*4+0] = 2 / (r - l);
m[1*4+1] = 2 / (t - b);
m[2*4+2] = - 2 / (f - n);
@ -655,7 +655,7 @@ pod::Matrix<T,R,C>& /*UF_API*/ uf::matrix::decode( const ext::json::Value& json,
template<typename T, size_t R, size_t C>
pod::Matrix<T,R,C> /*UF_API*/ uf::matrix::decode( const ext::json::Value& json, const pod::Matrix<T,R,C>& _m ) {
alignas(16) pod::Matrix<T,R,C> m = _m;
ALIGN16 pod::Matrix<T,R,C> m = _m;
if ( ext::json::isArray(json) )
#pragma unroll // GCC unroll T::size
for ( uint_fast8_t i = 0; i < R*C; ++i )

View File

@ -10,18 +10,18 @@ namespace pod {
static const uint32_t LEAF = 2;
static const uint32_t TREE = 3;
static const uint32_t ROOT = 4;
/*alignas(16)*/ pod::Vector4f position; // 4 * 4 = 16 bytes
/*alignas(4)*/ uint32_t type; // 4 * 1 = 4 bytes
pod::Vector4f position; // 4 * 4 = 16 bytes
uint32_t type; // 4 * 1 = 4 bytes
};
struct UF_API Light {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(16)*/ pod::Vector3f color;
pod::Vector3f position;
pod::Vector3f color;
};
struct UF_API Tree {
static const size_t TREE_SIZE = 8;
/*alignas(16)*/ pod::Vector4f position; // 4 * 4 = 16 bytes
/*alignas(4)*/ uint32_t type; // 4 * 1 = 4 bytes
/*alignas(4)*/ uint32_t children[Tree::TREE_SIZE]; // 4 * 8 = 32 bytes
pod::Vector4f position; // 4 * 4 = 16 bytes
uint32_t type; // 4 * 1 = 4 bytes
uint32_t children[Tree::TREE_SIZE]; // 4 * 8 = 32 bytes
};
}

View File

@ -473,7 +473,7 @@ namespace pod {
#if UF_VECTOR_ALIGNED
struct /*UF_API*/ alignas(16) Vector<T,4> {
#else
struct /*UF_API*/ /*alignas(16)*/ Vector<T,4> {
struct /*UF_API*/ Vector<T,4> {
#endif
// XYZW access
T x;

View File

@ -20,7 +20,7 @@ template<typename T, size_t N>
pod::Vector<T, N> /*UF_API*/ uf::vector::copy( const pod::Vector<T, N>& v ) { return v; }
template<typename T, size_t N, typename U>
pod::Vector<T, N> /*UF_API*/ uf::vector::cast( const U& from ) {
alignas(16) pod::Vector<T, N> to;
ALIGN16 pod::Vector<T, N> to;
#pragma unroll // GCC unroll N
for ( auto i = 0; i < N && i < U::size; ++i )
to[i] = from[i];
@ -45,7 +45,7 @@ T /*UF_API*/ uf::vector::add( const T& left, const T& right ) {
#if UF_USE_SIMD
return uf::simd::add( left, right );
#endif
alignas(16) T res;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = left[i] + right[i];
@ -56,7 +56,7 @@ T /*UF_API*/ uf::vector::add( const T& vector, /*const typename T::type_t&*/ typ
#if UF_USE_SIMD
return uf::simd::add( vector, scalar );
#endif
alignas(16) T res;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = vector[i] + scalar;
@ -67,7 +67,7 @@ T /*UF_API*/ uf::vector::subtract( const T& left, const T& right ) {
#if UF_USE_SIMD
return uf::simd::sub( left, right );
#endif
alignas(16) T res;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = left[i] - right[i];
@ -78,7 +78,7 @@ T /*UF_API*/ uf::vector::subtract( const T& vector, /*const typename T::type_t&*
#if UF_USE_SIMD
return uf::simd::sub( vector, scalar );
#endif
alignas(16) T res;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = vector[i] - scalar;
@ -89,7 +89,7 @@ T /*UF_API*/ uf::vector::multiply( const T& left, const T& right ) {
#if UF_USE_SIMD
return uf::simd::mul( left, right );
#endif
alignas(16) T res;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = left[i] * right[i];
@ -100,7 +100,7 @@ T /*UF_API*/ uf::vector::multiply( const T& vector, /*const typename T::type_t&*
#if UF_USE_SIMD
return uf::simd::mul( vector, scalar );
#endif
alignas(16) T res;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = vector[i] * scalar;
@ -110,15 +110,14 @@ template<typename T> // Divides two vectors of same type and size
T /*UF_API*/ uf::vector::divide( const T& left, const T& right ) {
#if UF_USE_SIMD
return uf::simd::div( left, right );
#elif UF_ENV_DREAMCAST
alignas(16) T res;
#elif UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = MATH_Fast_Divide(left[i], right[i]);
return res;
#else
alignas(16) T res;
scalar = 1.0 / scalar;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = left[i] * right[i];
@ -129,14 +128,14 @@ template<typename T> // Divides this vector by a scalar
T /*UF_API*/ uf::vector::divide( const T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) {
#if UF_USE_SIMD
return uf::simd::div( vector, scalar );
#elif UF_ENV_DREAMCAST
alignas(16) T res;
#elif UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = MATH_Fast_Divide(vector[i], scalar);
return res;
#else
alignas(16) T res;
ALIGN16 T res;
scalar = 1.0 / scalar;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
@ -165,7 +164,7 @@ T /*UF_API*/ uf::vector::negate( const T& vector ) {
#if UF_USE_SIMD
return uf::simd::mul( vector, -1.f );
#endif
alignas(16) T res;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = -vector[i];
@ -173,7 +172,7 @@ T /*UF_API*/ uf::vector::negate( const T& vector ) {
}
template<typename T> //
T /*UF_API*/ uf::vector::abs( const T& vector ) {
alignas(16) T res;
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = abs(vector[i]);
@ -309,7 +308,7 @@ T /*UF_API*/ uf::vector::round( const T& vector ) {
// Complex arithmetic
template<typename T> // Compute the dot product between two vectors
typename T::type_t /*UF_API*/ uf::vector::dot( const T& left, const T& right ) {
#if UF_ENV_DREAMCAST
#if UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
return MATH_fipr( UF_EZ_VEC4(left, T::size), UF_EZ_VEC4(right, T::size) );
#elif UF_USE_SIMD
return uf::simd::dot( left, right );
@ -324,8 +323,8 @@ template<typename T> // Linearly interpolate between two vectors
T /*UF_API*/ uf::vector::lerp( const T& from, const T& to, double delta, bool clamp ) {
delta = fmax( 0, fmin(1,delta) );
// from + ( ( to - from ) * delta )
#if UF_ENV_DREAMCAST
alignas(16) T res;
#if UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = MATH_Lerp( from[i], to[i], delta );
@ -339,8 +338,8 @@ template<typename T> // Linearly interpolate between two vectors
T /*UF_API*/ uf::vector::lerp( const T& from, const T& to, const T& delta, bool clamp ) {
//delta = fmax( 0, fmin(1,delta) );
// from + ( ( to - from ) * delta )
#if UF_ENV_DREAMCAST
alignas(16) T res;
#if UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = MATH_Lerp( from[i], to[i], delta[i] );
@ -375,18 +374,18 @@ T /*UF_API*/ uf::vector::mix( const T& x, const T& y, double a, bool clamp ) {
}
template<typename T> // Compute the distance between two vectors (doesn't sqrt)
typename T::type_t /*UF_API*/ uf::vector::distanceSquared( const T& a, const T& b ) {
#if UF_ENV_DREAMCAST
alignas(16) T delta = uf::vector::subtract(b, a);
#if UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
ALIGN16 T delta = uf::vector::subtract(b, a);
return MATH_Sum_of_Squares( UF_EZ_VEC4( delta, T::size ) );
#elif UF_USE_SIMD
uf::simd::value<typename T::type_t> delta = uf::simd::sub( b, a );
// return uf::vector::sum( uf::simd::vector( uf::simd::mul( delta, delta ) ) );
return uf::simd::dot( delta, delta );
#else
alignas(16) T delta = uf::vector::subtract(b, a);
ALIGN16 T delta = uf::vector::subtract(b, a);
return uf::vector::dot( delta, delta );
/*
alignas(16) T delta = uf::vector::subtract(b, a);
ALIGN16 T delta = uf::vector::subtract(b, a);
uf::vector::multiply( delta, delta );
return uf::vector::sum(delta);
*/
@ -394,7 +393,7 @@ typename T::type_t /*UF_API*/ uf::vector::distanceSquared( const T& a, const T&
}
template<typename T> // Compute the distance between two vectors
typename T::type_t /*UF_API*/ uf::vector::distance( const T& a, const T& b ) {
#if UF_ENV_DREAMCAST
#if UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
return MATH_Fast_Sqrt(uf::vector::distanceSquared(a,b));
#endif
return sqrt(uf::vector::distanceSquared(a,b));
@ -405,7 +404,7 @@ typename T::type_t /*UF_API*/ uf::vector::magnitude( const T& vector ) {
}
template<typename T> // Compute the norm of the vector
typename T::type_t /*UF_API*/ uf::vector::norm( const T& vector ) {
#if UF_ENV_DREAMCAST
#if UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
return MATH_Fast_Sqrt( uf::vector::magnitude(vector) );
#endif
return sqrt( uf::vector::magnitude(vector) );
@ -414,7 +413,7 @@ template<typename T> // Normalizes a vector
T /*UF_API*/ uf::vector::normalize( const T& vector ) {
typename T::type_t norm = uf::vector::norm(vector);
if ( norm == 0 ) return vector;
#if UF_ENV_DREAMCAST
#if UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
return uf::vector::multiply(vector, MATH_fsrra(norm));
#endif
return uf::vector::divide(vector, norm);
@ -422,8 +421,8 @@ T /*UF_API*/ uf::vector::normalize( const T& vector ) {
template<typename T> // Normalizes a vector
void /*UF_API*/ uf::vector::orthonormalize( T& normal, T& tangent ) {
normal = uf::vector::normalize( normal );
alignas(16) T norm = normal;
alignas(16) T tan = uf::vector::normalize( tangent );
ALIGN16 T norm = normal;
ALIGN16 T tan = uf::vector::normalize( tangent );
tangent = uf::vector::subtract( tan, uf::vector::multiply( norm, uf::vector::dot( norm, tan ) ) );
tangent = uf::vector::normalize( tangent );
}
@ -452,15 +451,15 @@ T /*UF_API*/ uf::vector::cross( const T& a, const T& b ) {
uf::simd::value<typename T::type_t> res = _mm_shuffle_ps(tmp2,tmp2,_MM_SHUFFLE(3,0,2,1));
return res;
#endif
#elif UF_ENV_DREAMCAST
auto res = MATH_Cross_Product( a.x, a.y, a.z, b.x, b.y, b.z );
#elif UF_ENV_DREAMCAST && UF_ENV_DREAMCAST_SIMD
ALIGN16 auto res = MATH_Cross_Product( a.x, a.y, a.z, b.x, b.y, b.z );
return *((T*) &res);
#else
alignas(16) T res{
ALIGN16 T res{
a.y * b.z - b.y * a.z,
a.z * b.x - b.z * a.x,
a.x * b.y - b.x * a.y
}
};
return res;
#endif
}

View File

@ -271,57 +271,57 @@ namespace ext {
namespace pod {
struct /*UF_API*/ Vertex_3F2F3F4F {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
/*alignas(16)*/ pod::Vector3f normal;
/*alignas(16)*/ pod::Vector4f color;
pod::Vector3f position;
pod::Vector2f uv;
pod::Vector3f normal;
pod::Vector4f color;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F2F3F32B {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
/*alignas(16)*/ pod::Vector3f normal;
/*alignas(16)*/ pod::Vector4t<uint8_t> color;
pod::Vector3f position;
pod::Vector2f uv;
pod::Vector3f normal;
pod::Vector4t<uint8_t> color;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F3F3F {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(16)*/ pod::Vector3f uv;
/*alignas(16)*/ pod::Vector3f normal;
pod::Vector3f position;
pod::Vector3f uv;
pod::Vector3f normal;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F2F3F1UI {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
/*alignas(16)*/ pod::Vector3f normal;
/*alignas(4)*/ pod::Vector1ui id;
pod::Vector3f position;
pod::Vector2f uv;
pod::Vector3f normal;
pod::Vector1ui id;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F2F3F {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
/*alignas(16)*/ pod::Vector3f normal;
pod::Vector3f position;
pod::Vector2f uv;
pod::Vector3f normal;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F2F {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
pod::Vector3f position;
pod::Vector2f uv;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_2F2F {
/*alignas(8)*/ pod::Vector2f position;
/*alignas(8)*/ pod::Vector2f uv;
pod::Vector2f position;
pod::Vector2f uv;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F {
/*alignas(16)*/ pod::Vector3f position;
pod::Vector3f position;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};

View File

@ -193,8 +193,8 @@ uf::Asset::Payload uf::Asset::resolveToPayload( const uf::stl::string& uri, cons
{ "lua", uf::Asset::Type::LUA },
#if !UF_USE_OPENGL
{ "glb", uf::Asset::Type::GRAPH },
#if !UF_USE_OPENGL
{ "gltf", uf::Asset::Type::GRAPH },
{ "mdl", uf::Asset::Type::GRAPH },
#endif

View File

@ -188,82 +188,53 @@ namespace {
uf::Mesh decodeMesh( ext::json::Value& json, pod::Graph& graph ) {
uf::Mesh mesh;
mesh.vertex.attributes.reserve( json["inputs"]["vertex"]["attributes"].size() );
mesh.vertex.count = json["inputs"]["vertex"]["count"].as( mesh.vertex.count );
mesh.vertex.first = json["inputs"]["vertex"]["first"].as( mesh.vertex.first );
mesh.vertex.stride = json["inputs"]["vertex"]["stride"].as( mesh.vertex.stride );
mesh.vertex.offset = json["inputs"]["vertex"]["stride"].as( mesh.vertex.offset );
mesh.vertex.interleaved = json["inputs"]["vertex"]["interleaved"].as( mesh.vertex.interleaved );
ext::json::forEach( json["inputs"]["vertex"]["attributes"], [&]( ext::json::Value& value ){
auto& attribute = mesh.vertex.attributes.emplace_back();
/*
struct Attribute {
ext::RENDERER::AttributeDescriptor descriptor;
int32_t buffer = -1;
size_t offset = 0;
attribute.descriptor.offset = value["descriptor"]["offset"].as(attribute.descriptor.offset);
attribute.descriptor.size = value["descriptor"]["size"].as(attribute.descriptor.size);
attribute.descriptor.format = (uf::renderer::enums::Format::type_t) value["descriptor"]["format"].as<size_t>(attribute.descriptor.format);
attribute.descriptor.name = value["descriptor"]["name"].as(attribute.descriptor.name);
attribute.descriptor.type = (uf::renderer::enums::Type::type_t) value["descriptor"]["type"].as(attribute.descriptor.type);
attribute.descriptor.components = value["descriptor"]["components"].as(attribute.descriptor.components);
attribute.buffer = value["buffer"].as(attribute.buffer);
attribute.offset = value["offset"].as(attribute.offset);
attribute.stride = value["stride"].as(attribute.stride);
});
mesh.index.attributes.reserve( json["inputs"]["index"]["attributes"].size() );
mesh.index.count = json["inputs"]["index"]["count"].as( mesh.index.count );
mesh.index.first = json["inputs"]["index"]["first"].as( mesh.index.first );
mesh.index.stride = json["inputs"]["index"]["stride"].as( mesh.index.stride );
mesh.index.offset = json["inputs"]["index"]["stride"].as( mesh.index.offset );
mesh.index.interleaved = json["inputs"]["index"]["interleaved"].as( mesh.index.interleaved );
ext::json::forEach( json["inputs"]["index"]["attributes"], [&]( ext::json::Value& value ){
auto& attribute = mesh.index.attributes.emplace_back();
size_t stride = 0;
size_t length = 0;
void* pointer = NULL;
};
struct Input {
uf::stl::vector<Attribute> attributes;
size_t count = 0; // how many elements is the input using
size_t first = 0; // base index to start from
size_t stride = 0; // size of one element in the input's buffer
size_t offset = 0; // bytes to offset from within the associated buffer
int32_t interleaved = -1; // index to interleaved buffer if in bounds
} vertex, index, instance, indirect;
*/
attribute.descriptor.offset = value["descriptor"]["offset"].as(attribute.descriptor.offset);
attribute.descriptor.size = value["descriptor"]["size"].as(attribute.descriptor.size);
attribute.descriptor.format = (uf::renderer::enums::Format::type_t) value["descriptor"]["format"].as<size_t>(attribute.descriptor.format);
attribute.descriptor.name = value["descriptor"]["name"].as(attribute.descriptor.name);
attribute.descriptor.type = (uf::renderer::enums::Type::type_t) value["descriptor"]["type"].as(attribute.descriptor.type);
attribute.descriptor.components = value["descriptor"]["components"].as(attribute.descriptor.components);
attribute.buffer = value["buffer"].as(attribute.buffer);
attribute.offset = value["offset"].as(attribute.offset);
attribute.stride = value["stride"].as(attribute.stride);
});
mesh.instance.attributes.reserve( json["inputs"]["instance"]["attributes"].size() );
mesh.instance.count = json["inputs"]["instance"]["count"].as( mesh.instance.count );
mesh.instance.first = json["inputs"]["instance"]["first"].as( mesh.instance.first );
mesh.instance.stride = json["inputs"]["instance"]["stride"].as( mesh.instance.stride );
mesh.instance.offset = json["inputs"]["instance"]["stride"].as( mesh.instance.offset );
mesh.instance.interleaved = json["inputs"]["instance"]["interleaved"].as( mesh.instance.interleaved );
ext::json::forEach( json["inputs"]["instance"]["attributes"], [&]( ext::json::Value& value ){
auto& attribute = mesh.instance.attributes.emplace_back();
#define DESERIALIZE_MESH(N) {\
auto& input = json["inputs"][#N];\
mesh.N.attributes.reserve( input["attributes"].size() );\
mesh.N.count = input["count"].as( mesh.N.count );\
mesh.N.first = input["first"].as( mesh.N.first );\
mesh.N.stride = input["stride"].as( mesh.N.stride );\
mesh.N.offset = input["stride"].as( mesh.N.offset );\
mesh.N.interleaved = input["interleaved"].as( mesh.N.interleaved );\
ext::json::forEach( input["attributes"], [&]( ext::json::Value& value ){\
auto& attribute = mesh.N.attributes.emplace_back();\
attribute.descriptor.offset = value["descriptor"]["offset"].as(attribute.descriptor.offset);\
attribute.descriptor.size = value["descriptor"]["size"].as(attribute.descriptor.size);\
attribute.descriptor.format = (uf::renderer::enums::Format::type_t) value["descriptor"]["format"].as<size_t>(attribute.descriptor.format);\
attribute.descriptor.name = value["descriptor"]["name"].as(attribute.descriptor.name);\
attribute.descriptor.type = (uf::renderer::enums::Type::type_t) value["descriptor"]["type"].as(attribute.descriptor.type);\
attribute.descriptor.components = value["descriptor"]["components"].as(attribute.descriptor.components);\
attribute.buffer = value["buffer"].as(attribute.buffer);\
attribute.offset = value["offset"].as(attribute.offset);\
attribute.stride = value["stride"].as(attribute.stride);\
attribute.length = value["length"].as(attribute.length);\
});\
}
attribute.descriptor.offset = value["descriptor"]["offset"].as(attribute.descriptor.offset);
attribute.descriptor.size = value["descriptor"]["size"].as(attribute.descriptor.size);
attribute.descriptor.format = (uf::renderer::enums::Format::type_t) value["descriptor"]["format"].as<size_t>(attribute.descriptor.format);
attribute.descriptor.name = value["descriptor"]["name"].as(attribute.descriptor.name);
attribute.descriptor.type = (uf::renderer::enums::Type::type_t) value["descriptor"]["type"].as(attribute.descriptor.type);
attribute.descriptor.components = value["descriptor"]["components"].as(attribute.descriptor.components);
attribute.buffer = value["buffer"].as(attribute.buffer);
attribute.offset = value["offset"].as(attribute.offset);
attribute.stride = value["stride"].as(attribute.stride);
});
mesh.indirect.attributes.reserve( json["inputs"]["indirect"]["attributes"].size() );
mesh.indirect.count = json["inputs"]["indirect"]["count"].as( mesh.indirect.count );
mesh.indirect.first = json["inputs"]["indirect"]["first"].as( mesh.indirect.first );
mesh.indirect.stride = json["inputs"]["indirect"]["stride"].as( mesh.indirect.stride );
mesh.indirect.offset = json["inputs"]["indirect"]["stride"].as( mesh.indirect.offset );
mesh.indirect.interleaved = json["inputs"]["indirect"]["interleaved"].as( mesh.indirect.interleaved );
ext::json::forEach( json["inputs"]["indirect"]["attributes"], [&]( ext::json::Value& value ){
auto& attribute = mesh.indirect.attributes.emplace_back();
attribute.descriptor.offset = value["descriptor"]["offset"].as(attribute.descriptor.offset);
attribute.descriptor.size = value["descriptor"]["size"].as(attribute.descriptor.size);
attribute.descriptor.format = (uf::renderer::enums::Format::type_t) value["descriptor"]["format"].as<size_t>(attribute.descriptor.format);
attribute.descriptor.name = value["descriptor"]["name"].as(attribute.descriptor.name);
attribute.descriptor.type = (uf::renderer::enums::Type::type_t) value["descriptor"]["type"].as(attribute.descriptor.type);
attribute.descriptor.components = value["descriptor"]["components"].as(attribute.descriptor.components);
attribute.buffer = value["buffer"].as(attribute.buffer);
attribute.offset = value["offset"].as(attribute.offset);
attribute.stride = value["stride"].as(attribute.stride);
});
DESERIALIZE_MESH(vertex);
DESERIALIZE_MESH(index);
DESERIALIZE_MESH(instance);
DESERIALIZE_MESH(indirect);
mesh.buffers.reserve( json["buffers"].size() );
ext::json::forEach( json["buffers"], [&]( ext::json::Value& value ){
@ -272,7 +243,9 @@ namespace {
auto& buffer = mesh.buffers.emplace_back(uf::io::readAsBuffer( directory + "/" + filename ));
});
mesh.updateDescriptor();
return mesh;
// return mesh.interleave();
}
pod::Node decodeNode( ext::json::Value& json, pod::Graph& graph ) {

View File

@ -146,6 +146,55 @@ namespace {
uf::Serializer encode( const uf::Mesh& mesh, const EncodingSettings& settings ) {
uf::Serializer json;
/*
struct Attribute {
ext::RENDERER::AttributeDescriptor descriptor;
int32_t buffer = -1;
size_t offset = 0;
size_t stride = 0;
size_t length = 0;
void* pointer = NULL;
};
struct Input {
uf::stl::vector<Attribute> attributes;
size_t count = 0; // how many elements is the input using
size_t first = 0; // base index to start from
size_t stride = 0; // size of one element in the input's buffer
size_t offset = 0; // bytes to offset from within the associated buffer
int32_t interleaved = -1; // index to interleaved buffer if in bounds
} vertex, index, instance, indirect;
*/
#define SERIALIZE_MESH(N) {\
auto& input = json["inputs"][#N];\
input["count"] = mesh.N.count;\
input["first"] = mesh.N.first;\
input["stride"] = mesh.N.stride;\
input["offset"] = mesh.N.offset;\
input["interleaved"] = mesh.N.interleaved;\
ext::json::reserve( input["attributes"], mesh.N.attributes.size() );\
for ( auto& attribute : mesh.N.attributes ) {\
auto& a = input["attributes"].emplace_back();\
a["descriptor"]["offset"] = attribute.descriptor.offset;\
a["descriptor"]["size"] = attribute.descriptor.size;\
a["descriptor"]["format"] = attribute.descriptor.format;\
a["descriptor"]["name"] = attribute.descriptor.name;\
a["descriptor"]["type"] = attribute.descriptor.type;\
a["descriptor"]["components"] = attribute.descriptor.components;\
a["buffer"] = attribute.buffer;\
a["offset"] = attribute.offset;\
a["stride"] = attribute.stride;\
a["length"] = attribute.length;\
}\
}
SERIALIZE_MESH(vertex);
SERIALIZE_MESH(index);
SERIALIZE_MESH(instance);
SERIALIZE_MESH(indirect);
/*
json["inputs"]["vertex"]["count"] = mesh.vertex.count;
json["inputs"]["vertex"]["first"] = mesh.vertex.first;
json["inputs"]["vertex"]["stride"] = mesh.vertex.stride;
@ -221,7 +270,7 @@ namespace {
a["offset"] = attribute.offset;
a["stride"] = attribute.stride;
}
*/
ext::json::reserve( json["buffers"], mesh.buffers.size() );
for ( auto i = 0; i < mesh.buffers.size(); ++i ) {
const uf::stl::string filename = settings.filename + ".buffer." + std::to_string(i) + "." + ( settings.compress ? "gz" : "bin" );

View File

@ -23,15 +23,15 @@ pod::Graph::Storage uf::graph::storage;
UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Base,
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R8G8B8A8_UNORM, color)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32_SFLOAT, uv)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R8G8B8A8_UNORM, color)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32_SFLOAT, st)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32B32_SFLOAT, normal)
);
UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Skinned,
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R8G8B8A8_UNORM, color)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32_SFLOAT, uv)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R8G8B8A8_UNORM, color)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32_SFLOAT, st)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, normal)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, tangent)

View File

@ -131,7 +131,7 @@ void uf::GraphBehavior::tick( uf::Object& self ) {
shader.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance /*storageBuffer*/ );
} else {
struct UniformDescriptor {
/*alignas(16)*/ pod::Matrix4f model;
pod::Matrix4f model;
};
#if UF_UNIFORMS_REUSE
auto& uniform = shader.getUniform("UBO");

View File

@ -49,7 +49,7 @@ void uf::RenderBehavior::tick( uf::Object& self ) {
shader.updateUniform("UBO", uniforms );
#else
struct UniformDescriptor {
/*alignas(16)*/ pod::Matrix4f model;
pod::Matrix4f model;
};
#if UF_UNIFORMS_REUSE
auto& uniforms = uniform.get<UniformDescriptor>();

View File

@ -117,11 +117,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
return uf::graph::load( filename, metadata );
}
#if UF_USE_OPENGL
UF_EXCEPTION("glTF loading is highly discouraged on this platform:" << filename);
return {};
#endif
tinygltf::Model model;
tinygltf::TinyGLTF loader;
@ -238,7 +233,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[keyName];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[keyName];
mesh.bindIndirect<pod::DrawCommand>();
#if UF_USE_VULKAN
#if 0 || UF_USE_VULKAN
bool full = true;
#else
bool full = graph.metadata["flags"]["SKINNED"].as<bool>();
@ -247,343 +242,14 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
uf::stl::vector<uf::graph::mesh::Skinned> vertices;
uf::stl::vector<uint32_t> indices;
for ( auto& p : m.primitives ) {
vertices.clear();
indices.clear();
auto& primitive = primitives.emplace_back();
struct Attribute {
uf::stl::string name = "";
size_t components = 0;
size_t length = 0;
size_t stride = 0;
uint8_t* buffer = NULL;
uf::stl::vector<float> floats;
uf::stl::vector<uint8_t> int8s;
uf::stl::vector<uint16_t> int16s;
uf::stl::vector<uint32_t> int32s;
};
uf::stl::unordered_map<uf::stl::string, Attribute> attributes = {
{"POSITION", {}},
{"TEXCOORD_0", {}},
{"NORMAL", {}},
{"TANGENT", {}},
{"JOINTS_0", {}},
{"WEIGHTS_0", {}},
};
for ( auto& kv : attributes ) {
auto& attribute = kv.second;
attribute.name = kv.first;
auto it = p.attributes.find(attribute.name);
if ( it == p.attributes.end() ) continue;
auto& accessor = model.accessors[it->second];
auto& view = model.bufferViews[accessor.bufferView];
if ( attribute.name == "POSITION" ) {
vertices.resize(accessor.count);
primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] };
primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] };
if ( !(graph.metadata["flags"]["INVERT"].as<bool>()) ){
primitive.instance.bounds.min.x = -primitive.instance.bounds.min.x;
primitive.instance.bounds.max.x = -primitive.instance.bounds.max.x;
}
}
switch ( accessor.componentType ) {
case TINYGLTF_COMPONENT_TYPE_BYTE:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: {
auto* buffer = reinterpret_cast<const uint8_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint8_t);
attribute.length = accessor.count * attribute.components;
attribute.int8s.assign( &buffer[0], &buffer[attribute.length] );
} break;
case TINYGLTF_COMPONENT_TYPE_SHORT:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: {
auto* buffer = reinterpret_cast<const uint16_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint16_t);
attribute.length = accessor.count * attribute.components;
attribute.int16s.assign( &buffer[0], &buffer[attribute.length] );
} break;
case TINYGLTF_COMPONENT_TYPE_INT:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: {
auto* buffer = reinterpret_cast<const uint32_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint32_t);
attribute.length = accessor.count * attribute.components;
attribute.int32s.assign( &buffer[0], &buffer[attribute.length] );
} break;
case TINYGLTF_COMPONENT_TYPE_FLOAT: {
auto* buffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(float);
attribute.length = accessor.count * attribute.components;
attribute.floats.assign( &buffer[0], &buffer[attribute.length] );
} break;
default: UF_MSG_ERROR("Unsupported component type");
}
}
for ( size_t i = 0; i < vertices.size(); ++i ) {
#if 0
#define ITERATE_ATTRIBUTE( name, member )\
memcpy( &vertex.member[0], &attributes[name].buffer[i * attributes[name].components], attributes[name].stride );
#else
#define ITERATE_ATTRIBUTE( name, member )\
if ( !attributes[name].int8s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int8s[i * attributes[name].components + j];\
} else if ( !attributes[name].int16s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int16s[i * attributes[name].components + j];\
} else if ( !attributes[name].int32s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int32s[i * attributes[name].components + j];\
} else if ( !attributes[name].floats.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].floats[i * attributes[name].components + j];\
}
#endif
auto& vertex = vertices[i];
ITERATE_ATTRIBUTE("POSITION", position);
ITERATE_ATTRIBUTE("TEXCOORD_0", uv);
ITERATE_ATTRIBUTE("NORMAL", normal);
ITERATE_ATTRIBUTE("TANGENT", tangent);
ITERATE_ATTRIBUTE("JOINTS_0", joints);
ITERATE_ATTRIBUTE("WEIGHTS_0", weights);
#undef ITERATE_ATTRIBUTE
// required due to reverse-Z projection matrix flipping the X axis as well
// default is to proceed with this
if ( !(graph.metadata["flags"]["INVERT"].as<bool>()) ){
vertex.position.x = -vertex.position.x;
vertex.normal.x = -vertex.normal.x;
vertex.tangent.x = -vertex.tangent.x;
}
}
if ( p.indices > -1 ) {
auto& accessor = model.accessors[p.indices];
auto& view = model.bufferViews[accessor.bufferView];
auto& buffer = model.buffers[view.buffer];
indices.reserve( static_cast<uint32_t>(accessor.count) );
#define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) indices.emplace_back(buf[index]);
const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]);
switch (accessor.componentType) {
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
auto* buf = static_cast<const uint32_t*>( pointer );
COPY_INDICES()
break;
}
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
auto* buf = static_cast<const uint16_t*>( pointer );
COPY_INDICES()
break;
}
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
auto* buf = static_cast<const uint8_t*>( pointer );
COPY_INDICES()
break;
}
}
#undef COPY_INDICES
}
primitive.instance.materialID = p.material;
primitive.instance.primitiveID = primitives.size() - 1;
primitive.instance.meshID = meshID;
primitive.instance.objectID = 0;
primitive.drawCommand.indices = indices.size();
primitive.drawCommand.instances = 1;
primitive.drawCommand.indexID = 0;
primitive.drawCommand.vertexID = 0;
primitive.drawCommand.instanceID = 0;
primitive.drawCommand.vertices = vertices.size();
auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{
.indices = indices.size(),
.instances = 1,
.indexID = mesh.index.count,
.vertexID = mesh.vertex.count,
.instanceID = 0,
.vertices = vertices.size(),
});
mesh.insertVertices(vertices);
mesh.insertIndices(indices);
}
#define UF_GRAPH_PROCESS_PRIMITIVES_FULL 1
#include "processPrimitives.inl"
#undef UF_GRAPH_PROCESS_PRIMITIVES_FULL
} else {
mesh.bind<uf::graph::mesh::Base, uint32_t>();
uf::stl::vector<uf::graph::mesh::Base> vertices;
uf::stl::vector<uint32_t> indices;
for ( auto& p : m.primitives ) {
vertices.clear();
indices.clear();
auto& primitive = primitives.emplace_back();
struct Attribute {
uf::stl::string name = "";
size_t components = 1;
uf::stl::vector<float> floats;
uf::stl::vector<uint8_t> int8s;
uf::stl::vector<uint16_t> int16s;
uf::stl::vector<uint32_t> int32s;
};
uf::stl::unordered_map<uf::stl::string, Attribute> attributes = {
{"POSITION", {}},
{"TEXCOORD_0", {}},
{"NORMAL", {}},
};
for ( auto& kv : attributes ) {
auto& attribute = kv.second;
attribute.name = kv.first;
auto it = p.attributes.find(attribute.name);
if ( it == p.attributes.end() ) continue;
auto& accessor = model.accessors[it->second];
auto& view = model.bufferViews[accessor.bufferView];
if ( attribute.name == "POSITION" ) {
vertices.resize(accessor.count);
primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] };
primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] };
if ( !(graph.metadata["flags"]["INVERT"].as<bool>()) ){
primitive.instance.bounds.min.x = -primitive.instance.bounds.min.x;
primitive.instance.bounds.max.x = -primitive.instance.bounds.max.x;
}
}
switch ( accessor.componentType ) {
case TINYGLTF_COMPONENT_TYPE_BYTE:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: {
auto* buffer = reinterpret_cast<const uint8_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint8_t);
size_t len = accessor.count * attribute.components;
attribute.int8s.assign( &buffer[0], &buffer[len] );
} break;
case TINYGLTF_COMPONENT_TYPE_SHORT:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: {
auto* buffer = reinterpret_cast<const uint16_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint16_t);
size_t len = accessor.count * attribute.components;
attribute.int16s.assign( &buffer[0], &buffer[len] );
} break;
case TINYGLTF_COMPONENT_TYPE_INT:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: {
auto* buffer = reinterpret_cast<const uint32_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint32_t);
size_t len = accessor.count * attribute.components;
attribute.int32s.assign( &buffer[0], &buffer[len] );
} break;
case TINYGLTF_COMPONENT_TYPE_FLOAT: {
auto* buffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(float);
size_t len = accessor.count * attribute.components;
attribute.floats.assign( &buffer[0], &buffer[len] );
} break;
default: UF_MSG_ERROR("Unsupported component type");
}
}
for ( size_t i = 0; i < vertices.size(); ++i ) {
#define ITERATE_ATTRIBUTE( name, member )\
if ( !attributes[name].int8s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int8s[i * attributes[name].components + j];\
} else if ( !attributes[name].int16s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int16s[i * attributes[name].components + j];\
} else if ( !attributes[name].int32s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int32s[i * attributes[name].components + j];\
} else if ( !attributes[name].floats.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].floats[i * attributes[name].components + j];\
}
auto& vertex = vertices[i];
ITERATE_ATTRIBUTE("POSITION", position);
ITERATE_ATTRIBUTE("TEXCOORD_0", uv);
ITERATE_ATTRIBUTE("NORMAL", normal);
#undef ITERATE_ATTRIBUTE
// required due to reverse-Z projection matrix flipping the X axis as well
// default is to proceed with this
if ( !(graph.metadata["flags"]["INVERT"].as<bool>()) ){
vertex.position.x = -vertex.position.x;
vertex.normal.x = -vertex.normal.x;
}
}
if ( p.indices > -1 ) {
auto& accessor = model.accessors[p.indices];
auto& view = model.bufferViews[accessor.bufferView];
auto& buffer = model.buffers[view.buffer];
indices.reserve( static_cast<uint32_t>(accessor.count) );
#define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) indices.emplace_back(buf[index]);
const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]);
switch (accessor.componentType) {
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
auto* buf = static_cast<const uint32_t*>( pointer );
COPY_INDICES()
break;
}
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
auto* buf = static_cast<const uint16_t*>( pointer );
COPY_INDICES()
break;
}
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
auto* buf = static_cast<const uint8_t*>( pointer );
COPY_INDICES()
break;
}
}
#undef COPY_INDICES
}
primitive.instance.materialID = p.material;
primitive.instance.primitiveID = primitives.size() - 1;
primitive.instance.meshID = meshID;
primitive.instance.objectID = 0;
primitive.drawCommand.indices = indices.size();
primitive.drawCommand.instances = 1;
primitive.drawCommand.indexID = 0;
primitive.drawCommand.vertexID = 0;
primitive.drawCommand.instanceID = 0;
primitive.drawCommand.vertices = vertices.size();
auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{
.indices = indices.size(),
.instances = 1,
.indexID = mesh.index.count,
.vertexID = mesh.vertex.count,
.instanceID = 0,
.vertices = vertices.size(),
});
mesh.insertVertices(vertices);
mesh.insertIndices(indices);
}
#include "processPrimitives.inl"
}
mesh.insertIndirects(drawCommands);
mesh.updateDescriptor();

View File

@ -0,0 +1,183 @@
for ( auto& p : m.primitives ) {
vertices.clear();
indices.clear();
auto& primitive = primitives.emplace_back();
struct Attribute {
uf::stl::string name = "";
size_t components = 0;
size_t length = 0;
size_t stride = 0;
uint8_t* buffer = NULL;
uf::stl::vector<float> floats;
uf::stl::vector<uint8_t> int8s;
uf::stl::vector<uint16_t> int16s;
uf::stl::vector<uint32_t> int32s;
};
uf::stl::unordered_map<uf::stl::string, Attribute> attributes = {
{"POSITION", {}},
{"TEXCOORD_0", {}},
{"COLOR_0", {}},
{"NORMAL", {}},
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
{"TANGENT", {}},
{"JOINTS_0", {}},
{"WEIGHTS_0", {}},
#endif
};
for ( auto& kv : attributes ) {
auto& attribute = kv.second;
attribute.name = kv.first;
auto it = p.attributes.find(attribute.name);
if ( it == p.attributes.end() ) continue;
auto& accessor = model.accessors[it->second];
auto& view = model.bufferViews[accessor.bufferView];
if ( attribute.name == "POSITION" ) {
vertices.resize(accessor.count);
primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] };
primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] };
if ( !(graph.metadata["flags"]["INVERT"].as<bool>()) ){
primitive.instance.bounds.min.x = -primitive.instance.bounds.min.x;
primitive.instance.bounds.max.x = -primitive.instance.bounds.max.x;
}
}
switch ( accessor.componentType ) {
case TINYGLTF_COMPONENT_TYPE_BYTE:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: {
auto* buffer = reinterpret_cast<const uint8_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint8_t);
attribute.length = accessor.count * attribute.components;
attribute.int8s.assign( &buffer[0], &buffer[attribute.length] );
} break;
case TINYGLTF_COMPONENT_TYPE_SHORT:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: {
auto* buffer = reinterpret_cast<const uint16_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint16_t);
attribute.length = accessor.count * attribute.components;
attribute.int16s.assign( &buffer[0], &buffer[attribute.length] );
} break;
case TINYGLTF_COMPONENT_TYPE_INT:
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: {
auto* buffer = reinterpret_cast<const uint32_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint32_t);
attribute.length = accessor.count * attribute.components;
attribute.int32s.assign( &buffer[0], &buffer[attribute.length] );
} break;
case TINYGLTF_COMPONENT_TYPE_FLOAT: {
auto* buffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(float);
attribute.length = accessor.count * attribute.components;
attribute.floats.assign( &buffer[0], &buffer[attribute.length] );
} break;
default: UF_MSG_ERROR("Unsupported component type");
}
}
for ( size_t i = 0; i < vertices.size(); ++i ) {
#if 0
#define ITERATE_ATTRIBUTE( name, member )\
memcpy( &vertex.member[0], &attributes[name].buffer[i * attributes[name].components], attributes[name].stride );
#else
#define ITERATE_ATTRIBUTE( name, member, floatScale )\
if ( !attributes[name].int8s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int8s[i * attributes[name].components + j];\
} else if ( !attributes[name].int16s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int16s[i * attributes[name].components + j];\
} else if ( !attributes[name].int32s.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].int32s[i * attributes[name].components + j];\
} else if ( !attributes[name].floats.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].floats[i * attributes[name].components + j] * floatScale;\
}
#endif
auto& vertex = vertices[i];
ITERATE_ATTRIBUTE("POSITION", position, 1);
ITERATE_ATTRIBUTE("TEXCOORD_0", uv, 1);
ITERATE_ATTRIBUTE("COLOR_0", color, 255.0f);
ITERATE_ATTRIBUTE("NORMAL", normal, 1);
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
ITERATE_ATTRIBUTE("TANGENT", tangent, 1);
ITERATE_ATTRIBUTE("JOINTS_0", joints, 1);
ITERATE_ATTRIBUTE("WEIGHTS_0", weights, 1);
#endif
#undef ITERATE_ATTRIBUTE
// required due to reverse-Z projection matrix flipping the X axis as well
// default is to proceed with this
if ( !(graph.metadata["flags"]["INVERT"].as<bool>()) ){
vertex.position.x = -vertex.position.x;
vertex.normal.x = -vertex.normal.x;
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
vertex.tangent.x = -vertex.tangent.x;
#endif
}
}
if ( p.indices > -1 ) {
auto& accessor = model.accessors[p.indices];
auto& view = model.bufferViews[accessor.bufferView];
auto& buffer = model.buffers[view.buffer];
indices.reserve( static_cast<uint32_t>(accessor.count) );
#define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) indices.emplace_back(buf[index]);
const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]);
switch (accessor.componentType) {
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
auto* buf = static_cast<const uint32_t*>( pointer );
COPY_INDICES()
break;
}
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
auto* buf = static_cast<const uint16_t*>( pointer );
COPY_INDICES()
break;
}
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
auto* buf = static_cast<const uint8_t*>( pointer );
COPY_INDICES()
break;
}
}
#undef COPY_INDICES
}
primitive.instance.materialID = p.material;
primitive.instance.primitiveID = primitives.size() - 1;
primitive.instance.meshID = meshID;
primitive.instance.objectID = 0;
primitive.drawCommand.indices = indices.size();
primitive.drawCommand.instances = 1;
primitive.drawCommand.indexID = 0;
primitive.drawCommand.vertexID = 0;
primitive.drawCommand.instanceID = 0;
primitive.drawCommand.vertices = vertices.size();
auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{
.indices = indices.size(),
.instances = 1,
.indexID = mesh.index.count,
.vertexID = mesh.vertex.count,
.instanceID = 0,
.vertices = vertices.size(),
});
mesh.insertVertices(vertices);
mesh.insertIndices(indices);
}

View File

@ -163,7 +163,7 @@ pod::Matrix4f ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer
namespace {
bool inside( const pod::Instance& instance, const pod::Matrix4f& mat ) {
bool visible = false;
#if 1
#if 0
pod::Vector4f corners[8] = {
pod::Vector4f{ instance.bounds.min.x, instance.bounds.min.y, instance.bounds.min.z, 1.0f },
pod::Vector4f{ instance.bounds.max.x, instance.bounds.min.y, instance.bounds.min.z, 1.0f },
@ -175,7 +175,7 @@ namespace {
pod::Vector4f{ instance.bounds.max.x, instance.bounds.max.y, instance.bounds.max.z, 1.0f },
pod::Vector4f{ instance.bounds.min.x, instance.bounds.max.y, instance.bounds.max.z, 1.0f },
};
//#pragma unroll
#pragma unroll
for ( uint p = 0; p < 8; ++p ) {
pod::Vector4f t = uf::matrix::multiply( mat, corners[p] );
float w = t.w * 1.25f;
@ -183,9 +183,9 @@ namespace {
}
#else
pod::Vector4f planes[6]; {
//#pragma unroll
#pragma unroll
for ( auto i = 0; i < 3; ++i )
//#pragma unroll
#pragma unroll
for ( auto j = 0; j < 2; ++j) {
float x = mat[4*0+3] + (j == 0 ? mat[4*0+i] : -mat[4*0+i]);
float y = mat[4*1+3] + (j == 0 ? mat[4*1+i] : -mat[4*1+i]);
@ -196,11 +196,11 @@ namespace {
planes[i*2+j] = pod::Vector4f{ x * length, y * length, z * length, w * length };
}
}
#if 0
//#pragma unroll
#if 1
#pragma unroll
for ( auto p = 0; p < 6; ++p ) {
float d = std::max(instance.bounds.min.x * planes[p].x, instance.bounds.max.x * planes[p].x)
+ std::max(instance.bounds.min.y * planes[p].y, instance.bounds.max.y * planes[p].y);
+ std::max(instance.bounds.min.y * planes[p].y, instance.bounds.max.y * planes[p].y)
+ std::max(instance.bounds.min.z * planes[p].z, instance.bounds.max.z * planes[p].z);
if ( d > -planes[p].w ) return true;
}
@ -216,14 +216,12 @@ namespace {
pod::Vector4f{ instance.bounds.max.x, instance.bounds.max.y, instance.bounds.max.z, 1.0f },
pod::Vector4f{ instance.bounds.min.x, instance.bounds.max.y, instance.bounds.max.z, 1.0f },
};
//#pragma unroll
#pragma unroll
for ( uint p = 0; p < 8; ++p ) corners[p] = uf::matrix::multiply( mat, corners[p] );
//#pragma unroll
#pragma unroll
for ( uint p = 0; p < 6; ++p ) {
//#pragma unroll
for ( uint q = 0; q < 8; ++q ) {
if ( uf::vector::dot( corners[q], planes[p] ) > 0 ) return true;
}
#pragma unroll
for ( uint q = 0; q < 8; ++q ) if ( uf::vector::dot( corners[q], planes[p] ) > 0 ) return true;
return false;
}
#endif
@ -277,7 +275,6 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
// CPU-buffer based command dispatching
if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glEnableClientState(GL_NORMAL_ARRAY));
if ( drawInfo.attributes.color.pointer ) GL_ERROR_CHECK(glEnableClientState(GL_COLOR_ARRAY));
if ( drawInfo.attributes.uv.pointer ) GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_ERROR_CHECK(glEnableClientState(GL_VERTEX_ARRAY));
GLenum indicesType = GL_UNSIGNED_INT;
@ -287,10 +284,14 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
case sizeof(uint8_t): indicesType = GL_UNSIGNED_BYTE; break;
}
GLboolean blending = glIsEnabled(GL_BLEND);
if ( drawInfo.textures.primary.image && drawInfo.attributes.uv.pointer ) {
// static GLuint previous = 0;
// if ( previous != drawInfo.textures.primary.image ) previous = drawInfo.textures.primary.image;
GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE0));
GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE0));
GL_ERROR_CHECK(glEnable(drawInfo.textures.primary.viewType));
@ -298,28 +299,36 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, drawInfo.textures.primary.image));
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.uv.stride, drawInfo.attributes.uv.pointer));
}
if ( drawInfo.textures.secondary.image && drawInfo.attributes.st.pointer ) {
// static GLuint previous = 0;
// if ( previous != drawInfo.textures.secondary.image ) previous = drawInfo.textures.secondary.image;
GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE1));
GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE1));
GL_ERROR_CHECK(glEnable(drawInfo.textures.secondary.viewType));
GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.secondary.viewType, drawInfo.textures.secondary.image));
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, drawInfo.attributes.st.pointer));
#if UF_ENV_DREAMCAST
GL_ERROR_CHECK(glDisable(GL_BLEND));
#endif
if ( drawInfo.textures.secondary.image && drawInfo.attributes.st.pointer ) {
// static GLuint previous = 0;
// if ( previous != drawInfo.textures.secondary.image ) previous = drawInfo.textures.secondary.image;
GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE1));
GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE1));
GL_ERROR_CHECK(glEnable(drawInfo.textures.secondary.viewType));
GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.secondary.viewType, drawInfo.textures.secondary.image));
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
#if UF_ENV_DREAMCAST
if ( blending ) GL_ERROR_CHECK(glDisable(GL_BLEND));
#endif
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, drawInfo.attributes.st.pointer));
}
}
if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glNormalPointer(GL_FLOAT, drawInfo.attributes.normal.stride, drawInfo.attributes.normal.pointer));
if ( drawInfo.attributes.color.pointer ) GL_ERROR_CHECK(glColorPointer(4, GL_UNSIGNED_BYTE, drawInfo.attributes.color.stride, drawInfo.attributes.color.pointer));
GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, drawInfo.attributes.position.stride, drawInfo.attributes.position.pointer));
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.attributes.index.length, indicesType, drawInfo.attributes.index.pointer));
if ( drawInfo.textures.secondary.image ) {
#if UF_ENV_DREAMCAST
if ( blending ) GL_ERROR_CHECK(glEnable(GL_BLEND));
#endif
}
#if 0
if ( drawInfo.textures.secondary.image ) {
#if UF_ENV_DREAMCAST

View File

@ -36,7 +36,7 @@ void ext::opengl::Device::HandlePool::allocate( size_t count ) {
available.resize(initial + count);
switch ( type ) {
case enums::Command::GENERATE_TEXTURE: GL_ERROR_CHECK(glGenTextures(count, &available[initial])); break;
#if !UF_ENV_DREAMCAST
#if !UF_USE_OPENGL_FIXED_FUNCTION
case enums::Command::GENERATE_BUFFER: GL_ERROR_CHECK(glGenBuffers(count, &available[initial])); break;
#endif
}
@ -44,7 +44,7 @@ void ext::opengl::Device::HandlePool::allocate( size_t count ) {
void ext::opengl::Device::HandlePool::clear() {
switch ( type ) {
case enums::Command::GENERATE_TEXTURE: GL_ERROR_CHECK(glDeleteTextures(available.size(), &available[0])); break;
#if !UF_ENV_DREAMCAST
#if !UF_USE_OPENGL_FIXED_FUNCTION
case enums::Command::GENERATE_BUFFER: GL_ERROR_CHECK(glDeleteBuffers(available.size(), &available[0])); break;
#endif
}
@ -57,7 +57,7 @@ bool ext::opengl::Device::HandlePool::used( ext::opengl::Device::HandlePool::han
size_t ext::opengl::Device::HandlePool::alloc( ext::opengl::Device::HandlePool::handle_t& target ) {
switch ( type ) {
case enums::Command::GENERATE_TEXTURE: if ( glIsTexture(target) ) return SIZE_MAX; break;
#if !UF_ENV_DREAMCAST
#if !UF_USE_OPENGL_FIXED_FUNCTION
case enums::Command::GENERATE_BUFFER: if ( glIsBuffer(target) ) return SIZE_MAX; break;
#endif
}
@ -79,7 +79,7 @@ void ext::opengl::Device::HandlePool::free( ext::opengl::Device::HandlePool::han
switch ( type ) {
case enums::Command::GENERATE_TEXTURE: if ( glIsTexture(index) ) glDeleteTextures(1, &index); break;
#if !UF_ENV_DREAMCAST
#if !UF_USE_OPENGL_FIXED_FUNCTION
case enums::Command::GENERATE_BUFFER: if ( glIsBuffer(index) ) glDeleteBuffers(1, &index); break;
#endif
}
@ -89,15 +89,15 @@ void ext::opengl::Device::initialize() {
spec::Context::globalInit();
activateContext();
#if UF_ENV_DREAMCAST
#if UF_USE_OPENGL_GLDC
GLdcConfig config;
glKosInitConfig(&config);
config.fsaa_enabled = GL_FALSE;
glKosInitEx(&config);
#else
glKosInit();
#endif
#if UF_USE_OPENGL_GLDC
GLdcConfig config;
glKosInitConfig(&config);
config.fsaa_enabled = GL_FALSE;
glKosInitEx(&config);
#elif UF_ENV_DREAMCAST
UF_MSG_DEBUG("?");
glKosInit();
UF_MSG_DEBUG("!");
#else
glewExperimental = GL_TRUE;
GLenum error;

View File

@ -397,17 +397,26 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
drawCommandInfo.attributes.index.pointer = (void*) ((uint8_t*) drawCommandInfo.attributes.index.pointer + drawCommand.indexID * drawCommandInfo.attributes.index.stride);
drawCommandInfo.attributes.index.length = drawCommand.indices;
for ( auto attribute : descriptor.inputs.vertex.attributes ) {
for ( uf::Mesh::Attribute attribute : descriptor.inputs.vertex.attributes ) {
attribute.pointer = (void*) ((uint8_t*) attribute.pointer + drawCommand.vertexID * attribute.stride);
attribute.length = drawCommand.vertices;
if ( attribute.descriptor.name == "position" ) drawCommandInfo.attributes.position = attribute;
else if ( attribute.descriptor.name == "uv" ) drawCommandInfo.attributes.uv = attribute;
else if ( attribute.descriptor.name == "st" ) drawCommandInfo.attributes.st = attribute;
// else if ( attribute.descriptor.name == "normal" ) drawCommandInfo.attributes.normal = attribute;
// else if ( attribute.descriptor.name == "color" ) drawCommandInfo.attributes.color = attribute;
else if ( attribute.descriptor.name == "normal" ) drawCommandInfo.attributes.normal = attribute;
else if ( attribute.descriptor.name == "color" ) drawCommandInfo.attributes.color = attribute;
}
/*
for ( size_t i = 0; i < drawCommand.vertices; ++i ) {
float* p = (float*) (drawCommandInfo.attributes.position.pointer + i * drawCommandInfo.attributes.position.stride + drawCommandInfo.attributes.position.descriptor.offset);
float* uv = (float*) (drawCommandInfo.attributes.uv.pointer + i * drawCommandInfo.attributes.uv.stride + drawCommandInfo.attributes.uv.descriptor.offset);
std::cout << "(" << p[0] << ", " << p[1] << ", " << p[2] << "|" << uv[0] << ", " << uv[1] << ") ";
}
std::cout << std::endl;
*/
drawCommandInfo.attributes.instance.pointer = &instance;
drawCommandInfo.attributes.instance.length = sizeof(instance);
@ -435,7 +444,6 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
auto uniformBuffer = (*uniformBufferIt++).buffer;
auto uniformOffset = (size_t) 0;
pod::Uniform* uniforms = (pod::Uniform*) device->getBuffer( uniformBuffer );
CommandBuffer::InfoDraw drawCommandInfo = {};
drawCommandInfo.type = ext::opengl::enums::Command::DRAW;
@ -451,9 +459,12 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
drawCommandInfo.textures.primary = this->material.textures.front().descriptor;
drawCommandInfo.matrices.model = NULL;
drawCommandInfo.matrices.view = &uniforms->modelView;
drawCommandInfo.matrices.projection = &uniforms->projection;
if ( !uniformBuffers.empty() ) {
pod::Uniform* uniforms = (pod::Uniform*) device->getBuffer( uniformBuffer );
drawCommandInfo.matrices.model = NULL;
drawCommandInfo.matrices.view = &uniforms->modelView;
drawCommandInfo.matrices.projection = &uniforms->projection;
}
commandBuffer.record(drawCommandInfo);
}

View File

@ -63,7 +63,7 @@ void ext::opengl::BaseRenderMode::initialize( Device& device ) {
if ( uf::matrix::reverseInfiniteProjection ) {
GL_ERROR_CHECK(glDepthFunc(GL_GEQUAL));
#if !UF_ENV_DREAMCAST || (UF_ENV_DREAMCAST && UF_USE_OPENGL_GLDC)
#if !UF_ENV_DREAMCAST || UF_USE_OPENGL_GLDC
glDepthRange(0, 1);
#endif
} else {

View File

@ -253,7 +253,7 @@ void ext::opengl::Texture::update( uf::Image& image, uint32_t layer ) {
return this->update( (void*) image.getPixelsPtr(), image.getPixels().size(), layer );
}
void ext::opengl::Texture::update( void* data, size_t bufferSize, uint32_t layer ) {
#if UF_ENV_DREAMCAST
#if UF_ENV_DREAMCAST || UF_USE_OPENGL_GLDC
if ( internalFormat > 0 ) {
GL_MUTEX_LOCK();
GL_ERROR_CHECK(glBindTexture(viewType, image));
@ -287,7 +287,7 @@ void ext::opengl::Texture::update( void* data, size_t bufferSize, uint32_t layer
GL_ERROR_CHECK(glBindTexture(viewType, image));
switch ( viewType ) {
case enums::Image::VIEW_TYPE_2D: { GL_ERROR_CHECK(glTexImage2D(viewType, 0, format, width, height, 0, format, type, data)); } break;
#if !UF_ENV_DREAMCAST
#if !UF_USE_OPENGL_FIXED_FUNCTION
case enums::Image::VIEW_TYPE_3D: { GL_ERROR_CHECK(glTexImage3D(viewType, 0, format, width, height, depth, 0, format, type, data)); } break;
#endif
}

View File

@ -2,7 +2,7 @@
#include <uf/utils/io/iostream.h>
#if UF_ENV_WINDOWS && !UF_USE_SFML
#if UF_ENV_WINDOWS && UF_USE_OPENGL && !UF_USE_OPENGL_GLDC
UF_API_CALL spec::win32::Context::Context( uni::Context* shared, const Context::Settings& settings ) :
uni::Context( NULL, true, settings ),
m_deviceContext (NULL),
@ -11,21 +11,18 @@ UF_API_CALL spec::win32::Context::Context( uni::Context* shared, const Context::
// Creating a dummy window is mandatory: we could create a memory DC but then
// its pixel format wouldn't match the regular contexts' format, and thus
// wglShareLists would always fail. Too bad...
#if UF_USE_OPENGL
// Create a dummy window (disabled and hidden)
this->m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(this->m_window, SW_HIDE);
this->m_deviceContext = GetDC(this->m_window);
if ( this->m_deviceContext ) this->create(shared);
#endif
}
UF_API_CALL spec::win32::Context::Context( uni::Context* shared, const Context::Settings& settings, const Context::window_t& window ) :
uni::Context( NULL, false, settings ),
m_deviceContext (NULL),
m_context (NULL)
{
#if UF_USE_OPENGL
// Get the owner window and its device context
this->m_window = window.getHandle();
this->m_deviceContext = GetDC(this->m_window);
@ -33,7 +30,6 @@ UF_API_CALL spec::win32::Context::Context( uni::Context* shared, const Context::
// Create the context
if ( this->m_deviceContext )
this->create(shared);
#endif
}
UF_API_CALL spec::win32::Context::Context( uni::Context* shared, const Context::Settings& settings, unsigned int width, unsigned int height ) : Context( shared, settings ) {
@ -43,7 +39,6 @@ spec::win32::Context::~Context() {
}
void UF_API_CALL spec::win32::Context::create( uni::Context* shared ) {
#if UF_USE_OPENGL
// this->m_settings = settings;
Context::Settings glSettings{24, 4, 8, 0, 3, 3};
@ -206,10 +201,8 @@ void UF_API_CALL spec::win32::Context::create( uni::Context* shared ) {
}
}
}
#endif
}
void UF_API_CALL spec::win32::Context::terminate() {
#if UF_USE_OPENGL
// Destroy the OpenGL context
if ( this->m_context ) {
if ( wglGetCurrentContext() == this->m_context) wglMakeCurrent(NULL, NULL);
@ -221,28 +214,19 @@ void UF_API_CALL spec::win32::Context::terminate() {
// Destroy the window if we own it
if ( this->m_window && this->m_ownsWindow ) DestroyWindow(this->m_window);
#endif
}
bool spec::win32::Context::makeCurrent() {
#if UF_USE_OPENGL
return this->m_deviceContext && this->m_context && wglMakeCurrent(this->m_deviceContext, this->m_context);
#else
return true;
#endif
}
void spec::win32::Context::display() {
#if UF_USE_OPENGL
if (this->m_deviceContext && this->m_context)
SwapBuffers(this->m_deviceContext);
#endif
}
void spec::win32::Context::setVerticalSyncEnabled(bool enabled) {
#if UF_USE_OPENGL
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(wglGetProcAddress("wglSwapIntervalEXT"));
if (wglSwapIntervalEXT) wglSwapIntervalEXT(enabled ? 1 : 0);
#endif
}
#endif

View File

@ -8,7 +8,7 @@
void spec::win32::controller::initialize() {}
void spec::win32::controller::tick() {
#if 0 || UF_USE_OPENVR
#if 0 && UF_USE_OPENVR
if ( ext::openvr::context ) {
uf::stl::string key = "";
if ( name == "R_DPAD_UP" ) { i = vr::Controller_Hand::Hand_Right; key = "dpadUp"; }

View File

@ -88,14 +88,14 @@ uf::stl::string uf::Image::getFilename() const {
// from file
bool uf::Image::open( const uf::stl::string& filename, bool flip ) {
#if UF_ENV_DREAMCAST
#if UF_USE_OPENGL_GLDC
uf::stl::string extension = uf::io::extension(filename);
if ( extension != "dtex" ) {
uf::stl::string dtex = uf::string::replace( filename, ".png", ".dtex" );
if ( uf::io::exists(dtex) ) return this->open(dtex, flip);
UF_EXCEPTION("non-dtex loading is highly discouraged on this platform:" << filename);
return false;
UF_MSG_WARNING("non-dtex loading is highly discouraged on this platform:" << filename);
// return false;
}
#endif
if ( !uf::io::exists(filename) ) UF_EXCEPTION("IO error: file does not exist: " + filename);
@ -103,7 +103,7 @@ bool uf::Image::open( const uf::stl::string& filename, bool flip ) {
this->m_filename = filename;
this->m_pixels.clear();
int width = 0, height = 0, channelsDud = 0, bit_depth = 8, channels = 4;
#if UF_ENV_DREAMCAST
#if UF_USE_OPENGL_GLDC
if ( extension == "dtex" ) {
struct {
char id[4]; // 'DTEX'

View File

@ -60,8 +60,30 @@ void uf::Mesh::destroy() {
}
uf::Mesh uf::Mesh::interleave() const {
uf::Mesh interleaved;
auto& buffer = interleaved.buffers.emplace_back();
interleaved.vertex.interleaved = true;
interleaved.index.interleaved = false;
interleaved.instance.interleaved = true;
interleaved.indirect.interleaved = false;
interleaved.bind(*this);
#define PARSE_INPUT_INTERLEAVED(N){\
uf::Mesh::Input input = N;\
interleaved.N = input;\
auto& buffer = interleaved.buffers.at(interleaved.N.interleaved);\
while ( input.count-- ) {\
for ( auto& attribute : input.attributes ) {\
buffer.insert( buffer.end(), (uint8_t*) attribute.pointer, (uint8_t*) attribute.pointer + attribute.descriptor.size );\
attribute.pointer += input.stride;\
}\
}\
}
PARSE_INPUT_INTERLEAVED(vertex);
interleaved.insertIndices(*this);
PARSE_INPUT_INTERLEAVED(instance);
interleaved.insertIndirects(*this);
/*
auto& buffer = interleaved.buffers.emplace_back();
#define PARSE_INPUT_INTERLEAVED(name) {\
interleaved.name = name;\
interleaved.name.offset = buffer.size();\
@ -72,7 +94,7 @@ uf::Mesh uf::Mesh::interleave() const {
PARSE_INPUT_INTERLEAVED(index);
PARSE_INPUT_INTERLEAVED(instance);
PARSE_INPUT_INTERLEAVED(indirect);
*/
return interleaved;
}
void uf::Mesh::updateDescriptor() {
@ -269,7 +291,7 @@ void uf::Mesh::_updateDescriptor( uf::Mesh::Input& input ) {
const bool interleaved = isInterleaved(input.interleaved);
auto& buffer = buffers[interleaved ? input.interleaved : attribute.buffer];
attribute.length = buffer.size();
attribute.pointer = (void*) (buffer.data());
attribute.pointer = (void*) (buffer.data() + attribute.offset);
if ( !interleaved ) attribute.stride = attribute.descriptor.size;
input.stride += attribute.descriptor.size;
}

View File

@ -36,10 +36,10 @@ namespace {
float scaleY = 1;
mesh.insertVertices<uf::graph::mesh::Base>({
{ {-1.0f * scaleX, 1.0f * scaleY, 0.0f}, {}, {0.0f, 1.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
{ {-1.0f * scaleX, -1.0f * scaleY, 0.0f}, {}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
{ {1.0f * scaleX, -1.0f * scaleY, 0.0f}, {}, {1.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
{ {1.0f * scaleX, 1.0f * scaleY, 0.0f}, {}, {1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, }
{ {-1.0f * scaleX, 1.0f * scaleY, 0.0f}, {0.0f, 1.0f}, {}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
{ {-1.0f * scaleX, -1.0f * scaleY, 0.0f}, {0.0f, 0.0f}, {}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
{ {1.0f * scaleX, -1.0f * scaleY, 0.0f}, {1.0f, 0.0f}, {}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
{ {1.0f * scaleX, 1.0f * scaleY, 0.0f}, {1.0f, 1.0f}, {}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, }
});
mesh.insertIndices<uint16_t>({
0, 1, 2, 2, 3, 0