attempt at generating a ragdoll from a skinned mesh (doesn't work right now), fixed normal mapping
This commit is contained in:
parent
3a2dfb0833
commit
0a92fed14a
@ -350,7 +350,8 @@
|
|||||||
"max": 0.01 // 0.2
|
"max": 0.01 // 0.2
|
||||||
},
|
},
|
||||||
"debug draw": {
|
"debug draw": {
|
||||||
"dynamic": true
|
"static": false,
|
||||||
|
"dynamic": false
|
||||||
},
|
},
|
||||||
"fixed step": true,
|
"fixed step": true,
|
||||||
"substeps": 4
|
"substeps": 4
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
"events": {
|
"events": {
|
||||||
"click": {
|
"click": {
|
||||||
"name": "game:Scene.Load",
|
"name": "game:Scene.Load",
|
||||||
"payload": { "scene": "SourceEngine" },
|
"payload": { "scene": "Sponza" },
|
||||||
"delay": 0.125
|
"delay": 0.125
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -200,7 +200,8 @@ local function tickGravGun( transform, inputs )
|
|||||||
else
|
else
|
||||||
-- update rotation
|
-- update rotation
|
||||||
if heldObject.rotate then
|
if heldObject.rotate then
|
||||||
heldObjectTransform.orientation = Quaternion.lookAt( (heldObjectTransform.position - transform.position):normalize(), transform.up )
|
--heldObjectTransform.orientation = Quaternion.lookAt( (heldObjectTransform.position - transform.position):normalize(), transform.up )
|
||||||
|
heldObjectTransform.orientation = cameraTransform:flatten().orientation
|
||||||
end
|
end
|
||||||
|
|
||||||
-- move held object
|
-- move held object
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
// { "filename": "./models/mds_mcdonalds.glb" }
|
// { "filename": "./models/mds_mcdonalds.glb" }
|
||||||
{ "filename": "./models/mds_mcdonalds/graph.json" }
|
{ "filename": "./models/mds_mcdonalds/graph.json" }
|
||||||
,{ "filename": "/ragdoll.json", "delay": 1 }
|
,{ "filename": "/ragdoll.json", "delay": 1 }
|
||||||
|
,{ "filename": "/craeture.json", "delay": 2.0 }
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"graph": {
|
"graph": {
|
||||||
|
|||||||
10
bin/data/scenes/sponza/player.json
Normal file
10
bin/data/scenes/sponza/player.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"import": "/player.json",
|
||||||
|
"assets": [
|
||||||
|
// { "filename": "/gui/hud/hud.json", "delay": 0 }
|
||||||
|
],
|
||||||
|
"transform": {
|
||||||
|
// "orientation": [ 0, 1, 0, 0 ]
|
||||||
|
}
|
||||||
|
// "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } }
|
||||||
|
}
|
||||||
25
bin/data/scenes/sponza/scene.json
Normal file
25
bin/data/scenes/sponza/scene.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"import": "/scene.json",
|
||||||
|
"assets": [
|
||||||
|
"./sponza.json"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"light": {
|
||||||
|
"fog-": {
|
||||||
|
// "color": [ 0.1, 0.1, 0.1 ],
|
||||||
|
// "color": [ 0.2, 0.2, 0.2 ],
|
||||||
|
"color": [ 0.3, 0.3, 0.3 ],
|
||||||
|
"range": [ 64, 256 ],
|
||||||
|
"step scale": 4,
|
||||||
|
"absorbtion": 0.125,
|
||||||
|
"density": {
|
||||||
|
"threshold": 0.35,
|
||||||
|
"multiplier": 1.0,
|
||||||
|
"scale": 25.0,
|
||||||
|
"offset": [0.2, 0, 1],
|
||||||
|
"timescale": 32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
bin/data/scenes/sponza/sponza.json
Normal file
36
bin/data/scenes/sponza/sponza.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"import": "/model.json",
|
||||||
|
"assets": [
|
||||||
|
// "./models/sponza.glb"
|
||||||
|
"./models/sponza/graph.json"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"graph": {
|
||||||
|
"renderer": { "separate": false },
|
||||||
|
"exporter": {
|
||||||
|
"optimize": { "simplify": 0, "lods": true, "print": true }
|
||||||
|
},
|
||||||
|
"baking": { "enabled": true },
|
||||||
|
"tags": {
|
||||||
|
"worldspawn": {
|
||||||
|
"physics": { "type": "mesh", "static": true, "mass": 0 },
|
||||||
|
"grid": { "size": [8,1,8], "epsilon": 0.001, "cleanup": true, "print": true, "clip": true },
|
||||||
|
"unwrap mesh": true
|
||||||
|
},
|
||||||
|
"info_player_spawn": { "action": "attach", "filename": "./player.json", "transform": { "orientation": [ 0, 1, 0, 0 ] } },
|
||||||
|
"light_environment": {"light": {
|
||||||
|
// "color": [0.1, 0.1, 0.1],
|
||||||
|
"power": 1000,
|
||||||
|
"global": true,
|
||||||
|
"bias": {
|
||||||
|
"constant": 0,
|
||||||
|
"slope": 5,
|
||||||
|
"shader": 0.000025
|
||||||
|
},
|
||||||
|
"radius": [0.9999999, 0],
|
||||||
|
"resolution": 2048
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -376,7 +376,23 @@ void populateSurface( InstanceAddresses instanceAddresses, uvec3 indices ) {
|
|||||||
if ( isValidAddress(instanceAddresses.tangent) ) {
|
if ( isValidAddress(instanceAddresses.tangent) ) {
|
||||||
VTangent buf = VTangent(nonuniformEXT(instanceAddresses.tangent));
|
VTangent buf = VTangent(nonuniformEXT(instanceAddresses.tangent));
|
||||||
#pragma unroll 3
|
#pragma unroll 3
|
||||||
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].tangent[_] = buf.v[/*triangle.*/indices[_]*3+_];
|
for ( uint _ = 0; _ < 3; ++_ ) points[_].tangent = vec3( buf.v[indices[_]*3+0], buf.v[indices[_]*3+1], buf.v[indices[_]*3+2] );
|
||||||
|
// for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].tangent[_] = buf.v[/*triangle.*/indices[_]*3+_];
|
||||||
|
} else {
|
||||||
|
vec3 edge1 = points[1].position - points[0].position;
|
||||||
|
vec3 edge2 = points[2].position - points[0].position;
|
||||||
|
vec2 deltaUV1 = points[1].uv - points[0].uv;
|
||||||
|
vec2 deltaUV2 = points[2].uv - points[0].uv;
|
||||||
|
|
||||||
|
float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
|
||||||
|
vec3 tangent_tri = (edge1 * deltaUV2.y - edge2 * deltaUV1.y) * r;
|
||||||
|
|
||||||
|
#pragma unroll 3
|
||||||
|
for ( uint i = 0; i < 3; ++i ) {
|
||||||
|
vec3 n = points[i].normal;
|
||||||
|
// Gram-Schmidt orthogonalization
|
||||||
|
points[i].tangent = normalize(tangent_tri - n * dot(n, tangent_tri));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,14 +429,6 @@ void populateSurface( InstanceAddresses instanceAddresses, uvec3 indices ) {
|
|||||||
triangle.point.st = /*triangle.*/points[0].st * surface.barycentric[0] + /*triangle.*/points[1].st * surface.barycentric[1] + /*triangle.*/points[2].st * surface.barycentric[2];
|
triangle.point.st = /*triangle.*/points[0].st * surface.barycentric[0] + /*triangle.*/points[1].st * surface.barycentric[1] + /*triangle.*/points[2].st * surface.barycentric[2];
|
||||||
triangle.point.tangent = /*triangle.*/points[0].tangent * surface.barycentric[0] + /*triangle.*/points[1].tangent * surface.barycentric[1] + /*triangle.*/points[2].tangent * surface.barycentric[2];
|
triangle.point.tangent = /*triangle.*/points[0].tangent * surface.barycentric[0] + /*triangle.*/points[1].tangent * surface.barycentric[1] + /*triangle.*/points[2].tangent * surface.barycentric[2];
|
||||||
|
|
||||||
// triangle.point.normal = triangle.geomNormal;
|
|
||||||
|
|
||||||
if ( triangle.point.tangent != vec3(0) ) {
|
|
||||||
surface.tangent.world = normalize(vec3( surface.object.model * vec4(triangle.point.tangent, 0.0) ));
|
|
||||||
vec3 bitangent = normalize(vec3( surface.object.model * vec4(cross( triangle.point.normal, triangle.point.tangent ), 0.0) ));
|
|
||||||
surface.tbn = mat3(surface.tangent.world, bitangent, triangle.point.normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind position (seems to muck with the skybox + fog)
|
// bind position (seems to muck with the skybox + fog)
|
||||||
#if 0 && BARYCENTRIC_CALCULATE
|
#if 0 && BARYCENTRIC_CALCULATE
|
||||||
{
|
{
|
||||||
@ -433,6 +441,12 @@ void populateSurface( InstanceAddresses instanceAddresses, uvec3 indices ) {
|
|||||||
surface.normal.world = normalize(vec3( surface.object.model * vec4(triangle.point.normal, 0.0 ) ));
|
surface.normal.world = normalize(vec3( surface.object.model * vec4(triangle.point.normal, 0.0 ) ));
|
||||||
// surface.normal.eye = vec3( VIEW_MATRIX * vec4(surface.normal.world, 0.0) );
|
// surface.normal.eye = vec3( VIEW_MATRIX * vec4(surface.normal.world, 0.0) );
|
||||||
}
|
}
|
||||||
|
// bind tangent
|
||||||
|
if ( triangle.point.tangent != vec3(0) ) {
|
||||||
|
surface.tangent.world = normalize(vec3( surface.object.model * vec4(triangle.point.tangent, 0.0) ));
|
||||||
|
vec3 bitangent = normalize(vec3( surface.object.model * vec4(cross( triangle.point.normal, triangle.point.tangent ), 0.0) ));
|
||||||
|
surface.tbn = mat3(surface.tangent.world, bitangent, surface.normal.world);
|
||||||
|
}
|
||||||
// bind UVs
|
// bind UVs
|
||||||
{
|
{
|
||||||
surface.uv.xy = triangle.point.uv;
|
surface.uv.xy = triangle.point.uv;
|
||||||
|
|||||||
@ -82,7 +82,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#if BARYCENTRIC
|
#if BARYCENTRIC
|
||||||
#ifndef BARYCENTRIC_CALCULATE
|
#ifndef BARYCENTRIC_CALCULATE
|
||||||
#define BARYCENTRIC_CALCULATE 0
|
#define BARYCENTRIC_CALCULATE 1
|
||||||
#endif
|
#endif
|
||||||
#ifndef BUFFER_REFERENCE
|
#ifndef BUFFER_REFERENCE
|
||||||
#define BUFFER_REFERENCE 1
|
#define BUFFER_REFERENCE 1
|
||||||
|
|||||||
@ -150,6 +150,9 @@ namespace uf {
|
|||||||
void UF_API override( pod::Graph& );
|
void UF_API override( pod::Graph& );
|
||||||
void UF_API animate( pod::Graph&, const uf::stl::string&, float = 1, bool = true );
|
void UF_API animate( pod::Graph&, const uf::stl::string&, float = 1, bool = true );
|
||||||
|
|
||||||
|
uf::stl::vector<pod::OBB> obbFromSkin( const pod::Graph& graph, const pod::Node& node );
|
||||||
|
void rigRagdoll( pod::Graph& graph, pod::Node& node );
|
||||||
|
|
||||||
void UF_API destroy( pod::Graph& );
|
void UF_API destroy( pod::Graph& );
|
||||||
|
|
||||||
void UF_API initialize();
|
void UF_API initialize();
|
||||||
|
|||||||
@ -4,11 +4,11 @@ namespace uf {
|
|||||||
struct Base {
|
struct Base {
|
||||||
pod::Vector3f position{};
|
pod::Vector3f position{};
|
||||||
pod::Vector2f uv{};
|
pod::Vector2f uv{};
|
||||||
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
pod::Vector4b color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
||||||
pod::Vector2f st{};
|
pod::Vector2f st{};
|
||||||
pod::Vector3f normal{};
|
pod::Vector3f normal{};
|
||||||
pod::Vector3f tangent{};
|
pod::Vector3f tangent{};
|
||||||
pod::Vector<uint16_t, 2> id{};
|
pod::Vector2us id{};
|
||||||
|
|
||||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||||
static UF_API Base interpolate( const Base& p1, const Base& p2, float t );
|
static UF_API Base interpolate( const Base& p1, const Base& p2, float t );
|
||||||
@ -16,12 +16,12 @@ namespace uf {
|
|||||||
struct Skinned {
|
struct Skinned {
|
||||||
pod::Vector3f position{};
|
pod::Vector3f position{};
|
||||||
pod::Vector2f uv{};
|
pod::Vector2f uv{};
|
||||||
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
pod::Vector4b color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
||||||
pod::Vector2f st{};
|
pod::Vector2f st{};
|
||||||
pod::Vector3f normal{};
|
pod::Vector3f normal{};
|
||||||
pod::Vector3f tangent{};
|
pod::Vector3f tangent{};
|
||||||
pod::Vector<uint16_t, 2> id{};
|
pod::Vector2us id{};
|
||||||
pod::Vector<uint16_t, 4> joints{};
|
pod::Vector4us joints{};
|
||||||
pod::Vector4f weights{};
|
pod::Vector4f weights{};
|
||||||
|
|
||||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||||
@ -31,11 +31,11 @@ namespace uf {
|
|||||||
struct Base_16f {
|
struct Base_16f {
|
||||||
pod::Vector3f16 position{};
|
pod::Vector3f16 position{};
|
||||||
pod::Vector2f16 uv{};
|
pod::Vector2f16 uv{};
|
||||||
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
pod::Vector4b color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
||||||
pod::Vector2f16 st{};
|
pod::Vector2f16 st{};
|
||||||
pod::Vector3f16 normal{};
|
pod::Vector3f16 normal{};
|
||||||
pod::Vector3f16 tangent{};
|
pod::Vector3f16 tangent{};
|
||||||
pod::Vector<uint16_t, 2> id{};
|
pod::Vector2us id{};
|
||||||
|
|
||||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||||
static UF_API Base_16f interpolate( const Base_16f& p1, const Base_16f& p2, float t );
|
static UF_API Base_16f interpolate( const Base_16f& p1, const Base_16f& p2, float t );
|
||||||
@ -43,12 +43,12 @@ namespace uf {
|
|||||||
struct Skinned_16f {
|
struct Skinned_16f {
|
||||||
pod::Vector3f16 position{};
|
pod::Vector3f16 position{};
|
||||||
pod::Vector2f16 uv{};
|
pod::Vector2f16 uv{};
|
||||||
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
pod::Vector4b color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
||||||
pod::Vector2f16 st{};
|
pod::Vector2f16 st{};
|
||||||
pod::Vector3f16 normal{};
|
pod::Vector3f16 normal{};
|
||||||
pod::Vector3f16 tangent{};
|
pod::Vector3f16 tangent{};
|
||||||
pod::Vector<uint16_t, 2> id{};
|
pod::Vector2us id{};
|
||||||
pod::Vector<uint16_t, 4> joints{};
|
pod::Vector4us joints{};
|
||||||
pod::Vector3f16 weights{};
|
pod::Vector3f16 weights{};
|
||||||
|
|
||||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||||
@ -56,27 +56,27 @@ namespace uf {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
struct Base_u16q {
|
struct Base_u16q {
|
||||||
pod::Vector<uint16_t, 3> position{};
|
pod::Vector3us position{};
|
||||||
pod::Vector<uint16_t, 2> uv{};
|
pod::Vector2us uv{};
|
||||||
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
pod::Vector4b color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
||||||
pod::Vector<uint16_t, 2> st{};
|
pod::Vector2us st{};
|
||||||
pod::Vector<uint16_t, 3> normal{};
|
pod::Vector3us normal{};
|
||||||
pod::Vector<uint16_t, 3> tangent{};
|
pod::Vector3us tangent{};
|
||||||
pod::Vector<uint16_t, 2> id{};
|
pod::Vector2us id{};
|
||||||
|
|
||||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||||
static UF_API Base_u16q interpolate( const Base_u16q& p1, const Base_u16q& p2, float t );
|
static UF_API Base_u16q interpolate( const Base_u16q& p1, const Base_u16q& p2, float t );
|
||||||
};
|
};
|
||||||
struct Skinned_u16q {
|
struct Skinned_u16q {
|
||||||
pod::Vector<uint16_t, 3> position{};
|
pod::Vector3us position{};
|
||||||
pod::Vector<uint16_t, 2> uv{};
|
pod::Vector2us uv{};
|
||||||
pod::ColorRgba color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
pod::Vector4b color{ (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0, (uint8_t) ~0 };
|
||||||
pod::Vector<uint16_t, 2> st{};
|
pod::Vector2us st{};
|
||||||
pod::Vector<uint16_t, 3> normal{};
|
pod::Vector3us normal{};
|
||||||
pod::Vector<uint16_t, 3> tangent{};
|
pod::Vector3us tangent{};
|
||||||
pod::Vector<uint16_t, 2> id{};
|
pod::Vector2us id{};
|
||||||
pod::Vector<uint16_t, 4> joints{};
|
pod::Vector4us joints{};
|
||||||
pod::Vector<uint16_t, 3> weights{};
|
pod::Vector3us weights{};
|
||||||
|
|
||||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||||
static UF_API Skinned_u16q interpolate( const Skinned_u16q& p1, const Skinned_u16q& p2, float t );
|
static UF_API Skinned_u16q interpolate( const Skinned_u16q& p1, const Skinned_u16q& p2, float t );
|
||||||
|
|||||||
@ -10,7 +10,7 @@ namespace uf {
|
|||||||
class UF_API Image {
|
class UF_API Image {
|
||||||
public:
|
public:
|
||||||
typedef pod::Vector2ui vec2_t;
|
typedef pod::Vector2ui vec2_t;
|
||||||
typedef pod::Vector<uint8_t, 4> pixel_t;
|
typedef pod::Vector4b pixel_t;
|
||||||
typedef uf::stl::vector<pixel_t::type_t> container_t;
|
typedef uf::stl::vector<pixel_t::type_t> container_t;
|
||||||
protected:
|
protected:
|
||||||
uf::stl::string m_filename;
|
uf::stl::string m_filename;
|
||||||
|
|||||||
@ -96,6 +96,11 @@ namespace uf {
|
|||||||
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ translate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ translate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ rotate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ rotate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ scale( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ T /*UF_API*/ scale( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||||
|
|
||||||
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ pod::Vector3t<typename T::type_t> extractTranslation( const T& matrix );
|
||||||
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ pod::Vector3t<typename T::type_t> extractScale( const T& matrix );
|
||||||
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ pod::Vector4t<typename T::type_t> extractRotation( const T& matrix );
|
||||||
|
|
||||||
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ pod::Vector3t<typename T::type_t> /*UF_API*/ eulerAngles( const T& matrix );
|
template<typename T=pod::Matrix4> /*FORCE_INLINE*/ pod::Vector3t<typename T::type_t> /*UF_API*/ eulerAngles( const T& matrix );
|
||||||
|
|
||||||
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ orthographic( T, T, T, T, T, T );
|
template<typename T=NUM> /*FORCE_INLINE*/ pod::Matrix4t<T> /*UF_API*/ orthographic( T, T, T, T, T, T );
|
||||||
|
|||||||
@ -362,6 +362,85 @@ template<typename T> T uf::matrix::scale( const T& matrix, const pod::Vector3t<t
|
|||||||
res(2,2) = vector.z;
|
res(2,2) = vector.z;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
// extract translation from matrix
|
||||||
|
template<typename T>
|
||||||
|
pod::Vector3t<typename T::type_t> uf::matrix::extractTranslation( const T& matrix ) {
|
||||||
|
return { matrix(0,3), matrix(1,3), matrix(2,3) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// extracts the scale by calculating the length of the 3 basis column vectors
|
||||||
|
template<typename T>
|
||||||
|
pod::Vector3t<typename T::type_t> uf::matrix::extractScale( const T& matrix ) {
|
||||||
|
using type_t = typename T::type_t;
|
||||||
|
|
||||||
|
type_t sx = std::sqrt( matrix(0,0) * matrix(0,0) + matrix(1,0) * matrix(1,0) + matrix(2,0) * matrix(2,0) );
|
||||||
|
type_t sy = std::sqrt( matrix(0,1) * matrix(0,1) + matrix(1,1) * matrix(1,1) + matrix(2,1) * matrix(2,1) );
|
||||||
|
type_t sz = std::sqrt( matrix(0,2) * matrix(0,2) + matrix(1,2) * matrix(1,2) + matrix(2,2) * matrix(2,2) );
|
||||||
|
|
||||||
|
// to-do: write uf::matrix::determinant()
|
||||||
|
type_t det = matrix(0,0) * ( matrix(1,1) * matrix(2,2) - matrix(2,1) * matrix(1,2))
|
||||||
|
- matrix(0,1) * ( matrix(1,0) * matrix(2,2) - matrix(1,2) * matrix(2,0))
|
||||||
|
+ matrix(0,2) * ( matrix(1,0) * matrix(2,1) - matrix(1,1) * matrix(2,0));
|
||||||
|
if ( det < 0 ) { sx = -sx; sy = -sy; sz = -sz; }
|
||||||
|
return { sx, sy, sz };
|
||||||
|
}
|
||||||
|
|
||||||
|
// extracts the rotation by normalizing out the scale
|
||||||
|
template<typename T>
|
||||||
|
pod::Vector4t<typename T::type_t> uf::matrix::extractRotation( const T& matrix ) {
|
||||||
|
using type_t = typename T::type_t;
|
||||||
|
|
||||||
|
pod::Vector4t<typename T::type_t> q;
|
||||||
|
pod::Vector3t<type_t> s = uf::matrix::extractScale( matrix );
|
||||||
|
|
||||||
|
type_t invX = (s.x != 0) ? (1.0 / s.x) : 0;
|
||||||
|
type_t invY = (s.y != 0) ? (1.0 / s.y) : 0;
|
||||||
|
type_t invZ = (s.z != 0) ? (1.0 / s.z) : 0;
|
||||||
|
|
||||||
|
type_t m00 = matrix(0,0) * invX; type_t m01 = matrix(0,1) * invY; type_t m02 = matrix(0,2) * invZ;
|
||||||
|
type_t m10 = matrix(1,0) * invX; type_t m11 = matrix(1,1) * invY; type_t m12 = matrix(1,2) * invZ;
|
||||||
|
type_t m20 = matrix(2,0) * invX; type_t m21 = matrix(2,1) * invY; type_t m22 = matrix(2,2) * invZ;
|
||||||
|
|
||||||
|
type_t trace = m00 + m11 + m22;
|
||||||
|
|
||||||
|
if ( trace > 0.0 ) {
|
||||||
|
type_t root = std::sqrt(trace + 1.0);
|
||||||
|
q.w = 0.5 * root;
|
||||||
|
root = 0.5 / root;
|
||||||
|
q.x = (m21 - m12) * root;
|
||||||
|
q.y = (m02 - m20) * root;
|
||||||
|
q.z = (m10 - m01) * root;
|
||||||
|
} else {
|
||||||
|
int i = 0;
|
||||||
|
if ( m11 > m00 ) i = 1;
|
||||||
|
if ( m22 > (i == 0 ? m00 : m11) ) i = 2;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
type_t root = std::sqrt(m00 - m11 - m22 + 1.0);
|
||||||
|
q.x = 0.5 * root;
|
||||||
|
root = 0.5 / root;
|
||||||
|
q.w = (m21 - m12) * root;
|
||||||
|
q.y = (m01 + m10) * root;
|
||||||
|
q.z = (m02 + m20) * root;
|
||||||
|
} else if (i == 1) {
|
||||||
|
type_t root = std::sqrt(m11 - m00 - m22 + 1.0);
|
||||||
|
q.y = 0.5 * root;
|
||||||
|
root = 0.5 / root;
|
||||||
|
q.w = (m02 - m20) * root;
|
||||||
|
q.x = (m01 + m10) * root;
|
||||||
|
q.z = (m12 + m21) * root;
|
||||||
|
} else {
|
||||||
|
type_t root = std::sqrt(m22 - m00 - m11 + 1.0);
|
||||||
|
q.z = 0.5 * root;
|
||||||
|
root = 0.5 / root;
|
||||||
|
q.w = (m10 - m01) * root;
|
||||||
|
q.x = (m02 + m20) * root;
|
||||||
|
q.y = (m12 + m21) * root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uf::vector::normalize( q );
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> uf::matrix::multiply_( T& left, const T& right ) {
|
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> uf::matrix::multiply_( T& left, const T& right ) {
|
||||||
return left = uf::matrix::multiply((const T&) left, right);
|
return left = uf::matrix::multiply((const T&) left, right);
|
||||||
|
|||||||
@ -45,13 +45,6 @@ namespace impl {
|
|||||||
pod::Vector3f triangleCenter( const pod::Triangle& tri );
|
pod::Vector3f triangleCenter( const pod::Triangle& tri );
|
||||||
pod::Vector3f triangleNormal( const pod::Triangle& tri );
|
pod::Vector3f triangleNormal( const pod::Triangle& tri );
|
||||||
pod::Vector3f triangleNormal( const pod::TriangleWithNormal& tri );
|
pod::Vector3f triangleNormal( const pod::TriangleWithNormal& tri );
|
||||||
|
|
||||||
size_t getIndex( const void* pointer, size_t stride, size_t index );
|
|
||||||
size_t getIndex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, size_t index );
|
|
||||||
pod::Vector3f getVertex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& positions, size_t index );
|
|
||||||
pod::Triangle fetchTriangle( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, const uf::Mesh::AttributeView& positions, size_t triID );
|
|
||||||
/*FORCE_INLINE*/ pod::Triangle fetchTriangle( const uf::Mesh::View& view, size_t triID );
|
|
||||||
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID );
|
|
||||||
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::PhysicsBody& body );
|
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::PhysicsBody& body );
|
||||||
|
|
||||||
/*FORCE_INLINE*/ bool aabbOverlap( const pod::AABB& a, const pod::AABB& b );
|
/*FORCE_INLINE*/ bool aabbOverlap( const pod::AABB& a, const pod::AABB& b );
|
||||||
|
|||||||
@ -28,6 +28,8 @@ namespace pod {
|
|||||||
|
|
||||||
template<typename T = float> using Vector1t = Vector<T,1>;
|
template<typename T = float> using Vector1t = Vector<T,1>;
|
||||||
typedef Vector1t<NUM> Vector1;
|
typedef Vector1t<NUM> Vector1;
|
||||||
|
typedef Vector1t<int16_t> Vector1s;
|
||||||
|
typedef Vector1t<uint16_t> Vector1us;
|
||||||
typedef Vector1t<int32_t> Vector1i;
|
typedef Vector1t<int32_t> Vector1i;
|
||||||
typedef Vector1t<uint32_t> Vector1ui;
|
typedef Vector1t<uint32_t> Vector1ui;
|
||||||
|
|
||||||
@ -37,6 +39,8 @@ namespace pod {
|
|||||||
|
|
||||||
template<typename T = float> using Vector2t = Vector<T,2>;
|
template<typename T = float> using Vector2t = Vector<T,2>;
|
||||||
typedef Vector2t<NUM> Vector2;
|
typedef Vector2t<NUM> Vector2;
|
||||||
|
typedef Vector2t<int16_t> Vector2s;
|
||||||
|
typedef Vector2t<uint16_t> Vector2us;
|
||||||
typedef Vector2t<int32_t> Vector2i;
|
typedef Vector2t<int32_t> Vector2i;
|
||||||
typedef Vector2t<uint32_t> Vector2ui;
|
typedef Vector2t<uint32_t> Vector2ui;
|
||||||
|
|
||||||
@ -46,9 +50,11 @@ namespace pod {
|
|||||||
|
|
||||||
template<typename T = float> using Vector3t = Vector<T,3>;
|
template<typename T = float> using Vector3t = Vector<T,3>;
|
||||||
typedef Vector3t<NUM> Vector3;
|
typedef Vector3t<NUM> Vector3;
|
||||||
|
typedef Vector3t<uint8_t> Vector3b;
|
||||||
|
typedef Vector3t<int16_t> Vector3s;
|
||||||
|
typedef Vector3t<uint16_t> Vector3us;
|
||||||
typedef Vector3t<int32_t> Vector3i;
|
typedef Vector3t<int32_t> Vector3i;
|
||||||
typedef Vector3t<uint32_t> Vector3ui;
|
typedef Vector3t<uint32_t> Vector3ui;
|
||||||
typedef Vector3t<uint8_t> ColorRGB;
|
|
||||||
|
|
||||||
typedef Vector3t<long> Vector3l;
|
typedef Vector3t<long> Vector3l;
|
||||||
typedef Vector3t<float> Vector3f;
|
typedef Vector3t<float> Vector3f;
|
||||||
@ -56,9 +62,11 @@ namespace pod {
|
|||||||
|
|
||||||
template<typename T = float> using Vector4t = Vector<T,4>;
|
template<typename T = float> using Vector4t = Vector<T,4>;
|
||||||
typedef Vector4t<NUM> Vector4;
|
typedef Vector4t<NUM> Vector4;
|
||||||
|
typedef Vector4t<uint8_t> Vector4b;
|
||||||
|
typedef Vector4t<int16_t> Vector4s;
|
||||||
|
typedef Vector4t<uint16_t> Vector4us;
|
||||||
typedef Vector4t<int32_t> Vector4i;
|
typedef Vector4t<int32_t> Vector4i;
|
||||||
typedef Vector4t<uint32_t> Vector4ui;
|
typedef Vector4t<uint32_t> Vector4ui;
|
||||||
typedef Vector4t<uint8_t> ColorRgba;
|
|
||||||
|
|
||||||
typedef Vector4t<long> Vector4l;
|
typedef Vector4t<long> Vector4l;
|
||||||
typedef Vector4t<float> Vector4f;
|
typedef Vector4t<float> Vector4f;
|
||||||
@ -86,6 +94,7 @@ namespace uf {
|
|||||||
template<typename T> /*FORCE_INLINE*/ pod::Vector3t<T> /*UF_API*/ create( T x, T y, T z ); // creates a 3D vector
|
template<typename T> /*FORCE_INLINE*/ pod::Vector3t<T> /*UF_API*/ create( T x, T y, T z ); // creates a 3D vector
|
||||||
template<typename T> /*FORCE_INLINE*/ pod::Vector4t<T> /*UF_API*/ create( T x, T y, T z, T w ); // creates a 4D vector
|
template<typename T> /*FORCE_INLINE*/ pod::Vector4t<T> /*UF_API*/ create( T x, T y, T z, T w ); // creates a 4D vector
|
||||||
template<typename T, size_t N> /*FORCE_INLINE*/ pod::Vector<T, N> /*UF_API*/ copy( const pod::Vector<T, N>& = {}); // creates a copy of a vector (for whatever reason)
|
template<typename T, size_t N> /*FORCE_INLINE*/ pod::Vector<T, N> /*UF_API*/ copy( const pod::Vector<T, N>& = {}); // creates a copy of a vector (for whatever reason)
|
||||||
|
template<typename T, size_t N> /*FORCE_INLINE*/ pod::Vector<T, N> /*UF_API*/ copy( const T* ); // creates a copy of a vector (for whatever reason)
|
||||||
template<typename T, size_t N, typename U> /*FORCE_INLINE*/ pod::Vector<T, N> /*UF_API*/ cast( const U& from ); // casts one vector of one type to another (of the same size)
|
template<typename T, size_t N, typename U> /*FORCE_INLINE*/ pod::Vector<T, N> /*UF_API*/ cast( const U& from ); // casts one vector of one type to another (of the same size)
|
||||||
// Equality checking
|
// Equality checking
|
||||||
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ equals( const T& left, const T& right ); // equality check between two vectors (==)
|
template<typename T> /*FORCE_INLINE*/ bool /*UF_API*/ equals( const T& left, const T& right ); // equality check between two vectors (==)
|
||||||
|
|||||||
@ -44,6 +44,10 @@ template<typename T, size_t N>
|
|||||||
pod::Vector<T, N> uf::vector::copy( const pod::Vector<T, N>& v ) {
|
pod::Vector<T, N> uf::vector::copy( const pod::Vector<T, N>& v ) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
template<typename T, size_t N>
|
||||||
|
pod::Vector<T, N> uf::vector::copy( const T* p ) {
|
||||||
|
return *((pod::Vector<T, N>*) p);
|
||||||
|
}
|
||||||
template<typename T, size_t N, typename U>
|
template<typename T, size_t N, typename U>
|
||||||
pod::Vector<T, N> uf::vector::cast( const U& from ) {
|
pod::Vector<T, N> uf::vector::cast( const U& from ) {
|
||||||
pod::Vector<T, N> to;
|
pod::Vector<T, N> to;
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <uf/utils/math/vector.h>
|
#include <uf/utils/math/vector.h>
|
||||||
#include <uf/utils/math/matrix.h>
|
#include <uf/utils/math/matrix.h>
|
||||||
#include <uf/utils/math/quant.h>
|
#include <uf/utils/math/quant.h>
|
||||||
|
#include <uf/utils/math/shapes.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <uf/utils/memory/unordered_map.h>
|
#include <uf/utils/memory/unordered_map.h>
|
||||||
@ -36,10 +37,10 @@ namespace ext {
|
|||||||
// essential for vertex input
|
// essential for vertex input
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ext::RENDERER::enums::Format::type_t format = ext::RENDERER::enums::Format::UNDEFINED;
|
uf::renderer::enums::Format::type_t format = uf::renderer::enums::Format::UNDEFINED;
|
||||||
// not as essential
|
// not as essential
|
||||||
uf::stl::string name = "";
|
uf::stl::string name = "";
|
||||||
ext::RENDERER::enums::Type::type_t type = 0;
|
uf::renderer::enums::Type::type_t type = 0;
|
||||||
size_t components = 0;
|
size_t components = 0;
|
||||||
|
|
||||||
bool operator==( const AttributeDescriptor& right ) const { return name == right.name;
|
bool operator==( const AttributeDescriptor& right ) const { return name == right.name;
|
||||||
@ -153,7 +154,7 @@ namespace uf {
|
|||||||
static bool defaultInterleaved;
|
static bool defaultInterleaved;
|
||||||
typedef uf::stl::vector<uint8_t> buffer_t;
|
typedef uf::stl::vector<uint8_t> buffer_t;
|
||||||
struct Attribute {
|
struct Attribute {
|
||||||
ext::RENDERER::AttributeDescriptor descriptor;
|
uf::renderer::AttributeDescriptor descriptor;
|
||||||
int32_t buffer = -1;
|
int32_t buffer = -1;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
|
||||||
@ -187,6 +188,7 @@ namespace uf {
|
|||||||
bool valid() const { return attribute.pointer != NULL; }
|
bool valid() const { return attribute.pointer != NULL; }
|
||||||
size_t stride() const { return attribute.stride; }
|
size_t stride() const { return attribute.stride; }
|
||||||
size_t components() const { return attribute.descriptor.components; }
|
size_t components() const { return attribute.descriptor.components; }
|
||||||
|
uf::renderer::enums::Type::type_t type() const { return attribute.descriptor.type; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct View {
|
struct View {
|
||||||
@ -202,6 +204,41 @@ namespace uf {
|
|||||||
UF_EXCEPTION("invalid view: {}", name);
|
UF_EXCEPTION("invalid view: {}", name);
|
||||||
//return null;
|
//return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// to-do: resolve dependency order hell
|
||||||
|
// these probably won't be directly called anyways?
|
||||||
|
#if 0
|
||||||
|
size_t fetchIndex( size_t index ) {
|
||||||
|
return uf::mesh::fetchIndex( index );
|
||||||
|
}
|
||||||
|
size_t fetchIndex( const uf::Mesh::AttributeView& indices, size_t index ) {
|
||||||
|
return uf::mesh::fetchIndex( indices, index );
|
||||||
|
}
|
||||||
|
size_t fetchIndex( const uf::stl::string& indices, size_t index ) {
|
||||||
|
return uf::mesh::fetchIndex( indices, index );
|
||||||
|
}
|
||||||
|
|
||||||
|
pod::Vector3f fetchVertex( size_t index ) {
|
||||||
|
return uf::mesh::fetchVertex( index );
|
||||||
|
}
|
||||||
|
pod::Vector3f fetchVertex( const uf::Mesh::AttributeView& positions, size_t index ) {
|
||||||
|
return uf::mesh::fetchVertex( positions, index );
|
||||||
|
}
|
||||||
|
pod::Vector3f fetchVertex( const uf::stl::string& positions, size_t index ) {
|
||||||
|
return uf::mesh::fetchVertex( positions, index );
|
||||||
|
}
|
||||||
|
|
||||||
|
pod::TriangleWithNormal fetchTriangle( size_t triID ) {
|
||||||
|
return uf::mesh::fetchTriangle( *this, triID );
|
||||||
|
}
|
||||||
|
pod::TriangleWithNormal fetchTriangle( const uf::Mesh::AttributeView& indices, const uf::Mesh::AttributeView& positions, size_t triID ) {
|
||||||
|
return uf::mesh::fetchTriangle( *this, indices, positions, triID );
|
||||||
|
}
|
||||||
|
pod::TriangleWithNormal fetchTriangle( const uf::stl::string& indices, const uf::stl::string& positions, size_t triID ) {
|
||||||
|
auto& view = *this;
|
||||||
|
return uf::mesh::fetchTriangle( view, view[indices], view[positions], triID );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
typedef uf::stl::vector<uf::Mesh::View> views_t;
|
typedef uf::stl::vector<uf::Mesh::View> views_t;
|
||||||
|
|
||||||
@ -218,9 +255,9 @@ namespace uf {
|
|||||||
void _updateViews();
|
void _updateViews();
|
||||||
uf::Mesh::Attribute _remapAttribute( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute, size_t i = 0 ) const;
|
uf::Mesh::Attribute _remapAttribute( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute, size_t i = 0 ) const;
|
||||||
|
|
||||||
bool _hasV( const uf::Mesh::Input& input, const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const;
|
bool _hasV( const uf::Mesh::Input& input, const uf::stl::vector<uf::renderer::AttributeDescriptor>& descriptors ) const;
|
||||||
bool _hasV( const uf::Mesh::Input& input, const uf::Mesh::Input& src ) const;
|
bool _hasV( const uf::Mesh::Input& input, const uf::Mesh::Input& src ) const;
|
||||||
void _bindV( uf::Mesh::Input& input, const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors );
|
void _bindV( uf::Mesh::Input& input, const uf::stl::vector<uf::renderer::AttributeDescriptor>& descriptors );
|
||||||
void _resizeVs( uf::Mesh::Input& input, size_t count );
|
void _resizeVs( uf::Mesh::Input& input, size_t count );
|
||||||
void _reserveVs( uf::Mesh::Input& input, size_t count );
|
void _reserveVs( uf::Mesh::Input& input, size_t count );
|
||||||
void _insertV( uf::Mesh::Input& input, const void* data );
|
void _insertV( uf::Mesh::Input& input, const void* data );
|
||||||
@ -232,14 +269,14 @@ namespace uf {
|
|||||||
template<typename T> inline void _insertV( uf::Mesh::Input& input, const T& vertex ) { return _insertV( input, (const void*) &vertex ); }
|
template<typename T> inline void _insertV( uf::Mesh::Input& input, const T& vertex ) { return _insertV( input, (const void*) &vertex ); }
|
||||||
template<typename T> inline void _insertVs( uf::Mesh::Input& input, const uf::stl::vector<T>& vs ) { return _insertVs( input, (const void*) vs.data(), vs.size() ); }
|
template<typename T> inline void _insertVs( uf::Mesh::Input& input, const uf::stl::vector<T>& vs ) { return _insertVs( input, (const void*) vs.data(), vs.size() ); }
|
||||||
|
|
||||||
void _bindI( uf::Mesh::Input& input, size_t size, ext::RENDERER::enums::Type::type_t type, size_t count = 1 );
|
void _bindI( uf::Mesh::Input& input, size_t size, uf::renderer::enums::Type::type_t type, size_t count = 1 );
|
||||||
void _reserveIs( uf::Mesh::Input& input, size_t count, size_t i = 0 );
|
void _reserveIs( uf::Mesh::Input& input, size_t count, size_t i = 0 );
|
||||||
void _resizeIs( uf::Mesh::Input& input, size_t count, size_t i = 0 );
|
void _resizeIs( uf::Mesh::Input& input, size_t count, size_t i = 0 );
|
||||||
void _insertI( uf::Mesh::Input& input, const void* data, size_t i );
|
void _insertI( uf::Mesh::Input& input, const void* data, size_t i );
|
||||||
void _insertIs( uf::Mesh::Input& input, const void* data, size_t size, size_t i );
|
void _insertIs( uf::Mesh::Input& input, const void* data, size_t size, size_t i );
|
||||||
void _insertIs( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput );
|
void _insertIs( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput );
|
||||||
|
|
||||||
template<typename U> inline void _bindI( uf::Mesh::Input& input, size_t indices = 1 ) { return _bindI( input, sizeof(U), ext::RENDERER::typeToEnum<U>(), indices ); }
|
template<typename U> inline void _bindI( uf::Mesh::Input& input, size_t indices = 1 ) { return _bindI( input, sizeof(U), uf::renderer::typeToEnum<U>(), indices ); }
|
||||||
template<typename U> inline void _insertI( uf::Mesh::Input& input, U index, size_t i = 0 ) { return _insertI( input, (const void*) &index, i ); }
|
template<typename U> inline void _insertI( uf::Mesh::Input& input, U index, size_t i = 0 ) { return _insertI( input, (const void*) &index, i ); }
|
||||||
template<typename U> inline void _insertIs( uf::Mesh::Input& input, const uf::stl::vector<U>& is, size_t i = 0 ) { return _insertIs( input, (const void*) is.data(), is.size(), i ); }
|
template<typename U> inline void _insertIs( uf::Mesh::Input& input, const uf::stl::vector<U>& is, size_t i = 0 ) { return _insertIs( input, (const void*) is.data(), is.size(), i ); }
|
||||||
public:
|
public:
|
||||||
@ -292,9 +329,9 @@ namespace uf {
|
|||||||
uf::Mesh::View makeView( size_t commandIndex, const uf::stl::vector<uf::stl::string>& wanted = {}, size_t index = 0 ) const;
|
uf::Mesh::View makeView( size_t commandIndex, const uf::stl::vector<uf::stl::string>& wanted = {}, size_t index = 0 ) const;
|
||||||
uf::stl::vector<uf::Mesh::View> makeViews( const uf::stl::vector<uf::stl::string>& wanted = {}, size_t index = 0 ) const;
|
uf::stl::vector<uf::Mesh::View> makeViews( const uf::stl::vector<uf::stl::string>& wanted = {}, size_t index = 0 ) const;
|
||||||
|
|
||||||
inline bool hasVertex( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const { return _hasV( vertex, descriptors ); }
|
inline bool hasVertex( const uf::stl::vector<uf::renderer::AttributeDescriptor>& descriptors ) const { return _hasV( vertex, descriptors ); }
|
||||||
inline bool hasVertex( const uf::Mesh& mesh ) const { return _hasV( vertex, mesh.vertex ); }
|
inline bool hasVertex( const uf::Mesh& mesh ) const { return _hasV( vertex, mesh.vertex ); }
|
||||||
inline void bindVertex( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) { return _bindV( vertex, descriptors ); }
|
inline void bindVertex( const uf::stl::vector<uf::renderer::AttributeDescriptor>& descriptors ) { return _bindV( vertex, descriptors ); }
|
||||||
inline void resizeVertices( size_t count ) { return _resizeVs( vertex, count ); }
|
inline void resizeVertices( size_t count ) { return _resizeVs( vertex, count ); }
|
||||||
inline void reserveVertices( size_t count ) { return _reserveVs( vertex, count ); }
|
inline void reserveVertices( size_t count ) { return _reserveVs( vertex, count ); }
|
||||||
inline void insertVertex( const void* data ) { return _insertV( vertex, data ); }
|
inline void insertVertex( const void* data ) { return _insertV( vertex, data ); }
|
||||||
@ -308,7 +345,7 @@ namespace uf {
|
|||||||
template<typename T> inline void insertVertex( const T& v ) { return _insertV( vertex, (const void*) &v ); }
|
template<typename T> inline void insertVertex( const T& v ) { return _insertV( vertex, (const void*) &v ); }
|
||||||
template<typename T> inline void insertVertices( const uf::stl::vector<T>& vertices ) { return _insertVs( vertex, (const void*) vertices.data(), vertices.size() ); }
|
template<typename T> inline void insertVertices( const uf::stl::vector<T>& vertices ) { return _insertVs( vertex, (const void*) vertices.data(), vertices.size() ); }
|
||||||
|
|
||||||
inline void bindIndex( size_t size, ext::RENDERER::enums::Type::type_t type, size_t count = 1 ) { return _bindI( index, size, type, count ); }
|
inline void bindIndex( size_t size, uf::renderer::enums::Type::type_t type, size_t count = 1 ) { return _bindI( index, size, type, count ); }
|
||||||
inline void reserveIndices( size_t count, size_t i = 0 ) { return _reserveIs( index, count, i ); }
|
inline void reserveIndices( size_t count, size_t i = 0 ) { return _reserveIs( index, count, i ); }
|
||||||
inline void resizeIndices( size_t count, size_t i = 0 ) { return _resizeIs( index, count, i ); }
|
inline void resizeIndices( size_t count, size_t i = 0 ) { return _resizeIs( index, count, i ); }
|
||||||
inline void insertIndex( const void* data, size_t i = 0 ) { return _insertI( index, data, i ); }
|
inline void insertIndex( const void* data, size_t i = 0 ) { return _insertI( index, data, i ); }
|
||||||
@ -317,13 +354,13 @@ namespace uf {
|
|||||||
inline void updateIndexDescriptor() { return _updateDescriptor( index ); }
|
inline void updateIndexDescriptor() { return _updateDescriptor( index ); }
|
||||||
inline uf::Mesh::Attribute remapIndexAttribute( const uf::Mesh::Attribute& attribute, size_t i = 0 ) const { return _remapAttribute( index, attribute, i ); }
|
inline uf::Mesh::Attribute remapIndexAttribute( const uf::Mesh::Attribute& attribute, size_t i = 0 ) const { return _remapAttribute( index, attribute, i ); }
|
||||||
|
|
||||||
template<typename U> inline void bindIndex( size_t count = 1 ) { return _bindI( index, sizeof(U), ext::RENDERER::typeToEnum<U>(), count ); }
|
template<typename U> inline void bindIndex( size_t count = 1 ) { return _bindI( index, sizeof(U), uf::renderer::typeToEnum<U>(), count ); }
|
||||||
template<typename U> inline void insertIndex( U I, size_t i = 0 ) { return _insertI( index, (const void*) &I, i ); }
|
template<typename U> inline void insertIndex( U I, size_t i = 0 ) { return _insertI( index, (const void*) &I, i ); }
|
||||||
template<typename U> inline void insertIndices( const uf::stl::vector<U>& indices, size_t i = 0 ) { return _insertIs( index, (const void*) indices.data(), indices.size(), i ); }
|
template<typename U> inline void insertIndices( const uf::stl::vector<U>& indices, size_t i = 0 ) { return _insertIs( index, (const void*) indices.data(), indices.size(), i ); }
|
||||||
|
|
||||||
inline bool hasInstance( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const { return _hasV( instance, descriptors ); }
|
inline bool hasInstance( const uf::stl::vector<uf::renderer::AttributeDescriptor>& descriptors ) const { return _hasV( instance, descriptors ); }
|
||||||
inline bool hasInstance( const uf::Mesh& mesh ) const { return _hasV( instance, mesh.instance ); }
|
inline bool hasInstance( const uf::Mesh& mesh ) const { return _hasV( instance, mesh.instance ); }
|
||||||
inline void bindInstance( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) { return _bindV( instance, descriptors ); }
|
inline void bindInstance( const uf::stl::vector<uf::renderer::AttributeDescriptor>& descriptors ) { return _bindV( instance, descriptors ); }
|
||||||
inline void resizeInstances( size_t count ) { return _resizeVs( instance, count ); }
|
inline void resizeInstances( size_t count ) { return _resizeVs( instance, count ); }
|
||||||
inline void reserveInstances( size_t count ) { return _reserveVs( instance, count ); }
|
inline void reserveInstances( size_t count ) { return _reserveVs( instance, count ); }
|
||||||
inline void insertInstance( const void* data ) { return _insertV( instance, data ); }
|
inline void insertInstance( const void* data ) { return _insertV( instance, data ); }
|
||||||
@ -336,7 +373,7 @@ namespace uf {
|
|||||||
template<typename T> inline void insertInstance( const T& v ) { return _insertV( instance, (const void*) &v ); }
|
template<typename T> inline void insertInstance( const T& v ) { return _insertV( instance, (const void*) &v ); }
|
||||||
template<typename T> inline void insertInstances( const uf::stl::vector<T>& instances ) { return _insertVs( instance, (const void*) instances.data(), instances.size() ); }
|
template<typename T> inline void insertInstances( const uf::stl::vector<T>& instances ) { return _insertVs( instance, (const void*) instances.data(), instances.size() ); }
|
||||||
|
|
||||||
inline void bindIndirect( size_t size, ext::RENDERER::enums::Type::type_t type, size_t count = 1 ) { return _bindI( indirect, size, type, count ); }
|
inline void bindIndirect( size_t size, uf::renderer::enums::Type::type_t type, size_t count = 1 ) { return _bindI( indirect, size, type, count ); }
|
||||||
inline void reserveIndirects( size_t count, size_t i = 0 ) { return _reserveIs( indirect, count, i ); }
|
inline void reserveIndirects( size_t count, size_t i = 0 ) { return _reserveIs( indirect, count, i ); }
|
||||||
inline void resizeIndirects( size_t count, size_t i = 0 ) { return _resizeIs( indirect, count, i ); }
|
inline void resizeIndirects( size_t count, size_t i = 0 ) { return _resizeIs( indirect, count, i ); }
|
||||||
inline void insertIndirect( const void* data, size_t i = 0 ) { return _insertI( indirect, data, i ); }
|
inline void insertIndirect( const void* data, size_t i = 0 ) { return _insertI( indirect, data, i ); }
|
||||||
@ -344,11 +381,11 @@ namespace uf {
|
|||||||
inline void insertIndirects( const uf::Mesh& mesh ) { return _insertIs( indirect, mesh, mesh.indirect ); }
|
inline void insertIndirects( const uf::Mesh& mesh ) { return _insertIs( indirect, mesh, mesh.indirect ); }
|
||||||
inline void updateIndirectDescriptor() { return _updateDescriptor( indirect ); }
|
inline void updateIndirectDescriptor() { return _updateDescriptor( indirect ); }
|
||||||
|
|
||||||
template<typename U> inline void bindIndirect( size_t i = 1 ) { return _bindI( indirect, sizeof(U), ext::RENDERER::typeToEnum<U>(), i ); }
|
template<typename U> inline void bindIndirect( size_t i = 1 ) { return _bindI( indirect, sizeof(U), uf::renderer::typeToEnum<U>(), i ); }
|
||||||
template<typename U> inline void insertIndirect( U v, size_t i = 0 ) { return _insertI( indirect, (const void*) &v, i ); }
|
template<typename U> inline void insertIndirect( U v, size_t i = 0 ) { return _insertI( indirect, (const void*) &v, i ); }
|
||||||
template<typename U> inline void insertIndirects( const uf::stl::vector<U>& indirects, size_t i = 0 ) { return _insertIs( indirect, (const void*) indirects.data(), indirects.size(), i ); }
|
template<typename U> inline void insertIndirects( const uf::stl::vector<U>& indirects, size_t i = 0 ) { return _insertIs( indirect, (const void*) indirects.data(), indirects.size(), i ); }
|
||||||
|
|
||||||
template<typename T, typename U = ext::RENDERER::index_t>
|
template<typename T, typename U = uf::renderer::index_t>
|
||||||
void bind( bool interleave = uf::Mesh::defaultInterleaved, size_t indices = 1 ) {
|
void bind( bool interleave = uf::Mesh::defaultInterleaved, size_t indices = 1 ) {
|
||||||
bindVertex<T>();
|
bindVertex<T>();
|
||||||
bindIndex<U>( indices );
|
bindIndex<U>( indices );
|
||||||
@ -448,16 +485,16 @@ namespace ext {
|
|||||||
size_t bufferOffset = 0;
|
size_t bufferOffset = 0;
|
||||||
} inputs;
|
} inputs;
|
||||||
|
|
||||||
ext::RENDERER::enums::PrimitiveTopology::type_t topology = ext::RENDERER::enums::PrimitiveTopology::TRIANGLE_LIST;
|
uf::renderer::enums::PrimitiveTopology::type_t topology = uf::renderer::enums::PrimitiveTopology::TRIANGLE_LIST;
|
||||||
ext::RENDERER::enums::PolygonMode::type_t fill = ext::RENDERER::enums::PolygonMode::FILL;
|
uf::renderer::enums::PolygonMode::type_t fill = uf::renderer::enums::PolygonMode::FILL;
|
||||||
ext::RENDERER::enums::CullMode::type_t cullMode = ext::RENDERER::enums::CullMode::BACK;
|
uf::renderer::enums::CullMode::type_t cullMode = uf::renderer::enums::CullMode::BACK;
|
||||||
ext::RENDERER::enums::Face::type_t frontFace = ext::RENDERER::enums::Face::CW;
|
uf::renderer::enums::Face::type_t frontFace = uf::renderer::enums::Face::CW;
|
||||||
float lineWidth = 1.0f;
|
float lineWidth = 1.0f;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool test = true;
|
bool test = true;
|
||||||
bool write = true;
|
bool write = true;
|
||||||
ext::RENDERER::enums::Compare::type_t operation = ext::RENDERER::enums::Compare::GREATER_OR_EQUAL;
|
uf::renderer::enums::Compare::type_t operation = uf::renderer::enums::Compare::GREATER_OR_EQUAL;
|
||||||
struct {
|
struct {
|
||||||
bool enable = false;
|
bool enable = false;
|
||||||
float constant = 0;
|
float constant = 0;
|
||||||
@ -492,8 +529,8 @@ namespace ext {
|
|||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
struct hash<ext::RENDERER::GraphicDescriptor> {
|
struct hash<uf::renderer::GraphicDescriptor> {
|
||||||
size_t operator()(const ext::RENDERER::GraphicDescriptor& descriptor) const { return descriptor.hash(); }
|
size_t operator()(const uf::renderer::GraphicDescriptor& descriptor) const { return descriptor.hash(); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +540,7 @@ namespace std {
|
|||||||
.size = sizeof(decltype(TYPE::ATTRIBUTE)),\
|
.size = sizeof(decltype(TYPE::ATTRIBUTE)),\
|
||||||
.format = uf::renderer::enums::Format::FORMAT,\
|
.format = uf::renderer::enums::Format::FORMAT,\
|
||||||
.name = #ATTRIBUTE,\
|
.name = #ATTRIBUTE,\
|
||||||
.type = ext::RENDERER::typeToEnum<decltype(TYPE::ATTRIBUTE)::type_t>(),\
|
.type = uf::renderer::typeToEnum<decltype(TYPE::ATTRIBUTE)::type_t>(),\
|
||||||
.components = decltype(TYPE::ATTRIBUTE)::size,\
|
.components = decltype(TYPE::ATTRIBUTE)::size,\
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -580,7 +617,7 @@ namespace pod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace uf {
|
namespace uf {
|
||||||
template<typename T = pod::Vertex_3F, typename U = ext::RENDERER::index_t>
|
template<typename T = pod::Vertex_3F, typename U = uf::renderer::index_t>
|
||||||
struct UF_API Mesh_T {
|
struct UF_API Mesh_T {
|
||||||
typedef T vertex_t;
|
typedef T vertex_t;
|
||||||
typedef U index_t;
|
typedef U index_t;
|
||||||
@ -590,7 +627,7 @@ namespace uf {
|
|||||||
uf::stl::vector<pod::Primitive> primitives;
|
uf::stl::vector<pod::Primitive> primitives;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T = pod::Vertex_3F, typename U = ext::RENDERER::index_t>
|
template<typename T = pod::Vertex_3F, typename U = uf::renderer::index_t>
|
||||||
struct UF_API Meshlet_T {
|
struct UF_API Meshlet_T {
|
||||||
typedef T vertex_t;
|
typedef T vertex_t;
|
||||||
typedef U index_t;
|
typedef U index_t;
|
||||||
@ -599,4 +636,78 @@ namespace uf {
|
|||||||
uf::stl::vector<index_t> indices;
|
uf::stl::vector<index_t> indices;
|
||||||
pod::Primitive primitive;
|
pod::Primitive primitive;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace mesh {
|
||||||
|
size_t UF_API fetchIndex( const void* pointer, size_t stride, size_t index );
|
||||||
|
pod::Vector3f UF_API fetchVertex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& positions, size_t index );
|
||||||
|
pod::Triangle UF_API fetchTriangle( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, const uf::Mesh::AttributeView& positions, size_t triID );
|
||||||
|
pod::TriangleWithNormal UF_API fetchTriangle( const uf::Mesh& mesh, size_t triID );
|
||||||
|
|
||||||
|
static inline size_t fetchIndex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, size_t index ) {
|
||||||
|
return uf::mesh::fetchIndex( indices.data(view.index.first), indices.stride(), index );
|
||||||
|
}
|
||||||
|
// for clean code, these would be preferable
|
||||||
|
// but they incur additional lookups every triangle fetch, and I doubt the optimizer will optimize that away, so explicitly passing attribute views is preferable
|
||||||
|
static inline size_t fetchIndex( const uf::Mesh::View& view, size_t index ) {
|
||||||
|
return uf::mesh::fetchIndex( view, view["indices"], index );
|
||||||
|
}
|
||||||
|
static inline size_t fetchIndex( const uf::Mesh::View& view, const uf::stl::string& indices, size_t index ) {
|
||||||
|
return uf::mesh::fetchIndex( view, view[indices], index );
|
||||||
|
}
|
||||||
|
static inline pod::Vector3f fetchVertex( const uf::Mesh::View& view, size_t index ) {
|
||||||
|
return uf::mesh::fetchVertex( view, view["positions"], index );
|
||||||
|
}
|
||||||
|
static inline pod::Vector3f fetchVertex( const uf::Mesh::View& view, const uf::stl::string& positions, size_t index ) {
|
||||||
|
return uf::mesh::fetchVertex( view, view[positions], index );
|
||||||
|
}
|
||||||
|
static inline pod::Triangle fetchTriangle( const uf::Mesh::View& view, const uf::stl::string& indices, const uf::stl::string& positions, size_t triID ) {
|
||||||
|
return uf::mesh::fetchTriangle( view, view[indices], view[positions], triID );
|
||||||
|
}
|
||||||
|
static inline pod::Triangle fetchTriangle( const uf::Mesh::View& view, size_t triID ) {
|
||||||
|
return uf::mesh::fetchTriangle( view, view["index"], view["position"], triID );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T fetchVertexAttribute( const uf::Mesh::View& view, const uf::Mesh::AttributeView& attributeView, size_t index ) {
|
||||||
|
#define CAST_VERTEX(type) {\
|
||||||
|
const type* vertices = (type*) attributeView.data(view.vertex.first + index);\
|
||||||
|
for ( auto i = 0; i < T::size; ++i ) res[i] = vertices[i];\
|
||||||
|
return res;\
|
||||||
|
}
|
||||||
|
#define DEQUANTIZE_VERTEX(type) {\
|
||||||
|
const type* vertices = (type*) attributeView.data(view.vertex.first + index);\
|
||||||
|
for ( auto i = 0; i < T::size; ++i ) res[i] = uf::quant::dequantize(vertices[i]);\
|
||||||
|
return res;\
|
||||||
|
}
|
||||||
|
|
||||||
|
// direct copy
|
||||||
|
if ( uf::renderer::typeToEnum<typename T::type_t>() == attributeView.type() && T::size == attributeView.components() ) {
|
||||||
|
return uf::vector::copy<typename T::type_t, T::size>( (typename T::type_t*) attributeView.data( view.vertex.first + index ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// implicit copy
|
||||||
|
T res;
|
||||||
|
switch ( attributeView.type() ) {
|
||||||
|
// dequantize
|
||||||
|
case uf::renderer::enums::Type::USHORT:
|
||||||
|
case uf::renderer::enums::Type::SHORT: {
|
||||||
|
DEQUANTIZE_VERTEX(uint16_t);
|
||||||
|
} break;
|
||||||
|
case uf::renderer::enums::Type::FLOAT: {
|
||||||
|
CAST_VERTEX(float);
|
||||||
|
} break;
|
||||||
|
#if UF_USE_FLOAT16
|
||||||
|
case uf::renderer::enums::Type::HALF: {
|
||||||
|
CAST_VERTEX(std::float16_t);
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
|
#if UF_USE_BFLOAT16
|
||||||
|
case uf::renderer::enums::Type::BFLOAT: {
|
||||||
|
CAST_VERTEX(std::bfloat16_t);
|
||||||
|
} break;
|
||||||
|
#endif
|
||||||
|
default: UF_EXCEPTION("unsupported attribute type: {}", attributeView.attribute.descriptor.type); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ namespace {
|
|||||||
#if EXT_COLOR_FLOATS
|
#if EXT_COLOR_FLOATS
|
||||||
pod::Vector4f color;
|
pod::Vector4f color;
|
||||||
#else
|
#else
|
||||||
pod::ColorRgba color;
|
pod::Vector4b color;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
static uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||||
|
|||||||
@ -39,7 +39,7 @@ namespace {
|
|||||||
#if EXT_COLOR_FLOATS
|
#if EXT_COLOR_FLOATS
|
||||||
pod::Vector4f color;
|
pod::Vector4f color;
|
||||||
#else
|
#else
|
||||||
pod::ColorRgba color;
|
pod::Vector4b color;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
static uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||||
@ -349,7 +349,7 @@ namespace {
|
|||||||
#if EXT_COLOR_FLOATS
|
#if EXT_COLOR_FLOATS
|
||||||
auto& color = g.color;
|
auto& color = g.color;
|
||||||
#else
|
#else
|
||||||
pod::ColorRgba color = {
|
pod::Vector4b color = {
|
||||||
(uint8_t)(g.color[0] * 255),
|
(uint8_t)(g.color[0] * 255),
|
||||||
(uint8_t)(g.color[1] * 255),
|
(uint8_t)(g.color[1] * 255),
|
||||||
(uint8_t)(g.color[2] * 255),
|
(uint8_t)(g.color[2] * 255),
|
||||||
|
|||||||
@ -257,3 +257,116 @@ void uf::graph::updateAnimation( pod::Graph& graph, pod::Node& node ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// separate function in the event something later might need it
|
||||||
|
uf::stl::vector<pod::OBB> uf::graph::obbFromSkin( const pod::Graph& graph, const pod::Node& node ) {
|
||||||
|
const float wThresold = 0.15f;
|
||||||
|
|
||||||
|
auto& storage = ::getGraphStorage( uf::scene::getCurrentScene() );
|
||||||
|
auto& meshName = graph.meshes[node.mesh];
|
||||||
|
auto& skinName = graph.skins[node.skin];
|
||||||
|
|
||||||
|
auto& skin = storage.skins[skinName];
|
||||||
|
auto& mesh = storage.meshes[meshName];
|
||||||
|
|
||||||
|
// store as min/max AABB
|
||||||
|
uf::stl::vector<pod::OBB> bounds(skin.joints.size(), {
|
||||||
|
pod::Vector3f{ FLT_MAX, FLT_MAX, FLT_MAX },
|
||||||
|
pod::Vector3f{-FLT_MAX,-FLT_MAX,-FLT_MAX }
|
||||||
|
});
|
||||||
|
|
||||||
|
// iterate through mesh to fetch attributes
|
||||||
|
for ( const auto& view : mesh.buffer_views ) {
|
||||||
|
auto posView = view["position"];
|
||||||
|
auto jointsView = view["joints"];
|
||||||
|
auto weightView = view["weights"];
|
||||||
|
|
||||||
|
for ( auto i = 0; i < view.vertex.count; ++i ) {
|
||||||
|
auto pos = uf::mesh::fetchVertex( view, posView, i );
|
||||||
|
auto joints = uf::mesh::fetchVertexAttribute<pod::Vector4us>( view, jointsView, i );
|
||||||
|
auto weights = uf::mesh::fetchVertexAttribute<pod::Vector4f>( view, weightView, i );
|
||||||
|
|
||||||
|
for ( auto w = 0; w < 4; ++w ) {
|
||||||
|
if ( weights[w] <= wThresold ) continue;
|
||||||
|
uint16_t boneID = joints[w];
|
||||||
|
pod::Vector3f localPos = uf::matrix::multiply( skin.inverseBindMatrices[boneID], pos );
|
||||||
|
|
||||||
|
bounds[boneID].center = uf::vector::min( bounds[boneID].center, localPos );
|
||||||
|
bounds[boneID].extent = uf::vector::max( bounds[boneID].extent, localPos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert from min-max to center-extent
|
||||||
|
for ( auto& box : bounds ) {
|
||||||
|
auto extent = (box.extent - box.center) * 0.5f;
|
||||||
|
auto center = (box.extent + box.center) * 0.5f;
|
||||||
|
box = pod::OBB{ center, extent * 0.5f };
|
||||||
|
}
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uf::graph::rigRagdoll( pod::Graph& graph, pod::Node& node ) {
|
||||||
|
auto& storage = ::getGraphStorage(uf::scene::getCurrentScene());
|
||||||
|
auto& name = graph.skins[node.skin];
|
||||||
|
auto& skin = storage.skins[name];
|
||||||
|
|
||||||
|
auto bounds = uf::graph::obbFromSkin( graph, node );
|
||||||
|
uf::stl::unordered_map<int32_t, pod::PhysicsBody*> bodies;
|
||||||
|
|
||||||
|
// create physics bodies
|
||||||
|
const float density = 1.0f;
|
||||||
|
for ( auto i = 0; i < skin.joints.size(); ++i ) {
|
||||||
|
auto& obb = bounds[i];
|
||||||
|
if ( obb.extent.x < 0 ) continue; // invalid bounds
|
||||||
|
auto jointID = skin.joints[i]; // gLTF standard guarantees a jointID is the nodeID
|
||||||
|
|
||||||
|
auto& node = graph.nodes[jointID];
|
||||||
|
auto& entity = *node.entity;
|
||||||
|
|
||||||
|
auto offset = obb.center;
|
||||||
|
/*
|
||||||
|
auto matrix = ::worldMatrix( graph, jointID );
|
||||||
|
auto offset = uf::matrix::multiply( matrix, obb.center );
|
||||||
|
*/
|
||||||
|
|
||||||
|
float volume = 8.0f * obb.extent.x * obb.extent.y * obb.extent.z;
|
||||||
|
float mass = 10.0f; // volume * density;
|
||||||
|
|
||||||
|
auto& body = uf::physics::create( entity, mass, offset );
|
||||||
|
uf::physics::initialize( body, pod::OBB{ pod::Vector3f{}, obb.extent } );
|
||||||
|
bodies[jointID] = &body;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create constraints
|
||||||
|
for ( auto i = 0; i < skin.joints.size(); ++i ) {
|
||||||
|
int32_t jointID = skin.joints[i];
|
||||||
|
auto& node = graph.nodes[jointID];
|
||||||
|
|
||||||
|
// no body: cannot constrain
|
||||||
|
if ( bodies.count( jointID ) == 0 ) continue;
|
||||||
|
// no parent: cannot constrain
|
||||||
|
if ( bodies.count( node.parent ) == 0 ) continue;
|
||||||
|
|
||||||
|
auto* bodyA = bodies[node.parent];
|
||||||
|
auto* bodyB = bodies[jointID];
|
||||||
|
|
||||||
|
auto matrixA = ::worldMatrix( graph, node.parent );
|
||||||
|
auto matrixB = ::worldMatrix( graph, jointID );
|
||||||
|
|
||||||
|
auto pivotA = uf::matrix::extractTranslation( matrixA );
|
||||||
|
auto pivotB = uf::matrix::extractTranslation( matrixB );
|
||||||
|
|
||||||
|
auto pivot = pivotB; // pivot is where the bone starts
|
||||||
|
auto axis = uf::vector::normalize( pivotB - pivotA );
|
||||||
|
|
||||||
|
// fallback
|
||||||
|
if ( uf::vector::distanceSquared( pivotB, pivotA ) < EPS2 ) {
|
||||||
|
axis = uf::quaternion::rotate( uf::matrix::extractRotation(matrixB), pod::Vector3f{0, 1, 0} );
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto& constraint = uf::physics::constrain( *bodyA, *bodyB );
|
||||||
|
// uf::physics::constrainConeTwist( constraint, pivot, axis );
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1107,6 +1107,17 @@ void uf::graph::process( pod::Graph& graph ) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
UF_DEBUG_TIMER_MULTITRACE("Rigging ragdolls");
|
||||||
|
for ( auto& node : graph.nodes ) {
|
||||||
|
if ( node.skin < 0 || node.mesh < 0 ) continue;
|
||||||
|
ext::json::Value tag = ext::json::find( node.name, graphMetadataJson["tags"] );
|
||||||
|
if ( ext::json::isNull( tag ) ) tag["physics"] = graphMetadataJson["physics"];
|
||||||
|
if ( tag["physics"]["ragdoll"].as<bool>(false) ) {
|
||||||
|
uf::graph::rigRagdoll( graph, node );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UF_DEBUG_TIMER_MULTITRACE_END("Rigged ragdolls.");
|
||||||
|
|
||||||
UF_DEBUG_TIMER_MULTITRACE("Updating master graph");
|
UF_DEBUG_TIMER_MULTITRACE("Updating master graph");
|
||||||
#if UF_GRAPH_EXTENDED
|
#if UF_GRAPH_EXTENDED
|
||||||
uf::graph::reload( graph );
|
uf::graph::reload( graph );
|
||||||
@ -1116,6 +1127,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
|||||||
UF_DEBUG_TIMER_MULTITRACE_END("Processed graph.");
|
UF_DEBUG_TIMER_MULTITRACE_END("Processed graph.");
|
||||||
}
|
}
|
||||||
void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) {
|
void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) {
|
||||||
|
|
||||||
auto& scene = uf::scene::getCurrentScene();
|
auto& scene = uf::scene::getCurrentScene();
|
||||||
auto& storage = ::getGraphStorage( scene );
|
auto& storage = ::getGraphStorage( scene );
|
||||||
|
|
||||||
@ -1333,7 +1345,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
|||||||
float mass = phyziks["mass"].as(0.0f);
|
float mass = phyziks["mass"].as(0.0f);
|
||||||
auto center = uf::vector::decode( phyziks["center"], pod::Vector3f{} );
|
auto center = uf::vector::decode( phyziks["center"], pod::Vector3f{} );
|
||||||
|
|
||||||
auto& body = rig.initialized() ? rig.get() : uf::physics::create( entity, mass, center );
|
auto& body = uf::physics::create( entity, mass, center );
|
||||||
uf::physics::initialize( body, mesh, type != "mesh" );
|
uf::physics::initialize( body, mesh, type != "mesh" );
|
||||||
|
|
||||||
body.material.staticFriction = phyziks["friction"].as(body.material.staticFriction);
|
body.material.staticFriction = phyziks["friction"].as(body.material.staticFriction);
|
||||||
|
|||||||
@ -115,6 +115,12 @@ namespace {
|
|||||||
}
|
}
|
||||||
return nodeIndex;
|
return nodeIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pod::Vector3f computeTangent( const pod::Vector3f& normal ) {
|
||||||
|
pod::Vector3f up = ( std::fabs(normal.y) < 0.999f ) ? pod::Vector3f{0,1,0} : pod::Vector3f{1,0,0}; // pick a vector not parallel to normal
|
||||||
|
pod::Vector3f tangent = uf::vector::normalize( uf::vector::cross( up, normal ) );
|
||||||
|
return tangent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const uf::Serializer& metadata ) {
|
void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const uf::Serializer& metadata ) {
|
||||||
|
|||||||
@ -12,13 +12,9 @@ struct {
|
|||||||
if ( graph.metadata["sanitizer"]["winding order"].as<bool>(true) || graph.metadata["renderer"]["invert"].as<bool>(true) ) {
|
if ( graph.metadata["sanitizer"]["winding order"].as<bool>(true) || graph.metadata["renderer"]["invert"].as<bool>(true) ) {
|
||||||
sanitizer.windingOrder.should = true;
|
sanitizer.windingOrder.should = true;
|
||||||
}
|
}
|
||||||
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
if ( graph.metadata["sanitizer"]["tangents"].as<bool>(false) ) {
|
||||||
if ( graph.metadata["sanitizer"]["tangents"].as<bool>(true) ) {
|
|
||||||
sanitizer.tangents.should = true;
|
sanitizer.tangents.should = true;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
sanitizer.tangents.should = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uf::stl::vector<uf::Meshlet_T<UF_GRAPH_MESH_FORMAT>> meshlets;
|
uf::stl::vector<uf::Meshlet_T<UF_GRAPH_MESH_FORMAT>> meshlets;
|
||||||
|
|
||||||
@ -44,8 +40,8 @@ for ( auto& p : m.primitives ) {
|
|||||||
{"TEXCOORD_0", {}},
|
{"TEXCOORD_0", {}},
|
||||||
{"COLOR_0", {}},
|
{"COLOR_0", {}},
|
||||||
{"NORMAL", {}},
|
{"NORMAL", {}},
|
||||||
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
|
||||||
{"TANGENT", {}},
|
{"TANGENT", {}},
|
||||||
|
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
||||||
{"JOINTS_0", {}},
|
{"JOINTS_0", {}},
|
||||||
{"WEIGHTS_0", {}},
|
{"WEIGHTS_0", {}},
|
||||||
#endif
|
#endif
|
||||||
@ -127,8 +123,8 @@ for ( auto& p : m.primitives ) {
|
|||||||
ITERATE_ATTRIBUTE("TEXCOORD_0", uv, 1);
|
ITERATE_ATTRIBUTE("TEXCOORD_0", uv, 1);
|
||||||
ITERATE_ATTRIBUTE("COLOR_0", color, 255.0f);
|
ITERATE_ATTRIBUTE("COLOR_0", color, 255.0f);
|
||||||
ITERATE_ATTRIBUTE("NORMAL", normal, 1);
|
ITERATE_ATTRIBUTE("NORMAL", normal, 1);
|
||||||
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
|
||||||
ITERATE_ATTRIBUTE("TANGENT", tangent, 1);
|
ITERATE_ATTRIBUTE("TANGENT", tangent, 1);
|
||||||
|
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
||||||
ITERATE_ATTRIBUTE("JOINTS_0", joints, 1);
|
ITERATE_ATTRIBUTE("JOINTS_0", joints, 1);
|
||||||
ITERATE_ATTRIBUTE("WEIGHTS_0", weights, 1);
|
ITERATE_ATTRIBUTE("WEIGHTS_0", weights, 1);
|
||||||
#endif
|
#endif
|
||||||
@ -243,7 +239,6 @@ for ( auto& p : m.primitives ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
|
||||||
/* calculate tangents */ if ( sanitizer.tangents.should ) {
|
/* calculate tangents */ if ( sanitizer.tangents.should ) {
|
||||||
if ( !meshlet.indices.empty() ) {
|
if ( !meshlet.indices.empty() ) {
|
||||||
for ( size_t i = 0; i < meshlet.indices.size() / 3; ++i ) {
|
for ( size_t i = 0; i < meshlet.indices.size() / 3; ++i ) {
|
||||||
@ -276,12 +271,12 @@ for ( auto& p : m.primitives ) {
|
|||||||
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
|
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
|
||||||
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
|
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
|
||||||
|
|
||||||
for ( auto i = 0; i < 3; ++i ) {
|
for ( auto j = 0; j < 3; ++j ) {
|
||||||
auto& normal = meshlet.vertices[indices[0]].normal;
|
auto& normal = meshlet.vertices[indices[j]].normal;
|
||||||
auto& tangent = meshlet.vertices[indices[0]].tangent;
|
auto& tangent = meshlet.vertices[indices[j]].tangent;
|
||||||
tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri));
|
tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri));
|
||||||
|
|
||||||
if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f)
|
if ( uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f )
|
||||||
tangent = tangent * -1.0f;
|
tangent = tangent * -1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -316,9 +311,9 @@ for ( auto& p : m.primitives ) {
|
|||||||
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
|
auto tangent_tri = (deltaTriPosition[0] * deltaTriUV[1].y - deltaTriPosition[1] * deltaTriUV[0].y) * r;
|
||||||
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
|
auto bitangent_tri = (deltaTriPosition[1] * deltaTriUV[0].x - deltaTriPosition[0] * deltaTriUV[1].x) * r;
|
||||||
|
|
||||||
for ( auto i = 0; i < 3; ++i ) {
|
for ( auto j = 0; j < 3; ++j ) {
|
||||||
auto& normal = meshlet.vertices[indices[0]].normal;
|
auto& normal = meshlet.vertices[indices[j]].normal;
|
||||||
auto& tangent = meshlet.vertices[indices[0]].tangent;
|
auto& tangent = meshlet.vertices[indices[j]].tangent;
|
||||||
tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri));
|
tangent = uf::vector::normalize(tangent_tri - normal * uf::vector::dot(normal, tangent_tri));
|
||||||
|
|
||||||
if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f)
|
if (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent_tri) < 0.0f)
|
||||||
@ -327,7 +322,6 @@ for ( auto& p : m.primitives ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sanitizer.windingOrder.should && !graph.metadata["renderer"]["invert"].as<bool>(true) ) {
|
if ( sanitizer.windingOrder.should && !graph.metadata["renderer"]["invert"].as<bool>(true) ) {
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
#if BARYCENTRIC
|
#if BARYCENTRIC
|
||||||
// 0 keeps a buffer for barycentric coordinates, 1 will reconstruct in the deferred pass
|
// 0 keeps a buffer for barycentric coordinates, 1 will reconstruct in the deferred pass
|
||||||
#ifndef BARYCENTRIC_CALCULATE
|
#ifndef BARYCENTRIC_CALCULATE
|
||||||
#define BARYCENTRIC_CALCULATE 0
|
#define BARYCENTRIC_CALCULATE 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -228,7 +228,7 @@ void impl::buildMeshBVH( pod::BVH& bvh, const uf::Mesh& mesh, pod::BVH::index_t
|
|||||||
|
|
||||||
auto tris = view.index.count / 3;
|
auto tris = view.index.count / 3;
|
||||||
for ( auto triIndexID = 0; triIndexID < tris; ++triIndexID ) {
|
for ( auto triIndexID = 0; triIndexID < tris; ++triIndexID ) {
|
||||||
auto tri = impl::fetchTriangle( view, indices, positions, triIndexID );
|
auto tri = uf::mesh::fetchTriangle( view, indices, positions, triIndexID );
|
||||||
auto aabb = impl::computeTriangleAABB( tri );
|
auto aabb = impl::computeTriangleAABB( tri );
|
||||||
auto triID = triIndexID + (view.index.first / 3);
|
auto triID = triIndexID + (view.index.first / 3);
|
||||||
|
|
||||||
@ -446,7 +446,7 @@ void impl::refitBVH( pod::BVH& bvh, const uf::Mesh& mesh ) {
|
|||||||
|
|
||||||
auto tris = view.index.count / 3;
|
auto tris = view.index.count / 3;
|
||||||
for ( auto triIndexID = 0; triIndexID < tris; ++triIndexID ) {
|
for ( auto triIndexID = 0; triIndexID < tris; ++triIndexID ) {
|
||||||
auto tri = impl::fetchTriangle( view, indices, positions, triIndexID );
|
auto tri = uf::mesh::fetchTriangle( view, indices, positions, triIndexID );
|
||||||
auto aabb = impl::computeTriangleAABB( tri );
|
auto aabb = impl::computeTriangleAABB( tri );
|
||||||
bounds.emplace_back(aabb);
|
bounds.emplace_back(aabb);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -500,98 +500,9 @@ pod::Vector3f impl::triangleNormal( const pod::TriangleWithNormal& tri ) {
|
|||||||
if ( uf::vector::magnitude( tri.normal ) < 0.001f ) return impl::triangleNormal( (const pod::Triangle&) tri );
|
if ( uf::vector::magnitude( tri.normal ) < 0.001f ) return impl::triangleNormal( (const pod::Triangle&) tri );
|
||||||
return tri.normal;
|
return tri.normal;
|
||||||
}
|
}
|
||||||
// mesh accessing
|
|
||||||
size_t impl::getIndex( const void* pointer, size_t stride, size_t index ) {
|
|
||||||
#define CAST_INDEX(T) case sizeof(T): return ((T*) pointer)[index];
|
|
||||||
switch ( stride ) {
|
|
||||||
CAST_INDEX(uint8_t);
|
|
||||||
CAST_INDEX(uint16_t);
|
|
||||||
CAST_INDEX(uint32_t);
|
|
||||||
default: {
|
|
||||||
UF_EXCEPTION("invalid stride type: {}", stride);
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size_t impl::getIndex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, size_t index ) {
|
|
||||||
return impl::getIndex( indices.data(view.index.first), indices.stride(), index );
|
|
||||||
}
|
|
||||||
pod::Vector3f impl::getVertex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& positions, size_t index ) {
|
|
||||||
const auto stride = positions.stride();
|
|
||||||
#define CAST_VERTEX(T) {\
|
|
||||||
const T* vertices = (T*) positions.data(view.vertex.first + index);\
|
|
||||||
return { vertices[0], vertices[1], vertices[2], };\
|
|
||||||
}
|
|
||||||
#define DEQUANTIZE_VERTEX(T) {\
|
|
||||||
const T* vertices = (T*) positions.data(view.vertex.first + index);\
|
|
||||||
return { uf::quant::dequantize(vertices[0]), uf::quant::dequantize(vertices[1]), uf::quant::dequantize(vertices[2]), };\
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( positions.attribute.descriptor.type ) {
|
|
||||||
// dequantize
|
|
||||||
case uf::renderer::enums::Type::USHORT:
|
|
||||||
case uf::renderer::enums::Type::SHORT: {
|
|
||||||
DEQUANTIZE_VERTEX(uint16_t);
|
|
||||||
} break;
|
|
||||||
case uf::renderer::enums::Type::FLOAT: {
|
|
||||||
CAST_VERTEX(float);
|
|
||||||
} break;
|
|
||||||
#if UF_USE_FLOAT16
|
|
||||||
case uf::renderer::enums::Type::HALF: {
|
|
||||||
CAST_VERTEX(std::float16_t);
|
|
||||||
} break;
|
|
||||||
#endif
|
|
||||||
#if UF_USE_BFLOAT16
|
|
||||||
case uf::renderer::enums::Type::BFLOAT: {
|
|
||||||
CAST_VERTEX(std::bfloat16_t);
|
|
||||||
} break;
|
|
||||||
#endif
|
|
||||||
default: UF_EXCEPTION("unsupported vertex type: {}", positions.attribute.descriptor.type); break;
|
|
||||||
}
|
|
||||||
// return impl::getVertex( positions.data(view.vertex.first), positions.stride(), index );
|
|
||||||
}
|
|
||||||
|
|
||||||
pod::Triangle impl::fetchTriangle( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, const uf::Mesh::AttributeView& positions, size_t triID ) {
|
|
||||||
auto index = triID * 3;
|
|
||||||
pod::Triangle tri;
|
|
||||||
FOR_EACH(3, {
|
|
||||||
tri.points[i] = impl::getVertex( view, positions, impl::getIndex( view, indices, index + i ) );
|
|
||||||
});
|
|
||||||
return tri;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for clean code, this would be preferable
|
|
||||||
// but this incurs two lookups every triangle fetch, and I doubt the optimizer will optimize that away, so explicitly passing attribute views is preferable
|
|
||||||
pod::Triangle impl::fetchTriangle( const uf::Mesh::View& view, size_t triID ) {
|
|
||||||
return impl::fetchTriangle( view, view["index"], view["position"], triID );
|
|
||||||
}
|
|
||||||
|
|
||||||
pod::TriangleWithNormal impl::fetchTriangle( const uf::Mesh& mesh, size_t triID ) {
|
|
||||||
const auto& views = mesh.buffer_views;
|
|
||||||
UF_ASSERT(!views.empty());
|
|
||||||
|
|
||||||
// find which view contains this triangle index.
|
|
||||||
size_t triBase = 0;
|
|
||||||
const uf::Mesh::View* view = nullptr;
|
|
||||||
for ( auto& v : views ) {
|
|
||||||
auto trisInView = v.index.count / 3;
|
|
||||||
if (triID < triBase + trisInView) {
|
|
||||||
view = &v;
|
|
||||||
triID -= triBase; // local triangle index inside this view
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
triBase += trisInView;
|
|
||||||
}
|
|
||||||
UF_ASSERT( view );
|
|
||||||
|
|
||||||
pod::TriangleWithNormal tri = { impl::fetchTriangle( *view, triID ) };
|
|
||||||
tri.normal = uf::vector::normalize(uf::vector::cross(tri.points[1] - tri.points[0], tri.points[2] - tri.points[0]));
|
|
||||||
|
|
||||||
return tri;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if body is a mesh, apply its transform to the triangles, else reorient the normal with respect to the body
|
// if body is a mesh, apply its transform to the triangles, else reorient the normal with respect to the body
|
||||||
pod::TriangleWithNormal impl::fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::PhysicsBody& body ) {
|
pod::TriangleWithNormal impl::fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::PhysicsBody& body ) {
|
||||||
auto tri = impl::fetchTriangle( mesh, triID );
|
auto tri = uf::mesh::fetchTriangle( mesh, triID );
|
||||||
|
|
||||||
auto transform = impl::getTransform( body );
|
auto transform = impl::getTransform( body );
|
||||||
|
|
||||||
@ -646,7 +557,7 @@ pod::AABB impl::computeTriangleAABB( const pod::Triangle& tri ) {
|
|||||||
// returns the AABB of a hull
|
// returns the AABB of a hull
|
||||||
pod::AABB impl::computeConvexHullAABB( const uf::Mesh::View& view, const uf::Mesh::AttributeView& positions, pod::AABB bounds ) {
|
pod::AABB impl::computeConvexHullAABB( const uf::Mesh::View& view, const uf::Mesh::AttributeView& positions, pod::AABB bounds ) {
|
||||||
for ( size_t i = 0; i < view.vertex.count; ++i ) {
|
for ( size_t i = 0; i < view.vertex.count; ++i ) {
|
||||||
pod::Vector3f v = impl::getVertex( view, positions, i );
|
pod::Vector3f v = uf::mesh::fetchVertex( view, positions, i );
|
||||||
bounds.min = uf::vector::min( bounds.min, v );
|
bounds.min = uf::vector::min( bounds.min, v );
|
||||||
bounds.max = uf::vector::max( bounds.max, v );
|
bounds.max = uf::vector::max( bounds.max, v );
|
||||||
}
|
}
|
||||||
|
|||||||
@ -154,7 +154,7 @@ void impl::getSupportFace( const pod::PhysicsBody& body, const pod::Vector3f& di
|
|||||||
auto& indices = view["index"];
|
auto& indices = view["index"];
|
||||||
auto& positions = view["position"];
|
auto& positions = view["position"];
|
||||||
for ( size_t i = 0; i < view.index.count / 3; ++i ) {
|
for ( size_t i = 0; i < view.index.count / 3; ++i ) {
|
||||||
pod::Triangle tri = impl::fetchTriangle( view, indices, positions, i );
|
pod::Triangle tri = uf::mesh::fetchTriangle( view, indices, positions, i );
|
||||||
pod::Vector3f normal = impl::triangleNormal( tri );
|
pod::Vector3f normal = impl::triangleNormal( tri );
|
||||||
float d = uf::vector::dot( normal, localDir );
|
float d = uf::vector::dot( normal, localDir );
|
||||||
if ( d > bestDot ) {
|
if ( d > bestDot ) {
|
||||||
|
|||||||
@ -68,7 +68,7 @@ pod::Vector3f impl::support( const pod::PhysicsBody& body, const pod::Vector3f&
|
|||||||
const auto& view = mesh.buffer_views[viewIdx];
|
const auto& view = mesh.buffer_views[viewIdx];
|
||||||
auto& positions = view["position"];
|
auto& positions = view["position"];
|
||||||
for ( size_t i = 0; i < view.vertex.count; ++i ) {
|
for ( size_t i = 0; i < view.vertex.count; ++i ) {
|
||||||
pod::Vector3f v = impl::getVertex( view, positions, i );
|
pod::Vector3f v = uf::mesh::fetchVertex( view, positions, i );
|
||||||
float dist = uf::vector::dot( v, localDir );
|
float dist = uf::vector::dot( v, localDir );
|
||||||
if ( dist > maxDist ) {
|
if ( dist > maxDist ) {
|
||||||
maxDist = dist;
|
maxDist = dist;
|
||||||
|
|||||||
@ -142,7 +142,7 @@ bool impl::obbObb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Ma
|
|||||||
|
|
||||||
|
|
||||||
bool impl::obbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold ) {
|
bool impl::obbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold ) {
|
||||||
ASSERT_COLLIDER_TYPES( OBB, OBB );
|
ASSERT_COLLIDER_TYPES( OBB, AABB );
|
||||||
|
|
||||||
auto tA = impl::getTransform( a );
|
auto tA = impl::getTransform( a );
|
||||||
auto tB = impl::getTransform( b );
|
auto tB = impl::getTransform( b );
|
||||||
|
|||||||
@ -243,7 +243,7 @@ bool impl::rayMesh( const pod::Ray& r, const pod::PhysicsBody& body, pod::RayQue
|
|||||||
impl::queryBVH( bvh, ray, candidates );
|
impl::queryBVH( bvh, ray, candidates );
|
||||||
|
|
||||||
for ( auto triID : candidates ) {
|
for ( auto triID : candidates ) {
|
||||||
auto tri = impl::fetchTriangle( meshData, triID );
|
auto tri = uf::mesh::fetchTriangle( meshData, triID );
|
||||||
|
|
||||||
float t, u, v;
|
float t, u, v;
|
||||||
if ( !impl::rayTriangleIntersect( ray, tri, t, u, v ) ) continue;
|
if ( !impl::rayTriangleIntersect( ray, tri, t, u, v ) ) continue;
|
||||||
|
|||||||
@ -757,3 +757,53 @@ void uf::Mesh::_insertIs( uf::Mesh::Input& input, const void* data, size_t size,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
size_t uf::mesh::fetchIndex( const void* pointer, size_t stride, size_t index ) {
|
||||||
|
#define CAST_INDEX(T) case sizeof(T): return ((T*) pointer)[index];
|
||||||
|
switch ( stride ) {
|
||||||
|
CAST_INDEX(uint8_t);
|
||||||
|
CAST_INDEX(uint16_t);
|
||||||
|
CAST_INDEX(uint32_t);
|
||||||
|
default: {
|
||||||
|
UF_EXCEPTION("invalid stride type: {}", stride);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pod::Vector3f uf::mesh::fetchVertex( const uf::Mesh::View& view, const uf::Mesh::AttributeView& positions, size_t index ) {
|
||||||
|
return uf::mesh::fetchVertexAttribute<pod::Vector3f>( view, positions, index );
|
||||||
|
}
|
||||||
|
|
||||||
|
pod::Triangle uf::mesh::fetchTriangle( const uf::Mesh::View& view, const uf::Mesh::AttributeView& indices, const uf::Mesh::AttributeView& positions, size_t triID ) {
|
||||||
|
auto index = triID * 3;
|
||||||
|
pod::Triangle tri;
|
||||||
|
FOR_EACH(3, {
|
||||||
|
tri.points[i] = uf::mesh::fetchVertex( view, positions, uf::mesh::fetchIndex( view, indices, index + i ) );
|
||||||
|
});
|
||||||
|
return tri;
|
||||||
|
}
|
||||||
|
|
||||||
|
pod::TriangleWithNormal uf::mesh::fetchTriangle( const uf::Mesh& mesh, size_t triID ) {
|
||||||
|
const auto& views = mesh.buffer_views;
|
||||||
|
UF_ASSERT(!views.empty());
|
||||||
|
|
||||||
|
// find which view contains this triangle index.
|
||||||
|
size_t triBase = 0;
|
||||||
|
const uf::Mesh::View* view = nullptr;
|
||||||
|
for ( auto& v : views ) {
|
||||||
|
auto trisInView = v.index.count / 3;
|
||||||
|
if (triID < triBase + trisInView) {
|
||||||
|
view = &v;
|
||||||
|
triID -= triBase; // local triangle index inside this view
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
triBase += trisInView;
|
||||||
|
}
|
||||||
|
UF_ASSERT( view );
|
||||||
|
|
||||||
|
pod::TriangleWithNormal tri = { uf::mesh::fetchTriangle( *view, triID ) };
|
||||||
|
tri.normal = uf::vector::normalize(uf::vector::cross(tri.points[1] - tri.points[0], tri.points[2] - tri.points[0]));
|
||||||
|
|
||||||
|
return tri;
|
||||||
|
}
|
||||||
@ -56,7 +56,7 @@ namespace {
|
|||||||
pod::Vector4f tangent;
|
pod::Vector4f tangent;
|
||||||
};
|
};
|
||||||
struct TexCoord {
|
struct TexCoord {
|
||||||
pod::ColorRgba color;
|
pod::Vector4b color;
|
||||||
pod::Vector2f16 uv;
|
pod::Vector2f16 uv;
|
||||||
pod::Vector2f st;
|
pod::Vector2f st;
|
||||||
pod::Vector2f16 wx;
|
pod::Vector2f16 wx;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user