diff options
Diffstat (limited to 'apps/openmb/renderer/EditorHelpers.cpp')
| -rw-r--r-- | apps/openmb/renderer/EditorHelpers.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/apps/openmb/renderer/EditorHelpers.cpp b/apps/openmb/renderer/EditorHelpers.cpp new file mode 100644 index 0000000..9531fb0 --- /dev/null +++ b/apps/openmb/renderer/EditorHelpers.cpp @@ -0,0 +1,148 @@ +#include "EditorHelpers.hpp" +#include <cmath> + +#include <glm/gtc/matrix_inverse.hpp> +#include <vector> + +namespace renderer { +namespace editor { +Mesh makeWireCube ( float size ) { + float h = size * 0.5f; + std::vector<float> verts = { + -h, -h, -h, h, -h, -h, h, -h, -h, h, -h, h, h, -h, h, -h, -h, h, -h, -h, h, -h, -h, -h, + + -h, h, -h, h, h, -h, h, h, -h, h, h, h, h, h, h, -h, h, h, -h, h, h, -h, h, -h, + + -h, -h, -h, -h, h, -h, h, -h, -h, h, h, -h, h, -h, h, h, h, h, -h, -h, h, -h, h, h }; + + Mesh m; + m.createFromPositions( verts, true ); + return m; +} + +Mesh makeCircleWire ( float radius, int segments ) { + if( segments < 3 ) + segments = 3; + + std::vector<float> verts; + verts.reserve( segments * 3 ); + + const float twoPi = 6.28318530717958647692f; + + for( int i = 0; i < segments; ++i ) { + int ni = ( i + 1 ) % segments; + float ti = (float)i / (float)segments; + float angi = ti * twoPi; + float xi = cosf( angi ) * radius; + float zi = sinf( angi ) * radius; + + float tni = (float)ni / (float)segments; + float angni = tni * twoPi; + float xni = cosf( angni ) * radius; + float zni = sinf( angni ) * radius; + + verts.push_back( xi ); + verts.push_back( 0.0f ); + verts.push_back( zi ); + + verts.push_back( xni ); + verts.push_back( 0.0f ); + verts.push_back( zni ); + } + + Mesh m; + m.createFromPositions( verts, true ); + return m; +} + +Mesh makeCircleFilled ( float radius, int segments ) { + if( segments < 3 ) + segments = 3; + + std::vector<float> data; + data.reserve( ( segments + 2 ) * 5 ); + + const float twoPi = 6.28318530717958647692f; + + float cx = 0.0f, cz = 0.0f; + float cu = 0.5f, cv = 0.5f; + + for( int i = 0; i < segments; ++i ) { + int i1 = i; + int i2 = ( i + 1 ) % segments; + + float t1 = (float)i1 / (float)segments; + float ang1 = t1 * twoPi; + float x1 = cosf( ang1 ) * radius; + float z1 = sinf( ang1 ) * radius; + float u1 = ( x1 / ( radius * 2.0f ) ) + 0.5f; + float v1 = ( z1 / ( radius * 2.0f ) ) + 0.5f; + + float t2 = (float)i2 / (float)segments; + float ang2 = t2 * twoPi; + float x2 = cosf( ang2 ) * radius; + float z2 = sinf( ang2 ) * radius; + float u2 = ( x2 / ( radius * 2.0f ) ) + 0.5f; + float v2 = ( z2 / ( radius * 2.0f ) ) + 0.5f; + + data.push_back( cx ); + data.push_back( 0.0f ); + data.push_back( cz ); + data.push_back( cu ); + data.push_back( cv ); + + data.push_back( x1 ); + data.push_back( 0.0f ); + data.push_back( z1 ); + data.push_back( u1 ); + data.push_back( v1 ); + + data.push_back( x2 ); + data.push_back( 0.0f ); + data.push_back( z2 ); + data.push_back( u2 ); + data.push_back( v2 ); + } + + Mesh m; + m.createFromPosTex( data ); + return m; +} + +bool makeRayFromMouse ( const glm::vec2& mousePx, int fbw, int fbh, const glm::mat4& view, + const glm::mat4& proj, const glm::vec3& camPos, glm::vec3& outOrigin, + glm::vec3& outDir ) { + if( fbw <= 0 || fbh <= 0 ) + return false; + + float ndcX = ( mousePx.x / (float)fbw ) * 2.0f - 1.0f; + float ndcY = 1.0f - ( mousePx.y / (float)fbh ) * 2.0f; + + glm::vec4 nearPointNDC( ndcX, ndcY, -1.0f, 1.0f ); + glm::vec4 farPointNDC( ndcX, ndcY, 1.0f, 1.0f ); + + glm::mat4 invPV = glm::inverse( proj * view ); + + glm::vec4 nearWorld = invPV * nearPointNDC; + glm::vec4 farWorld = invPV * farPointNDC; + if( nearWorld.w == 0.0f || farWorld.w == 0.0f ) + return false; + + nearWorld /= nearWorld.w; + farWorld /= farWorld.w; + + glm::vec3 nearPos = glm::vec3( nearWorld ); + glm::vec3 farPos = glm::vec3( farWorld ); + + outOrigin = nearPos; + outDir = glm::normalize( farPos - nearPos ); + + if( !isfinite( outDir.x ) || !isfinite( outDir.y ) || !isfinite( outDir.z ) ) { + outOrigin = camPos; + outDir = glm::normalize( glm::vec3( 0.0f, 0.0f, -1.0f ) ); + } + + return true; +} +} // namespace editor +} // namespace renderer |