Created
January 7, 2016 01:34
-
-
Save axjxwright/d28e3dfde355297214a4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cinder/app/App.h" | |
#include "cinder/app/RendererGl.h" | |
#include "cinder/gl/gl.h" | |
#include "cinder/Rand.h" | |
#include "cinder/Camera.h" | |
#include "cinder/CameraUi.h" | |
#include "cinder/ip/Checkerboard.h" | |
using namespace ci; | |
using namespace ci::app; | |
using namespace std; | |
struct Quad | |
{ | |
vec3 position; | |
vec3 scale; | |
quat rotation; | |
mat4 transform; | |
mat4 inverseTransform; | |
vec3 normal; | |
vec3 a, b, c, d; | |
vec2 hitPosition; | |
Quad ( const vec3& p, const vec3& s, const quat& r ) | |
: position(p) | |
, scale(s) | |
, rotation(r) | |
{ | |
transform = glm::translate(p) * toMat4(r) * glm::scale(s); | |
inverseTransform = glm::inverse ( transform ); | |
normal = glm::normalize ( vec3 ( transform * vec4 ( 0, 0, 1, 0 ) ) ); | |
a = vec3 ( transform * vec4 ( -0.5, -0.5, 0, 1 ) ); | |
b = vec3 ( transform * vec4 ( 0.5, -0.5, 0, 1 ) ); | |
c = vec3 ( transform * vec4 ( 0.5, 0.5, 0, 1 ) ); | |
d = vec3 ( transform * vec4 ( -0.5, 0.5, 0, 1 ) ); | |
} | |
bool intersectsRay ( const Ray& ray, vec3& result ) | |
{ | |
float r = 0.0f; | |
if ( ray.calcTriangleIntersection ( a, b, c, &r ) ) | |
{ | |
result = ray.calcPosition(r); | |
hitPosition = vec2 ( inverseTransform * vec4 ( result, 1.0f ) ); | |
return true; | |
} | |
if ( ray.calcTriangleIntersection ( a, d, c, &r ) ) | |
{ | |
result = ray.calcPosition(r); | |
hitPosition = vec2 ( inverseTransform * vec4 ( result, 1.0f ) ); | |
return true; | |
} | |
return false; | |
} | |
}; | |
class QuadsApp : public App | |
{ | |
public: | |
static void init ( App::Settings * settings ); | |
void setup ( ) override; | |
void draw ( ) override; | |
void rayCast ( const MouseEvent& event ); | |
std::vector<Quad> _quads; | |
gl::BatchRef _quadBatch; | |
CameraPersp _camera; | |
CameraUi _camUi; | |
int _hitIndex{-1}; | |
gl::TextureRef _texture; | |
}; | |
void QuadsApp::init ( App::Settings * settings ) | |
{ | |
settings->setWindowSize ( 1280, 720 ); | |
} | |
void QuadsApp::setup() | |
{ | |
for ( uint32_t i = 0; i < 100; i++ ) | |
{ | |
vec3 pos = vec3{Rand::randFloat(-1, 1), Rand::randFloat(-1, 1), Rand::randFloat(-1, 1)} * 300.0f; | |
vec3 scale = vec3{Rand::randFloat(0.01, 1), Rand::randFloat(0.01, 1), Rand::randFloat(0.01, 1)} * 100.0f; | |
quat rot = glm::normalize(quat{Rand::randFloat(-1, 1), Rand::randFloat(-1, 1), Rand::randFloat(-1, 1), Rand::randFloat(-1, 1)}); | |
_quads.emplace_back(pos, scale, rot); | |
} | |
getWindow()->getSignalMouseDown().connect( std::bind ( &QuadsApp::rayCast, this, std::placeholders::_1 ) ); | |
_camera = CameraPersp ( getWindowWidth(), getWindowHeight(), 60.0f, 0.1f, 10000.0f ); | |
_camera.lookAt(vec3(0), vec3(0, 0, 1)); | |
_camUi = CameraUi ( &_camera, getWindow() ); | |
_texture = gl::Texture::create ( ip::checkerboard( 128, 128 ) ); | |
_quadBatch = gl::Batch::create( geom::Rect().rect( Rectf ( -0.5, -0.5, 0.5, 0.5 ) ), gl::getStockShader( gl::ShaderDef().color().texture() ) ); | |
} | |
void QuadsApp::rayCast ( const MouseEvent& event ) | |
{ | |
// Should probably sort quads by distance to the camera. | |
vec2 uv = vec2(event.getPos()) / vec2(getWindowSize()); | |
Ray r = _camera.generateRay(uv.x, 1.0f - uv.y, getWindowAspectRatio()); | |
_hitIndex = -1; | |
int counter = 0; | |
for ( auto& q : _quads ) | |
{ | |
vec3 hit; | |
if ( q.intersectsRay( r, hit ) ) | |
{ | |
if ( _camera.worldToEye(hit).z < 0.0f ) // in front | |
{ | |
_hitIndex = counter; | |
break; | |
} | |
} | |
counter++; | |
} | |
} | |
void QuadsApp::draw() | |
{ | |
gl::clear( Color( 0, 0, 0 ) ); | |
gl::setMatrices(_camera); | |
int counter = 0; | |
for ( auto& q : _quads ) | |
{ | |
bool isSelection = _hitIndex == counter; | |
Color c = isSelection ? Colorf(1, 0, 0) : Colorf::white(); | |
gl::ScopedColor color(c); | |
gl::ScopedModelMatrix m; | |
gl::ScopedTextureBind tex0(_texture); | |
gl::setModelMatrix(q.transform); | |
_quadBatch->draw(); | |
if ( isSelection ) | |
{ | |
gl::ScopedColor color(Colorf(0, 0, 1)); | |
gl::drawSolidRect( Rectf ( q.hitPosition - vec2(0.03), q.hitPosition + vec2(0.03) ) ); | |
} | |
counter++; | |
} | |
} | |
CINDER_APP( QuadsApp, RendererGl, QuadsApp::init ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment