render entity information, properly handle when there's no lines/strings to render (as it would never update the buffers to say theres nothing to draw), skip resolving manifold contacts if a body is a trigger (idle thought told me that i needed to do this before i bother with triggers)
This commit is contained in:
parent
4f03712001
commit
90758175ca
@ -16,6 +16,12 @@
|
||||
#define M_PI 3.141592653589793f
|
||||
#endif
|
||||
|
||||
#define EPS 1.0e-6f
|
||||
#define EPS2 (EPS * EPS)
|
||||
|
||||
#define RAD_2_DEG (180.0f / M_PI)
|
||||
#define DEG_2_RAD (M_PI / 180.0f)
|
||||
|
||||
namespace pod {
|
||||
namespace Math {
|
||||
typedef float num_t;
|
||||
|
||||
@ -16,9 +16,6 @@
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
|
||||
#define EPS 1.0e-6f
|
||||
#define EPS2 (EPS * EPS)
|
||||
#define ASSERT_COLLIDER_TYPES( A, B ) UF_ASSERT( a.collider.type == pod::ShapeType::A && b.collider.type == pod::ShapeType::B );
|
||||
|
||||
#define REORIENT_NORMALS_ON_FETCH 0
|
||||
|
||||
@ -150,14 +150,12 @@ template<typename T> pod::Quaternion<T> uf::quaternion::axisAngle( const pod::Ve
|
||||
return uf::quaternion::normalize( q );
|
||||
}
|
||||
template<typename T> pod::Quaternion<T> uf::quaternion::unitVectors( const pod::Vector3t<T>& u, const pod::Vector3t<T>& v ) {
|
||||
static const T EPSILON = static_cast<T>(1e-6);
|
||||
|
||||
pod::Vector3t<T> uNorm = uf::vector::normalize( u );
|
||||
pod::Vector3t<T> vNorm = uf::vector::normalize( v );
|
||||
|
||||
T dot = uf::vector::dot( uNorm, vNorm );
|
||||
|
||||
if ( dot < -1 + EPSILON ) {
|
||||
if ( dot < -1 + EPS ) {
|
||||
pod::Vector3t<T> orthogonal = (fabs(uNorm.x) > fabs(uNorm.z)) ? pod::Vector3t<T>{ -uNorm.y, uNorm.x, 0 } : pod::Vector3t<T>{ 0, -uNorm.z, uNorm.y };
|
||||
orthogonal = uf::vector::normalize( orthogonal );
|
||||
return uf::quaternion::axisAngle( orthogonal, static_cast<T>(M_PI) );
|
||||
|
||||
@ -171,7 +171,7 @@ namespace uf {
|
||||
template<typename T> /*FORCE_INLINE*/ T /*UF_API*/ orthonormalize( const T& x, const T& y ); // orthonormalizes a vector against another vector
|
||||
|
||||
template<typename T> /*FORCE_INLINE*/ size_t /*UF_API*/ hash( const T& vector ); // hashes a vector
|
||||
template<typename T> /*FORCE_INLINE*/ uf::stl::string /*UF_API*/ toString( const T& vector ); // parses a vector as a string
|
||||
template<typename T> /*FORCE_INLINE*/ uf::stl::string /*UF_API*/ toString( const T& vector, const uf::stl::string& = "Vector({})" ); // parses a vector as a string
|
||||
template<typename T, size_t N> /*FORCE_INLINE*/ ext::json::Value encode( const pod::Vector<T,N>& v, const ext::json::EncodingSettings& = {} ); // parses a vector into a JSON value
|
||||
|
||||
template<typename T, size_t N> /*FORCE_INLINE*/ pod::Vector<T,N>& decode( const ext::json::Value& v, pod::Vector<T,N>& ); // parses a JSON value into a vector
|
||||
@ -273,7 +273,7 @@ DEFINE_VECTOR_EXT(T, 4);
|
||||
// stringify
|
||||
namespace uf {
|
||||
namespace string {
|
||||
template<typename T, size_t N> FORCE_INLINE uf::stl::string toString( const pod::Vector<T,N>& v );
|
||||
template<typename T, size_t N> FORCE_INLINE uf::stl::string toString( const pod::Vector<T,N>& v, const uf::stl::string& = "Vector({})" );
|
||||
}
|
||||
}
|
||||
// jsonify
|
||||
|
||||
@ -794,16 +794,13 @@ size_t uf::vector::hash( const T& v ) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
uf::stl::string uf::vector::toString( const T& v ) {
|
||||
uf::stl::string uf::vector::toString( const T& v, const uf::stl::string& s ) {
|
||||
uf::stl::stringstream ss;
|
||||
ss << "Vector(";
|
||||
#pragma unroll // GCC unroll T::size
|
||||
for ( auto i = 0; i < T::size; ++i ) {
|
||||
FOR_EACH( T::size, {
|
||||
ss << v[i];
|
||||
if ( i + 1 < T::size ) ss << ", ";
|
||||
}
|
||||
ss << ")";
|
||||
return ss.str();
|
||||
});
|
||||
return ::fmt::format( fmt::runtime(s), ss.str() );
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#include "pod.inl"
|
||||
|
||||
template<typename T, size_t N>
|
||||
uf::stl::string /*UF_API*/ uf::string::toString( const pod::Vector<T,N>& v ) {
|
||||
return uf::vector::toString(v);
|
||||
uf::stl::string /*UF_API*/ uf::string::toString( const pod::Vector<T,N>& v, const uf::stl::string& s ) {
|
||||
return uf::vector::toString(v, s);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
|
||||
@ -172,8 +172,8 @@ uf::Entity* uf::Entity::globalFindByName( const uf::stl::string& name ) {
|
||||
|
||||
uf::stl::string uf::string::toString( const uf::Entity& entity ) {
|
||||
#if UF_USE_FMT
|
||||
return ::fmt::format("{} ({}): {}", entity.getName(), entity.getUid(), (void*) &entity);
|
||||
return ::fmt::format("({}): {}", entity.getUid(), entity.getName());
|
||||
#else
|
||||
return entity.getName() + " (" + std::to_string(entity.getUid()) + "): " + std::to_string(&entity);
|
||||
return "(" + std::to_string(entity.getUid()) + ") :" + entity.getName();
|
||||
#endif
|
||||
}
|
||||
@ -426,8 +426,8 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
|
||||
metadata.system.noclipped = state;
|
||||
if ( !state ) {
|
||||
uf::physics::setGravity( physicsBody );
|
||||
uf::physics::setColliderCategory( physicsBody, "ALL");
|
||||
uf::physics::setColliderMask( physicsBody, "ALL");
|
||||
uf::physics::setColliderCategory( physicsBody, "DYNAMIC");
|
||||
uf::physics::setColliderMask( physicsBody, "DYNAMIC");
|
||||
} else {
|
||||
uf::physics::setGravity( physicsBody, pod::Vector3f{0,0,0});
|
||||
uf::physics::setColliderCategory( physicsBody, "NONE");
|
||||
|
||||
@ -40,7 +40,7 @@ namespace impl {
|
||||
pod::GlyphSettings textSettings = {
|
||||
.alignment = "center",
|
||||
.font = "FragmentMono.ttf",
|
||||
.size = 96,
|
||||
.size = 24,
|
||||
.sdf = false,
|
||||
};
|
||||
}
|
||||
@ -220,20 +220,26 @@ void uf::debug::drawLines( float dt ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( impl::lines.empty() ) return;
|
||||
// double buffer
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<impl::Vertex>, lines);
|
||||
std::swap( impl::lines, lines );
|
||||
|
||||
impl::lineMesh.clear();
|
||||
impl::lineMesh.bind<impl::Vertex>();
|
||||
|
||||
// to-do: only do this when the previous mesh already had lines in it
|
||||
// and if it was already empty just return
|
||||
if ( lines.empty() ) {
|
||||
lines.emplace_back( impl::Vertex{} );
|
||||
lines.emplace_back( impl::Vertex{} );
|
||||
}
|
||||
|
||||
impl::lineMesh.insertVertices<impl::Vertex>(lines);
|
||||
impl::lineMesh.generateIndirect();
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& graphics = scene.getComponent<uf::renderer::Graphics>();
|
||||
|
||||
auto& graphic = graphics["immediate:lines"];
|
||||
|
||||
if ( !graphic.initialized ) {
|
||||
graphic.device = &uf::renderer::device;
|
||||
graphic.material.device = &uf::renderer::device;
|
||||
@ -275,8 +281,6 @@ void uf::debug::drawText( const uf::stl::string& string, const pod::Vector3f& po
|
||||
}
|
||||
|
||||
void uf::debug::drawTexts( float dt ) {
|
||||
if ( impl::texts.empty() ) return;
|
||||
// double buffer
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<impl::Text>, texts);
|
||||
std::swap( impl::texts, texts );
|
||||
|
||||
@ -287,7 +291,7 @@ void uf::debug::drawTexts( float dt ) {
|
||||
|
||||
uf::stl::vector<pod::GlyphBox> textLayout;
|
||||
// pre-init with ASCII characters
|
||||
if ( !impl::textAtlas.generated() ) {
|
||||
if ( !impl::textAtlas.generated() || texts.empty() ) {
|
||||
uf::stl::string ascii = "";
|
||||
for ( char c = 32; c < 127; ++c ) ascii += c;
|
||||
auto tokens = uf::glyph::parseTextTokens( ascii, {0,0,0,0} );
|
||||
|
||||
@ -342,6 +342,9 @@ void impl::warmupManifold( pod::PhysicsBody& a, pod::PhysicsBody& b, const pod::
|
||||
}
|
||||
|
||||
void impl::resolveManifold( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) {
|
||||
// ignore if a body is a trigger
|
||||
if ( (a.collider.category & pod::Collider::CATEGORY_TRIGGER) || (b.collider.category & pod::Collider::CATEGORY_TRIGGER) ) return;
|
||||
|
||||
if ( uf::physics::settings.blockContactSolver ) {
|
||||
if ( impl::blockSolver( a, b, manifold, dt ) ) return;
|
||||
}
|
||||
|
||||
@ -55,37 +55,35 @@ void impl::drawBody( const pod::PhysicsBody& body ) {
|
||||
auto cameraAxes = uf::transform::axes( cameraTransform );
|
||||
auto& projection = camera.getProjection();
|
||||
auto fov = std::atan(1.0f / fabs(projection(1,1)));
|
||||
auto viewThreshold = std::cos(fov * 1.5f);
|
||||
auto angleThreshold = std::cos(fov * 1.5f);
|
||||
auto viewThresholdSq = std::pow(5, 2);
|
||||
|
||||
#if 1
|
||||
// (an attempt to) continuously pick the closest point on the AABB
|
||||
// continuously pick the closest point on the AABB
|
||||
auto position = impl::closestPointOnAABB( cameraTransform.position, bounds );
|
||||
auto dir = position - cameraTransform.position;
|
||||
auto magSq = uf::vector::magnitude( dir );
|
||||
if ( magSq > EPS2 ) dir /= std::sqrt( magSq );
|
||||
auto dot = uf::vector::dot( cameraAxes.forward, dir );
|
||||
position -= cameraAxes.forward * 0.1f;
|
||||
if ( dot > viewThreshold ) uf::debug::drawText( body.object->getName(), position );
|
||||
#else
|
||||
// picks the closest corner
|
||||
int closestCorner = -1;
|
||||
float closestDistanceSq = FLT_MAX;
|
||||
float closestDot = FLT_MAX; //
|
||||
pod::Vector3f corners[8];
|
||||
impl::getCorners( bounds, corners );
|
||||
for ( auto i = 0; i < 8; ++i ) {
|
||||
auto dir = corners[i] - cameraTransform.position;
|
||||
auto distanceSq = uf::vector::magnitude( dir );
|
||||
if ( distanceSq > EPS2 ) dir /= std::sqrt( distanceSq );
|
||||
auto dot = uf::vector::dot( cameraAxes.forward, dir );
|
||||
if ( dot <= viewThreshold ) continue;
|
||||
if ( distanceSq >= closestDistanceSq ) continue;
|
||||
closestDistanceSq = distanceSq;
|
||||
closestCorner = i;
|
||||
}
|
||||
|
||||
if ( 0 <= closestCorner ) uf::debug::drawText( body.object->getName(), corners[closestCorner] );
|
||||
#endif
|
||||
if ( magSq < viewThresholdSq && dot > angleThreshold ) {
|
||||
STATIC_THREAD_LOCAL(uf::stl::vector<uf::stl::string>, strings);
|
||||
strings.emplace_back( ::fmt::format("{}\n", uf::string::toString( *body.object ) ) );
|
||||
strings.emplace_back( ::fmt::format("Mass: {:.3f} kg\n", body.inverseMass == 0.0f ? 0.0f : 1.0f / body.inverseMass) );
|
||||
strings.emplace_back( ::fmt::format(
|
||||
"Position: {} | Pitch: {:.1f} | Yaw: {:.1f} | Roll: {:.1f}\n",
|
||||
uf::vector::toString( transform.position, "{}" ),
|
||||
(RAD_2_DEG) * uf::quaternion::pitch( transform.orientation ),
|
||||
(RAD_2_DEG) * uf::quaternion::yaw( transform.orientation ),
|
||||
(RAD_2_DEG) * uf::quaternion::roll( transform.orientation )
|
||||
) );
|
||||
if ( body.velocity != pod::Vector3f{} && body.angularVelocity != pod::Vector3f{} ) {
|
||||
strings.emplace_back( ::fmt::format( "Velocity: {} | Angular Velocity: {}\n", uf::vector::toString( body.velocity, "{}" ), uf::vector::toString( body.angularVelocity, "{}" ) ) );
|
||||
}
|
||||
strings.emplace_back( ::fmt::format("Awake: {} | Timer: {:.3f} | Grounded: {}\n", body.activity.awake, body.activity.sleepTimer, body.activity.grounded) );
|
||||
strings.emplace_back( ::fmt::format("Category: {:#X} | Mask: {:#X}", body.collider.category, body.collider.mask) );
|
||||
uf::debug::drawText( uf::string::join(strings, ""), position );
|
||||
}
|
||||
}
|
||||
void impl::drawConstraint( const pod::Constraint& constraint ) {
|
||||
if ( !uf::physics::settings.debugDraw.constraints ) return;
|
||||
|
||||
@ -300,9 +300,6 @@ void uf::glyph::generateMesh( const uf::stl::vector<pod::GlyphBox>& layout, cons
|
||||
for ( const auto& g : layout ) {
|
||||
auto hash = std::to_string( uf::glyph::hashSettings(g.code, metadata) );
|
||||
|
||||
// zero-width
|
||||
if ( g.box.w == 0 || g.box.h == 0 || g.color.w == 0.0f ) continue;
|
||||
|
||||
#if EXT_COLOR_FLOATS
|
||||
auto& color = g.color;
|
||||
#else
|
||||
|
||||
Loading…
Reference in New Issue
Block a user