From 0403197f4074247832ec11472a966099a3499e4e Mon Sep 17 00:00:00 2001 From: FabienM Date: Mon, 17 Oct 2016 15:52:10 +0200 Subject: [PATCH 1/2] Improvements of VL --- .../Applets/App_GLSL_TransformFeedback.cpp | 156 ++++ .../Applets/App_TransformManipulator.cpp | 537 ++++++++++++ src/examples/tests.hpp | 6 +- src/vlCore/vlnamespace.hpp | 11 + src/vlGraphics/CoreFont.cpp | 507 +++++++++++ src/vlGraphics/CoreFont.hpp | 224 +++++ src/vlGraphics/CoreText.cpp | 819 ++++++++++++----- src/vlGraphics/CoreText.hpp | 55 +- src/vlGraphics/DrawArrays.hpp | 22 + src/vlGraphics/DrawCall.hpp | 17 + src/vlGraphics/DrawElements.hpp | 28 + src/vlGraphics/DrawRangeElements.hpp | 28 + src/vlGraphics/Extrusion.cpp | 12 +- src/vlGraphics/Extrusion.hpp | 2 +- src/vlGraphics/Extrusions.cpp | 237 +++++ src/vlGraphics/Extrusions.hpp | 150 ++++ src/vlGraphics/FontManager.cpp | 33 + src/vlGraphics/FontManager.hpp | 14 + src/vlGraphics/FramebufferObject.cpp | 5 +- src/vlGraphics/GLSL.cpp | 5 + src/vlGraphics/GLSL.hpp | 24 + src/vlGraphics/LineAccessor.hpp | 587 +++++++++++++ src/vlGraphics/LineIterator.hpp | 447 ++++++++++ src/vlGraphics/MultiDrawElements.hpp | 37 + src/vlGraphics/OpenGL.cpp | 12 + src/vlGraphics/OpenGLContext.cpp | 1 + src/vlGraphics/RayIntersector.cpp | 231 ++++- src/vlGraphics/RayIntersector.hpp | 30 +- src/vlGraphics/Renderer.cpp | 14 + src/vlGraphics/Shader.cpp | 2 + src/vlGraphics/Shader.hpp | 5 + src/vlGraphics/TransformFeedback.cpp | 102 +++ src/vlGraphics/TransformFeedback.hpp | 195 ++++ src/vlGraphics/TransformManipulator.cpp | 427 +++++++++ src/vlGraphics/TransformManipulator.hpp | 217 +++++ src/vlGraphics/TriangleAccessor.hpp | 829 ++++++++++++++++++ src/vlWin32/Win32Context.cpp | 18 +- src/vlWin32/Win32Window.cpp | 3 +- 38 files changed, 5781 insertions(+), 268 deletions(-) create mode 100644 src/examples/Applets/App_GLSL_TransformFeedback.cpp create mode 100644 src/examples/Applets/App_TransformManipulator.cpp create mode 100644 src/vlGraphics/CoreFont.cpp create mode 100644 src/vlGraphics/CoreFont.hpp create mode 100644 src/vlGraphics/Extrusions.cpp create mode 100644 src/vlGraphics/Extrusions.hpp create mode 100644 src/vlGraphics/LineAccessor.hpp create mode 100644 src/vlGraphics/LineIterator.hpp create mode 100644 src/vlGraphics/TransformFeedback.cpp create mode 100644 src/vlGraphics/TransformFeedback.hpp create mode 100644 src/vlGraphics/TransformManipulator.cpp create mode 100644 src/vlGraphics/TransformManipulator.hpp create mode 100644 src/vlGraphics/TriangleAccessor.hpp diff --git a/src/examples/Applets/App_GLSL_TransformFeedback.cpp b/src/examples/Applets/App_GLSL_TransformFeedback.cpp new file mode 100644 index 000000000..424615e27 --- /dev/null +++ b/src/examples/Applets/App_GLSL_TransformFeedback.cpp @@ -0,0 +1,156 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#include "BaseDemo.hpp" +#include +#include +#include + +#include +//#include <3rdparty/Khronos/GL/khronos_glext.h> + +using namespace vl; + +class App_GLSL_TransformFeedback: public BaseDemo +{ +public: + App_GLSL_TransformFeedback() + { + } + + void initEvent() + { + if (!Has_GLSL) + { + Log::error("OpenGL Shading Language not supported.\n"); + Time::sleep(2000); + exit(1); + } + + if(!Has_Transform_Feedback) + { + Log::error("Transform Feedback not supported.\n"); + Time::sleep(2000); + exit(1); + } + + trackball()->setPivot(vl::vec3(0.0f, 0.0f, 0.0f)); + + Log::notify(appletInfo()); + } + + void updateScene() + { + + } + + void keyReleaseEvent(unsigned short, EKey key) + { + if(key == Key_T) + { + ref glsl = new GLSLProgram; + + ref transformFeedback_vs = new GLSLVertexShader("/glsl/transform_feedback.vs"); + ref transformFeedback_gs = new GLSLGeometryShader("/glsl/transform_feedback.gs"); + glsl->attachShader(transformFeedback_vs.get()); + glsl->attachShader(transformFeedback_gs.get()); + glsl->bindAttribLocation(VA_Position, "VertexPosition"); + + ref fx = new Effect; + fx->shader()->enable(EN_DEPTH_TEST); + fx->shader()->enable(EN_RASTERIZER_DISCARD); + fx->shader()->setRenderState(glsl.get()); + ref< TransformFeedback > tf = fx->shader()->gocTransformFeedback(); + fx->shader()->setRenderState(tf.get()); + glsl->setTransformFeedback(tf.get()); + std::list< String > varyings; + varyings.push_back("normale"); + tf->setTransformFeedbackVaryings(varyings); + + normales = new ArrayInt1; + normales->resize(6); + + + + tf->addArray(normales.get()); + + tf->set(PT_POINTS); + + ref geom = new Geometry; + geom->setObjectName("Pyramid"); + + ref vert3 = new ArrayFloat3; + geom->setVertexAttribArray(VA_Position, vert3.get()); + + real x = 5.0f / 2.0f; + real y = 10.0f; + real z = 5.0f / 2.0f; + + fvec3 a0( (fvec3)(vec3(+0,+y,+0) + vec3(0.0f, 0.0f, 0.0f)) ); + fvec3 a1( (fvec3)(vec3(-x,+0,-z) + vec3(0.0f, 0.0f, 0.0f)) ); + fvec3 a2( (fvec3)(vec3(-x,-0,+z) + vec3(0.0f, 0.0f, 0.0f)) ); + fvec3 a3( (fvec3)(vec3(+x,-0,+z) + vec3(0.0f, 0.0f, 0.0f)) ); + fvec3 a4( (fvec3)(vec3(+x,+0,-z) + vec3(0.0f, 0.0f, 0.0f)) ); + + ref polys = new DrawArrays(PT_TRIANGLES, 0, 6*3); + geom->drawCalls().push_back( polys.get() ); + + vert3->resize(6*3); + + vert3->at(0) = a4; vert3->at(1) = a2; vert3->at(2) = a1; + vert3->at(3) = a2; vert3->at(4) = a4; vert3->at(5) = a3; + vert3->at(6) = a4; vert3->at(7) = a1; vert3->at(8) = a0; + vert3->at(9) = a1; vert3->at(10) = a2; vert3->at(11) = a0; + vert3->at(12) = a2; vert3->at(13) = a3; vert3->at(14) = a0; + vert3->at(15) = a3; vert3->at(16) = a4; vert3->at(17) = a0; + + ref< Actor > actor = sceneManager()->tree()->addActor( geom.get(), fx.get(), NULL); + + rendering()->render(); + + sceneManager()->tree()->eraseActor(actor.get()); + + tf->updateArray(normales.get()); + + for(unsigned int i = 0; i < normales->size(); ++i) + { + defLogger()->error("primitive " + String::fromUInt(i) + " : " + String::fromDouble(normales->at(i)) + "\n"); + } + } + } + +protected: + ref< ArrayInt1 > normales; +}; + +// Have fun! + +BaseDemo* Create_App_GLSL_TransformFeedback() { return new App_GLSL_TransformFeedback; } diff --git a/src/examples/Applets/App_TransformManipulator.cpp b/src/examples/Applets/App_TransformManipulator.cpp new file mode 100644 index 000000000..e68867bac --- /dev/null +++ b/src/examples/Applets/App_TransformManipulator.cpp @@ -0,0 +1,537 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#include "BaseDemo.hpp" +#include +#include +#include +#include +#include +#include +#include + +#include + +const float screenHeight = 5.0f; + +/* +This applet tests transform manipulator +*/ +class App_TransformManipulator: public BaseDemo +{ +public: + void initEvent() + { + vl::Log::notify(appletInfo()); + + vl::vec4 colorX = vl::vec4(1.0f, 0.0f, 0.0f, 1.0f); + vl::vec4 colorY = vl::vec4(0.0f, 1.0f, 0.0f, 1.0f); + vl::vec4 colorZ = vl::vec4(0.0f, 0.0f, 1.0f, 1.0f); + + /* effect to be applied to the manipulator */ + mEffectX = new vl::Effect; + mEffectY = new vl::Effect; + mEffectZ = new vl::Effect; + + /* uniform used to transform actor */ + mCubeModelMatrixUniform = new vl::Uniform("ModelMatrix"); + mCubeModelMatrixUniform->setUniform(vl::mat4::getIdentity()); + + mPyramidModelMatrixUniform = new vl::Uniform("ModelMatrix"); + mPyramidModelMatrixUniform->setUniform(vl::mat4::getIdentity()); + + mCurrentModelMatrixUniform = mCubeModelMatrixUniform; + + // use context to determine fix size of gizmo + float alpha = std::atan((static_cast< float >(openglContext()->height()) / 2.0f) / 50.0f) * 2.0f; + + //mProjectionGizmoMatrix = new vl::Uniform("ProjectionMatrix"); + + /*mProjectionGizmoMatrix->setUniform(vl::mat4::getPerspective((alpha * 180) / M_PI, static_cast< float >(openglContext()->width()) / static_cast< float >(openglContext()->height()), + 0.001f, 100000.0f));*/ + + vl::ref< vl::Rendering > appletRendering = rendering()->as< vl::Rendering >(); + //appletRendering->camera()->setProjectionPerspective(60.0f, 0.001f, 10000.0f); + appletRendering->camera()->setViewMatrixLookAt(vl::vec3(0.0, 0.0, 50.0f), vl::vec3(0.0, 0.0, 0.0f), vl::vec3(0.0, 1.0, 0.0f)); + + mViewMatrixUniform = new vl::Uniform("ViewMatrix"); + mViewMatrixUniform->setUniform(appletRendering->camera()->viewMatrix()); + + mManipulatorPositionMatrixUniform = new vl::Uniform("ManipulatorPositionMatrix"); + mManipulatorPositionMatrixUniform->setUniform(vl::mat4::getIdentity()); + + mProjectionMatrixUniform = new vl::Uniform("ProjectionMatrix"); + mProjectionMatrixUniform->setUniform(appletRendering->camera()->projectionMatrix()); + + /*mViewMatrixGizmoMatrix = new vl::Uniform("ViewMatrix"); + mViewMatrixGizmoMatrix->setUniform(vl::mat4::getLookAt(vl::vec3(0.0f, 0.0f, 50.0f), vl::vec3(0.0f, 0.0f, 0.0f), vl::vec3(0.0f, 1.0f, 0.0f)));*/ + //mViewMatrixGizmoMatrix->setUniform(appletRendering->camera()->viewMatrix()); + + vl::ref< vl::GLSLVertexShader > vertexShader = new vl::GLSLVertexShader("glsl/transformManipulator.vs"); + vl::ref< vl::GLSLFragmentShader > fragmentShader = new vl::GLSLFragmentShader("glsl/transformManipulator.fs"); + + mEffectX->shader()->enable(vl::EN_DEPTH_TEST); + vl::ref< vl::GLSLProgram > programX = mEffectX->shader()->gocGLSLProgram(); + programX->attachShader(vertexShader.get()); + programX->attachShader(fragmentShader.get()); + programX->bindAttribLocation(vl::VA_Position, "VertexPosition"); + //programX->setUniform(mModelMatrixUniform.get()); + programX->setUniform(mViewMatrixUniform.get()); + //programX->setUniform(mProjectionGizmoMatrix.get()); + programX->setUniform(mProjectionMatrixUniform.get()); + programX->gocUniform("Color")->setUniform(colorX); + programX->setUniform(mManipulatorPositionMatrixUniform.get()); + //programX->gocUniform("ManipulatorPositionMatrix")->setUniform(vl::mat4::getIdentity()); + + + mEffectY->shader()->enable(vl::EN_DEPTH_TEST); + vl::ref< vl::GLSLProgram > programY = mEffectY->shader()->gocGLSLProgram(); + programY->attachShader(vertexShader.get()); + programY->attachShader(fragmentShader.get()); + programY->bindAttribLocation(vl::VA_Position, "VertexPosition"); + //programY->setUniform(mModelMatrixUniform.get()); + programY->setUniform(mViewMatrixUniform.get()); + //programY->setUniform(mProjectionGizmoMatrix.get()); + programY->setUniform(mProjectionMatrixUniform.get()); + programY->gocUniform("Color")->setUniform(colorY); + programY->setUniform(mManipulatorPositionMatrixUniform.get()); + //programY->gocUniform("ManipulatorPositionMatrix")->setUniform(vl::mat4::getIdentity()); + + mEffectZ->shader()->enable(vl::EN_DEPTH_TEST); + vl::ref< vl::GLSLProgram > programZ = mEffectZ->shader()->gocGLSLProgram(); + programZ->attachShader(vertexShader.get()); + programZ->attachShader(fragmentShader.get()); + programZ->bindAttribLocation(vl::VA_Position, "VertexPosition"); + //programZ->setUniform(mModelMatrixUniform.get()); + programZ->setUniform(mViewMatrixUniform.get()); + //programZ->setUniform(mProjectionGizmoMatrix.get()); + programZ->setUniform(mProjectionMatrixUniform.get()); + programZ->gocUniform("Color")->setUniform(colorZ); + programZ->setUniform(mManipulatorPositionMatrixUniform.get()); + //programZ->gocUniform("ManipulatorPositionMatrix")->setUniform(vl::mat4::getIdentity()); + + /*vl::ref< vl::Actor > manipulatorActorX = sceneManager()->tree()->addActor( mTransformManipulatorGeometryX.get(), effectManipulatorX.get(), NULL); + vl::ref< vl::Actor > manipulatorActorY = sceneManager()->tree()->addActor( mTransformManipulatorGeometryY.get(), effectManipulatorY.get(), NULL); + vl::ref< vl::Actor > manipulatorActorZ = sceneManager()->tree()->addActor( mTransformManipulatorGeometryZ.get(), effectManipulatorZ.get(), NULL);*/ + + /*mTransformManipulatorX->setManipulatorActor(manipulatorActorX.get()); + mTransformManipulatorX->setViewMatrixUniform(mViewMatrixUniform.get()); + mTransformManipulatorX->setProjectionMatrixUniform(mProjectionMatrixUniform.get()); + mTransformManipulatorX->setCamera(appletRendering->camera()); + mTransformManipulatorX->setConstraint(vl::TransformManipulator::CONSTRAINT_X); + + mTransformManipulatorY->setManipulatorActor(manipulatorActorY.get()); + mTransformManipulatorY->setViewMatrixUniform(mViewMatrixUniform.get()); + mTransformManipulatorY->setProjectionMatrixUniform(mProjectionMatrixUniform.get()); + mTransformManipulatorY->setCamera(appletRendering->camera()); + mTransformManipulatorY->setConstraint(vl::TransformManipulator::CONSTRAINT_Y); + + mTransformManipulatorZ->setManipulatorActor(manipulatorActorZ.get()); + mTransformManipulatorZ->setViewMatrixUniform(mViewMatrixUniform.get()); + mTransformManipulatorZ->setProjectionMatrixUniform(mProjectionMatrixUniform.get()); + mTransformManipulatorZ->setCamera(appletRendering->camera()); + mTransformManipulatorZ->setConstraint(vl::TransformManipulator::CONSTRAINT_Z);*/ + + + + /* landmark */ + vl::ref< vl::Geometry > landMark = new vl::Geometry; + vl::ref< vl::ArrayFloat3 > arrayPosition = new vl::ArrayFloat3; + arrayPosition->resize(6); + arrayPosition->at(0) = vl::vec3(0.0f, 0.0f, 0.0f); arrayPosition->at(1) = vl::vec3(10.0f, 0.0f, 0.0f); + arrayPosition->at(2) = vl::vec3(0.0f, 0.0f, 0.0f); arrayPosition->at(3) = vl::vec3(0.0f, 10.0f, 0.0f); + arrayPosition->at(4) = vl::vec3(0.0f, 0.0f, 0.0f); arrayPosition->at(5) = vl::vec3(0.0f, 0.0f, 10.0f); + vl::ref< vl::ArrayFloat3 > arrayColor = new vl::ArrayFloat3; + arrayColor->resize(6); + arrayColor->at(0) = vl::vec3(1.0f, 0.0f, 0.0f); arrayColor->at(1) = vl::vec3(1.0f, 0.0f, 0.0f); + arrayColor->at(2) = vl::vec3(0.0f, 1.0f, 0.0f); arrayColor->at(3) = vl::vec3(0.0f, 1.0f, 0.0f); + arrayColor->at(4) = vl::vec3(0.0f, 0.0f, 1.0f); arrayColor->at(5) = vl::vec3(0.0f, 0.0f, 1.0f); + vl::ref< vl::DrawCall > drawArrays = new vl::DrawArrays(vl::PT_LINES, 0, 6); + landMark->setVertexAttribArray(vl::VA_Position, arrayPosition.get()); + landMark->setVertexAttribArray(vl::VA_Color, arrayColor.get()); + landMark->drawCalls().push_back(drawArrays.get()); + + vl::ref effect_landmark = new vl::Effect; + effect_landmark->shader()->enable(vl::EN_DEPTH_TEST); + + + + vl::ref< vl::GLSLProgram > program_landmark = effect_landmark->shader()->gocGLSLProgram(); + program_landmark->attachShader(new vl::GLSLVertexShader("glsl/simpleColored.vs")); + program_landmark->attachShader(new vl::GLSLFragmentShader("glsl/simpleColored.fs")); + program_landmark->bindAttribLocation(vl::VA_Position, "VertexPosition"); + program_landmark->bindAttribLocation(vl::VA_Color, "VertexColor"); + //program_landmark->gocUniform("ProjectionMatrix")->setUniform(appletRendering->camera()->projectionMatrix()); + program_landmark->setUniform(mViewMatrixUniform.get()); + program_landmark->setUniform(mProjectionMatrixUniform.get()); + program_landmark->gocUniform("ModelMatrix")->setUniform(vl::mat4::getIdentity()); + + sceneManager()->tree()->addActor( landMark.get(), effect_landmark.get(), NULL); + + mCubeGeometry = vl::makeBox(vl::vec3(10.0f, 0.0f, 0.0f), 2.0f, 2.0f, 2.0f, false); + mCubeGeometry->convertToVertexAttribs(); + + mPyramidGeometry = vl::makePyramid(vl::vec3(-4.0f, 10.0f, -7.0f), 5.0f, 5.0f); + mPyramidGeometry->convertToVertexAttribs(); + + mEffectBox = new vl::Effect; + mEffectBox->shader()->enable(vl::EN_DEPTH_TEST); + mEffectBox->shader()->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE); + vl::ref< vl::GLSLProgram > programBox = mEffectBox->shader()->gocGLSLProgram(); + programBox->attachShader(new vl::GLSLVertexShader("glsl/simple.vs")); + programBox->attachShader(new vl::GLSLFragmentShader("glsl/simple.fs")); + programBox->bindAttribLocation(vl::VA_Position, "VertexPosition"); + programBox->setUniform(mViewMatrixUniform.get()); + programBox->setUniform(mProjectionMatrixUniform.get()); + programBox->setUniform(mCubeModelMatrixUniform.get()); + programBox->gocUniform("Color")->setUniform(vl::vec4(0.0f, 1.0f, 1.0f, 1.0f)); + + mEffectPyramid = new vl::Effect; + mEffectPyramid->shader()->enable(vl::EN_DEPTH_TEST); + mEffectPyramid->shader()->gocPolygonMode()->set(vl::PM_LINE, vl::PM_LINE); + vl::ref< vl::GLSLProgram > programPyramid = mEffectPyramid->shader()->gocGLSLProgram(); + programPyramid->attachShader(new vl::GLSLVertexShader("glsl/simple.vs")); + programPyramid->attachShader(new vl::GLSLFragmentShader("glsl/simple.fs")); + programPyramid->bindAttribLocation(vl::VA_Position, "VertexPosition"); + programPyramid->setUniform(mViewMatrixUniform.get()); + programPyramid->setUniform(mProjectionMatrixUniform.get()); + programPyramid->setUniform(mPyramidModelMatrixUniform.get()); + programPyramid->gocUniform("Color")->setUniform(vl::vec4(0.0f, 1.0f, 1.0f, 1.0f)); + + sceneManager()->tree()->addActor( mCubeGeometry.get(), mEffectBox.get(), NULL); + sceneManager()->tree()->addActor( mPyramidGeometry.get(), mEffectPyramid.get(), NULL); + + mCubeGeometry->computeBounds(); + vl::AABB boundingBox = mCubeGeometry->boundingBox(); + vl::vec3 center = boundingBox.center(); + + mCurrentGeometry = mCubeGeometry; + + mManipulatorPositionMatrixUniform->setUniform(vl::mat4::getTranslation(center)); + + /*vl::ref< vl::Uniform > scaleMatrixUniform = new vl::Uniform("ScaleMatrix"); + scaleMatrixUniform->setUniform(scaleMatrix); + + programX->setUniform(scaleMatrixUniform.get()); + programY->setUniform(scaleMatrixUniform.get()); + programZ->setUniform(scaleMatrixUniform.get());*/ + + createTranslationManipulators(); + } + + void createTranslationManipulators() + { + /* remove the manipulator to the applet */ + if(mTransformManipulatorX.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorX.get()); + if(mTransformManipulatorY.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorY.get()); + if(mTransformManipulatorZ.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorZ.get()); + + /* manipulators */ + mTransformManipulatorX = new vl::TranslationManipulator; + mTransformManipulatorY = new vl::TranslationManipulator; + mTransformManipulatorZ = new vl::TranslationManipulator; + + /* add the manipulator to the applet */ + openglContext()->addEventListener(mTransformManipulatorX.get()); + openglContext()->addEventListener(mTransformManipulatorY.get()); + openglContext()->addEventListener(mTransformManipulatorZ.get()); + + mTransformManipulatorX->setEventListener(trackball()); + mTransformManipulatorY->setEventListener(trackball()); + mTransformManipulatorZ->setEventListener(trackball()); + + createTranslationManipulatorsGeometry(); + + updateManipulators(); + } + + void createTranslationManipulatorsGeometry() + { + /* Gyzmo translation geometry */ + vl::AABB aabb = mCurrentGeometry->boundingBox(); + float size = aabb.longestSideLength() * 1.2f; + + mTransformManipulatorGeometryX = vl::makeCylinder(vl::vec3(0.0f, size / 2.0f, 0.0f), 0.1f * size, size); // Replace with an arrow + mTransformManipulatorGeometryX->convertToVertexAttribs(); + vl::ref< vl::ArrayAbstract > vertexPositionsX = mTransformManipulatorGeometryX->vertexArray() != NULL ? mTransformManipulatorGeometryX->vertexArray() : mTransformManipulatorGeometryX->vertexAttribArray(vl::VA_Position)->data(); + vertexPositionsX->transform(vl::mat4::getRotation(vl::vec3(0.0f, 1.0f, 0.0f), vl::vec3(1.0f, 0.0f, 0.0f))); + mTransformManipulatorGeometryX->updateDirtyBufferObject(vl::BUM_KeepRamBufferAndForceUpdate); + + mTransformManipulatorGeometryY = vl::makeCylinder(vl::vec3(0.0f, size / 2.0f, 0.0f), 0.1f * size, size); // Replace with an arrow + mTransformManipulatorGeometryY->convertToVertexAttribs(); + + mTransformManipulatorGeometryZ = vl::makeCylinder(vl::vec3(0.0f, size / 2.0f, 0.0f), 0.1f * size, size); // Replace with an arrow + mTransformManipulatorGeometryZ->convertToVertexAttribs(); + vl::ref< vl::ArrayAbstract > vertexPositionsZ = mTransformManipulatorGeometryZ->vertexArray() != NULL ? mTransformManipulatorGeometryZ->vertexArray() : mTransformManipulatorGeometryZ->vertexAttribArray(vl::VA_Position)->data(); + vertexPositionsZ->transform(vl::mat4::getRotation(vl::vec3(0.0f, 1.0f, 0.0f), vl::vec3(0.0f, 0.0f, 1.0f))); + mTransformManipulatorGeometryZ->updateDirtyBufferObject(vl::BUM_KeepRamBufferAndForceUpdate); + } + + void createRotationManipulators() + { + /* remove the manipulator to the applet */ + if(mTransformManipulatorX.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorX.get()); + if(mTransformManipulatorY.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorY.get()); + if(mTransformManipulatorZ.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorZ.get()); + + /* manipulators */ + mTransformManipulatorX = new vl::RotationManipulator; + mTransformManipulatorY = new vl::RotationManipulator; + mTransformManipulatorZ = new vl::RotationManipulator; + + /* add the manipulator to the applet */ + openglContext()->addEventListener(mTransformManipulatorX.get()); + openglContext()->addEventListener(mTransformManipulatorY.get()); + openglContext()->addEventListener(mTransformManipulatorZ.get()); + + mTransformManipulatorX->setEventListener(trackball()); + mTransformManipulatorY->setEventListener(trackball()); + mTransformManipulatorZ->setEventListener(trackball()); + + createRotationManipulatorsGeometry(); + + updateManipulators(); + } + + void createRotationManipulatorsGeometry() + { + /* Gyzmo translation geometry */ + vl::AABB aabb = mCurrentGeometry->boundingBox(); + float size = aabb.longestSideLength() * 1.2f; + + mTransformManipulatorGeometryX = vl::makeTorus(vl::vec3(0.0f, 0.0f, 0.0f), size, 0.02f * size); + mTransformManipulatorGeometryX->convertToVertexAttribs(); + vl::ref< vl::ArrayAbstract > vertexPositionsX = mTransformManipulatorGeometryX->vertexArray() != NULL ? mTransformManipulatorGeometryX->vertexArray() : mTransformManipulatorGeometryX->vertexAttribArray(vl::VA_Position)->data(); + vertexPositionsX->transform(vl::mat4::getRotation(vl::vec3(0.0f, 0.0f, 1.0f), vl::vec3(1.0f, 0.0f, 0.0f))); + mTransformManipulatorGeometryX->updateDirtyBufferObject(vl::BUM_KeepRamBufferAndForceUpdate); + + mTransformManipulatorGeometryY = vl::makeTorus(vl::vec3(0.0f, 0.0f, 0.0f), size, 0.02f * size); // Replace with an arrow + mTransformManipulatorGeometryY->convertToVertexAttribs(); + vl::ref< vl::ArrayAbstract > vertexPositionsY = mTransformManipulatorGeometryY->vertexArray() != NULL ? mTransformManipulatorGeometryY->vertexArray() : mTransformManipulatorGeometryY->vertexAttribArray(vl::VA_Position)->data(); + vertexPositionsY->transform(vl::mat4::getRotation(vl::vec3(0.0f, 0.0f, 1.0f), vl::vec3(0.0f, 1.0f, 0.0f))); + mTransformManipulatorGeometryY->updateDirtyBufferObject(vl::BUM_KeepRamBufferAndForceUpdate); + + mTransformManipulatorGeometryZ = vl::makeTorus(vl::vec3(0.0f, 0.0f, 0.0f), size, 0.02f * size); // Replace with an arrow + mTransformManipulatorGeometryZ->convertToVertexAttribs(); + + } + + void createScaleManipulators() + { + /* remove the manipulator to the applet */ + if(mTransformManipulatorX.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorX.get()); + if(mTransformManipulatorY.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorY.get()); + if(mTransformManipulatorZ.get() != NULL) openglContext()->removeEventListener(mTransformManipulatorZ.get()); + + /* manipulators */ + mTransformManipulatorX = new vl::ScaleManipulator; + mTransformManipulatorY = new vl::ScaleManipulator; + mTransformManipulatorZ = new vl::ScaleManipulator; + + /* add the manipulator to the applet */ + openglContext()->addEventListener(mTransformManipulatorX.get()); + openglContext()->addEventListener(mTransformManipulatorY.get()); + openglContext()->addEventListener(mTransformManipulatorZ.get()); + + mTransformManipulatorX->setEventListener(trackball()); + mTransformManipulatorY->setEventListener(trackball()); + mTransformManipulatorZ->setEventListener(trackball()); + + createTranslationManipulatorsGeometry(); + + updateManipulators(); + } + + void createScaleManipulatorsGeometry() + { + /* Gyzmo translation geometry */ + vl::AABB aabb = mCurrentGeometry->boundingBox(); + float size = aabb.longestSideLength() * 1.2f; + + mTransformManipulatorGeometryX = vl::makeCylinder(vl::vec3(0.0f, size / 2.0f, 0.0f), 0.1f * size, size); // Replace with an arrow + mTransformManipulatorGeometryX->convertToVertexAttribs(); + vl::ref< vl::ArrayAbstract > vertexPositionsX = mTransformManipulatorGeometryX->vertexArray() != NULL ? mTransformManipulatorGeometryX->vertexArray() : mTransformManipulatorGeometryX->vertexAttribArray(vl::VA_Position)->data(); + vertexPositionsX->transform(vl::mat4::getRotation(vl::vec3(0.0f, 1.0f, 0.0f), vl::vec3(1.0f, 0.0f, 0.0f))); + mTransformManipulatorGeometryX->updateDirtyBufferObject(vl::BUM_KeepRamBufferAndForceUpdate); + + mTransformManipulatorGeometryY = vl::makeCylinder(vl::vec3(0.0f, size / 2.0f, 0.0f), 0.1f * size, size); // Replace with an arrow + mTransformManipulatorGeometryY->convertToVertexAttribs(); + + mTransformManipulatorGeometryZ = vl::makeCylinder(vl::vec3(0.0f, size / 2.0f, 0.0f), 0.1f * size, size); // Replace with an arrow + mTransformManipulatorGeometryZ->convertToVertexAttribs(); + vl::ref< vl::ArrayAbstract > vertexPositionsZ = mTransformManipulatorGeometryZ->vertexArray() != NULL ? mTransformManipulatorGeometryZ->vertexArray() : mTransformManipulatorGeometryZ->vertexAttribArray(vl::VA_Position)->data(); + vertexPositionsZ->transform(vl::mat4::getRotation(vl::vec3(0.0f, 1.0f, 0.0f), vl::vec3(0.0f, 0.0f, 1.0f))); + mTransformManipulatorGeometryZ->updateDirtyBufferObject(vl::BUM_KeepRamBufferAndForceUpdate); + } + + void updateManipulators() + { + sceneManager()->tree()->eraseActor(mTransformManipulatorActorX.get()); + sceneManager()->tree()->eraseActor(mTransformManipulatorActorY.get()); + sceneManager()->tree()->eraseActor(mTransformManipulatorActorZ.get()); + + mTransformManipulatorActorX = sceneManager()->tree()->addActor( mTransformManipulatorGeometryX.get(), mEffectX.get(), NULL); + mTransformManipulatorActorY = sceneManager()->tree()->addActor( mTransformManipulatorGeometryY.get(), mEffectY.get(), NULL); + mTransformManipulatorActorZ = sceneManager()->tree()->addActor( mTransformManipulatorGeometryZ.get(), mEffectZ.get(), NULL); + + mTransformManipulatorX->setManipulatorActor(mTransformManipulatorActorX.get()); + mTransformManipulatorX->setViewMatrixUniform(mViewMatrixUniform.get()); + //mTransformManipulatorX->setProjectionMatrixUniform(mProjectionGizmoMatrix.get()); + mTransformManipulatorX->setProjectionMatrixUniform(mProjectionMatrixUniform.get()); + mTransformManipulatorX->setCamera(rendering()->as< vl::Rendering >()->camera()); + mTransformManipulatorX->setConstraint(vl::TransformManipulator::CONSTRAINT_X); + + mTransformManipulatorY->setManipulatorActor(mTransformManipulatorActorY.get()); + mTransformManipulatorY->setViewMatrixUniform(mViewMatrixUniform.get()); + //mTransformManipulatorY->setProjectionMatrixUniform(mProjectionGizmoMatrix.get()); + mTransformManipulatorY->setProjectionMatrixUniform(mProjectionMatrixUniform.get()); + mTransformManipulatorY->setCamera(rendering()->as< vl::Rendering >()->camera()); + mTransformManipulatorY->setConstraint(vl::TransformManipulator::CONSTRAINT_Y); + + mTransformManipulatorZ->setManipulatorActor(mTransformManipulatorActorZ.get()); + mTransformManipulatorZ->setViewMatrixUniform(mViewMatrixUniform.get()); + //mTransformManipulatorZ->setProjectionMatrixUniform(mProjectionGizmoMatrix.get()); + mTransformManipulatorZ->setProjectionMatrixUniform(mProjectionMatrixUniform.get()); + mTransformManipulatorZ->setCamera(rendering()->as< vl::Rendering >()->camera()); + mTransformManipulatorZ->setConstraint(vl::TransformManipulator::CONSTRAINT_Z); + + if(dynamic_cast< vl::ScaleManipulator* >(mTransformManipulatorX.get()) == NULL) // Do not scale manipulator to scale object + { + mEffectX->shader()->glslProgram()->setUniform(mCurrentModelMatrixUniform.get()); + mEffectY->shader()->glslProgram()->setUniform(mCurrentModelMatrixUniform.get()); + mEffectZ->shader()->glslProgram()->setUniform(mCurrentModelMatrixUniform.get()); + } + else + { + vl::ref< vl::Uniform > modelMatrixUniformX, modelMatrixUniformY, modelMatrixUniformZ; + modelMatrixUniformX = new vl::Uniform("ModelMatrix"); + modelMatrixUniformX->setUniform(vl::mat4::getIdentity()); + modelMatrixUniformY = new vl::Uniform("ModelMatrix"); + modelMatrixUniformY->setUniform(vl::mat4::getIdentity()); + modelMatrixUniformZ = new vl::Uniform("ModelMatrix"); + modelMatrixUniformZ->setUniform(vl::mat4::getIdentity()); + mEffectX->shader()->glslProgram()->setUniform(modelMatrixUniformX.get()); + mEffectY->shader()->glslProgram()->setUniform(modelMatrixUniformY.get()); + mEffectZ->shader()->glslProgram()->setUniform(modelMatrixUniformZ.get()); + } + + //mEffectBox->shader()->glslProgram()->setUniform(mCurrentModelMatrixUniform.get()); + + mTransformManipulatorX->setEditGeometry(mCurrentGeometry.get(), mCurrentModelMatrixUniform.get()); + mTransformManipulatorY->setEditGeometry(mCurrentGeometry.get(), mCurrentModelMatrixUniform.get()); + mTransformManipulatorZ->setEditGeometry(mCurrentGeometry.get(), mCurrentModelMatrixUniform.get()); + } + + /* rotate the camera around the sphere */ + void updateScene() + { + vl::ref< vl::Rendering > appletRendering = rendering()->as< vl::Rendering >(); + mViewMatrixUniform->setUniform(appletRendering->camera()->viewMatrix()); + } + + void keyReleaseEvent(unsigned short, vl::EKey key) + { + if(key == vl::Key_T) + { + if(dynamic_cast< vl::TranslationManipulator* >(mTransformManipulatorX.get()) == NULL) + createTranslationManipulators(); + } + else if(key == vl::Key_R) + { + if(dynamic_cast< vl::RotationManipulator* >(mTransformManipulatorX.get()) == NULL) + createRotationManipulators(); + } + else if(key == vl::Key_S) + { + if(dynamic_cast< vl::ScaleManipulator* >(mTransformManipulatorX.get()) == NULL) + createScaleManipulators(); + } + else if(key == vl::Key_Left || key == vl::Key_Right) + { + if(mCurrentGeometry.get() == mCubeGeometry.get()) + { + mCurrentGeometry = mPyramidGeometry; + mCurrentModelMatrixUniform = mPyramidModelMatrixUniform; + //mCurrentEffect = mEffectPyramid; + } + else if(mCurrentGeometry.get() == mPyramidGeometry.get()) + { + mCurrentGeometry = mCubeGeometry; + mCurrentModelMatrixUniform = mCubeModelMatrixUniform; + //mCurrentEffect = mEffectBox; + } + + mCurrentGeometry->computeBounds(); + vl::AABB boundingBox = mCurrentGeometry->boundingBox(); + vl::vec3 center = boundingBox.center(); + + mManipulatorPositionMatrixUniform->setUniform(vl::mat4::getTranslation(center)); + + if(dynamic_cast< vl::TranslationManipulator* >(mTransformManipulatorX.get()) != NULL) + createTranslationManipulators(); + else if(dynamic_cast< vl::RotationManipulator* >(mTransformManipulatorX.get()) != NULL) + createRotationManipulators(); + else if(dynamic_cast< vl::ScaleManipulator* >(mTransformManipulatorX.get()) != NULL) + createScaleManipulators(); + } + } + + vl::ref< vl::Uniform > mViewMatrixUniform; + vl::ref< vl::Uniform > mProjectionMatrixUniform; + vl::ref< vl::Uniform > mCubeModelMatrixUniform; + vl::ref< vl::Uniform > mPyramidModelMatrixUniform; + vl::ref< vl::Uniform > mCurrentModelMatrixUniform; + vl::ref< vl::TransformManipulator > mTransformManipulatorX; + vl::ref< vl::TransformManipulator > mTransformManipulatorY; + vl::ref< vl::TransformManipulator > mTransformManipulatorZ; + vl::ref< vl::Geometry > mTransformManipulatorGeometryX; + vl::ref< vl::Geometry > mTransformManipulatorGeometryY; + vl::ref< vl::Geometry > mTransformManipulatorGeometryZ; + vl::ref< vl::Effect > mEffectX; + vl::ref< vl::Effect > mEffectY; + vl::ref< vl::Effect > mEffectZ; + vl::ref< vl::Effect > mEffectBox; + vl::ref< vl::Effect > mEffectPyramid; + vl::ref< vl::Effect > mCurrentEffect; + vl::ref< vl::Actor > mTransformManipulatorActorX; + vl::ref< vl::Actor > mTransformManipulatorActorY; + vl::ref< vl::Actor > mTransformManipulatorActorZ; + vl::ref< vl::Geometry > mCubeGeometry; + vl::ref< vl::Geometry > mPyramidGeometry; + vl::ref< vl::Geometry > mCurrentGeometry; + vl::ref< vl::Uniform > mProjectionGizmoMatrix; + vl::ref< vl::Uniform > mViewMatrixGizmoMatrix; + vl::ref< vl::Uniform > mManipulatorPositionMatrixUniform; +}; + +// Have fun! + +BaseDemo* Create_App_TransformManipulator() { return new App_TransformManipulator(); } diff --git a/src/examples/tests.hpp b/src/examples/tests.hpp index 03c49ec55..3fd8c96b9 100644 --- a/src/examples/tests.hpp +++ b/src/examples/tests.hpp @@ -90,6 +90,8 @@ BaseDemo* Create_App_Primitives(); BaseDemo* Create_App_DrawCalls(); BaseDemo* Create_App_VLX(); BaseDemo* Create_App_Stereo(); +BaseDemo* Create_App_GLSL_TransformFeedback(); +BaseDemo* Create_App_TransformManipulator(); BaseDemo* Create_App_Vivid(); // win32 console for sdtout output @@ -199,7 +201,9 @@ class TestBattery { "picking", Create_App_Picking(), 10,10, 512, 512, vl::black, vl::vec3(0,0,10), vl::vec3(0,0,0) }, { "tessellation_shader", Create_App_TessellationShader(), 10,10, 512, 512, vl::skyblue, vl::vec3(300,40,0), vl::vec3(1000,0,0) }, { "stereo", Create_App_Stereo(), 10,10, 512, 512, vl::lightgray, vl::vec3(0,2.5,15), vl::vec3(0,0,0) }, - { "vivid", Create_App_Vivid(), 10,10, 512, 512, vl::lightgray, vl::vec3(0,2.5,15), vl::vec3(0,0,0) }, + { "transform feedback", Create_App_GLSL_TransformFeedback(), 10,10, 512, 512, vl::black, vl::vec3(-20,10,10), vl::vec3(0,0,0) }, + { "transform manipulator", Create_App_TransformManipulator(), 10,10, 512, 512, vl::black, vl::vec3(-20,10,10), vl::vec3(0,0,0) }, + { "vivid", Create_App_Vivid(), 10,10, 512, 512, vl::lightgray, vl::vec3(0,2.5,15), vl::vec3(0,0,0) }, // { "mini_earth", Create_App_MiniEarth(), 10,10, 512, 512, vl::black, vl::vec3(0,0,4), vl::vec3(0,0,0) }, }; diff --git a/src/vlCore/vlnamespace.hpp b/src/vlCore/vlnamespace.hpp index 4a728f750..506c7f898 100644 --- a/src/vlCore/vlnamespace.hpp +++ b/src/vlCore/vlnamespace.hpp @@ -845,6 +845,9 @@ namespace vl EN_POINT_SPRITE, //!< If enabled, calculate texture coordinates for points based on texture environment and point parameter settings; Otherwise texture coordinates are constant across points. EN_PROGRAM_POINT_SIZE, //!< [GL_VERTEX_PROGRAM_POINT_SIZE/GL_PROGRAM_POINT_SIZE] If enabled, and a vertex shader is active, then the derived point size is taken from the (potentially clipped) shader builtin \p gl_PointSize and clamped to the implementation-dependent point size range| + // Rasterizer + EN_RASTERIZER_DISCARD, + // Fixed function pipeline EN_ALPHA_TEST, //!< If enabled, performs alpha testing, see also AlphaFunc for more information. EN_LIGHTING, //!< If enabled, use the current lighting parameters to compute the vertex color; Otherwise, simply associate the current color with each vertex, see also Material, LightModel, and Light. @@ -1001,6 +1004,8 @@ namespace vl RS_StencilMask, RS_StencilOp, RS_GLSLProgram, + + RS_TransformFeedback, RS_Light, RS_Light0 = RS_Light, @@ -1532,6 +1537,12 @@ namespace vl RCS_RenderingStarted, RCS_RenderingFinished } EResetContextStates; + + typedef enum + { + BM_SeparateAttribs = GL_SEPARATE_ATTRIBS, + BM_InterleavedAttribs = GL_INTERLEAVED_ATTRIBS + } EBufferMode; } diff --git a/src/vlGraphics/CoreFont.cpp b/src/vlGraphics/CoreFont.cpp new file mode 100644 index 000000000..ab8f1673f --- /dev/null +++ b/src/vlGraphics/CoreFont.cpp @@ -0,0 +1,507 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include FT_FREETYPE_H + +using namespace vl; + +// FreeType error table construction start ------------------------------------------ +// taken from "fterrors.h" example +#undef __FTERRORS_H__ +#define FT_ERRORDEF( e, v, s ) { e, s }, +#define FT_ERROR_START_LIST { +#define FT_ERROR_END_LIST { 0, 0 } }; + +const struct +{ + int err_code; + const char* err_msg; +} ft_errors[] = + +#include FT_ERRORS_H +// FreeType error table construction end ------------------------------------------ + +const char* get_ft_error_message_core(int error) +{ + int i=0; + while( ft_errors[i].err_msg && ft_errors[i].err_code != error ) + ++i; + return ft_errors[i].err_msg; +} + +//----------------------------------------------------------------------------- +// Glyph +//----------------------------------------------------------------------------- +CoreGlyph::~CoreGlyph() +{ + /*if (mTextureHandle) + { + glDeleteTextures(1, &mTextureHandle); + mTextureHandle = 0; + }*/ +} +//----------------------------------------------------------------------------- +// Font +//----------------------------------------------------------------------------- +CoreFont::CoreFont(FontManager* fm) +{ + VL_DEBUG_SET_OBJECT_NAME() + mFontManager = fm; + mHeight = 0; + mFT_Face = NULL; + mSmooth = false; + mFreeTypeLoadForceAutoHint = true; + //mTextureHandle = 0; + setSize(32); +} +//----------------------------------------------------------------------------- +CoreFont::CoreFont(FontManager* fm, const String& font_file, int size) +{ + VL_DEBUG_SET_OBJECT_NAME() + mFontManager = fm; + mHeight = 0; + mFT_Face = NULL; + mSmooth = false; + mFreeTypeLoadForceAutoHint = true; + //mTextureHandle = 0; + loadFont(font_file); + setSize(size); +} +//----------------------------------------------------------------------------- +CoreFont::~CoreFont() +{ + releaseFreeTypeData(); +} +//----------------------------------------------------------------------------- +void CoreFont::releaseFreeTypeData() +{ + if (mFT_Face) + { + if (!mFontManager->freeTypeLibrary()) + { + vl::Log::error("Font::releaseFreeTypeData(): mFontManager->freeTypeLibrary() is NULL!\n"); + VL_TRAP() + } + else + { + FT_Done_Face(mFT_Face); + } + mFT_Face = NULL; + } +} +//----------------------------------------------------------------------------- +void CoreFont::setSize(int size) +{ + if(mSize != size) + { + mSize = size; + // removes all the cached glyphs + //mGlyphMap.clear(); + } +} +//----------------------------------------------------------------------------- +void CoreFont::loadFont(const String& path) +{ + if(path == mFilePath) + return; + + mFilePath = path; + // removes all the cached glyphs + mGlyphMap.clear(); + + // remove FreeType font face object + if (mFT_Face) + { + FT_Done_Face(mFT_Face); + mFT_Face = NULL; + } + + FT_Error error = 0; + + ref font_file = defFileSystem()->locateFile( filePath() ); + + if (!font_file) + Log::error( Say("Font::loadFont('%s'): font file not found.\n") << filePath() ); + + if ( font_file && font_file->load(mMemoryFile) ) + { + if ( (int)mMemoryFile.size() == font_file->size() ) + { + error = FT_New_Memory_Face( (FT_Library)mFontManager->freeTypeLibrary(), + (FT_Byte*)&mMemoryFile[0], + (int)mMemoryFile.size(), + 0, + &mFT_Face ); + } + else + Log::error( Say("Font::loadFont('%s'): could not read file.\n") << filePath() ); + } + + if (error) + { + Log::error(Say("FT_New_Face error (%s): %s\n") << filePath() << get_ft_error_message_core(error) ); + VL_TRAP() + return; + } + + createTexture(); +} +//----------------------------------------------------------------------------- +CoreGlyph* CoreFont::glyph(int character) +{ + ref& glyph = mGlyphMap[character]; + + if (glyph.get() == NULL) + { + Log::error(Say("Error during gettin glyph\n")); + return NULL; + } + + return glyph.get(); +} +//----------------------------------------------------------------------------- +void CoreFont::setSmooth(bool smooth) +{ + mSmooth = smooth; + if(mAtlas->handle() == 0) + return; + + vl::TexParameter* parameters = mAtlas->getTexParameter(); + + //glBindTexture( GL_TEXTURE_2D, mAtlas->handle() ); + if (smooth) + { + parameters->setMagFilter(vl::TPF_LINEAR); + parameters->setMinFilter(vl::TPF_LINEAR); + parameters->setWrapS(vl::TPW_CLAMP); + parameters->setWrapT(vl::TPW_CLAMP); + + /*glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );*/ + } + else + { + parameters->setMagFilter(vl::TPF_NEAREST); + parameters->setMinFilter(vl::TPF_NEAREST); + parameters->setWrapS(vl::TPW_CLAMP); + parameters->setWrapT(vl::TPW_CLAMP); + + /*glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );*/ + } + //glBindTexture( GL_TEXTURE_2D, 0 ); + /*std::map >::iterator it = mGlyphMap.begin(); + for(; it != mGlyphMap.end(); ++it ) + { + const ref& glyph = it->second; + if (glyph->textureHandle() == 0) + continue; + + glBindTexture( GL_TEXTURE_2D, glyph->textureHandle() ); + if (smooth) + { + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + } + else + { + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + } + } + glBindTexture( GL_TEXTURE_2D, 0 );*/ +} +//----------------------------------------------------------------------------- +void CoreFont::createTexture() +{ + /*if(mTextureHandle != 0) + { + glDeleteTextures(1, &mTextureHandle); + mTextureHandle = 0; + }*/ + + + FT_Error error = 0; + + error = FT_Set_Char_Size( + mFT_Face, /* handle to face object */ + 0, /* char_width in 1/64th of points */ + mSize*64, /* char_height in 1/64th of points */ + 96, /* horizontal device resolution */ + 96 ); /* vertical device resolution */ + + if(error) + { + // Log::error(Say("FT_Set_Char_Size error: %s\n") << get_ft_error_message(error) ); + if ( (mFT_Face->face_flags & FT_FACE_FLAG_SCALABLE) == 0 && mFT_Face->num_fixed_sizes) + { + // look for the size which is less or equal to the given size + + int best_match_index = -1; + int best_match_size = 0; + for( int i=0; i < mFT_Face->num_fixed_sizes; ++i ) + { + int size = mFT_Face->available_sizes[i].y_ppem/64; + // skip bigger characters + if (size <= mSize) + { + if (best_match_index == -1 || (mSize - size) < (mSize - best_match_size) ) + { + best_match_index = i; + best_match_size = size; + } + } + } + + if (best_match_index == -1) + best_match_index = 0; + + error = FT_Select_Size(mFT_Face, best_match_index); + if (error) + Log::error(Say("FT_Select_Size error (%s): %s\n") << filePath() << get_ft_error_message_core(error) ); + VL_CHECK(!error) + } + // else + { + Log::error(Say("FT_Set_Char_Size error (%s): %s\n") << filePath() << get_ft_error_message_core(error) ); + VL_TRAP() + return; + } + } + + mHeight = mFT_Face->size->metrics.height / 64.0f; + + // for now, only ASCII characters + FT_GlyphSlot g = mFT_Face->glyph; + int w, h; + w = h = 0; + int margin = 1; + for(int i = 32; i < 128; ++i) + { + error = FT_Load_Char(mFT_Face, i, freeTypeLoadForceAutoHint() ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT); + if(error) + { + Log::error(Say("FT_Load_Char error (%s): %s\n") << filePath() << get_ft_error_message_core(error) ); + continue; + } + + error = FT_Render_Glyph( + mFT_Face->glyph, /* glyph slot */ + FT_RENDER_MODE_NORMAL ); /* render mode: FT_RENDER_MODE_MONO or FT_RENDER_MODE_NORMAL */ + + if(error) + { + // Log::error(Say("FT_Render_Glyph error: %s") << get_ft_error_message(error) ); + // VL_TRAP() + error = FT_Load_Glyph( + mFT_Face,/* handle to face object */ + 0, /* glyph index */ + FT_LOAD_DEFAULT ); /* load flags, see below */ + + error = FT_Render_Glyph( + mFT_Face->glyph, /* glyph slot */ + FT_RENDER_MODE_NORMAL ); /* render mode: FT_RENDER_MODE_MONO or FT_RENDER_MODE_NORMAL */ + } + + if(error) + { + Log::error(Say("FT_Render_Glyph error (%s): %s\n") << filePath() << get_ft_error_message_core(error) ); + VL_TRAP() + return; + } + + if(g->bitmap.width == 0) + w += 2 * margin; + else + w += g->bitmap.width + 2 * margin; + + h = std::max(h, g->bitmap.rows); + } + + int texsize[] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 }; + int max_tex_size = 0; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); + + //int w=0, h=0, margin = 1; + + for(int i = 0; texsize[i]; ++i) + { + if( texsize[i] >= w + margin * 2 || texsize[i+1] > max_tex_size) + { + w = texsize[i]; + break; + } + } + + for(int i = 0; texsize[i]; ++i) + { + if( texsize[i] >= h + margin * 2 || texsize[i+1] > max_tex_size) + { + h = texsize[i]; + break; + } + } + VL_CHECK(w) + VL_CHECK(h) + + ref img = new Image; + img->allocate2D(w, h, 1, IF_RED, IT_UNSIGNED_BYTE); + + // init to all transparent white + for(unsigned char *px = img->pixels(), *end = px + img->requiredMemory(); pxwidth(), img->height(), 0, img->format(), img->type(), 0 ); VL_CHECK_OGL(); */ + + unsigned int x = 0; + // for now, only ASCII characters + for(int i = 32; i < 128; ++i) + { + if(FT_Load_Char(mFT_Face, i, freeTypeLoadForceAutoHint() ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT)) + continue; + + error = FT_Render_Glyph( + mFT_Face->glyph, /* glyph slot */ + FT_RENDER_MODE_NORMAL ); /* render mode: FT_RENDER_MODE_MONO or FT_RENDER_MODE_NORMAL */ + + if(g->bitmap.width != 0) + { + ref imgGlyph = new Image; + //imgGlyph->allocate2D(g->bitmap.width + 2 * margin, g->bitmap.rows + 2 * margin, 1, IF_RED, IT_UNSIGNED_BYTE); + imgGlyph->allocate2D(g->bitmap.width + 2 * margin, h, 1, IF_RED, IT_UNSIGNED_BYTE); // Dans la texture carre, w == h (w correspond a la longueur de la texture globale) + + // init to all transparent white + for(unsigned char *px = imgGlyph->pixels(), *end = px + imgGlyph->requiredMemory(); pxbitmap.rows; yg++) + { + for(int xg=0; xgbitmap.width; xg++) + { + //imgGlyph->pixels()[ind++] = g->bitmap.buffer[yg * g->bitmap.width + xg]; + + int offset_1 = (xg+margin) * 1 + (h-1-yg-margin) * imgGlyph->pitch(); + int offset_2 = 0; + if (g->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) + offset_2 = xg / 8 + yg * ::abs(g->bitmap.pitch); + else + offset_2 = xg + yg * g->bitmap.pitch; + + #if (1) + if (g->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) + imgGlyph->pixels()[ offset_1/*+3*/ ] = (g->bitmap.buffer[ offset_2 ] >> (7-x%8)) & 0x1 ? 0xFF : 0x0; + else + imgGlyph->pixels()[ offset_1/*+3*/ ] = g->bitmap.buffer[ offset_2 ]; + #else + // debug code + img->pixels()[ offset_1+0 ] = g->bitmap.buffer[ offset_2 ]; // 0xFF; + img->pixels()[ offset_1+1 ] = g->bitmap.buffer[ offset_2 ]; // 0xFF; + img->pixels()[ offset_1+2 ] = g->bitmap.buffer[ offset_2 ]; // 0xFF; + img->pixels()[ offset_1+3 ] = 0xFF; // face->glyph->bitmap.buffer[ offset_2 ]; + #endif + } + } + + img->copySubImage(imgGlyph.get(), RectI(0, 0, imgGlyph->width(), imgGlyph->height()), ivec2(x, 0)); + } + //glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_RGBA, GL_UNSIGNED_BYTE, g->bitmap.buffer); + //glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, imgGlyph->width(), imgGlyph->height(), GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer/*imgGlyph->pixels()*/); + + + CoreGlyph* glyph = new CoreGlyph; + glyph->setFont(this); + glyph->setAdvance(fvec2(g->advance.x >> 6, g->advance.y >> 6) ); + glyph->setWidth(g->bitmap.width); + glyph->setHeight(g->bitmap.rows); + glyph->setLeft(g->bitmap_left); + glyph->setTop(g->bitmap_top); + if(g->bitmap.width != 0) + { + glyph->setS0(x /(float)(w-1)); + glyph->setT0( 1 ); + //glyph->setS1(static_cast< float >(x) / static_cast< float >(w)); + glyph->setS1((margin*2 + x + glyph->width() ) /(float)(w-1)); + glyph->setT1( 1 -(margin*2 + glyph->height() ) /(float)(h-1) ); + //glyph->setT1((margin*2 + glyph->height() ) /(float)(h-1) ); + x += g->bitmap.width + 2 * margin; + } + else + { + glyph->setS0(x /(float)(w-1)); + glyph->setT0( 1 ); + glyph->setS1(x /(float)(w-1)); + glyph->setT1( 1 -(margin*2 + glyph->height() ) /(float)(h-1) ); + x += 1; + } + + mGlyphMap[i] = glyph; + + } + // tmps + mAtlas = new Texture(img.get(), TF_RED, false); + vl::TexParameter* parameters = mAtlas->getTexParameter(); + parameters->setMagFilter(vl::TPF_NEAREST); + parameters->setMinFilter(vl::TPF_NEAREST); + parameters->setWrapS(vl::TPW_CLAMP); + parameters->setWrapT(vl::TPW_CLAMP); + + + +} diff --git a/src/vlGraphics/CoreFont.hpp b/src/vlGraphics/CoreFont.hpp new file mode 100644 index 000000000..6db88fc78 --- /dev/null +++ b/src/vlGraphics/CoreFont.hpp @@ -0,0 +1,224 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#ifndef CoreFont_INCLUDE_ONCE +#define CoreFont_INCLUDE_ONCE + +#include +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------------------- +struct FT_FaceRec_; +typedef struct FT_FaceRec_* FT_Face; +//----------------------------------------------------------------------------- +namespace vl +{ + class CoreFont; + class FontManager; + //----------------------------------------------------------------------------- + // Glyph + //----------------------------------------------------------------------------- + /** + * The Glyph associated to a character of a given Font. + */ + class CoreGlyph: public Object + { + VL_INSTRUMENT_CLASS(vl::Glyph, Object) + + private: + CoreGlyph(const CoreGlyph& other): Object(other) + { + VL_DEBUG_SET_OBJECT_NAME() + } + void operator=(const CoreGlyph&){} + + public: + CoreGlyph(): mFont(NULL), mS0(0), mT0(0), mS1(0), mT1(0), mGlyphIndex(0)/*, mTextureHandle(0)*/, mWidth(0), mHeight(0), mLeft(0), mTop(0) {} + + ~CoreGlyph(); + + /*unsigned int textureHandle() const { return mTextureHandle; } + void setTextureHandle(unsigned int handle) { mTextureHandle = handle; }*/ + + int width() const { return mWidth; } + void setWidth(int width) { mWidth = width; } + + int height() const { return mHeight; } + void setHeight(int height) { mHeight = height; } + + int left() const { return mLeft; } + void setLeft(int left) { mLeft = left; } + + int top() const { return mTop; } + void setTop(int top) { mTop = top; } + + float s0() const { return mS0; } + void setS0(float s0) { mS0 = s0; } + + float t0() const { return mT0; } + void setT0(float t0) { mT0 = t0; } + + float s1() const { return mS1; } + void setS1(float s1) { mS1 = s1; } + + float t1() const { return mT1; } + void setT1(float t1) { mT1 = t1; } + + const fvec2& advance() const { return mAdvance; } + void setAdvance(const fvec2& advance) { mAdvance = advance; } + + unsigned int glyphIndex() const { return mGlyphIndex; } + void setGlyphIndex(unsigned int glyph_index) { mGlyphIndex = glyph_index; } + + const CoreFont* font() const { return mFont; } + void setFont(CoreFont* font) { mFont = font; } + + protected: + CoreFont* mFont; + fvec2 mAdvance; + float mS0; + float mT0; + float mS1; + float mT1; + unsigned int mGlyphIndex; + int mWidth; + int mHeight; + int mLeft; + int mTop; + }; + //----------------------------------------------------------------------------- + // Font + //----------------------------------------------------------------------------- + /** + * A font to be used with a Text renderable. + */ + class VLGRAPHICS_EXPORT CoreFont: public Object + { + VL_INSTRUMENT_CLASS(vl::Font, Object) + + friend class CoreText; + friend class Text; + friend class FontManager; + + //! Assignment operator + void operator=(const CoreFont&) { VL_TRAP() } // should never get used + + //! Copy constructor. + CoreFont(const CoreFont& other): Object(other)/*, mTextureHandle(0) */{ VL_TRAP() } // should never get used + + //! Constructor. + CoreFont(FontManager* fm = NULL); + + //! Constructor. The specified 'font_file' is immediately loaded. + CoreFont(FontManager* fm, const String& font_file, int size ); + + public: + //! Destructor. + ~CoreFont(); + + //! Less-than operator. + bool operator<(const CoreFont& other) const + { + if (filePath() != other.filePath()) + return filePath() < other.filePath(); + else + return size() < other.size(); + } + + //! The font's file path. + const String& filePath() const { return mFilePath; } + + //! Loads a font using fileSystem()::locateFile(). + void loadFont(const String& path); + + //! The size of the font. + int size() const { return mSize; } + + //! The size of the font. + void setSize(int size); + + //! Returns (and eventually creates) the Glyph* associated to the given character. + CoreGlyph* glyph(int character); + + //! Whether the font rendering should use linear filtering or not. + void setSmooth(bool smooth); + + //! Whether the font rendering should use linear filtering or not. + bool smooth() const { return mSmooth; } + + //! Releases the FreeType's FT_Face used by a Font. + void releaseFreeTypeData(); + + //! The FontManager associated to this Font used to acquire/release FreeType resources. + void setFontManager(FontManager* fm) { mFontManager = fm; } + + //! The FontManager associated to this Font used to acquire/release FreeType resources. + const FontManager* fontManager() const { return mFontManager; } + + //! The FontManager associated to this Font used to acquire/release FreeType resources. + FontManager* fontManager() { return mFontManager; } + + //! Whether FT_Load_Char() should be called with FT_LOAD_FORCE_AUTOHINT (default) or FT_LOAD_DEFAULT. + //! There isn't a "best" option for all the fonts, the results can be better or worse depending on the particular font loaded. + bool freeTypeLoadForceAutoHint() const { return mFreeTypeLoadForceAutoHint; } + + //! Whether FT_Load_Char() should be called with FT_LOAD_FORCE_AUTOHINT (default) or FT_LOAD_DEFAULT. + //! There isn't a "best" option for all the fonts, the results can be better or worse depending on the particular font loaded. + void setFreeTypLoadForceAutoHint(bool enable) { mFreeTypeLoadForceAutoHint = enable; } + + //! Create the texture of the atlas + void createTexture(); + + //! Get the atlas texture + Texture* getAtlas() { return mAtlas.get(); } + + protected: + FontManager* mFontManager; + String mFilePath; + std::map< int, ref > mGlyphMap; + FT_Face mFT_Face; + std::vector mMemoryFile; + int mSize; + float mHeight; + bool mSmooth; + bool mFreeTypeLoadForceAutoHint; + ref< Texture > mAtlas; + + }; + //----------------------------------------------------------------------------- +} + +#endif diff --git a/src/vlGraphics/CoreText.cpp b/src/vlGraphics/CoreText.cpp index fd3cea50f..4bceae7d7 100644 --- a/src/vlGraphics/CoreText.cpp +++ b/src/vlGraphics/CoreText.cpp @@ -1,7 +1,7 @@ /**************************************************************************************/ /* */ /* Visualization Library */ -/* http://visualizationlibrary.org */ +/* http://www.visualizationlibrary.org */ /* */ /* Copyright (c) 2005-2010, Michele Bosi */ /* All rights reserved. */ @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -57,186 +58,125 @@ using namespace vl; // - Outline rendering should use 2 pass with enlarged glyphs instead of 5 passes or precompute an high quality outline texture. // - Avoid using doubles and floats if possible, use integer and Rect rather floats and AABBs. -//----------------------------------------------------------------------------- -void CoreText::render_Implementation(const Actor* actor, const Shader*, const Camera* camera, OpenGLContext* gl_context) const +CoreText::~CoreText() { - gl_context->bindVAS(NULL, false, false); - - VL_CHECK(font()) - - if (!font() || !font()->mFT_Face) - return; - - if ( text().empty() ) - return; - - // Lighting can be enabled or disabled. - // glDisable(GL_LIGHTING); - - // Blending must be enabled explicity by the vl::Shader, also to perform z-sort. - // glEnable(GL_BLEND); - - // Trucchetto che usiamo per evitare z-fighting: - // Pass #1 - fill color and stencil - // - disable depth write mask - // - depth test can be enabled or not by the user - // - depth func can be choosen by the user - // - render in the order: background, border, shadow, outline, text - // Pass #2 - fill z-buffer - // - enable depth write mask - // - disable color mask - // - disable stencil - // - drawing background and border - - // Pass #1 - - // disable z-writing - GLboolean depth_mask=0; - glGetBooleanv(GL_DEPTH_WRITEMASK, &depth_mask); - glDepthMask(GL_FALSE); - - // background - if (backgroundEnabled()) - renderBackground( actor, camera ); - - // border - if (borderEnabled()) - renderBorder( actor, camera ); - - // to have the most correct results we should render the text twice one for color and stencil, the other for the z-buffer - - // shadow render - if (shadowEnabled()) - renderText( actor, camera, shadowColor(), shadowVector() ); - // outline render - if (outlineEnabled()) - { - renderText( actor, camera, outlineColor(), fvec2(-1,0) ); - renderText( actor, camera, outlineColor(), fvec2(+1,0) ); - renderText( actor, camera, outlineColor(), fvec2(0,-1) ); - renderText( actor, camera, outlineColor(), fvec2(0,+1) ); - } - // text render - renderText( actor, camera, color(), fvec2(0,0) ); - - // Pass #2 - // fills the z-buffer (not the stencil buffer): approximated to the text bbox - - // restores depth mask - glDepthMask(depth_mask); - - if (depth_mask) - { - // disables writing to the color buffer - GLboolean color_mask[4]; - glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - - // disable writing to the stencil buffer - int stencil_front_mask=0; - glGetIntegerv(GL_STENCIL_WRITEMASK, &stencil_front_mask); - int stencil_back_mask=0; - if (Has_GL_Version_2_0) - glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &stencil_back_mask); - glStencilMask(0); + glDeleteBuffers(1, &mBufferID); // if the buffer wasn't create, the id is 0 and will be ignored by the function +} - // background - renderBackground( actor, camera ); +void CoreText::setText(const String& text) +{ + mText = text; + + // mic fixme: + // - lines split and lines dimensions (linebox) should be precomputed on text set! + // - or convert this function to generate a pre-computed rendering-list! + // | + // v + // is now - // border - renderBorder( actor, camera ); + // split the text in different lines - // restores color writing - glColorMask(color_mask[0],color_mask[1],color_mask[2],color_mask[3]); + VL_CHECK(mText.length()) - // restore the stencil masks - glStencilMask(stencil_front_mask); - if (Has_GL_Version_2_0) - glStencilMaskSeparate(GL_BACK, stencil_back_mask); - } -} -//----------------------------------------------------------------------------- -void CoreText::renderText(const Actor*, const Camera*, const fvec4& color, const fvec2& offset) const -{ - if(!mFont) + mLines.push_back( String() ); + for(int i=0; imFT_Face) + for(size_t ilines = 0; ilines < mLines.size(); ++ilines) { - Log::error("CoreText::renderText() error: invalid FT_Face: probably you tried to load an unsupported font format.\n"); - VL_TRAP() - return; + if(!mLines.at(ilines).empty()) + { + AABB aabb = computeRawBoundingRect(mLines.at(ilines)); + mDimensionsLines.push_back(aabb); + // compute total bounding rect + mRawBoundingRect += aabb; + } } - - // mic fixme: these should be pre-computed when the text is set!!! - - AABB rbbox = rawboundingRect( text() ); // for text alignment - VL_CHECK(rbbox.maxCorner().z() == 0) - VL_CHECK(rbbox.minCorner().z() == 0) - AABB bbox = rbbox; - bbox.setMaxCorner( bbox.maxCorner() + vec3(2.0f*margin(), 2.0f*margin(), 0) ); - VL_CHECK(bbox.maxCorner().z() == 0) - VL_CHECK(bbox.minCorner().z() == 0) - - // basic render states - - // mic fixme: detect GLSLProgram and use VertexAttribPointer if present. - - float texc[] = { 0,0,0,0,0,0,0,0 }; - VL_glActiveTexture( GL_TEXTURE0 ); - VL_glClientActiveTexture( GL_TEXTURE0 ); - glEnable(GL_TEXTURE_2D); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - glTexCoordPointer(2, GL_FLOAT, 0, texc); - - // color - glColor4fv(color.ptr()); - - // Constant normal - glNormal3fv( fvec3(0,0,1).ptr() ); - - fvec3 vect[4]; - glEnableClientState( GL_VERTEX_ARRAY ); - glVertexPointer(3, GL_FLOAT, 0, vect[0].ptr()); - - FT_Long use_kerning = FT_HAS_KERNING( font()->mFT_Face ); + + //vl::ref< Texture > texture = textTexture(mText); + + // we create the buffer + glGenBuffers(1, &mBufferID); + + glBindBuffer(GL_ARRAY_BUFFER, mBufferID); + + // with the number of lines and the number of character per lines, we can compute the size of the buffer + glBufferData(GL_ARRAY_BUFFER, (mText.length() * (4 * 3 + 4 * 2) + 4 * 3) * sizeof(GL_FLOAT), 0, GL_STATIC_DRAW); // x,y,z,s,t per char ( with 4 vertex ) and 4 vertex for the background and the border + + // Fill the buffer + + //for(int c=0; cmFT_Face ); FT_UInt previous = 0; - fvec2 pen(0,0); + /* int w = camera->viewport()->width(); + int h = camera->viewport()->height(); - // mic fixme: - // - lines split and lines dimensions (linebox) should be precomputed on text set! - // - or convert this function to generate a pre-computed rendering-list! + if (w < 1) w = 1; + if (h < 1) h = 1;*/ + fvec2 pen(0,0); + // split the text in different lines - VL_CHECK(text().length()) + VL_CHECK(text.length()) std::vector< String > lines; lines.push_back( String() ); - for(int i=0; iglyph( lines[iline][c] ); + const CoreGlyph* glyph = mFont->glyph( lines[iline][c] ); if (!glyph) continue; - if ( kerningEnabled() && use_kerning && previous && glyph->glyphIndex() ) + if ( kerningEnabled() && has_kerning && previous && glyph->glyphIndex() ) { FT_Vector delta; delta.y = 0; if (layout() == LeftToRightText) @@ -313,21 +259,26 @@ void CoreText::renderText(const Actor*, const Camera*, const fvec4& color, const } previous = glyph->glyphIndex(); - if (glyph->textureHandle()) + //if (glyph->textureHandle()) { - glBindTexture( GL_TEXTURE_2D, glyph->textureHandle() ); + //glBindTexture( GL_TEXTURE_2D, glyph->textureHandle() ); - texc[0] = glyph->s0(); + /*texc[0] = glyph->s0(); texc[1] = glyph->t1(); + texc[2] = glyph->s1(); texc[3] = glyph->t1(); + texc[4] = glyph->s1(); texc[5] = glyph->t0(); + texc[6] = glyph->s0(); texc[7] = glyph->t0(); int left = layout() == RightToLeftText ? -glyph->left() : +glyph->left(); + // triangle strip layout + vect[0].x() = pen.x() + glyph->width()*0 + left -1; vect[0].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1; @@ -338,88 +289,157 @@ void CoreText::renderText(const Actor*, const Camera*, const fvec4& color, const vect[2].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1; vect[3].x() = pen.x() + glyph->width()*0 + left -1; - vect[3].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1; + vect[3].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1;*/ + + vec3 vect[4]; + vec2 texcoord[4]; + + // coord + /*data[indexData++] = pen.x() + glyph->width()*0 + left -1; + data[indexData++] = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1; + data[indexData++] = 0; + // texcoord + data[indexData++] = glyph->s0; + data[indexData++] = glyph->t1; + + data[indexData++] = pen.x() + glyph->width()*1 + left +1; + data[indexData++] = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1; + data[indexData++] = 0; + // texcoord + data[indexData++] = glyph->s1; + data[indexData++] = glyph->t1; + + data[indexData++] = pen.x() + glyph->width()*1 + left +1; + data[indexData++] = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1; + data[indexData++] = 0; + // texcoord + data[indexData++] = glyph->s1; + data[indexData++] = glyph->t0; + + data[indexData++] = pen.x() + glyph->width()*0 + left -1; + data[indexData++] = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1; + data[indexData++] = 0; + // texcoord + data[indexData++] = glyph->s0; + data[indexData++] = glyph->t0;*/ + + int left = layout() == RightToLeftText ? -glyph->left() : +glyph->left(); + + vect[0].x() = pen.x() + glyph->width()*0 + left -1; + vect[0].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1; + vect[0].z() = 0; + // texcoord + texcoord[0].x() = glyph->s0(); + texcoord[0].y() = glyph->t1(); + + vect[1].x() = pen.x() + glyph->width()*1 + left +1; + vect[1].y() = pen.y() + glyph->height()*0 + glyph->top() - glyph->height() -1; + vect[1].z() = 0; + // texcoord + texcoord[1].x() = glyph->s1(); + texcoord[1].y() = glyph->t1(); + + vect[2].x() = pen.x() + glyph->width()*1 + left +1; + vect[2].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1; + vect[2].z() = 0; + // texcoord + texcoord[2].x() = glyph->s1(); + texcoord[2].y() = glyph->t0(); + + vect[3].x() = pen.x() + glyph->width()*0 + left -1; + vect[3].y() = pen.y() + glyph->height()*1 + glyph->top() - glyph->height() +1; + vect[3].z() = 0; + // texcoord + texcoord[3].x() = glyph->s0(); + texcoord[3].y() = glyph->t0(); + if (layout() == RightToLeftText) { + #if (1) vect[0].x() -= glyph->width()-1 +2; vect[1].x() -= glyph->width()-1 +2; vect[2].x() -= glyph->width()-1 +2; vect[3].x() -= glyph->width()-1 +2; + #endif } - vect[0].y() -= mFont->mHeight; + /*vect[0].y() -= mFont->mHeight; vect[1].y() -= mFont->mHeight; vect[2].y() -= mFont->mHeight; - vect[3].y() -= mFont->mHeight; + vect[3].y() -= mFont->mHeight;*/ + #if (1) // normalize coordinate orgin to the bottom/left corner vect[0] -= (fvec3)bbox.minCorner(); vect[1] -= (fvec3)bbox.minCorner(); vect[2] -= (fvec3)bbox.minCorner(); vect[3] -= (fvec3)bbox.minCorner(); + #endif - // margin & horz_text_align - vect[0].x() += margin() + horz_text_align; - vect[0].y() += margin(); - vect[1].x() += margin() + horz_text_align; - vect[1].y() += margin(); - vect[2].x() += margin() + horz_text_align; - vect[2].y() += margin(); - vect[3].x() += margin() + horz_text_align; - vect[3].y() += margin(); + #if (1) + vect[0].x() += applied_margin + displace; + vect[1].x() += applied_margin + displace; + vect[2].x() += applied_margin + displace; + vect[3].x() += applied_margin + displace; + + vect[0].y() += applied_margin; + vect[1].y() += applied_margin; + vect[2].y() += applied_margin; + vect[3].y() += applied_margin; + #endif // apply offset for outline rendering - vect[0].x() += offset.x(); + /* vect[0].x() += offset.x(); vect[0].y() += offset.y(); vect[1].x() += offset.x(); vect[1].y() += offset.y(); vect[2].x() += offset.x(); vect[2].y() += offset.y(); vect[3].x() += offset.x(); - vect[3].y() += offset.y(); + vect[3].y() += offset.y();*/ - // text pivot - for(int i=0; i<4; ++i) + // alignment + /*for(int i=0; i<4; ++i) { - if (textOrigin() & AlignHCenter) + if (alignment() & AlignHCenter) { - VL_CHECK( !(textOrigin() & AlignRight) ) - VL_CHECK( !(textOrigin() & AlignLeft) ) + VL_CHECK( !(alignment() & AlignRight) ) + VL_CHECK( !(alignment() & AlignLeft) ) vect[i].x() -= (int)(bbox.width() / 2.0f); } - if (textOrigin() & AlignRight) + if (alignment() & AlignRight) { - VL_CHECK( !(textOrigin() & AlignHCenter) ) - VL_CHECK( !(textOrigin() & AlignLeft) ) + VL_CHECK( !(alignment() & AlignHCenter) ) + VL_CHECK( !(alignment() & AlignLeft) ) vect[i].x() -= (int)bbox.width(); } - if (textOrigin() & AlignTop) + if (alignment() & AlignTop) { - VL_CHECK( !(textOrigin() & AlignBottom) ) - VL_CHECK( !(textOrigin() & AlignVCenter) ) + VL_CHECK( !(alignment() & AlignBottom) ) + VL_CHECK( !(alignment() & AlignVCenter) ) vect[i].y() -= (int)bbox.height(); } - if (textOrigin() & AlignVCenter) + if (alignment() & AlignVCenter) { - VL_CHECK( !(textOrigin() & AlignTop) ) - VL_CHECK( !(textOrigin() & AlignBottom) ) + VL_CHECK( !(alignment() & AlignTop) ) + VL_CHECK( !(alignment() & AlignBottom) ) vect[i].y() -= int(bbox.height() / 2.0); } - } - - glDrawArrays(GL_QUADS, 0, 4); - - #if (0) - glDisable(GL_TEXTURE_2D); - glColor3fv(vec3(1,0,0).ptr()); - glDrawArrays(GL_LINE_LOOP, 0, 4); - glColor4fv(color.ptr()); - glEnable(GL_TEXTURE_2D); - #endif + }*/ + + for(int i = 0; i < 4; ++i) + { + data[indexData++] = vect[i].x(); + data[indexData++] = vect[i].y(); + data[indexData++] = vect[i].z(); + data[indexData++] = texcoord[i].x(); + data[indexData++] = texcoord[i].y(); + } + } if (just_space && lines[iline][c] == ' ' && iline != lines.size()-1) @@ -453,18 +473,230 @@ void CoreText::renderText(const Actor*, const Camera*, const fvec4& color, const } } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /*fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d }; + + //glBufferSubData(GL_ARRAY_BUFFER, 0, mText.length() * 4 * 3 * sizeof(GL_FLOAT), &vect[0]); + + //float texc[mText.length() * 4 * 2]; + float texc[] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; + //getCoordinates(texc); + + //glBufferSubData(GL_ARRAY_BUFFER, (mText.length() * 4 * 3) * sizeof(GL_FLOAT), 4 * 2 * sizeof(GL_FLOAT), texc); + + float data[20]; + int index = 0; + for(int i = 0; i < 4; ++i) + { + data[index++] = vect[i].x(); + data[index++] = vect[i].y(); + data[index++] = vect[i].z(); + data[index++] = texc[i * 2]; + data[index++] = texc[i * 2 + 1]; + } + + glBufferSubData(GL_ARRAY_BUFFER, 0, (mText.length() * 4 * 5) * sizeof(GL_FLOAT), data);*/ + glBufferSubData(GL_ARRAY_BUFFER, 0, (mText.length() * (4 * 3 + 4 * 2)) * sizeof(GL_FLOAT), data); + //} + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); +//----------------------------------------------------------------------------- +void CoreText::render_Implementation(const Actor* actor, const Shader* shader, const Camera* camera, OpenGLContext* gl_context) const +{ + // bind Vertex Attrib Set - VL_CHECK_OGL(); + //bool vbo_on = Has_BufferObject && isBufferObjectEnabled() && !isDisplayListEnabled(); - glDisable(GL_TEXTURE_2D); + gl_context->bindVAS(NULL, false, false); + + VL_CHECK(font()) + + if (!font() || !font()->mFT_Face) + return; + + if ( text().empty() ) + return; + + // Lighting can be enabled or disabled. + // glDisable(GL_LIGHTING); + + // Blending must be enabled explicity by the vl::Shader, also to perform z-sort. + // glEnable(GL_BLEND); + + // Trucchetto che usiamo per evitare z-fighting: + // Pass #1 - fill color and stencil + // - disable depth write mask + // - depth test can be enabled or not by the user + // - depth func can be choosen by the user + // - render in the order: background, border, shadow, outline, text + // Pass #2 - fill z-buffer + // - enable depth write mask + // - disable color mask + // - disable stencil + // - drawing background and border + + glBindBuffer(GL_ARRAY_BUFFER, mBufferID); + + // Get or Create the uniform for the sampler 2D. + /*if(shader && shader->glslProgram() && glyph->textureHandle()) + shader->glslProgram()->gocUniform("TextSampler")->setUniform(glyph()->textureHandle());*/ + + // Pass #1 + + // disable z-writing + GLboolean depth_mask=0; + glGetBooleanv(GL_DEPTH_WRITEMASK, &depth_mask); + glDepthMask(GL_FALSE); + + // background + if (backgroundEnabled()) + renderBackground( actor, camera ); + + // border + if (borderEnabled()) + renderBorder( actor, camera ); + + // to have the most correct results we should render the text twice one for color and stencil, the other for the z-buffer + + // shadow render + if (shadowEnabled()) + renderText( actor, camera, shadowColor(), shadowVector() ); + // outline render + if (outlineEnabled()) + { + renderText( actor, camera, outlineColor(), fvec2(-1,0) ); + renderText( actor, camera, outlineColor(), fvec2(+1,0) ); + renderText( actor, camera, outlineColor(), fvec2(0,-1) ); + renderText( actor, camera, outlineColor(), fvec2(0,+1) ); + } + // text render + renderText( actor, camera, color(), fvec2(0,0) ); + + // Pass #2 + // fills the z-buffer (not the stencil buffer): approximated to the text bbox + + // restores depth mask + glDepthMask(depth_mask); + + if (depth_mask) + { + // disables writing to the color buffer + GLboolean color_mask[4]; + glGetBooleanv(GL_COLOR_WRITEMASK, color_mask); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + // disable writing to the stencil buffer + int stencil_front_mask=0; + glGetIntegerv(GL_STENCIL_WRITEMASK, &stencil_front_mask); + int stencil_back_mask=0; + if (Has_GL_Version_2_0) + glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &stencil_back_mask); + glStencilMask(0); + + // background + renderBackground( actor, camera ); + + // border + renderBorder( actor, camera ); + + // restores color writing + glColorMask(color_mask[0],color_mask[1],color_mask[2],color_mask[3]); + + // restore the stencil masks + glStencilMask(stencil_front_mask); + if (Has_GL_Version_2_0) + glStencilMaskSeparate(GL_BACK, stencil_back_mask); + + // Unbind buffer + glBindBuffer(GL_ARRAY_BUFFER, 0); + } +} +//----------------------------------------------------------------------------- +void CoreText::renderText(const Actor*, const Camera*, const fvec4& color, const fvec2& offset) const +{ + if(!mFont) + { + Log::error("CoreText::renderText() error: no Font assigned to the CoreText object.\n"); + VL_TRAP() + return; + } + + if (!font()->mFT_Face) + { + Log::error("CoreText::renderText() error: invalid FT_Face: probably you tried to load an unsupported font format.\n"); + VL_TRAP() + return; + } + + VL_glActiveTexture( GL_TEXTURE0 ); + glEnable(GL_TEXTURE_2D); + + for(int c=0; c& glyph = mFont->glyph(mText[c]); + //if(glyph->textureHandle()) + { + //glBindTexture(GL_TEXTURE_2D, glyph->textureHandle()); + //glBindTexture(GL_TEXTURE_2D, mTextTexture->handle()); + //VL_glUniform1uiv( + + glEnableVertexAttribArray(vl::VA_TexCoord0); + glVertexAttribPointer(vl::VA_TexCoord0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), reinterpret_cast< GLvoid* >(c * 20 * sizeof(GL_FLOAT) + 3 * sizeof(GL_FLOAT))); + + glEnableVertexAttribArray(vl::VA_Position); + glVertexAttribPointer(vl::VA_Position, 3, GL_FLOAT, GL_TRUE, 5 * sizeof(GL_FLOAT), reinterpret_cast< GLvoid* >(c * 20 * sizeof(GL_FLOAT))); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + + } + } + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + glDisableVertexAttribArray(vl::VA_Position); + glDisableVertexAttribArray(vl::VA_TexCoord0); + + VL_CHECK_OGL(); + + /*glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0);*/ } //----------------------------------------------------------------------------- // returns the raw bounding box of the string, i.e. without alignment, margin and matrix transform. -AABB CoreText::rawboundingRect(const String& text) const +AABB CoreText::computeRawBoundingRect(const String& text) const { AABB aabb; @@ -497,7 +729,7 @@ AABB CoreText::rawboundingRect(const String& text) const continue; } - const ref& glyph = mFont->glyph(text[c]); + const ref& glyph = mFont->glyph(text[c]); // if glyph == NULL there was an error during its creation... if (glyph.get() == NULL) @@ -521,8 +753,9 @@ AABB CoreText::rawboundingRect(const String& text) const } previous = glyph->glyphIndex(); - if ( glyph->textureHandle() ) + //if ( glyph->textureHandle() ) { + int left = layout() == RightToLeftText ? -glyph->left() : +glyph->left(); vect[0].x() = pen.x() + glyph->width()*0 + left -1; @@ -572,12 +805,12 @@ void CoreText::renderBackground(const Actor*, const Camera*) const // rendering of border and background follows different rules in 3D compared from 2D: lines and polygons follow different rasterization rules! // Background color - glColor4fv(mBackgroundColor.ptr()); + //glColor4fv(mBackgroundColor.ptr()); // Constant normal - glNormal3fv( fvec3(0,0,1).ptr() ); + //glNormal3fv( fvec3(0,0,1).ptr() ); - vec3 a,b,c,d; + /*vec3 a,b,c,d; AABB bbox = boundingRect(); // mic fixme: this guy recomputes the bounds again instead of using the precomputed one!! a = bbox.minCorner(); b.x() = (float)bbox.maxCorner().x(); @@ -588,13 +821,15 @@ void CoreText::renderBackground(const Actor*, const Camera*) const // set z to 0 a.z() = b.z() = c.z() = d.z() = 0; - fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d }; - glEnableClientState( GL_VERTEX_ARRAY ); - glVertexPointer(3, GL_FLOAT, 0, vect); + fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d };*/ + + glEnableVertexAttribArray(vl::VA_Position); + //glVertexAttribPointer(vl::VA_Position, 3, GL_FLOAT, GL_FALSE, 0, vect); - glDrawArrays(GL_QUADS,0,4); + glDrawArrays(GL_QUADS,mText.length() * 2,4); - glDisableClientState( GL_VERTEX_ARRAY ); + //glDisableClientState( GL_VERTEX_ARRAY ); + glDisableVertexAttribArray(vl::VA_Position); } //----------------------------------------------------------------------------- void CoreText::renderBorder(const Actor*, const Camera*) const @@ -603,12 +838,12 @@ void CoreText::renderBorder(const Actor*, const Camera*) const // rendering of border and background follows different rules in 3D compared from 2D: lines and polygons follow different rasterization rules! // Border color - glColor4fv(mBorderColor.ptr()); + //glColor4fv(mBorderColor.ptr()); // Constant normal - glNormal3fv( fvec3(0,0,1).ptr() ); + //glNormal3fv( fvec3(0,0,1).ptr() ); - vec3 a,b,c,d; + /*vec3 a,b,c,d; AABB bbox = boundingRect(); // mic fixme: this guy recomputes the bounds again instead of using the precomputed one!! a = bbox.minCorner(); b.x() = (float)bbox.maxCorner().x(); @@ -619,24 +854,26 @@ void CoreText::renderBorder(const Actor*, const Camera*) const // set z to 0 a.z() = b.z() = c.z() = d.z() = 0; - fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d }; - glEnableClientState( GL_VERTEX_ARRAY ); - glVertexPointer(3, GL_FLOAT, 0, vect); + fvec3 vect[] = { (fvec3)a, (fvec3)b, (fvec3)c, (fvec3)d };*/ + glEnableVertexAttribArray(vl::VA_Position); + //glVertexAttribPointer(vl::VA_Position, 3, GL_FLOAT, GL_FALSE, 0, vect); - glDrawArrays(GL_LINE_LOOP,0,4); + glDrawArrays(GL_LINE_LOOP,mText.length() * 2,4); - glDisableClientState( GL_VERTEX_ARRAY ); + //glDisableClientState( GL_VERTEX_ARRAY ); + glDisableVertexAttribArray(vl::VA_Position); } //----------------------------------------------------------------------------- -AABB CoreText::boundingRect() const +/*AABB CoreText::boundingRect() const { return boundingRect(text()); -} +}*/ //----------------------------------------------------------------------------- -AABB CoreText::boundingRect(const String& text) const +AABB CoreText::boundingRect(/*const String& text*/) const { - AABB bbox = rawboundingRect( text ); - bbox.setMaxCorner( bbox.maxCorner() + vec3(2.0f*margin(), 2.0f*margin(), 0) ); + int applied_margin = backgroundEnabled() || borderEnabled() ? margin() : 0; + AABB bbox = mRawBoundingRect; // Compute when text was setted or kerning was changed //rawboundingRect( text ); + bbox.setMaxCorner( bbox.maxCorner() + vec3(2.0f*applied_margin, 2.0f*applied_margin, 0) ); // normalize coordinate orgin to the bottom/left corner vec3 min = bbox.minCorner() - bbox.minCorner(); @@ -680,5 +917,129 @@ AABB CoreText::boundingRect(const String& text) const aabb.setMinCorner(min); aabb.setMaxCorner(max); return aabb; +}//----------------------------------------------------------------------------- +int CoreText::getSampler() const +{ + // Artificial because they're probably more than one character in the text + VL_CHECK(mText.length()); + VL_CHECK(mFont.get() != NULL); + + /*for(int c=0; c& glyph = mFont->glyph(mText[c]); + return glyph->textureHandle(); + }*/ + + return -1; +} +//----------------------------------------------------------------------------- +vl::Image* CoreText::getImage() +{ + // Artificial because they're probably more than one character in the text + VL_CHECK(mText.length()); + VL_CHECK(mFont.get() != NULL); + + /*for(int c=0; c& glyph = mFont->glyph(mText[c]); + return const_cast< vl::Image* >(glyph->mGlyphImage.get()); + }*/ + + return NULL; } //----------------------------------------------------------------------------- +Image* CoreText::textImage(const String &text) +{ + if(mTextImage) + return mTextImage.get(); + + // Get all the glyph of the text + unsigned int width = 0; + unsigned int maxHeight = 0; + const unsigned int margin = 1; // never change + /*for(int c=0; c<(int)text.length(); c++) + { + const ref& glyph = mFont->glyph(text[c]); + + if(glyph->mGlyphImage.get() != NULL) + { + width += glyph->width(); + } + else + { + width += glyph->advance().x(); + } + + if(glyph->height() > maxHeight) + maxHeight = glyph->height(); + } + + // Generate the texture of all the text + mTextImage = new Image(); + mTextImage->allocate2D(width + 2 * margin, maxHeight + 2 * margin, 1, IF_RGBA, IT_UNSIGNED_BYTE); + + // Initialize the image + std::vector emptyData((width + 2 * margin) * (maxHeight + 2 * margin) * 4, 0); + std::memcpy(mTextImage->imageBuffer()->ptr(), &emptyData[0], mTextImage->imageBuffer()->bytesUsed()); + + fvec2 pen(0, 0);*/ + + /*for(int c=0; c<(int)text.length(); c++) + { + ref glyph = mFont->glyph(text[c]); + + if(glyph->mGlyphImage.get() != NULL) + { + mTextImage->copySubImage(glyph->mGlyphImage.get(), RectI(0, glyph->mGlyphImage->height() - (margin * 2 + glyph->height()), margin*2 + glyph->width(), margin * 2 + glyph->height()), ivec2(pen.x(), pen.y())); + //pen += fvec2(glyph->width(), 0.0f); + } + /* else + {*/ + /* pen += glyph->advance()/* + fvec2(1.0f, 0.0f)*//*; + //} + + + }*/ + + return mTextImage.get(); +} +//----------------------------------------------------------------------------- +Texture* CoreText::textTexture(const String &text) +{ + if(mTextTexture) + return mTextTexture.get(); + + ref< Image > image = textImage(text); + + mTextTexture = new Texture(image.get(), TF_RGBA, false); + vl::TexParameter* parameters = mTextTexture->getTexParameter(); + parameters->setMagFilter(vl::TPF_NEAREST); + parameters->setMinFilter(vl::TPF_NEAREST); + parameters->setWrapS(vl::TPW_CLAMP); + parameters->setWrapT(vl::TPW_CLAMP); + + return mTextTexture.get(); +} +//----------------------------------------------------------------------------- +void CoreText::getCoordinates(float* texc) +{ + VL_CHECK(mText.length()); + VL_CHECK(mFont.get() != NULL); + + int index = 0; + for(int c=0; c& glyph = mFont->glyph(mText[c]); + /*if(glyph->textureHandle()) + { + texc[index++] = glyph->s0(); + texc[index++] = glyph->t1(); + texc[index++] = glyph->s1(); + texc[index++] = glyph->t1(); + texc[index++] = glyph->s1(); + texc[index++] = glyph->t0(); + texc[index++] = glyph->s0(); + texc[index++] = glyph->t0(); + }*/ + } +} diff --git a/src/vlGraphics/CoreText.hpp b/src/vlGraphics/CoreText.hpp index 1f353ee8d..d79ef1f23 100644 --- a/src/vlGraphics/CoreText.hpp +++ b/src/vlGraphics/CoreText.hpp @@ -1,7 +1,7 @@ /**************************************************************************************/ /* */ /* Visualization Library */ -/* http://visualizationlibrary.org */ +/* http://www.visualizationlibrary.org */ /* */ /* Copyright (c) 2005-2010, Michele Bosi */ /* All rights reserved. */ @@ -32,11 +32,13 @@ #ifndef CoreText_INCLUDE_ONCE #define CoreText_INCLUDE_ONCE -#include -#include +#include +#include +#include #include #include #include +#include #include namespace vl @@ -51,15 +53,18 @@ namespace vl public: CoreText(): mColor(1,1,1,1), mBorderColor(0,0,0,1), mBackgroundColor(1,1,1,1), mOutlineColor(0,0,0,1), mShadowColor(0,0,0,0.5f), mShadowVector(2,-2), mTextOrigin(AlignBottom|AlignLeft), mMargin(5), mLayout(LeftToRightText), mTextAlignment(TextAlignLeft), - mBorderEnabled(false), mBackgroundEnabled(false), mOutlineEnabled(false), mShadowEnabled(false), mKerningEnabled(true) + mBorderEnabled(false), mBackgroundEnabled(false), mOutlineEnabled(false), mShadowEnabled(false), mKerningEnabled(true), + mBufferID(0) { VL_DEBUG_SET_OBJECT_NAME() } + + ~CoreText(); //! The text to be rendered. const String& text() const { return mText; } //! The text to be rendered. - void setText(const String& text) { mText = text; } + void setText(const String& text); //! The color of the text. const fvec4& color() const { return mColor; } @@ -72,12 +77,12 @@ namespace vl void setMargin(int margin) { mMargin = margin; } //! The font to be used to render the text. - const Font* font() const { return mFont.get(); } + const CoreFont* font() const { return mFont.get(); } //! The font to be used to render the text. - Font* font() { return mFont.get(); } + CoreFont* font() { return mFont.get(); } //! The font to be used to render the text. - void setFont(Font* font) { mFont = font; } - + void setFont(CoreFont* font) { mFont = font; } + //! Text layout: left to right, right to left. ETextLayout layout() const { return mLayout; } //! Text layout: left to right, right to left. @@ -147,8 +152,17 @@ namespace vl AABB boundingRect() const; //! Returns the plain 2D bounding box of the text, in local coordinates. - AABB boundingRect(const String& text) const; - + //AABB boundingRect(const String& text) const; + + //! Get the sampler of the texture + int getSampler() const; + + //! Get the Image of the texture + vl::Image* getImage(); + + //! Get the texture + vl::Texture* getTexture() { return mTextTexture.get(); } + // --- Renderable interface implementation --- virtual void updateDirtyBufferObject(EBufferObjectUpdateMode) {} @@ -162,10 +176,17 @@ namespace vl void renderText(const Actor*, const Camera* camera, const fvec4& color, const fvec2& offset) const; void renderBackground(const Actor* actor, const Camera* camera) const; void renderBorder(const Actor* actor, const Camera* camera) const; - AABB rawboundingRect(const String& text) const; + AABB computeRawBoundingRect(const String& text) const; + + Image* textImage(const String& text); + + //! Get the texture + vl::Texture* textTexture(const String& text); + + void getCoordinates(float* texc); protected: - mutable ref mFont; + mutable ref mFont; String mText; fvec4 mColor; fvec4 mBorderColor; @@ -182,6 +203,14 @@ namespace vl bool mOutlineEnabled; bool mShadowEnabled; bool mKerningEnabled; + GLuint mBufferID; + + private: + mutable std::vector< String > mLines; + mutable std::vector< AABB > mDimensionsLines; + AABB mRawBoundingRect; + ref< Image > mTextImage; + ref< Texture > mTextTexture; }; } diff --git a/src/vlGraphics/DrawArrays.hpp b/src/vlGraphics/DrawArrays.hpp index 4e59c8461..da10f8c96 100644 --- a/src/vlGraphics/DrawArrays.hpp +++ b/src/vlGraphics/DrawArrays.hpp @@ -34,6 +34,7 @@ #include #include +#include namespace vl { @@ -139,6 +140,27 @@ namespace vl return TriangleIterator(tid.get()); } + LineIterator lineIterator() const + { + ref lid = new LineIteratorDirect( primitiveType() ); + lid->initialize(mStart, mStart+mCount); + return LineIterator(lid.get()); + } + + TriangleAccessor triangleAccessor() const + { + ref tad = new TriangleAccessorDirect( primitiveType() ); + tad->initialize(mStart, mStart+mCount); + return TriangleAccessor(tad.get()); + } + + LineAccessor lineAccessor() const + { + ref lad = new LineAccessorDirect( primitiveType() ); + lad->initialize(mStart, mStart+mCount); + return LineAccessor(lad.get()); + } + IndexIterator indexIterator() const { ref iida = new IndexIteratorDrawArrays; diff --git a/src/vlGraphics/DrawCall.hpp b/src/vlGraphics/DrawCall.hpp index c2a8149c5..9aa570e31 100644 --- a/src/vlGraphics/DrawCall.hpp +++ b/src/vlGraphics/DrawCall.hpp @@ -34,6 +34,9 @@ #include #include +#include +#include +#include #include #include @@ -133,6 +136,20 @@ namespace vl * PT_TRIANGLE_FAN, PT_POLYGON, PT_QUADS, PT_QUAD_STRIP. */ virtual TriangleIterator triangleIterator() const = 0; + /** + * Returns a LineIterator used to iterate through the lines of a DrawCall. */ + virtual LineIterator lineIterator() const = 0; + + /** + * Returns a TriangleAccessor used to access a triangle of a DrawCall. + */ + virtual TriangleAccessor triangleAccessor() const = 0; + + /** + * Returns a LineIterator used to access a line of a DrawCall. + */ + virtual LineAccessor lineAccessor() const = 0; + /** * Returns a IndexIterator used to iterate through the virtual indices of a DrawCall. * This \note The returned indices already take into account primitive restart and base vertex. */ diff --git a/src/vlGraphics/DrawElements.hpp b/src/vlGraphics/DrawElements.hpp index 0469b98f8..e90cb6933 100644 --- a/src/vlGraphics/DrawElements.hpp +++ b/src/vlGraphics/DrawElements.hpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -354,6 +355,33 @@ namespace vl return TriangleIterator(it.get()); } + LineIterator lineIterator() const + { + ref< LineIteratorIndexed > it = + new LineIteratorIndexed( mIndexBuffer.get(), primitiveType(), + baseVertex(), primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return LineIterator(it.get()); + } + + TriangleAccessor triangleAccessor() const + { + ref< TriangleAccessorIndexed > it = + new TriangleAccessorIndexed( mIndexBuffer.get(), primitiveType(), + baseVertex(), primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return TriangleAccessor(it.get()); + } + + LineAccessor lineAccessor() const + { + ref< LineAccessorIndexed > it = + new LineAccessorIndexed( mIndexBuffer.get(), primitiveType(), + baseVertex(), primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return LineAccessor(it.get()); + } + IndexIterator indexIterator() const { ref< IndexIteratorElements > iie = new IndexIteratorElements; diff --git a/src/vlGraphics/DrawRangeElements.hpp b/src/vlGraphics/DrawRangeElements.hpp index 837ecb482..b8034c839 100644 --- a/src/vlGraphics/DrawRangeElements.hpp +++ b/src/vlGraphics/DrawRangeElements.hpp @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -300,6 +301,33 @@ namespace vl return TriangleIterator(it.get()); } + LineIterator lineIterator() const + { + ref< LineIteratorIndexed > it = + new LineIteratorIndexed( mIndexBuffer.get(), primitiveType(), + baseVertex(), primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return LineIterator(it.get()); + } + + TriangleAccessor triangleAccessor() const + { + ref< TriangleAccessorIndexed > it = + new TriangleAccessorIndexed( mIndexBuffer.get(), primitiveType(), + baseVertex(), primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return TriangleAccessor(it.get()); + } + + LineAccessor lineAccessor() const + { + ref< LineAccessorIndexed > it = + new LineAccessorIndexed( mIndexBuffer.get(), primitiveType(), + baseVertex(), primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return LineAccessor(it.get()); + } + IndexIterator indexIterator() const { ref< IndexIteratorElements > iie = new IndexIteratorElements; diff --git a/src/vlGraphics/Extrusion.cpp b/src/vlGraphics/Extrusion.cpp index 6a65befa3..1f7d9d482 100644 --- a/src/vlGraphics/Extrusion.cpp +++ b/src/vlGraphics/Extrusion.cpp @@ -35,7 +35,7 @@ using namespace vl; -ref Extrusion::extrude() +ref Extrusion::extrude(bool compatibilityProfile) { if (silhouette().empty()) { @@ -190,13 +190,19 @@ ref Extrusion::extrude() } ref vert_array = new ArrayFloat3; - geom->setVertexArray( vert_array.get() ); + if(compatibilityProfile) + geom->setVertexArray( vert_array.get() ); + else + geom->setVertexAttribArray(VA_Position, vert_array.get()); vert_array->initFrom(verts); if (!colorPath().empty()) { ref col_array = new ArrayFloat4; - geom->setColorArray(col_array.get()); + if(compatibilityProfile) + geom->setColorArray(col_array.get()); + else + geom->setVertexAttribArray(VA_Color, col_array.get()); col_array->resize(geom->vertexArray()->size()); int offs = 0; for(size_t iseg=0; iseg extrude(); + vl::ref extrude(bool compatibilityProfile = true); //! Sets the silhouette to be extruded. void setSilhouette(const std::vector& silhouette) { mSilhouette = silhouette; } diff --git a/src/vlGraphics/Extrusions.cpp b/src/vlGraphics/Extrusions.cpp new file mode 100644 index 000000000..89ab473f7 --- /dev/null +++ b/src/vlGraphics/Extrusions.cpp @@ -0,0 +1,237 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#include +#include +#include + +using namespace vl; + +ref Extrusions::extrude(bool compatibilityProfile) +{ + if (silhouette().empty()) + { + Log::error("Extrusion::extrude(): no silhouette defined.\n"); + return NULL; + } + if (positionPath().empty()) + { + Log::error("Extrusion::extrude() needs at least a non empty positionPath().\n"); + return NULL; + } + if (!scalingPath().empty() && scalingPath().size() != positionPath().size()-2) + { + Log::error("Extrusion::extrude(): scalingPath() must have the same number of control points as positionPath().\n"); + return NULL; + } + if (!rotationPath().empty() && rotationPath().size() != positionPath().size()-2) + { + Log::error("Extrusion::extrude(): rotationPath() must have the same number of control points as positionPath().\n"); + return NULL; + } + if (!colorPath().empty() && colorPath().size() != positionPath().size()-2) + { + Log::error("Extrusion::extrude(): colorPath() must have the same number of control points as positionPath().\n"); + return NULL; + } + + ref geom = new Geometry; + + size_t segments = positionPath().size()-2; + + std::vector verts; + verts.resize( silhouette().size() * segments ); + + vl::fmat4 m = fmat4::getRotation(fvec3(0,1,0), positionPath()[1]-positionPath()[0]); + + // initialize silhouette on the x/z plane + std::vector projected_sil; + projected_sil.resize(silhouette().size()); + for(unsigned i=0; i plane_normals; + plane_normals.resize(positionPath().size()); + for(unsigned i=1; ip1 vector + verts.at(j+silhouette().size()*(i-1)) = projected_sil[j] = P + V*t; + } + } + + // rotation + if(!rotationPath().empty()) + { + for(unsigned i=1; i de = new DrawElementsUInt(PT_QUADS); + geom->drawCalls().push_back(de.get()); + de->indexBuffer()->resize(4 * prof_count * (segments-1)); + for(size_t iseg=0; isegindexBuffer()->at((iquad)*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize; + de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize; // % is used for loop + de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize; // % is used for loop + de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize; + } + } + } + + // bottom/top caps + + size_t tess_bottom_count = 0; + size_t tess_top_count = 0; + + if(fillBottom()) + { + size_t start = verts.size(); + Tessellator tessellator; + for(unsigned i=0; i < silhouettes().size(); ++i) + tessellator.contours().push_back(silhouettes().at(i)); + for(unsigned i=0; idrawCalls().push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) ); + tess_bottom_count = tessellator.tessellatedTris().size(); + } + if(fillTop()) + { + size_t start = verts.size(); + Tessellator tessellator; + for(int i=silhouettes().size() - 1; i >= 0; --i) + tessellator.contours().push_back(silhouettes().at(i)); + for(unsigned i=0; i < silhouette().size(); ++i) + tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]); + tessellator.setWindingRule(vl::TW_TESS_WINDING_ODD); + tessellator.tessellate(); + for(unsigned i=0; idrawCalls().push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) ); + tess_top_count = tessellator.tessellatedTris().size(); + } + + ref vert_array = new ArrayFloat3; + if(compatibilityProfile) + geom->setVertexArray( vert_array.get() ); + else + geom->setVertexAttribArray(VA_Position, vert_array.get()); + vert_array->initFrom(verts); + + if (!colorPath().empty()) + { + ref col_array = new ArrayFloat4; + if(compatibilityProfile) + geom->setColorArray(col_array.get()); + else + geom->setVertexAttribArray(VA_Color, col_array.get()); + col_array->resize(geom->vertexArray()->size()); + int offs = 0; + for(size_t iseg=0; isegat(offs) = colorPath()[iseg]; + } + if (fillBottom()) + { + for(unsigned j=0; jat(offs) = colorPath()[0]; + } + if (fillTop()) + { + for(unsigned j=0; jat(offs) = colorPath().back(); + } + } + + if (!smooth()) + geom->convertDrawCallToDrawArrays(); + + geom->computeNormals(); + + return geom; +} diff --git a/src/vlGraphics/Extrusions.hpp b/src/vlGraphics/Extrusions.hpp new file mode 100644 index 000000000..c98601463 --- /dev/null +++ b/src/vlGraphics/Extrusions.hpp @@ -0,0 +1,150 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#ifndef Extrusions_INCLUDE_ONCE +#define Extrusions_INCLUDE_ONCE + +#include +#include +#include +#include +#include +#include + +namespace vl +{ + /** + * The Extrusion class generates a Geometry extruding a silhouette along a path. + * \sa + * + * - \ref pagGuideExtrusion "Extrusion Tutorial" for a practical example of how to use extrusions. + * - Interpolator, LinearInterpolator, CatmullRomInterpolator to generate silhouettes and extrusion paths. + * + * + */ + class VLGRAPHICS_EXPORT Extrusions: public vl::Object + { + VL_INSTRUMENT_CLASS(vl::Extrusions, Object) + + public: + //! Constructor. + Extrusions() + { + VL_DEBUG_SET_OBJECT_NAME() + mSmooth = false; + mFillBottom = true; + mFillTop = true; + mSilhouetteMode = SilhouetteClosed; + } + + //! Performs the actual extrusion. + vl::ref extrude(bool compatibilityProfile = true); + + //! Sets the number of points in each silhouette + void setSilhouettes(const std::vector& silhouettes) { mSilhouettes = silhouettes; } + //! Return the number of points in each silhouette + const std::vector& silhouettes() const { return mSilhouettes; } + //! Return the number of points in each silhouette + std::vector& silhouettes() { return mSilhouettes;} + + //! Sets the silhouette to be extruded. + void setSilhouette(const std::vector& silhouette) { mSilhouette = silhouette; } + //! Returns the silhouette to be extruded. + const std::vector& silhouette() const { return mSilhouette; } + //! Returns the silhouette to be extruded. + std::vector& silhouette() { return mSilhouette; } + + //! Wether the silhouette is considered closed, i.e. a line-loop, or open. + void setSilhouetteMode(ESilhouetteMode mode) { mSilhouetteMode = mode; } + //! Wether the silhouette is considered closed, i.e. a line-loop, or open. + ESilhouetteMode silhouetteMode() const { return mSilhouetteMode; } + + //! If true the normals of the geometry are smoothed. + void setSmooth(bool smooth) { mSmooth = smooth; } + //! If true the normals of the geometry are smoothed. + bool smooth() const { return mSmooth; } + + //! Whether a set of triangles should be generated to fill the beginning of the extrusion (default is \p true). + void setFillBottom(bool fill) { mFillBottom = fill; } + //! Whether a set of triangles should be generated to fill the beginning of the extrusion (default is \p true). + bool fillBottom() const { return mFillBottom; } + + //! Whether a set of triangles should be generated to fill the ending of the extrusion (default is \p true). + void setFillTop(bool fill) { mFillTop = fill; } + //! Whether a set of triangles should be generated to fill the ending of the extrusion (default is \p true). + bool fillTop() const { return mFillTop; } + + //! The path along which the silhouette is extruded. + //! The path starts and ends with one extra control point on each side that define the orientation of the start/end extruded segments. + const std::vector& positionPath() const { return mPositionPath; } + //! The path along which the silhouette is extruded. + //! The path starts and ends with one extra control point on each side that define the orientation of the start/end extruded segments. + std::vector& positionPath() { return mPositionPath; } + //! The scaling to be applied along the extrusion. + //! There must be one scaling control point for each position control point in the positionPath() with the exclusion + //! of the starting and ending control points, i.e scalingPath().size() must be equal to positionPath().size()-2. + const std::vector& scalingPath() const { return mScalingPath; } + //! The scaling to be applied along the extrusion. + //! There must be one scaling control point for each position control point in the positionPath() with the exclusion + //! of the starting and ending control points, i.e scalingPath().size() must be equal to positionPath().size()-2. + std::vector& scalingPath() { return mScalingPath; } + //! The rotation to be applied along the extrusion. + //! There must be one rotation control point for each position control point in the positionPath() with the exclusion + //! of the starting and ending control points, i.e rotationPath().size() must be equal to positionPath().size()-2. + const std::vector& rotationPath() const { return mRotationPath; } + //! The rotation to be applied along the extrusion. + //! There must be one rotation control point for each position control point in the positionPath() with the exclusion + //! of the starting and ending control points, i.e rotationPath().size() must be equal to positionPath().size()-2. + std::vector& rotationPath() { return mRotationPath; } + //! The color to be applied to the extrusion. + //! There must be one color control point for each position control point in the positionPath() with the exclusion + //! of the starting and ending control points, i.e colorPath().size() must be equal to positionPath().size()-2. + const std::vector& colorPath() const { return mColorPath; } + //! The color to be applied to the extrusion. + //! There must be one color control point for each position control point in the positionPath() with the exclusion + //! of the starting and ending control points, i.e colorPath().size() must be equal to positionPath().size()-2. + std::vector& colorPath() { return mColorPath; } + + protected: + std::vector mSilhouettes; + std::vector mSilhouette; + std::vector mPositionPath; + std::vector mScalingPath; + std::vector mRotationPath; + std::vector mColorPath; + ESilhouetteMode mSilhouetteMode; + bool mSmooth; + bool mFillBottom; + bool mFillTop; + }; +} + +#endif diff --git a/src/vlGraphics/FontManager.cpp b/src/vlGraphics/FontManager.cpp index 4a3ee0682..a05ea29f6 100644 --- a/src/vlGraphics/FontManager.cpp +++ b/src/vlGraphics/FontManager.cpp @@ -58,6 +58,7 @@ FontManager::FontManager(void* free_type_library) FontManager::~FontManager() { releaseAllFonts(); + releaseAllCoreFonts(); if (mFreeTypeLibrary) { FT_Done_FreeType( (FT_Library)mFreeTypeLibrary ); @@ -84,6 +85,25 @@ Font* FontManager::acquireFont(const String& path, int size, bool smooth) return font.get(); } //----------------------------------------------------------------------------- +CoreFont* FontManager::acquireCoreFont(const String& path, int size, bool smooth) +{ + ref coreFont; + for(unsigned i=0; !coreFont && ifilePath() == path && coreFonts()[i]->size() == size/* && coreFonts()[i]->smooth() == smooth*/) + coreFont = coreFonts()[i]; + + if (!coreFont) + { + coreFont = new CoreFont(this); + coreFont->setSize(size); + coreFont->loadFont(path); + coreFont->setSmooth(smooth); + mCoreFonts.push_back( coreFont ); + } + + return coreFont.get(); +} +//----------------------------------------------------------------------------- void FontManager::releaseFont(Font* font) { std::vector< ref >::iterator it = std::find(mFonts.begin(), mFonts.end(), font); @@ -91,9 +111,22 @@ void FontManager::releaseFont(Font* font) mFonts.erase(it); } //----------------------------------------------------------------------------- +void FontManager::releaseCoreFont(CoreFont* coreFont) +{ + std::vector< ref >::iterator it = std::find(mCoreFonts.begin(), mCoreFonts.end(), coreFont); + if (it != mCoreFonts.end()) + mCoreFonts.erase(it); +} +//----------------------------------------------------------------------------- void FontManager::releaseAllFonts() { for(unsigned i=0; ireleaseFreeTypeData(); } //----------------------------------------------------------------------------- +void FontManager::releaseAllCoreFonts() +{ + for(unsigned i=0; ireleaseFreeTypeData(); +} +//----------------------------------------------------------------------------- diff --git a/src/vlGraphics/FontManager.hpp b/src/vlGraphics/FontManager.hpp index 2d4334b24..bd3bc1124 100644 --- a/src/vlGraphics/FontManager.hpp +++ b/src/vlGraphics/FontManager.hpp @@ -33,6 +33,7 @@ #define FontManager_INCLUDE_ONCE #include +#include namespace vl { @@ -57,15 +58,27 @@ namespace vl //! Creates or returns an already created Font. Font* acquireFont(const String& font, int size, bool smooth=false); + + //! Creates or returns an already created Font. + CoreFont* acquireCoreFont(const String& font, int size, bool smooth=false); //! Returns the list of Fonts created till now. const std::vector< ref >& fonts() const { return mFonts; } + + //! Returns the list of Fonts created till now. + const std::vector< ref >& coreFonts() const { return mCoreFonts; } //! Releases a given Font and its associated resources and memory. void releaseFont(Font* font); + + //! Releases a given Font and its associated resources and memory. + void releaseCoreFont(CoreFont* font); //! Releases all Fonts and associated resources and memory. void releaseAllFonts(); + + //! Releases all Fonts and associated resources and memory. + void releaseAllCoreFonts(); //! Returns the FT_Library handle. const void* freeTypeLibrary() const { return mFreeTypeLibrary; } @@ -79,6 +92,7 @@ namespace vl protected: std::vector< ref > mFonts; + std::vector< ref > mCoreFonts; void* mFreeTypeLibrary; }; diff --git a/src/vlGraphics/FramebufferObject.cpp b/src/vlGraphics/FramebufferObject.cpp index 285b0b148..577143256 100644 --- a/src/vlGraphics/FramebufferObject.cpp +++ b/src/vlGraphics/FramebufferObject.cpp @@ -250,7 +250,10 @@ void FramebufferObject::addColorAttachment( EAttachmentPoint attach_point, FBOCo //----------------------------------------------------------------------------- void FramebufferObject::addTextureAttachment( EAttachmentPoint attach_point, FBOAbstractTextureAttachment* attachment ) { - VL_CHECK( attach_point >= AP_COLOR_ATTACHMENT0 && attach_point <= AP_COLOR_ATTACHMENT15 ); + VL_CHECK( attach_point >= AP_COLOR_ATTACHMENT0 && attach_point <= AP_COLOR_ATTACHMENT15 || + attach_point == AP_DEPTH_ATTACHMENT || + attach_point == AP_STENCIL_ATTACHMENT || + attach_point == AP_DEPTH_STENCIL_ATTACHMENT); // Texture attachment can be depth or stencil too (see glFrameBufferTexture documentation) VL_CHECK( Has_FBO ) if( !Has_FBO ) return; diff --git a/src/vlGraphics/GLSL.cpp b/src/vlGraphics/GLSL.cpp index 74516537a..182c8518d 100644 --- a/src/vlGraphics/GLSL.cpp +++ b/src/vlGraphics/GLSL.cpp @@ -509,6 +509,11 @@ void GLSLProgram::preLink() } } } + + if (Has_Transform_Feedback && transformFeedback() ) + { + glTransformFeedbackVaryings(handle(), transformFeedback()->transformFeedbackVaryingsCount(), transformFeedback()->transformFeedbackVaryings(), transformFeedback()->bufferMode()); + } // OpenGL 4 program parameters diff --git a/src/vlGraphics/GLSL.hpp b/src/vlGraphics/GLSL.hpp index 919140037..6d709350c 100644 --- a/src/vlGraphics/GLSL.hpp +++ b/src/vlGraphics/GLSL.hpp @@ -36,6 +36,7 @@ #include #include #include +#include namespace vl { @@ -508,6 +509,27 @@ namespace vl int location = glGetUniformLocation(handle(), name); return location; } + + // --------------- transform feedback ----------------------- + + void setTransformFeedback(TransformFeedback* transformFeedback) + { + VL_CHECK( Has_Transform_Feedback ) + if( !Has_Transform_Feedback ) + return; + VL_CHECK(!linked()) + + mTransformFeedback = transformFeedback; + } + + const TransformFeedback* transformFeedback() const + { + VL_CHECK( Has_Transform_Feedback ) + if( !Has_Transform_Feedback ) + return NULL; + + return mTransformFeedback.get(); + } // --------------- uniform variables: getters --------------- @@ -641,6 +663,8 @@ namespace vl EGeometryOutputType mGeometryOutputType; bool mProgramBinaryRetrievableHint; bool mProgramSeparable; + + vl::ref< TransformFeedback > mTransformFeedback; int m_vl_ModelViewMatrix; int m_vl_ProjectionMatrix; diff --git a/src/vlGraphics/LineAccessor.hpp b/src/vlGraphics/LineAccessor.hpp new file mode 100644 index 000000000..6aec2bb83 --- /dev/null +++ b/src/vlGraphics/LineAccessor.hpp @@ -0,0 +1,587 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#ifndef LineAccessor_INCLUDE_ONCE +#define LineAccessor_INCLUDE_ONCE + +#include +#include + +namespace vl +{ +//----------------------------------------------------------------------------- +// TriangleIteratorAbstract +//----------------------------------------------------------------------------- + /** For internal use only. See vl::LineAccessor instead. */ + class LineAccessorAbstract: public Object + { + VL_INSTRUMENT_ABSTRACT_CLASS(vl::LineAccessorAbstract, Object) + + public: + virtual bool next() = 0; + virtual bool hasNext() const = 0; + virtual int a(unsigned int idx) = 0; + virtual int b(unsigned int idx) = 0; + }; +//----------------------------------------------------------------------------- +// LineAccessorIndexed +//----------------------------------------------------------------------------- + /** For internal use only. See vl::LineAccessor instead. */ + template + class LineAccessorIndexed: public LineAccessorAbstract + { + VL_INSTRUMENT_CLASS(vl::LineAccessorIndexed, LineAccessorAbstract) + + public: + + LineAccessorIndexed() + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = 0; + mEnd = 0; + mA = mB = -1; + mEven = true; + mIndex0 = 0; + mArray = NULL; + mPrimRestartIndex = (unsigned int)-1; + mPrimRestartOn = false; + mBaseVertex = 0; + mPrimType = PT_UNKNOWN; + mPrimRestartNumber = 0; + } + + LineAccessorIndexed(const TArray* idx_array, EPrimitiveType prim_type, int base_vert, bool prim_restart_on, unsigned int prim_restart_idx) + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = 0; + mEnd = 0; + mA = mB = -1; + mEven = true; + mIndex0 = 0; + mArray = idx_array; + mPrimRestartIndex = prim_restart_idx; + mPrimRestartOn = prim_restart_on; + mBaseVertex = base_vert; + mPrimType = prim_type; + mPrimRestartNumber = 0; + if(mPrimRestartOn) + { + for(unsigned int i = 0; i < mArray->size(); ++i) + if(mArray->at(i) == mPrimRestartIndex) + mPrimRestartNumber++; + } + } + + bool hasNext() const { return mCurrentIndex != mEnd; } + + virtual int a(unsigned int idx) { get(idx); return mA; } + virtual int b(unsigned int idx) { get(idx); return mB; } + + void get(unsigned int idx) + { + // reached the end + if ( idx > static_cast< unsigned int >(mEnd) ) + return; + + switch(mPrimType) + { + + case PT_LINES: + //mCurrentIndex += 2; + // check for the end + if ( idx * 2 + 2 >= static_cast< unsigned int >(mEnd) ) + break; + else + /*if ( isPrimRestart(mCurrentIndex) ) + { + mCurrentIndex += 1; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + } + else + {*/ + mA = mArray->at(idx * 2 + 0); + mB = mArray->at(idx * 2 + 1); + //} + break; + + case PT_LINE_STRIP: + //mCurrentIndex += 1; + if ( idx * 2 + 1 >= static_cast< unsigned int >(mEnd) ) + mCurrentIndex = mEnd; + else + /*if ( isPrimRestart(mCurrentIndex + 1) ) + { + mCurrentIndex += 2; + mEven = true; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + } + else + {*/ + mEven = !mEven; + ///if (mEven) + ///{ + mA = mArray->at(idx * 2 + 0); + mB = mArray->at(idx * 2 + 1); + /**} + else + { + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 2); + }*/ + // } + break; + + case PT_LINE_LOOP: + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (idx != static_cast< unsigned int >(mEnd)) + { + mA += mBaseVertex; + mB += mBaseVertex; + return; + } + else + { + mA = mB = -1; + return; + } + } + + void initialize(int start=0, int end=-1) + { + VL_CHECK( start >= 0 ) + VL_CHECK( end <= (int)mArray->size() ) + + if (end == -1) + end = (int)mArray->size(); + + mCurrentIndex = end; // end + mA = mB = -1; + mEven = true; + mIndex0 = start; + mEnd = end; + /*if (mArray->size()) + { + switch(mPrimType) + { + case PT_LINES: + case PT_LINE_STRIP: + mCurrentIndex = start; + mA = mArray->at(start+0); + mB = mArray->at(start+1); + break; + default: + break; + } + } + + // if we are not at the end then add base vertices + if ( mCurrentIndex != mEnd ) + { + mA += mBaseVertex; + mB += mBaseVertex; + } + else + { + mA = mB = -1; + }*/ + } + + bool next() + { + // reached the end + if ( mCurrentIndex == mEnd ) + return false; + + switch(mPrimType) + { + + case PT_LINES: + mCurrentIndex += 2; + // check for the end + if ( mCurrentIndex >= mEnd ) + mCurrentIndex = mEnd; + else + if ( isPrimRestart(mCurrentIndex) ) + { + mCurrentIndex += 1; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + } + else + { + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + } + break; + + case PT_LINE_STRIP: + mCurrentIndex += 1; + if ( mCurrentIndex + 1 >= mEnd ) + mCurrentIndex = mEnd; + else + if ( isPrimRestart(mCurrentIndex + 1) ) + { + mCurrentIndex += 2; + mEven = true; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + } + else + { + mEven = !mEven; + ///if (mEven) + ///{ + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + /**} + else + { + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 2); + }*/ + } + break; + + case PT_LINE_LOOP: + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (mCurrentIndex != mEnd) + { + mA += mBaseVertex; + mB += mBaseVertex; + return true; + } + else + { + mA = mB = -1; + return false; + } + } + + void setBaseVertex(int base_vert) { mBaseVertex = base_vert; } + int baseVertex() const { return mBaseVertex; } + + private: + bool isPrimRestart(int i) const { return mPrimRestartOn && mArray->at(i) == mPrimRestartIndex; } + + private: + const TArray* mArray; + EPrimitiveType mPrimType; + int mA, mB; + int mCurrentIndex; + int mIndex0; + int mEnd; + int mBaseVertex; + unsigned int mPrimRestartIndex; + bool mPrimRestartOn; + bool mEven; + unsigned int mPrimRestartNumber; + }; +//----------------------------------------------------------------------------- +// TriangleIteratorDirect +//----------------------------------------------------------------------------- + /** For internal use only. See vl::LineAccessor instead. */ + class LineAccessorDirect: public LineAccessorAbstract + { + VL_INSTRUMENT_CLASS(vl::LineAccessorDirect, LineAccessorAbstract) + + public: + LineAccessorDirect(EPrimitiveType prim_type=PT_UNKNOWN) + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = mStart = mEnd = 0; + mA = mB = -1; + mPrimType = prim_type; + mEven = true; + } + + bool hasNext() const { return mCurrentIndex != mEnd; } + + virtual int a(unsigned int idx) { get(idx); return mA; } + virtual int b(unsigned int idx) { get(idx); return mB; } + + void get(unsigned int idx) + { + // reached the end + if ( idx * 2 >= static_cast< unsigned int >(mEnd) ) + return; + + switch(mPrimType) + { + + case PT_LINES: + //mCurrentIndex += 2; + // check for the end + if ( idx * 2 + 2 >= static_cast< unsigned int >(mEnd) ) + mCurrentIndex = mEnd; + else + { + mA = idx * 2 + 0; + mB = idx * 2 + 1; + } + break; + + case PT_LINE_STRIP: + //mCurrentIndex += 1; + if ( idx + 1 > static_cast< unsigned int >(mEnd) ) + break; + //mCurrentIndex = mEnd; + else + { + mEven = !mEven; + ///if (mEven) + ///{ + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + /**} + else + { + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 2; + }*/ + } + break; + + case PT_LINE_LOOP: + //++mCurrentIndex; + mEven = !mEven; + mA = idx + 0; + mB = idx + 1; + if(mB == mEnd) + mB = mStart; // Back to the begining + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (mCurrentIndex == mEnd) + { + mA = mB = -1; + return; + } + else + return; + } + + void initialize(int start, int end) + { + VL_CHECK(end >= start) + mStart = start; + mCurrentIndex = mEnd = end; + mA = mB = -1; + mEven = true; + } + + bool next() + { + // reached the end + if ( mCurrentIndex == mEnd ) + return false; + + switch(mPrimType) + { + + case PT_LINES: + mCurrentIndex += 2; + // check for the end + if ( mCurrentIndex >= mEnd ) + mCurrentIndex = mEnd; + else + { + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + } + break; + + case PT_LINE_STRIP: + mCurrentIndex += 1; + if ( mCurrentIndex + 1 > mEnd ) + mCurrentIndex = mEnd; + else + { + mEven = !mEven; + ///if (mEven) + ///{ + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + /**} + else + { + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 2; + }*/ + } + break; + + case PT_LINE_LOOP: + ++mCurrentIndex; + mEven = !mEven; + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + if(mB == mEnd) + mB = mStart; // Back to the begining + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (mCurrentIndex == mEnd) + { + mA = mB = -1; + return false; + } + else + return true; + } + + private: + EPrimitiveType mPrimType; + int mA, mB; + int mCurrentIndex; + int mStart; + int mEnd; + bool mEven; + }; +//----------------------------------------------------------------------------- +// TriangleIteratorMulti +//----------------------------------------------------------------------------- + /** For internal use only. See vl::LineAccessor instead. */ + template + class LineAccessorMulti: public LineAccessorIndexed + { + VL_INSTRUMENT_CLASS(vl::LineAccessorMulti, LineAccessorIndexed) + + public: + LineAccessorMulti( const std::vector* p_base_vertices, const std::vector* p_count_vector, const TArray* idx_array, EPrimitiveType prim_type, bool prim_restart_on, int prim_restart_idx) + :LineAccessorIndexed( idx_array, prim_type, 0, prim_restart_on, prim_restart_idx) + { + VL_DEBUG_SET_OBJECT_NAME() + mpBaseVertices = p_base_vertices; + mpCountVector = p_count_vector; + mStart = 0; + mCurPrim = 0; + } + + void initialize() + { + VL_CHECK( mpBaseVertices->size() == mpCountVector->size() ) + if ( (*mpBaseVertices).size() ) + LineAccessorIndexed::setBaseVertex( (*mpBaseVertices)[mCurPrim] ); + int end = mStart + (*mpCountVector)[mCurPrim]; + LineAccessorIndexed::initialize( mStart, end ); + // abort if could not initialize (primitive not supported) + if ( !LineAccessorIndexed::hasNext() ) + mCurPrim = (int)(*mpCountVector).size()-1; + } + + bool next() + { + /*if ( LineAccessorIndexed::next() ) + return true; + else + if ( mCurPrim < (int)(*mpCountVector).size()-1 ) + { + mStart += (*mpCountVector)[mCurPrim]; + mCurPrim++; + initialize(); + return true; + } + else*/ + return false; + } + + bool hasNext() const + { + /*if ( !LineAccessorIndexed::hasNext() && mCurPrim == (int)(*mpCountVector).size()-1 ) + return false; + else*/ + return true; + } + + protected: + const std::vector* mpBaseVertices; + const std::vector* mpCountVector; + int mCurPrim; + int mStart; + }; +//----------------------------------------------------------------------------- +// TriangleIterator +//----------------------------------------------------------------------------- + /** Iterator used to extract the indices of every single triangle of a DrawCall + * regardless of the primitive type. + * \sa DrawCall::triangles() */ + class LineAccessor + { + public: + LineAccessor(LineAccessorAbstract* it): mAccessor(it) { } + + /** Requires the next triangle. Returns \p false the iterator reached the end of the triangle list. */ + bool next() { return mAccessor->next(); } + + bool operator++() { return next(); } + + /** Returns false if the iterator has reached the end of the triangle list. In this case a() and b() return -1. */ + bool hasNext() { return mAccessor->hasNext(); } + + /** First index of the line. */ + int a(unsigned int idx) { return mAccessor->a(idx); } + + /** Second index of the line. */ + int b(unsigned int idx) { return mAccessor->b(idx); } + + protected: + ref mAccessor; + }; +//----------------------------------------------------------------------------- +} + +#endif diff --git a/src/vlGraphics/LineIterator.hpp b/src/vlGraphics/LineIterator.hpp new file mode 100644 index 000000000..f0e492f46 --- /dev/null +++ b/src/vlGraphics/LineIterator.hpp @@ -0,0 +1,447 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#ifndef LineIterator_INCLUDE_ONCE +#define LineIterator_INCLUDE_ONCE + +#include +#include + +namespace vl +{ +//----------------------------------------------------------------------------- +// TriangleIteratorAbstract +//----------------------------------------------------------------------------- + /** For internal use only. See vl::LineIterator instead. */ + class LineIteratorAbstract: public Object + { + VL_INSTRUMENT_ABSTRACT_CLASS(vl::LineIteratorAbstract, Object) + + public: + virtual bool next() = 0; + virtual bool hasNext() const = 0; + virtual int a() const = 0; + virtual int b() const = 0; + }; +//----------------------------------------------------------------------------- +// LineIteratorIndexed +//----------------------------------------------------------------------------- + /** For internal use only. See vl::LineIterator instead. */ + template + class LineIteratorIndexed: public LineIteratorAbstract + { + VL_INSTRUMENT_CLASS(vl::LineIteratorIndexed, LineIteratorAbstract) + + public: + + LineIteratorIndexed() + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = 0; + mEnd = 0; + mA = mB = -1; + mEven = true; + mIndex0 = 0; + mArray = NULL; + mPrimRestartIndex = (unsigned int)-1; + mPrimRestartOn = false; + mBaseVertex = 0; + mPrimType = PT_UNKNOWN; + } + + LineIteratorIndexed(const TArray* idx_array, EPrimitiveType prim_type, int base_vert, bool prim_restart_on, unsigned int prim_restart_idx) + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = 0; + mEnd = 0; + mA = mB = -1; + mEven = true; + mIndex0 = 0; + mArray = idx_array; + mPrimRestartIndex = prim_restart_idx; + mPrimRestartOn = prim_restart_on; + mBaseVertex = base_vert; + mPrimType = prim_type; + } + + bool hasNext() const { return mCurrentIndex != mEnd; } + + virtual int a() const { return mA; } + virtual int b() const { return mB; } + + void initialize(int start=0, int end=-1) + { + VL_CHECK( start >= 0 ) + VL_CHECK( end <= (int)mArray->size() ) + + if (end == -1) + end = (int)mArray->size(); + + mCurrentIndex = end; // end + mA = mB = -1; + mEven = true; + mIndex0 = start; + mEnd = end; + if (mArray->size()) + { + switch(mPrimType) + { + case PT_LINES: + case PT_LINE_STRIP: + mCurrentIndex = start; + mA = mArray->at(start+0); + mB = mArray->at(start+1); + break; + default: + break; + } + } + + // if we are not at the end then add base vertices + if ( mCurrentIndex != mEnd ) + { + mA += mBaseVertex; + mB += mBaseVertex; + } + else + { + mA = mB = -1; + } + } + + bool next() + { + // reached the end + if ( mCurrentIndex == mEnd ) + return false; + + switch(mPrimType) + { + + case PT_LINES: + mCurrentIndex += 2; + // check for the end + if ( mCurrentIndex >= mEnd ) + mCurrentIndex = mEnd; + else + if ( isPrimRestart(mCurrentIndex) ) + { + mCurrentIndex += 1; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + } + else + { + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + } + break; + + case PT_LINE_STRIP: + mCurrentIndex += 1; + if ( mCurrentIndex + 1 >= mEnd ) + mCurrentIndex = mEnd; + else + if ( isPrimRestart(mCurrentIndex + 1) ) + { + mCurrentIndex += 2; + mEven = true; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + } + else + { + mEven = !mEven; + ///if (mEven) + ///{ + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + /**} + else + { + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 2); + }*/ + } + break; + + case PT_LINE_LOOP: + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (mCurrentIndex != mEnd) + { + mA += mBaseVertex; + mB += mBaseVertex; + return true; + } + else + { + mA = mB = -1; + return false; + } + } + + void setBaseVertex(int base_vert) { mBaseVertex = base_vert; } + int baseVertex() const { return mBaseVertex; } + + private: + bool isPrimRestart(int i) const { return mPrimRestartOn && mArray->at(i) == mPrimRestartIndex; } + + private: + const TArray* mArray; + EPrimitiveType mPrimType; + int mA, mB; + int mCurrentIndex; + int mIndex0; + int mEnd; + int mBaseVertex; + unsigned int mPrimRestartIndex; + bool mPrimRestartOn; + bool mEven; + }; +//----------------------------------------------------------------------------- +// TriangleIteratorDirect +//----------------------------------------------------------------------------- + /** For internal use only. See vl::LineIterator instead. */ + class LineIteratorDirect: public LineIteratorAbstract + { + VL_INSTRUMENT_CLASS(vl::LineIteratorDirect, LineIteratorAbstract) + + public: + LineIteratorDirect(EPrimitiveType prim_type=PT_UNKNOWN) + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = mStart = mEnd = 0; + mA = mB = -1; + mPrimType = prim_type; + mEven = true; + } + + bool hasNext() const { return mCurrentIndex != mEnd; } + + virtual int a() const { return mA; } + virtual int b() const { return mB; } + + void initialize(int start, int end) + { + VL_CHECK(end >= start) + mStart = start; + mCurrentIndex = mEnd = end; + mA = mB = -1; + mEven = true; + switch(mPrimType) + { + case PT_LINES: + case PT_LINE_STRIP: + case PT_LINE_LOOP: + // VL_CHECK( (end - start) % 3 == 0 ) /* primitive restart might screw up this */ + mCurrentIndex = start; + mA = start + 0; + mB = start + 1; + break; + default: + break; + } + } + + bool next() + { + // reached the end + if ( mCurrentIndex == mEnd ) + return false; + + switch(mPrimType) + { + + case PT_LINES: + mCurrentIndex += 2; + // check for the end + if ( mCurrentIndex >= mEnd ) + mCurrentIndex = mEnd; + else + { + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + } + break; + + case PT_LINE_STRIP: + mCurrentIndex += 1; + if ( mCurrentIndex + 1 > mEnd ) + mCurrentIndex = mEnd; + else + { + mEven = !mEven; + ///if (mEven) + ///{ + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + /**} + else + { + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 2; + }*/ + } + break; + + case PT_LINE_LOOP: + ++mCurrentIndex; + mEven = !mEven; + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + if(mB == mEnd) + mB = mStart; // Back to the begining + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (mCurrentIndex == mEnd) + { + mA = mB = -1; + return false; + } + else + return true; + } + + private: + EPrimitiveType mPrimType; + int mA, mB; + int mCurrentIndex; + int mStart; + int mEnd; + bool mEven; + }; +//----------------------------------------------------------------------------- +// TriangleIteratorMulti +//----------------------------------------------------------------------------- + /** For internal use only. See vl::LineIterator instead. */ + template + class LineIteratorMulti: public LineIteratorIndexed + { + VL_INSTRUMENT_CLASS(vl::LineIteratorMulti, LineIteratorIndexed) + + public: + LineIteratorMulti( const std::vector* p_base_vertices, const std::vector* p_count_vector, const TArray* idx_array, EPrimitiveType prim_type, bool prim_restart_on, int prim_restart_idx) + :LineIteratorIndexed( idx_array, prim_type, 0, prim_restart_on, prim_restart_idx) + { + VL_DEBUG_SET_OBJECT_NAME() + mpBaseVertices = p_base_vertices; + mpCountVector = p_count_vector; + mStart = 0; + mCurPrim = 0; + } + + void initialize() + { + VL_CHECK( mpBaseVertices->size() == mpCountVector->size() ) + if ( (*mpBaseVertices).size() ) + LineIteratorIndexed::setBaseVertex( (*mpBaseVertices)[mCurPrim] ); + int end = mStart + (*mpCountVector)[mCurPrim]; + LineIteratorIndexed::initialize( mStart, end ); + // abort if could not initialize (primitive not supported) + if ( !LineIteratorIndexed::hasNext() ) + mCurPrim = (int)(*mpCountVector).size()-1; + } + + bool next() + { + if ( LineIteratorIndexed::next() ) + return true; + else + if ( mCurPrim < (int)(*mpCountVector).size()-1 ) + { + mStart += (*mpCountVector)[mCurPrim]; + mCurPrim++; + initialize(); + return true; + } + else + return false; + } + + bool hasNext() const + { + if ( !LineIteratorIndexed::hasNext() && mCurPrim == (int)(*mpCountVector).size()-1 ) + return false; + else + return true; + } + + protected: + const std::vector* mpBaseVertices; + const std::vector* mpCountVector; + int mCurPrim; + int mStart; + }; +//----------------------------------------------------------------------------- +// TriangleIterator +//----------------------------------------------------------------------------- + /** Iterator used to extract the indices of every single triangle of a DrawCall + * regardless of the primitive type. + * \sa DrawCall::triangles() */ + class LineIterator + { + public: + LineIterator(LineIteratorAbstract* it): mIterator(it) { } + + /** Requires the next triangle. Returns \p false the iterator reached the end of the triangle list. */ + bool next() { return mIterator->next(); } + + bool operator++() { return next(); } + + /** Returns false if the iterator has reached the end of the triangle list. In this case a() and b() return -1. */ + bool hasNext() { return mIterator->hasNext(); } + + /** First index of the line. */ + int a() const { return mIterator->a(); } + + /** Second index of the line. */ + int b() const { return mIterator->b(); } + + protected: + ref mIterator; + }; +//----------------------------------------------------------------------------- +} + +#endif diff --git a/src/vlGraphics/MultiDrawElements.hpp b/src/vlGraphics/MultiDrawElements.hpp index a29c84a70..789904276 100644 --- a/src/vlGraphics/MultiDrawElements.hpp +++ b/src/vlGraphics/MultiDrawElements.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -263,6 +264,12 @@ namespace vl TriangleIterator triangleIterator() const; + LineIterator lineIterator() const; + + TriangleAccessor triangleAccessor() const; + + LineAccessor lineAccessor() const; + IndexIterator indexIterator() const { ref< IndexIteratorElements > iie = new IndexIteratorElements; @@ -368,6 +375,36 @@ namespace vl it->initialize(); return TriangleIterator(it.get()); } +//----------------------------------------------------------------------------- + template + LineIterator MultiDrawElements::lineIterator() const + { + ref< LineIteratorMulti > it = + new LineIteratorMulti( &mBaseVertices, &mCountVector, mIndexBuffer.get(), primitiveType(), + primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return LineIterator(it.get()); + } +//----------------------------------------------------------------------------- + template + TriangleAccessor MultiDrawElements::triangleAccessor() const + { + ref< TriangleAccessorMulti > it = + new TriangleAccessorMulti( &mBaseVertices, &mCountVector, mIndexBuffer.get(), primitiveType(), + primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return TriangleAccessor(it.get()); + } +//----------------------------------------------------------------------------- + template + LineAccessor MultiDrawElements::lineAccessor() const + { + ref< LineAccessorMulti > it = + new LineAccessorMulti( &mBaseVertices, &mCountVector, mIndexBuffer.get(), primitiveType(), + primitiveRestartEnabled(), primitive_restart_index ); + it->initialize(); + return LineAccessor(it.get()); + } //----------------------------------------------------------------------------- } diff --git a/src/vlGraphics/OpenGL.cpp b/src/vlGraphics/OpenGL.cpp index 63babf528..cd82d9e66 100644 --- a/src/vlGraphics/OpenGL.cpp +++ b/src/vlGraphics/OpenGL.cpp @@ -151,6 +151,9 @@ namespace vl // Point sprites GL_POINT_SPRITE, GL_PROGRAM_POINT_SIZE, + + // Rasterizer + GL_RASTERIZER_DISCARD, // Fixed function pipeline GL_ALPHA_TEST, @@ -208,6 +211,9 @@ namespace vl // Point sprites "GL_POINT_SPRITE", "GL_PROGRAM_POINT_SIZE", + + // Rasterizer + "GL_RASTERIZER_DISCARD", // Fixed function pipeline "GL_ALPHA_TEST", @@ -266,6 +272,9 @@ namespace vl false /*GL_POINT_SPRITE*/, false /*GL_PROGRAM_POINT_SIZE*/, + // Rasterizer + false /*GL_RASTERIZER_DISCARD*/, + // Fixed function pipeline false /*GL_ALPHA_TEST*/, false /*GL_LIGHTING*/, @@ -505,6 +514,9 @@ bool vl::initializeOpenGL() Is_Enable_Supported[EN_POINT_SPRITE] = (Has_GL_NV_point_sprite||Has_GL_ARB_point_sprite||Has_GL_Version_2_0||Has_GL_OES_point_sprite||Has_GLES_Version_1_1) && Has_Fixed_Function_Pipeline; Is_Enable_Supported[EN_PROGRAM_POINT_SIZE] = Has_GLSL && !Has_GLES_Version_2_0; // Only OpenGL ES 2 does not support glPointSize()/GL_POINT_SIZE + // Rasterizer + Is_Enable_Supported[EN_RASTERIZER_DISCARD] = Has_GLSL && Has_GL_Version_3_0; + // Fixed function pipeline Is_Enable_Supported[EN_ALPHA_TEST] = Has_GL_Version_1_1||Has_GLES_Version_1_1; Is_Enable_Supported[EN_LIGHTING] = Has_GL_Version_1_1||Has_GLES_Version_1_1; diff --git a/src/vlGraphics/OpenGLContext.cpp b/src/vlGraphics/OpenGLContext.cpp index f6fc05b52..678c3696f 100644 --- a/src/vlGraphics/OpenGLContext.cpp +++ b/src/vlGraphics/OpenGLContext.cpp @@ -624,6 +624,7 @@ void OpenGLContext::setupDefaultRenderStates() mDefaultRenderStates[RS_StencilMask] = RenderStateSlot(new StencilMask, 0); mDefaultRenderStates[RS_StencilOp] = RenderStateSlot(new StencilOp, 0); mDefaultRenderStates[RS_GLSLProgram] = RenderStateSlot(new GLSLProgram, 0); + mDefaultRenderStates[RS_TransformFeedback] = RenderStateSlot(new TransformFeedback, 0); for(int i=0; i #include +#include using namespace vl; @@ -74,21 +75,55 @@ void RayIntersector::intersectGeometry(Actor* act, Geometry* geom) { DrawCall* prim = geom->drawCalls().at(i); int itri = 0; - for(TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next(), ++itri) + if(prim->primitiveType() == vl::PT_LINES || + prim->primitiveType() == vl::PT_LINE_STRIP || + prim->primitiveType() == vl::PT_LINE_LOOP) { - int ia = trit.a(); - int ib = trit.b(); - int ic = trit.c(); - vec3 a = posarr->getAsVec3(ia); - vec3 b = posarr->getAsVec3(ib); - vec3 c = posarr->getAsVec3(ic); - if (act->transform()) + for(LineIterator liit = prim->lineIterator(); liit.hasNext(); liit.next(), ++itri) { - a = matrix * a; - b = matrix * b; - c = matrix * c; + int ia = liit.a(); + int ib = liit.b(); + vec3 a = posarr->getAsVec3(ia); + vec3 b = posarr->getAsVec3(ib); + if(act->transform()) + { + a = matrix * a; + b = matrix * b; + } + // Compute distance to the line. Compute all and keep the minimum( attribute for an epsilon?) + intersectLine(a, b, ia, ib, act, geom, prim, itri); + } + } + else if(prim->primitiveType() == vl::PT_POINTS) + { + for(unsigned int i = 0; i < posarr->size(); i++, ++itri) + { + vec3 a = posarr->getAsVec3(i); + if(act->transform()) + { + a = matrix * a; + } + intersectPoint(a, i, act, geom, prim, itri); + } + } + else + { + for(TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next(), ++itri) + { + int ia = trit.a(); + int ib = trit.b(); + int ic = trit.c(); + vec3 a = posarr->getAsVec3(ia); + vec3 b = posarr->getAsVec3(ib); + vec3 c = posarr->getAsVec3(ic); + if (act->transform()) + { + a = matrix * a; + b = matrix * b; + c = matrix * c; + } + intersectTriangle(a, b, c, ia, ib, ic, act, geom, prim, itri); } - intersectTriangle(a, b, c, ia, ib, ic, act, geom, prim, itri); } } } @@ -115,10 +150,57 @@ void RayIntersector::intersectTriangle(const T& a, const T& b, const T& c, int i if (dot(fp-pts[i],bi_norm) < 0) return; } + + // compute the nearest point + T aRp = rp - a; + T bRp = rp - b; + T cRp = rp - c; + + T v3 = b - c; + float d1 = cross(aRp, v1).length() / v1.length(); + float d2 = cross(aRp, v2).length() / v2.length(); + float d3 = cross(cRp, v3).length() / v3.length(); + + int ila, ilb; + int l_idx; + if(d1 < d2) + { + if(d1 < d3) + { + ila = ia; + ilb = ib; + l_idx = 1; + } + else + { + ila = ic; + ilb = ib; + l_idx = 2; + } + } + else + { + if(d2 < d3) + { + ila = ia; + ilb = ic; + l_idx = 3; + } + else + { + ila = ic; + ilb = ib; + l_idx = 2; + } + } + ref record = new vl::RayIntersectionGeometry; record->setIntersectionPoint( rp ); record->setTriangleIndex(tri_idx); record->setTriangle(ia, ib, ic); + record->setLineIndex(l_idx); + record->setLine(ila, ilb); + record->setNearestPoint(aRp.lengthSquared() < bRp.lengthSquared() ? (aRp.lengthSquared() < cRp.lengthSquared() ? ia : ic) : (bRp.lengthSquared() < cRp.lengthSquared() ? ib : ic)); record->setActor(act); record->setGeometry(geom); record->setPrimitives(prim); @@ -126,3 +208,128 @@ void RayIntersector::intersectTriangle(const T& a, const T& b, const T& c, int i mIntersections.push_back(record); } //----------------------------------------------------------------------------- +template +void RayIntersector::intersectLine(const T& a, const T& b, int ia, int ib, Actor* act, Geometry* geom, DrawCall* prim, int tri_idx) +{ + T u = b - a; + T w = a - ray().origin(); + T v = ray().direction(); + + // In 3D + // // We got the parametric representation of both line + // Line AB + // x = a.x() + u.x() * t + // y = a.y() + u.y() * t + // z = a.z() + u.z() * t + // Ray direction + // x' = ray().origin().x() + ray().direction().x() * s + // y' = ray().origin().y() + ray().direction().y() * s + // z' = ray().origin().z() + ray().direction().z() * s + // So we have to solve + // x = x' + // y = y' + // z = z' + // We change to express all above with s ant then we do + // 2s - s - s = 0 + // So we can find t + float denominator = 2 * ray().direction().y() * ray().direction().z() * u.x() - ray().direction().x() * ray().direction().z() * u.y() - ray().direction().x() * ray().direction().y() * u.z(); + if(denominator == 0) + return; + float t = (ray().direction().x() * ray().direction().z() * w.y() + ray().direction().x() * ray().direction().y() * w.z() - 2 * ray().direction().y() * ray().direction().z() * w.x()) / denominator; + /* + In 2D + float denominator = ray().direction().y() * (b.x() - a.x()) - ray().direction().x() * (b.y() - a.y()); + if(denominator == 0) + return; + float t = (ray().direction().x() * (a.y() - ray().origin().y()) - ray().direction().y() * (a.x() - ray().origin().x())) / denominator;*/ + if(t < 0 || t > 1) + return; + + + //-------------------------------------------------------------------------- + + + + + + + float a1 = dot(u,u); // always >= 0 + float b1 = dot(u,v); + float c = dot(v,v); // always >= 0 + float d = dot(u,w); + float e = dot(v,w); + float D = a1*c - b1*b1; // always >= 0 + float sc, tc; + + // compute the line parameters of the two closest points + if (D < 00000001) { // the lines are almost parallel + sc = 0.0; + tc = (b1>c ? d/b1 : e/c); // use the largest denominator + } + else { + sc = (b1*e - c*d) / D; + tc = (a1*e - b1*d) / D; + } + + // get the difference of the two closest points + T dP = w + (sc * u) - (tc * v); // = L1(sc) - L2(tc) + + float dist = dP.length(); // return the closest distance + + if(dist > mDistance) + return; + + + ref record = new vl::RayIntersectionGeometry; + //record->setIntersectionPoint( -1 ); + record->setTriangleIndex(-1); + record->setTriangle(-1, -1, -1); + record->setLineIndex(tri_idx); + record->setLine(ia, ib); + record->setNearestPoint(-1); // pour que ca ne crash pas dans ViewerActorTree au moment du decoupage de l'actor + //record->setNearestPoint(aRp.lengthSquared() < bRp.lengthSquared() ? (aRp.lengthSquared() < cRp.lengthSquared() ? ia : ic) : (bRp.lengthSquared() < cRp.lengthSquared() ? ib : ic)); + record->setActor(act); + record->setGeometry(geom); + record->setPrimitives(prim); + record->setDistance( dist ); + mIntersections.push_back(record); + +} +//----------------------------------------------------------------------------- +template +void RayIntersector::intersectPoint(const T& a, int ia, Actor* act, Geometry* geom, DrawCall* prim, int prim_idx) +{ + // Find the equation of the plan thanks to the normal and one point + float nd = ray().direction().x() * a.x() + ray().direction().y() * a.y() + ray().direction().z() * a.z(); + + // Find the intersection between the ray and the plan + float k = (-nd + ray().direction().x() * ray().origin().x() + ray().direction().y() * ray().origin().y() + ray().direction().z() * ray().origin().z()) / + (-ray().direction().x() * ray().direction().x() - ray().direction().y() * ray().direction().y() - ray().direction().z() * ray().direction().z()); + + //vl::defLogger()->error(vl::String("k = ") + vl::String::fromDouble(k)); + + // Compute the distance between the intersection and our point (a) + T intersectionPoint(ray().origin().x() + k * ray().direction().x(), + ray().origin().y() + k * ray().direction().y(), + ray().origin().z() + k * ray().direction().z()); + + float distance = length(a - intersectionPoint); + + //vl::defLogger()->error(vl::String("distance = ") + vl::String::fromDouble(distance)); + if(distance > 0.1f) // To convert into pixel + return; + + ref record = new vl::RayIntersectionGeometry; + record->setIntersectionPoint(a); + record->setTriangleIndex(-1); + record->setTriangle(-1, -1, -1); + record->setLineIndex(-1); + record->setLine(-1, -1); + record->setNearestPoint(prim_idx); + record->setActor(act); + record->setGeometry(geom); + record->setPrimitives(prim); + mIntersections.push_back(record); + +} +//----------------------------------------------------------------------------- diff --git a/src/vlGraphics/RayIntersector.hpp b/src/vlGraphics/RayIntersector.hpp index bc3071155..09a207aab 100644 --- a/src/vlGraphics/RayIntersector.hpp +++ b/src/vlGraphics/RayIntersector.hpp @@ -105,8 +105,14 @@ namespace vl const DrawCall* drawCalls() const { return mDrawCalls; } //! The starting index of the intersected primitive inside drawCalls() int triangleIndex() const { return mTriangleIndex; } + //! The starting index of the intersected line inside TriangleIndex() + int lineIndex() const { return mLineIndex; } //! An int[3] representing the indices of the intersected triangle. const int* triangle() const { return mTriangle; } + //! An int[2] representing the indices of the intersected line. + const int* line() { return mLine; } + //! An int representing the indice of the nearest point to the intersection + int nearestPoint() { return mNearestPoint; } //! The intersected Geometry void setGeometry(Geometry* g) { mGeometry = g; } @@ -116,6 +122,12 @@ namespace vl void setTriangleIndex(int t_idx) { mTriangleIndex = t_idx; } //! An int[3] representing the indices of the intersected triangle. void setTriangle(int a, int b, int c) { mTriangle[0] = a; mTriangle[1] = b; mTriangle[2] = c; } + //! The starting index of the intersected line inside TriangleIndex() + void setLineIndex(int l_idx) { mLineIndex = l_idx; } + //! An int[2] representing the indices of the intersected line. + void setLine(int a, int b) { mLine[0] = a; mLine[1] = b; } + //! An int representing the indice of the nearest point to the intersection + void setNearestPoint(int a) { mNearestPoint = a; } protected: vec3 mIntersectionPoint; @@ -123,6 +135,9 @@ namespace vl DrawCall* mDrawCalls; int mTriangleIndex; int mTriangle[3]; + int mLine[2]; + int mNearestPoint; + int mLineIndex; float mDistance; }; //----------------------------------------------------------------------------- @@ -135,7 +150,7 @@ namespace vl VL_INSTRUMENT_CLASS(vl::RayIntersector, Object) public: - RayIntersector() + RayIntersector() : mDistance(0.1) { VL_DEBUG_SET_OBJECT_NAME() mActors = new ActorCollection; @@ -155,6 +170,11 @@ namespace vl const Frustum& frustum() const { return mFrustum; } //! The frustum in world coordinates used to cull the objects. void setFrustum(const Frustum& frustum) { mFrustum = frustum; } + + //! The maximal distance for a line or a point intersection + real distance() const { return mDistance; } + //! The maximal distance for a line or a point intersection + void setDistance(real distance) { mDistance = distance; } //! The intersection points detected by the last intersect() call sorted according to their distance (the first one is the closest). const std::vector< ref >& intersections() const { return mIntersections; } @@ -186,11 +206,19 @@ namespace vl template void intersectTriangle(const T& a, const T& b, const T& c, int ia, int ib, int ic, Actor*, Geometry* geom, DrawCall* prim, int prim_idx); + // From http://geomalgorithms.com/a07-_distance.html + template + void intersectLine(const T& a, const T& b, int ia, int ib, Actor*, Geometry* geom, DrawCall* prim, int prim_idx); + + template + void intersectPoint(const T& a, int ia, Actor*, Geometry* geom, DrawCall* prim, int prim_idx); + protected: Frustum mFrustum; std::vector< ref > mIntersections; ref mActors; Ray mRay; + real mDistance; }; } diff --git a/src/vlGraphics/Renderer.cpp b/src/vlGraphics/Renderer.cpp index 03f31d9d5..9a9cd7f65 100644 --- a/src/vlGraphics/Renderer.cpp +++ b/src/vlGraphics/Renderer.cpp @@ -383,6 +383,13 @@ const RenderQueue* Renderer::render(const RenderQueue* render_queue, Camera* cam } VL_CHECK_OGL() + + if( shader->glslProgram() && shader->glslProgram()->handle() && shader->glslProgram()->transformFeedback() ) + { + shader->glslProgram()->transformFeedback()->beginTransformFeedback(); + } + + VL_CHECK_OGL() // --------------- Actor rendering --------------- @@ -390,6 +397,13 @@ const RenderQueue* Renderer::render(const RenderQueue* render_queue, Camera* cam tok->mRenderable->render( actor, shader, camera, opengl_context ); VL_CHECK_OGL() + + if( shader->glslProgram() && shader->glslProgram()->handle() && shader->glslProgram()->transformFeedback() ) + { + shader->glslProgram()->transformFeedback()->endTransformFeedback(); + } + + VL_CHECK_OGL() // if shader is overridden it does not make sense to perform multipassing so we break the loop here. if (shader != tok->mShader) diff --git a/src/vlGraphics/Shader.cpp b/src/vlGraphics/Shader.cpp index 37b008a19..2f356ae03 100644 --- a/src/vlGraphics/Shader.cpp +++ b/src/vlGraphics/Shader.cpp @@ -108,6 +108,8 @@ Normal* Shader::gocNormal() { GET_OR_CREATE(Normal) } //------------------------------------------------------------------------------ ColorMask* Shader::gocColorMask() { GET_OR_CREATE(ColorMask) } //------------------------------------------------------------------------------ +TransformFeedback* Shader::gocTransformFeedback() { GET_OR_CREATE(TransformFeedback) } +//------------------------------------------------------------------------------ PolygonMode* Shader::gocPolygonMode() { GET_OR_CREATE(PolygonMode) } //------------------------------------------------------------------------------ ShadeModel* Shader::gocShadeModel() { GET_OR_CREATE(ShadeModel) } diff --git a/src/vlGraphics/Shader.hpp b/src/vlGraphics/Shader.hpp index e17f09c9d..21f1fa5f1 100644 --- a/src/vlGraphics/Shader.hpp +++ b/src/vlGraphics/Shader.hpp @@ -43,6 +43,7 @@ #include #include #include +#include #include namespace vl @@ -2102,6 +2103,10 @@ namespace vl SampleCoverage* gocSampleCoverage(); const SampleCoverage* getSampleCoverage() const { if (!getRenderStateSet()) return NULL; else return static_cast( getRenderStateSet()->renderState( RS_SampleCoverage ) ); } SampleCoverage* getSampleCoverage() { if (!getRenderStateSet()) return NULL; else return static_cast( getRenderStateSet()->renderState( RS_SampleCoverage ) ); } + + TransformFeedback* gocTransformFeedback(); + const TransformFeedback* getTransformFeedback() const { if(!getRenderStateSet()) return NULL; else return static_cast( getRenderStateSet()->renderState( RS_TransformFeedback ) ); } + TransformFeedback* getTransformFeedback() { if(!getRenderStateSet()) return NULL; else return static_cast( getRenderStateSet()->renderState( RS_TransformFeedback ) ); } // indexed render states diff --git a/src/vlGraphics/TransformFeedback.cpp b/src/vlGraphics/TransformFeedback.cpp new file mode 100644 index 000000000..d18b15bd7 --- /dev/null +++ b/src/vlGraphics/TransformFeedback.cpp @@ -0,0 +1,102 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2011, Michele Bosi, Fabien Mathieu */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#include +#include + +using namespace vl; + +void TransformFeedback::createTransformFeedbacks() +{ + glGenTransformFeedbacks(1, &mHandle); +} + +void TransformFeedback::bindTransformFeedback() const +{ + VL_CHECK_OGL(); + + if ( !Has_Transform_Feedback ) + { + Log::error( "TransformFeedback::bindTransformFeedback(): transform feedback not supported.\n" ); + return; + } + if(handle() != 0) + { + glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TransformFeedback::handle()); VL_CHECK_OGL(); + } +} + +void TransformFeedback::beginTransformFeedback( ) const +{ + + if(mHandleQuery != 0) + glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mHandleQuery); + + glBeginTransformFeedback(mType); VL_CHECK_OGL(); +} + +void TransformFeedback::endTransformFeedback() const +{ + glEndTransformFeedback(); + + if(mHandleQuery != 0) + glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + + VL_CHECK_OGL(); +} + +void TransformFeedback::pauseTransformFeedback() const +{ + glPauseTransformFeedback(); VL_CHECK_OGL(); +} + +void TransformFeedback::resumeTransformFeedback() const +{ + glResumeTransformFeedback(); VL_CHECK_OGL(); +} + +void TransformFeedback::setTransformFeedbackVaryings(std::list< String >& varyings) +{ + mVaryingsCount = varyings.size(); + mVaryings = new char*[varyings.size()]; + std::list< String >::iterator it; + int i = 0; + for(it = varyings.begin(); it != varyings.end(); ++it) + { + mVaryings[i] = new char[it->length()]; + std::memcpy(mVaryings[i++], it->toStdString().c_str(), it->length() + 1); + } +} + +char** TransformFeedback::transformFeedbackVaryings() const +{ + return mVaryings; +} diff --git a/src/vlGraphics/TransformFeedback.hpp b/src/vlGraphics/TransformFeedback.hpp new file mode 100644 index 000000000..fc74ccf22 --- /dev/null +++ b/src/vlGraphics/TransformFeedback.hpp @@ -0,0 +1,195 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2011, Michele Bosi, Fabien Mathieu */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#ifndef TransformFeedback_INCLUDE_ONCE +#define TransformFeedback_INCLUDE_ONCE + +#include +#include +#include +#include +#include +#include + +namespace vl +{ + class OpenGLContext; + class Camera; + //------------------------------------------------------------------------------ + // TransformFeedback + //------------------------------------------------------------------------------ + /** + * Class that represents a Transform Feedback associated to a shader + */ + class VLGRAPHICS_EXPORT TransformFeedback: public RenderStateNonIndexed + { + VL_INSTRUMENT_ABSTRACT_CLASS(vl::TransformFeedback, RenderStateNonIndexed); + + public: + /** Constructor */ + TransformFeedback(EPrimitiveType type = PT_TRIANGLES) : mHandle(0), mHandleQuery(0), mType(type), mBufferMode(BM_SeparateAttribs), mReallocateTransformFeedback( true ) + { + VL_DEBUG_SET_OBJECT_NAME() + } + + /** Destructor */ + ~TransformFeedback() + { + if(mHandleQuery != 0) // We have created a query + { + glDeleteQueries(1, &mHandleQuery); + } + } + + /** + * Creates a renderbuffer object calling glGenTransformFeedbacks(). + * The identifier returned by glGenTransformFeedbacks() can be queried calling the handle() method. + */ + void createTransformFeedbacks(); + + /** + * Sets the handle for this transform feedback, the handle must have been created by glGenTransformFeedbacks(). + * Normally you don't need to call this. See also: createTransformFeedbacks(), handle(). + */ + void setHandle( GLuint handle ) { if ( mHandle != handle ) { mHandle = handle; mReallocateTransformFeedback = false; } } + + /** Returns the handle obtained by createTransformFeedbacks() using glGenTransformFeedbacks() */ + GLuint handle() const { return mHandle; } + + /** + * Makes the transform feedback bound calling glBindTransformFeedback( GL_TRANSFORM_FEEDBACK, TransformFeedback::handle() ) + * \sa http://www.opengl.org/sdk/docs/man4/xhtml/glBindTransformFeedback.xml + */ + void bindTransformFeedback() const; + + void beginTransformFeedback( ) const; + + void endTransformFeedback() const; + + void pauseTransformFeedback() const; + + void resumeTransformFeedback() const; + + void setTransformFeedbackVaryings(std::list< String >& varyings); + + unsigned int transformFeedbackVaryingsCount() const { return mVaryingsCount; } + + void setTransformFeedbackBufferMode(EBufferMode bufferMode) { mBufferMode = bufferMode; } + + EBufferMode bufferMode() const { return mBufferMode; } + + char** transformFeedbackVaryings() const; + + virtual ERenderState type() const { return RS_TransformFeedback; } + + virtual void apply(int, const Camera*, OpenGLContext*) const + { + if(mVBOsOut.empty()) + { + VL_glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); + } + else + { + for(int i = 0; i < mVBOsOut.size(); ++i) + { + if(mVBOsOut[i]->bufferObject()->handle()) + { + VL_glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mVBOsOut[i]->bufferObject()->handle()); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mVBOsOut[i]->bufferObject()->handle()); + } + } + } + } + + /*template + void addArray(Array< T_VectorType, T_Scalar, T_GL_Size, T_GL_Type >* array, int size) */ + void addArray(ArrayAbstract* array) + { + array->bufferObject()->createBufferObject(); // Necessary to create buffer to send to transform feedback + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, array->bufferObject()->handle()); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, array->bytesUsed(), NULL, GL_DYNAMIC_COPY); // Have to put size of the data + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); + mVBOsOut.push_back(array); + } + + /*template + void updateArray(Array< T_VectorType, T_Scalar, T_GL_Size, T_GL_Type >* array, int size) */ + void updateArray(ArrayAbstract* array) + { + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, array->bufferObject()->handle()); + glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, array->bytesUsed(), array->ptr()); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0); + } + + void updateArrays() + { + for(int i = 0; i < mVBOsOut.size(); ++i) + { + updateArray(mVBOsOut[i].get()); + } + } + + void queryWrittenPrimitive() + { + glGenQueries(1, &mHandleQuery); + } + + unsigned int getWrittenPrimitives() + { + unsigned int writtenPrimitives; + glGetQueryObjectuiv(mHandleQuery, GL_QUERY_RESULT, &writtenPrimitives); + return writtenPrimitives; + } + + void set(EPrimitiveType type) { mType = type; } + + virtual ref clone() const + { + ref rs = new TransformFeedback(mType); + *rs = *this; + return rs; + } + + private: + GLuint mHandle; + GLuint mHandleQuery; + EPrimitiveType mType; + EBufferMode mBufferMode; + bool mReallocateTransformFeedback; + char** mVaryings; + unsigned int mVaryingsCount; + Collection< ArrayAbstract > mVBOsOut; + }; + +} + +#endif \ No newline at end of file diff --git a/src/vlGraphics/TransformManipulator.cpp b/src/vlGraphics/TransformManipulator.cpp new file mode 100644 index 000000000..0cdf10b11 --- /dev/null +++ b/src/vlGraphics/TransformManipulator.cpp @@ -0,0 +1,427 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2011, Michele Bosi, Fabien Mathieu */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#include +#include +#include +#include +#include + +const float dRef = 50.0f; +const float angleRef = M_PI / 8.0f; +const float oppositeRef = std::tan(angleRef / 2.0f) * 2.0 * dRef; + +using namespace vl; + +//------------------------------------------------------------------------------ +// TransformManipulator +//------------------------------------------------------------------------------ + +void TransformManipulator::setEditGeometry(Geometry* editGeometry, vl::Uniform* modelMatrixUniform) +{ + mEditGeometry = editGeometry; + + mModelMatrixUniform = modelMatrixUniform; +} + +void TransformManipulator::mouseDownEvent(vl::EMouseButton button, int x, int y) +{ + if(mManipulatorActor.get() == NULL) + return; + + vl::mat4 viewMatrix, projectionMatrix, manipulatorPositionMatrix; + mViewMatrixUniform->getUniform(&viewMatrix); + mProjectionMatrixUniform->getUniform(&projectionMatrix); + + ref< GLSLProgram > manipulatorProgram = mManipulatorActor->effect()->shader()->gocGLSLProgram(); + + if(manipulatorProgram.get() == NULL) + return; + manipulatorProgram->gocUniform("ManipulatorPositionMatrix")->getUniform(&manipulatorPositionMatrix); + + + int reversedY = openglContext()->height() - y; + RayIntersector intersector; + + intersector.actors()->push_back(mManipulatorActor.get()); + + /*for(int i = 0; i < 16; ++i) + { + if(i % 4 == 0) + std::cout << std::endl; + std::cout << viewMatrix.ptr()[i] << "\t"; + } + + for(int i = 0; i < 16; ++i) + { + if(i % 4 == 0) + std::cout << std::endl; + std::cout << projectionMatrix.ptr()[i] << "\t"; + }*/ + + + Ray ray = createRay(x, reversedY, viewMatrix * manipulatorPositionMatrix, projectionMatrix); + /*ray.setOrigin(vl::vec3(x, reversedY, 0.0f)); + ray.setDirection(vl::vec3(0.0f,0.0, -1.0f));*/ + intersector.setRay(ray); + intersector.intersect(); + + std::cout << std::endl; + + std::cout << "ray.origin : (" << ray.origin().x() << ";" << ray.origin().y() << ";" << ray.origin().z() << ")" << std::endl; + std::cout << "ray.direction : (" << ray.direction().x() << ";" << ray.direction().y() << ";" << ray.direction().z() << ")" << std::endl; + + std::cout << "down x: " << x << ";y: " << y << std::endl; + + if(intersector.intersections().size() != 0) // We have an intersection + { + std::cout << "Manipulator Intersection" << std::endl; + mActive = true; + mStartPosition.x() = x; + mStartPosition.y() = y; + + + mEventListener->setEnabled(false); + + mFirstIntersection = intersector.intersections().at(0)->intersectionPoint(); + + } +} + +void TransformManipulator::mouseUpEvent(vl::EMouseButton button, int x, int y) +{ + if(mActive) + { + //vl::defLogger()->debug("mouse up event\n"); + std::cout << "up x: " << x << ";y: " << y << std::endl; + mActive = false; + + mEventListener->setEnabled(true); + openglContext()->setContinuousUpdate(true); + + + if(mEditGeometry.get() != NULL) + { + vl::ref< vl::ArrayAbstract > vertexPositions = mEditGeometry->vertexArray() != NULL ? mEditGeometry->vertexArray() : mEditGeometry->vertexAttribArray(vl::VA_Position)->data(); + vertexPositions->transform(mModelMatrix); + mEditGeometry->updateDirtyBufferObject(vl::BUM_KeepRamBufferAndForceUpdate); + } + + ref< GLSLProgram > manipulatorProgram = mManipulatorActor->effect()->shader()->gocGLSLProgram(); + + if(manipulatorProgram.get() == NULL) + return; + + mEditGeometry->computeBounds(); + vl::AABB boundingBox = mEditGeometry->boundingBox(); + vl::vec3 center = boundingBox.center(); + + manipulatorProgram->gocUniform("ManipulatorPositionMatrix")->setUniform(vl::mat4::getTranslation(center)); + + mOldModelMatrix = mModelMatrix; + mModelMatrix = vl::mat4::getIdentity(); + mModelMatrixUniform->setUniform(mModelMatrix); + } +} + + +vl::Ray TransformManipulator::createRay(int x, int y, const vl::mat4& viewMatrix, const vl::mat4& projectionMatrix) +{ + vl::vec4 out; + vl::Ray ray; + if (!unprojectFromUniform( vl::vec3((vl::real)x,(vl::real)y,0), out, viewMatrix, projectionMatrix )) + ray = vl::Ray(); + else + { + ray.setOrigin(out.xyz()); + ray.setDirection( (out.xyz() - viewMatrix.getInverse().getT()).normalize() ); + } + + return ray; +} + +bool TransformManipulator::unprojectFromUniform(const vl::vec3& in, vl::vec4& out, const vl::mat4& viewMatrix, const vl::mat4& projectionMatrix) +{ + + vl::vec4 v; + v.x() = in.x(); + v.y() = in.y(); + v.z() = in.z(); + v.w() = 1.0; + + // map from viewport to 0-1 + v.x() = (v.x() - mCamera->viewport()->x()) / mCamera->viewport()->width(); + v.y() = (v.y() - mCamera->viewport()->y()) / mCamera->viewport()->height(); + + // map to range -1 to 1 + v.x() = v.x() * 2.0f - 1.0f; + v.y() = v.y() * 2.0f - 1.0f; + v.z() = v.z() * 2.0f - 1.0f; + + vl::real det=0; + vl::mat4 inverse = (projectionMatrix * viewMatrix).getInverse(&det); + if (!det) + return false; + + v = inverse * v; + if (v.w() == 0.0) + return false; + + out = v / v.w(); + return true; + +} + +//------------------------------------------------------------------------------ +// TranslationManipulator +//------------------------------------------------------------------------------ + +void TranslationManipulator::mouseMoveEvent(int x, int y) +{ + if(mActive) + { + vl::mat4 viewMatrix, projectionMatrix, manipulatorPositionMatrix; + mViewMatrixUniform->getUniform(&viewMatrix); + mProjectionMatrixUniform->getUniform(&projectionMatrix); + + ref< GLSLProgram > manipulatorProgram = mManipulatorActor->effect()->shader()->gocGLSLProgram(); + + if(manipulatorProgram.get() == NULL) + return; + manipulatorProgram->gocUniform("ManipulatorPositionMatrix")->getUniform(&manipulatorPositionMatrix); + + vl::Ray ray = createRay(x, openglContext()->height() - y, viewMatrix * manipulatorPositionMatrix, projectionMatrix); + + vec4 plane; + + if((mConstraint & CONSTRAINT_X) != 0) + { + if((mConstraint & CONSTRAINT_Z) != 0) + { + // Plan XZ + plane = vec4(0.0f, 1.0f, 0.0f, mFirstIntersection.y()); + } + else + { + // Plan XY ou Axe X seul + plane = vec4(0.0f, 0.0f, 1.0f, mFirstIntersection.z()); + } + } + else if((mConstraint & CONSTRAINT_Y) != 0) + { + if((mConstraint & CONSTRAINT_Z) != 0) + { + // Plan YZ + plane = vec4(1.0f, 0.0f, 0.0f, mFirstIntersection.x()); + } + else + { + // Axe Y seul car géré par le premier if, on se place sur le plan XY + plane = vec4(0.0f, 0.0f, 1.0f, mFirstIntersection.z()); + + } + } + else if((mConstraint & CONSTRAINT_Z) != 0) + { + // Plan YZ + plane = vec4(1.0f, 0.0f, 0.0f, mFirstIntersection.x()); + } + + + float numerator = -((plane.x() * ray.origin().x()) + (plane.y() * ray.origin().y()) + (plane.z() * ray.origin().z()) - plane.w()); + float denominator = ray.direction().x() * plane.x() + ray.direction().y() * plane.y() + ray.direction().z() * plane.z(); + + float t0 = numerator / denominator; + + vec3 secondIntersection = ray.origin() + t0 * ray.direction(); + + vec3 translation = secondIntersection - mFirstIntersection; + translation.x() = (mConstraint & CONSTRAINT_X) == 0 ? 0.0f : translation.x(); + translation.y() = (mConstraint & CONSTRAINT_Y) == 0 ? 0.0f : translation.y(); + translation.z() = (mConstraint & CONSTRAINT_Z) == 0 ? 0.0f : translation.z(); + + mModelMatrix = mat4::getTranslation(translation); + mModelMatrixUniform->setUniform(mModelMatrix); + + openglContext()->update(); + } +} + +//------------------------------------------------------------------------------ +// RotationManipulator +//------------------------------------------------------------------------------ + +void RotationManipulator::mouseMoveEvent(int x, int y) +{ + if(mActive) + { + float yf = openglContext()->height() - y; + float yf0 = openglContext()->height() - mStartPosition.y(); + + float xf = x; + float xf0 = mStartPosition.x(); + + vl::mat4 viewMatrix, projectionMatrix, manipulatorPositionMatrix; + mViewMatrixUniform->getUniform(&viewMatrix); + mProjectionMatrixUniform->getUniform(&projectionMatrix); + + ref< GLSLProgram > manipulatorProgram = mManipulatorActor->effect()->shader()->gocGLSLProgram(); + + vl::vec3 center; + if(manipulatorProgram.get() == NULL) + return; + manipulatorProgram->gocUniform("ManipulatorPositionMatrix")->getUniform(&manipulatorPositionMatrix); + + vl::mat4 rot = viewMatrix.getInverse().as3x3(); + vl::vec3 dir = rot * vl::vec3(0.0f,0.0f,-1.0f); + + vl::vec4 out = projectionMatrix * viewMatrix * vl::vec4(manipulatorPositionMatrix.getT(), 1.0f); + + if (out.w() == 0.0f) + return; + + out.x() /= out.w(); + out.y() /= out.w(); + + // map to range 0-(width/height) + out.x() = (out.x() * 0.5f + 0.5f) * openglContext()->width(); + out.y() = (out.y() * 0.5f + 0.5f) * openglContext()->height(); + + vec2 u = vec2(xf0, yf0) - out.xy(); + vec2 v = vec2(xf, yf) - out.xy(); + u.normalize(); + v.normalize(); + + // alpha compris [-pi, pi] + float alpha = std::atan2(v.y(), v.x()) - std::atan2(u.y(), u.x()); + + if(mConstraint == CONSTRAINT_X) + { + alpha = vl::dot(dir, vec3(1.0f, 0.0f, 0.0f)) > 0 ? -alpha : alpha; + mModelMatrix = manipulatorPositionMatrix * vl::mat4::getRotation(alpha * 180 / M_PI, 1.0f, 0.0f, 0.0f) * manipulatorPositionMatrix.getInverse(); + } + else if(mConstraint == CONSTRAINT_Y) + { + alpha = vl::dot(dir, vec3(0.0f, 1.0f, 0.0f)) > 0 ? -alpha : alpha; + mModelMatrix = manipulatorPositionMatrix * vl::mat4::getRotation(alpha * 180 / M_PI, 0.0f, 1.0f, 0.0f) * manipulatorPositionMatrix.getInverse(); + } + else if(mConstraint == CONSTRAINT_Z) + { + alpha = vl::dot(dir, vec3(0.0f, 0.0f, 1.0f)) > 0 ? -alpha : alpha; + mModelMatrix = manipulatorPositionMatrix * vl::mat4::getRotation(alpha * 180 / M_PI, 0.0f, 0.0f, 1.0f) * manipulatorPositionMatrix.getInverse(); + } + mModelMatrixUniform->setUniform(mModelMatrix); + + openglContext()->update(); + } +} + +//------------------------------------------------------------------------------ +// ScaleManipulator +//------------------------------------------------------------------------------ + +void ScaleManipulator::mouseMoveEvent(int x, int y) +{ + if(mActive) + { + vl::mat4 viewMatrix, projectionMatrix, manipulatorPositionMatrix; + mViewMatrixUniform->getUniform(&viewMatrix); + mProjectionMatrixUniform->getUniform(&projectionMatrix); + + ref< GLSLProgram > manipulatorProgram = mManipulatorActor->effect()->shader()->gocGLSLProgram(); + + if(manipulatorProgram.get() == NULL) + return; + manipulatorProgram->gocUniform("ManipulatorPositionMatrix")->getUniform(&manipulatorPositionMatrix); + + vl::Ray ray = createRay(x, openglContext()->height() - y, viewMatrix * manipulatorPositionMatrix, projectionMatrix); + + vec4 plane; + + if((mConstraint & CONSTRAINT_X) != 0) + { + if((mConstraint & CONSTRAINT_Z) != 0) + { + // Plan XZ + plane = vec4(0.0f, 1.0f, 0.0f, mFirstIntersection.y()); + } + else + { + // Plan XY ou Axe X seul + plane = vec4(0.0f, 0.0f, 1.0f, mFirstIntersection.z()); + } + } + else if((mConstraint & CONSTRAINT_Y) != 0) + { + if((mConstraint & CONSTRAINT_Z) != 0) + { + // Plan YZ + plane = vec4(1.0f, 0.0f, 0.0f, mFirstIntersection.x()); + } + else + { + // Axe Y seul car géré par le premier if, on se place sur le plan XY + plane = vec4(0.0f, 0.0f, 1.0f, mFirstIntersection.z()); + + } + } + else if((mConstraint & CONSTRAINT_Z) != 0) + { + // Plan YZ + plane = vec4(1.0f, 0.0f, 0.0f, mFirstIntersection.x()); + } + + + float numerator = -((plane.x() * ray.origin().x()) + (plane.y() * ray.origin().y()) + (plane.z() * ray.origin().z()) - plane.w()); + float denominator = ray.direction().x() * plane.x() + ray.direction().y() * plane.y() + ray.direction().z() * plane.z(); + + float t0 = numerator / denominator; + + vec3 secondIntersection = ray.origin() + t0 * ray.direction(); + + vec3 scale = secondIntersection - mFirstIntersection; + + //vec3 scale = -up * dy - right * dx; + scale.x() = (mConstraint & CONSTRAINT_X) == 0 ? 1.0f : 1.0f + scale.x(); + scale.y() = (mConstraint & CONSTRAINT_Y) == 0 ? 1.0f : 1.0f + scale.y(); + scale.z() = (mConstraint & CONSTRAINT_Z) == 0 ? 1.0f : 1.0f + scale.z(); + + + mModelMatrix = manipulatorPositionMatrix * vl::mat4::getScaling(scale) * manipulatorPositionMatrix.getInverse(); + //mModelMatrix = manipulatorPositionMatrix * vl::mat4::getTranslation(-1.0f, 0.0f, 0.0f) * vl::mat4::getScaling(scale) * vl::mat4::getTranslation(1.0f, 0.0f, 0.0f) * manipulatorPositionMatrix.getInverse(); + + mModelMatrixUniform->setUniform(mModelMatrix); + + openglContext()->update(); + } +} + + diff --git a/src/vlGraphics/TransformManipulator.hpp b/src/vlGraphics/TransformManipulator.hpp new file mode 100644 index 000000000..28e4a32a2 --- /dev/null +++ b/src/vlGraphics/TransformManipulator.hpp @@ -0,0 +1,217 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2011, Michele Bosi, Fabien Mathieu */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#ifndef TransformManipulator_INCLUDE_ONCE +#define TransformManipulator_INCLUDE_ONCE + +#include +#include +#include +#include +#include + +namespace vl +{ + //------------------------------------------------------------------------------ + // TransformManipulator + //------------------------------------------------------------------------------ + /** + * Class that represents a Transform Manipulator associated to a visual gyzmo + */ + class VLGRAPHICS_EXPORT TransformManipulator: public UIEventListener + { + VL_INSTRUMENT_ABSTRACT_CLASS(vl::TransformManipulator, UIEventListener); + + public: + /** Axe constraint manipulation */ + enum Constraint + { + NO_CONSTRAINT = 0, + CONSTRAINT_X = 1, + CONSTRAINT_Y = 2, + CONSTRAINT_Z = 4 + }; + + public: + /** Constructor */ + TransformManipulator() : + mActive(false), + mConstraint(NO_CONSTRAINT) + { + VL_DEBUG_SET_OBJECT_NAME() + } + + /** Destructor */ + ~TransformManipulator() + { + } + + void setModelMatrixUniform(Uniform* modelMatrixUniform) { mModelMatrixUniform = modelMatrixUniform; } + + void setViewMatrixUniform(Uniform* viewMatrixUniform) { mViewMatrixUniform = viewMatrixUniform; } + + void setProjectionMatrixUniform(Uniform* projectionMatrixUniform) { mProjectionMatrixUniform = projectionMatrixUniform; } + + void setManipulatorActor(Actor* manipulatorActor) { mManipulatorActor = manipulatorActor; } + + void setCamera(Camera* camera) { mCamera = camera; } + + void setModelMatrix(mat4 modelMatrix) { mModelMatrix = modelMatrix; } + + void setEventListener( UIEventListener* eventListener) { mEventListener = eventListener; } + + void setConstraint(short int constraint) { mConstraint = constraint; } + + void setEditGeometry(Geometry* editGeometry, vl::Uniform* modelMatrixUniform); + + vl::mat4 oldModelMatrix() const { return mOldModelMatrix; } + + Ray createRay(int x, int y, const vl::mat4& viewMatrix, const vl::mat4& projectionMatrix); + + bool unprojectFromUniform(const vl::vec3& in, vl::vec4& out, const vl::mat4& viewMatrix, const vl::mat4& projectionMatrix); + + // --- UIEventListener --- + + virtual void mouseDownEvent(vl::EMouseButton button, int x, int y); + + virtual void mouseUpEvent(vl::EMouseButton button, int x, int y); + + virtual void enableEvent(bool enabled) {} + + virtual void initEvent() {} + + virtual void destroyEvent() {} + + virtual void updateEvent() {} + + virtual void addedListenerEvent(vl::OpenGLContext*) {} + + virtual void removedListenerEvent(vl::OpenGLContext*) {} + + virtual void mouseWheelEvent(int) {} + + virtual void keyPressEvent(unsigned short, vl::EKey) {} + + virtual void keyReleaseEvent(unsigned short, vl::EKey) {} + + virtual void resizeEvent(int, int) {} + + virtual void fileDroppedEvent(const std::vector< vl::String>& ) {} + + virtual void visibilityEvent(bool) {} + + protected: + bool mActive; + ref< Uniform > mModelMatrixUniform; + ref< Uniform > mViewMatrixUniform; + ref< Uniform > mProjectionMatrixUniform; + vec2 mStartPosition; + ref< Actor > mManipulatorActor; + ref< Camera > mCamera; + mat4 mModelMatrix; + ref< UIEventListener > mEventListener; + short int mConstraint; + ref< Geometry > mEditGeometry; // To update real object + vec3 mFirstIntersection; + mat4 mOldModelMatrix; + }; + + //------------------------------------------------------------------------------ + // TranslationManipulator + //------------------------------------------------------------------------------ + /** + * Class that represent a Translation manipulator + */ + class VLGRAPHICS_EXPORT TranslationManipulator: public TransformManipulator + { + VL_INSTRUMENT_ABSTRACT_CLASS(vl::TranslationManipulator, TransformManipulator); + + public: + /** Constructor */ + TranslationManipulator() : + TransformManipulator() + {} + + /** Destructor*/ + ~TranslationManipulator() {} + + // --- UIEventListener --- + virtual void mouseMoveEvent(int x, int y); + }; + + //------------------------------------------------------------------------------ + // RotationManipulator + //------------------------------------------------------------------------------ + /** + * Class that represet a Rotation Manipulator + */ + class VLGRAPHICS_EXPORT RotationManipulator: public TransformManipulator + { + VL_INSTRUMENT_ABSTRACT_CLASS(vl::RotationManipulator, TransformManipulator); + + public: + /** Constructor */ + RotationManipulator() : + TransformManipulator() + {} + + /** Destructor*/ + ~RotationManipulator() {} + + // --- UIEventListener --- + virtual void mouseMoveEvent(int x, int y); + }; + + //------------------------------------------------------------------------------ + // ScaleManipulator + //------------------------------------------------------------------------------ + /** + * Class that represent a Scale Manipulator + */ + class VLGRAPHICS_EXPORT ScaleManipulator: public TransformManipulator + { + VL_INSTRUMENT_ABSTRACT_CLASS(vl::ScaleManipulator, TransformManipulator); + + public: + /** Constructor */ + ScaleManipulator() : + TransformManipulator() + {} + + /** Destructor*/ + ~ScaleManipulator() {} + + // --- UIEventListener --- + virtual void mouseMoveEvent(int x, int y); + }; +} + +#endif diff --git a/src/vlGraphics/TriangleAccessor.hpp b/src/vlGraphics/TriangleAccessor.hpp new file mode 100644 index 000000000..08f07c9d8 --- /dev/null +++ b/src/vlGraphics/TriangleAccessor.hpp @@ -0,0 +1,829 @@ +/**************************************************************************************/ +/* */ +/* Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Copyright (c) 2005-2010, Michele Bosi */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without modification, */ +/* are permitted provided that the following conditions are met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, this */ +/* list of conditions and the following disclaimer. */ +/* */ +/* - Redistributions in binary form must reproduce the above copyright notice, this */ +/* list of conditions and the following disclaimer in the documentation and/or */ +/* other materials provided with the distribution. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ +/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ +/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ +/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ +/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ +/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/**************************************************************************************/ + +#ifndef TriangleAccessor_INCLUDE_ONCE +#define TriangleAccessor_INCLUDE_ONCE + +#include +#include + +namespace vl +{ +//----------------------------------------------------------------------------- +// TriangleAccessorAbstract +//----------------------------------------------------------------------------- + /** For internal use only. See vl::TriangleAccessor instead. */ + class TriangleAccessorAbstract: public Object + { + VL_INSTRUMENT_ABSTRACT_CLASS(vl::TriangleAccessorAbstract, Object) + + public: + virtual int a(unsigned int idx) = 0; + virtual int b(unsigned int idx) = 0; + virtual int c(unsigned int idx) = 0; + }; +//----------------------------------------------------------------------------- +// TriangleAccessorIndexed +//----------------------------------------------------------------------------- + /** For internal use only. See vl::TriangleAccessor instead. */ + template + class TriangleAccessorIndexed: public TriangleAccessorAbstract + { + VL_INSTRUMENT_CLASS(vl::TriangleAccessorIndexed, TriangleAccessorAbstract) + + public: + + TriangleAccessorIndexed() + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = 0; + mEnd = 0; + mA = mB = mC = -1; + mEven = true; + mIndex0 = 0; + mArray = NULL; + mPrimRestartIndex = (unsigned int)-1; + mPrimRestartOn = false; + mBaseVertex = 0; + mPrimType = PT_UNKNOWN; + mPrimRestartNumber = 0; + } + + TriangleAccessorIndexed(const TArray* idx_array, EPrimitiveType prim_type, int base_vert, bool prim_restart_on, unsigned int prim_restart_idx) + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = 0; + mEnd = 0; + mA = mB = mC = -1; + mEven = true; + mIndex0 = 0; + mArray = idx_array; + mPrimRestartIndex = prim_restart_idx; + mPrimRestartOn = prim_restart_on; + mBaseVertex = base_vert; + mPrimType = prim_type; + if(mPrimRestartOn) + { + for(unsigned int i = 0; i < mArray->size(); ++i) + if(mArray->at(i) == mPrimRestartIndex) + mPrimRestartNumber++; + } + } + + //bool hasNext() const { return mCurrentIndex != mEnd; } + + virtual int a(unsigned int idx) { get(idx); return mA; } + virtual int b(unsigned int idx) { get(idx); return mB; } + virtual int c(unsigned int idx) { get(idx); return mC; } + + void get(unsigned int idx) + { + if(idx > static_cast< unsigned int >(mEnd)) + return; + + switch(mPrimType) + { + case PT_TRIANGLES: + //mCurrentIndex += 3; + // check for the end + if ( idx * 3 + 3 > static_cast< unsigned int >(mEnd) ) + //mCurrentIndex = mEnd; + break; + else + /*if ( isPrimRestart(mCurrentIndex) ) + { + mCurrentIndex += 1; + mA = mArray->at(idx * 3 + 0); + mB = mArray->at(idx * 3 + 1); + mC = mArray->at(idx * 3 + 2); + } + else + {*/ + mA = mArray->at(idx * 3 + 0); + mB = mArray->at(idx * 3 + 1); + mC = mArray->at(idx * 3 + 2); + //} + break; + + case PT_QUAD_STRIP: + case PT_TRIANGLE_STRIP: + //mCurrentIndex += 1; + if ( idx * 3 + 2 >= static_cast< unsigned int >(mEnd) ) + idx = mEnd; + else + /*if ( isPrimRestart(mCurrentIndex + 2) ) + { + mCurrentIndex += 3; + mEven = true; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + mC = mArray->at(mCurrentIndex + 2); + } + else + {*/ + mEven = !mEven; + if (mEven) + { + mA = mArray->at(idx * 3 + 0); + mB = mArray->at(idx * 3 + 1); + mC = mArray->at(idx * 3 + 2); + } + else + { + mA = mArray->at(idx * 3 + 0); + mB = mArray->at(idx * 3 + 2); + mC = mArray->at(idx * 3 + 1); + } + //} + break; + + case PT_TRIANGLE_FAN: + case PT_POLYGON: + //mCurrentIndex += 1; + if ( idx + 1 >= static_cast< unsigned int >(mEnd) ) + { + //mCurrentIndex = mEnd; + idx = mEnd; + } + else + /*if ( isPrimRestart(mCurrentIndex + 1) ) + { + mIndex0 = mCurrentIndex + 2; + mCurrentIndex = mIndex0 + 1; + mA = mArray->at(mIndex0); + mB = mArray->at(mCurrentIndex + 0); + mC = mArray->at(mCurrentIndex + 1); + } + else + {*/ + mA = mArray->at(mIndex0); + mB = mArray->at(idx + 0); + mC = mArray->at(idx + 1); + //} + break; + + case PT_QUADS: + //mCurrentIndex += 2; + if ( mCurrentIndex + 2 >= mEnd ) + { + idx = mEnd; + } + else + /* if ( isPrimRestart(mCurrentIndex) ) + { + mCurrentIndex += 1; + mEven = true; + mA = mArray->at(mCurrentIndex+0); + mB = mArray->at(mCurrentIndex+1); + mC = mArray->at(mCurrentIndex+2); + } + else + {*/ + mEven = !mEven; + if ( mEven ) + { + mA = mArray->at(idx + 0); + mB = mArray->at(idx + 1); + mC = mArray->at(idx + 2); + } + else + { + mA = mArray->at(idx + 0); + mB = mArray->at(idx + 1); + mC = mArray->at(idx - 2); + } + // } + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (idx != static_cast< unsigned int >(mEnd) ) + { + mA += mBaseVertex; + mB += mBaseVertex; + mC += mBaseVertex; + return; + } + else + { + mA = mB = mC = -1; + return; + } + } + + void initialize(int start=0, int end=-1) + { + VL_CHECK( start >= 0 ) + VL_CHECK( end <= (int)mArray->size() ) + + if (end == -1) + end = (int)mArray->size(); + + mCurrentIndex = end; // end + mA = mB = mC = -1; + mEven = true; + mIndex0 = start; + mEnd = end; + /*if (mArray->size()) + { + switch(mPrimType) + { + case PT_TRIANGLES: + mCurrentIndex = start; + mA = mArray->at(start+0); + mB = mArray->at(start+1); + mC = mArray->at(start+2); + break; + case PT_TRIANGLE_STRIP: + mCurrentIndex = start; + mA = mArray->at(start+0); + mB = mArray->at(start+1); + mC = mArray->at(start+2); + break; + case PT_TRIANGLE_FAN: + case PT_POLYGON: + mCurrentIndex = start + 1; + mA = mArray->at(start+0); + mB = mArray->at(start+1); + mC = mArray->at(start+2); + break; + case PT_QUADS: + mCurrentIndex = start; + mA = mArray->at(start+0); + mB = mArray->at(start+1); + mC = mArray->at(start+2); + break; + case PT_QUAD_STRIP: + mCurrentIndex = start; + mA = mArray->at(start+0); + mB = mArray->at(start+1); + mC = mArray->at(start+2); + break; + default: + break; + } + } + + // if we are not at the end then add base vertices + if ( mCurrentIndex != mEnd ) + { + mA += mBaseVertex; + mB += mBaseVertex; + mC += mBaseVertex; + } + else + { + mA = mB = mC = -1; + }*/ + } + + /*bool next() + { + // reached the end + if ( mCurrentIndex == mEnd ) + return false; + + switch(mPrimType) + { + + case PT_TRIANGLES: + mCurrentIndex += 3; + // check for the end + if ( mCurrentIndex >= mEnd ) + mCurrentIndex = mEnd; + else + if ( isPrimRestart(mCurrentIndex) ) + { + mCurrentIndex += 1; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + mC = mArray->at(mCurrentIndex + 2); + } + else + { + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + mC = mArray->at(mCurrentIndex + 2); + } + break; + + case PT_QUAD_STRIP: + case PT_TRIANGLE_STRIP: + mCurrentIndex += 1; + if ( mCurrentIndex + 2 >= mEnd ) + mCurrentIndex = mEnd; + else + if ( isPrimRestart(mCurrentIndex + 2) ) + { + mCurrentIndex += 3; + mEven = true; + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + mC = mArray->at(mCurrentIndex + 2); + } + else + { + mEven = !mEven; + if (mEven) + { + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 1); + mC = mArray->at(mCurrentIndex + 2); + } + else + { + mA = mArray->at(mCurrentIndex + 0); + mB = mArray->at(mCurrentIndex + 2); + mC = mArray->at(mCurrentIndex + 1); + } + } + break; + + case PT_TRIANGLE_FAN: + case PT_POLYGON: + mCurrentIndex += 1; + if ( mCurrentIndex + 1 >= mEnd ) + { + mCurrentIndex = mEnd; + } + else + if ( isPrimRestart(mCurrentIndex + 1) ) + { + mIndex0 = mCurrentIndex + 2; + mCurrentIndex = mIndex0 + 1; + mA = mArray->at(mIndex0); + mB = mArray->at(mCurrentIndex + 0); + mC = mArray->at(mCurrentIndex + 1); + } + else + { + mA = mArray->at(mIndex0); + mB = mArray->at(mCurrentIndex + 0); + mC = mArray->at(mCurrentIndex + 1); + } + break; + + case PT_QUADS: + mCurrentIndex += 2; + if ( mCurrentIndex >= mEnd ) + { + mCurrentIndex = mEnd; + } + else + if ( isPrimRestart(mCurrentIndex) ) + { + mCurrentIndex += 1; + mEven = true; + mA = mArray->at(mCurrentIndex+0); + mB = mArray->at(mCurrentIndex+1); + mC = mArray->at(mCurrentIndex+2); + } + else + { + mEven = !mEven; + if ( mEven ) + { + mA = mArray->at(mCurrentIndex+0); + mB = mArray->at(mCurrentIndex+1); + mC = mArray->at(mCurrentIndex+2); + } + else + { + mA = mArray->at(mCurrentIndex+0); + mB = mArray->at(mCurrentIndex+1); + mC = mArray->at(mCurrentIndex-2); + } + } + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (mCurrentIndex != mEnd) + { + mA += mBaseVertex; + mB += mBaseVertex; + mC += mBaseVertex; + return true; + } + else + { + mA = mB = mC = -1; + return false; + } + }*/ + + void setBaseVertex(int base_vert) { mBaseVertex = base_vert; } + int baseVertex() const { return mBaseVertex; } + + private: + bool isPrimRestart(int i) const { return mPrimRestartOn && mArray->at(i) == mPrimRestartIndex; } + + private: + const TArray* mArray; + EPrimitiveType mPrimType; + int mA, mB, mC; + int mCurrentIndex; + int mIndex0; + int mEnd; + int mBaseVertex; + unsigned int mPrimRestartIndex; + bool mPrimRestartOn; + bool mEven; + unsigned int mPrimRestartNumber; + }; +//----------------------------------------------------------------------------- +// TriangleAccessorDirect +//----------------------------------------------------------------------------- + /** For internal use only. See vl::TriangleAccessor instead. */ + class TriangleAccessorDirect: public TriangleAccessorAbstract + { + VL_INSTRUMENT_CLASS(vl::TriangleAccessorDirect, TriangleAccessorAbstract) + + public: + TriangleAccessorDirect(EPrimitiveType prim_type=PT_UNKNOWN) + { + VL_DEBUG_SET_OBJECT_NAME() + mCurrentIndex = mStart = mEnd = 0; + mA = mB = mC = -1; + mPrimType = prim_type; + mEven = true; + } + + bool hasNext() const { return mCurrentIndex != mEnd; } + + virtual int a(unsigned int idx) { get(idx); return mA; } + virtual int b(unsigned int idx) { get(idx); return mB; } + virtual int c(unsigned int idx) { get(idx); return mC; } + + void get(unsigned int idx) + { + // reached the end + if ( idx * 3 >= static_cast< unsigned int >(mEnd) ) + return; + + switch(mPrimType) + { + case PT_TRIANGLES: + // VL_CHECK( (end - start) % 3 == 0 ) /* primitive restart might screw up this */ + //mCurrentIndex = start; + mA = idx * 3 + 0; + mB = idx * 3 + 1; + mC = idx * 3 + 2; + break; + + case PT_QUAD_STRIP: + break; + case PT_TRIANGLE_STRIP: + //mCurrentIndex += 1; + + if ( idx + 1 >= static_cast< unsigned int >(mEnd) ) + break; + else + { + mEven = !mEven; + if (mEven) + { + mA = idx + 0; + mB = idx + 1; + mC = idx + 2; + } + else + { + mA = idx + 0; + mB = idx + 2; + mC = idx + 1; + } + } + break; + + case PT_TRIANGLE_FAN: + case PT_POLYGON: + //mCurrentIndex += 1; + if ( idx + 2 >= static_cast< unsigned int >(mEnd) ) + { + break; + } + else + { + mA = mStart; + mB = idx + 1; + mC = idx + 2; + } + break; + + case PT_QUADS: + mCurrentIndex += 2; + if ( idx + 2 >= static_cast< unsigned int >(mEnd) ) + { + //mCurrentIndex = mEnd; + break; + } + else + { + mEven = !mEven; + if ( mEven ) + { + mA = idx + 0; + mB = idx + 1; + mC = idx + 2; + } + else + { + mA = idx + 0; + mB = idx + 1; + mC = idx - 2; + } + } + break; + + default: + VL_TRAP(); + break; + } + } + + void initialize(int start, int end) + { + VL_CHECK(end >= start) + mStart = start; + mCurrentIndex = mEnd = end; + mA = mB = mC = -1; + mEven = true; + /*switch(mPrimType) + { + case PT_TRIANGLES: + mCurrentIndex = start; + mA = start + 0; + mB = start + 1; + mC = start + 2; + break; + case PT_TRIANGLE_STRIP: + mCurrentIndex = start; + mA = start + 0; + mB = start + 1; + mC = start + 2; + break; + case PT_TRIANGLE_FAN: + case PT_POLYGON: + mCurrentIndex = start + 1; + mA = start + 0; + mB = start + 1; + mC = start + 2; + break; + case PT_QUADS: + mCurrentIndex = start; + mA = start + 0; + mB = start + 1; + mC = start + 2; + break; + case PT_QUAD_STRIP: + mCurrentIndex = start; + mA = start + 0; + mB = start + 1; + mC = start + 2; + break; + default: + break; + }*/ + } + + /*bool next() + { + // reached the end + if ( mCurrentIndex == mEnd ) + return false; + + switch(mPrimType) + { + + case PT_TRIANGLES: + mCurrentIndex += 3; + // check for the end + if ( mCurrentIndex >= mEnd ) + mCurrentIndex = mEnd; + else + { + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + mC = mCurrentIndex + 2; + } + break; + + case PT_QUAD_STRIP: + case PT_TRIANGLE_STRIP: + mCurrentIndex += 1; + if ( mCurrentIndex + 2 >= mEnd ) + mCurrentIndex = mEnd; + else + { + mEven = !mEven; + if (mEven) + { + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 1; + mC = mCurrentIndex + 2; + } + else + { + mA = mCurrentIndex + 0; + mB = mCurrentIndex + 2; + mC = mCurrentIndex + 1; + } + } + break; + + case PT_TRIANGLE_FAN: + case PT_POLYGON: + mCurrentIndex += 1; + if ( mCurrentIndex + 1 >= mEnd ) + { + mCurrentIndex = mEnd; + } + else + { + mA = mStart; + mB = mCurrentIndex+0; + mC = mCurrentIndex+1; + } + break; + + case PT_QUADS: + mCurrentIndex += 2; + if ( mCurrentIndex >= mEnd ) + { + mCurrentIndex = mEnd; + } + else + { + mEven = !mEven; + if ( mEven ) + { + mA = mCurrentIndex+0; + mB = mCurrentIndex+1; + mC = mCurrentIndex+2; + } + else + { + mA = mCurrentIndex+0; + mB = mCurrentIndex+1; + mC = mCurrentIndex-2; + } + } + break; + + default: + VL_TRAP(); + break; + } + + // if we are not at the end then add base vertices + if (mCurrentIndex == mEnd) + { + mA = mB = mC = -1; + return false; + } + else + return true; + }*/ + + private: + EPrimitiveType mPrimType; + int mA, mB, mC; + int mCurrentIndex; + int mStart; + int mEnd; + bool mEven; + }; +//----------------------------------------------------------------------------- +// TriangleAccessorMulti +//----------------------------------------------------------------------------- + /** For internal use only. See vl::TriangleAccessor instead. */ + template + class TriangleAccessorMulti: public TriangleAccessorIndexed + { + VL_INSTRUMENT_CLASS(vl::TriangleAccessorMulti, TriangleAccessorIndexed) + + public: + TriangleAccessorMulti( const std::vector* p_base_vertices, const std::vector* p_count_vector, const TArray* idx_array, EPrimitiveType prim_type, bool prim_restart_on, int prim_restart_idx) + :TriangleAccessorIndexed( idx_array, prim_type, 0, prim_restart_on, prim_restart_idx) + { + VL_DEBUG_SET_OBJECT_NAME() + mpBaseVertices = p_base_vertices; + mpCountVector = p_count_vector; + mStart = 0; + mCurPrim = 0; + } + + void initialize() + { + /*VL_CHECK( mpBaseVertices->size() == mpCountVector->size() ) + if ( (*mpBaseVertices).size() ) + TriangleAccessorIndexed::setBaseVertex( (*mpBaseVertices)[mCurPrim] ); + int end = mStart + (*mpCountVector)[mCurPrim]; + TriangleAccessorIndexed::initialize( mStart, end ); + // abort if could not initialize (primitive not supported) + if ( !TriangleAccessorIndexed::hasNext() ) + mCurPrim = (int)(*mpCountVector).size()-1;*/ + } + + bool next() + { + /* if ( TriangleAccessorIndexed::next() ) + return true; + else + if ( mCurPrim < (int)(*mpCountVector).size()-1 ) + { + mStart += (*mpCountVector)[mCurPrim]; + mCurPrim++; + initialize(); + return true; + } + else*/ + return false; + } + + bool hasNext() const + { + /*if ( !TriangleAccessorIndexed::hasNext() && mCurPrim == (int)(*mpCountVector).size()-1 ) + return false; + else*/ + return true; + } + + protected: + const std::vector* mpBaseVertices; + const std::vector* mpCountVector; + int mCurPrim; + int mStart; + }; +//----------------------------------------------------------------------------- +// TriangleAccessor +//----------------------------------------------------------------------------- + /** Iterator used to extract the indices of every single triangle of a DrawCall + * regardless of the primitive type. + * \sa DrawCall::triangles() */ + class TriangleAccessor + { + public: + TriangleAccessor(TriangleAccessorAbstract* it): mAccessor(it) { } + + /** Requires the next triangle. Returns \p false the iterator reached the end of the triangle list. */ + //bool next() { return mIterator->next(); } + + //bool operator++() { return next(); } + + /** Returns false if the iterator has reached the end of the triangle list. In this case a(), b() and c() return -1. */ + //bool hasNext() { return mIterator->hasNext(); } + + /** First index of the triangle. */ + int a(unsigned int idx) { return mAccessor->a(idx); } + + /** First index of the triangle. */ + int b(unsigned int idx) { return mAccessor->b(idx); } + + /** First index of the triangle. */ + int c(unsigned int idx) { return mAccessor->c(idx); } + + protected: + ref mAccessor; + }; +//----------------------------------------------------------------------------- +} + +#endif diff --git a/src/vlWin32/Win32Context.cpp b/src/vlWin32/Win32Context.cpp index 675e0e93c..494e8e0bd 100644 --- a/src/vlWin32/Win32Context.cpp +++ b/src/vlWin32/Win32Context.cpp @@ -271,7 +271,8 @@ bool Win32Context::initWin32GLContext(HGLRC share_context, const vl::String& tit // delete HDC if (mContext->mHDC) { - DeleteDC(mContext->mHDC); + //DeleteDC(mContext->mHDC); + ReleaseDC(mContext->hwnd(), mContext->mHDC); mContext->mHDC = NULL; } @@ -441,7 +442,8 @@ int vlWin32::choosePixelFormat(const vl::OpenGLContextFormat& fmt, bool verbose) if (pixel_format_index == 0) { if (verbose) MessageBox(NULL, L"choosePixelFormat() critical failure: could not choose temporary format.", L"Visualization Library error", MB_OK); - DeleteDC(hDC); + //DeleteDC(hDC); + ReleaseDC(hWnd, hDC); DestroyWindow(hWnd); return -1; } @@ -449,7 +451,8 @@ int vlWin32::choosePixelFormat(const vl::OpenGLContextFormat& fmt, bool verbose) if (SetPixelFormat(hDC, pixel_format_index, &pfd) == FALSE) { if (verbose) MessageBox(NULL, L"choosePixelFormat() critical failure: could not set temporary format.", L"Visualization Library error", MB_OK); - DeleteDC(hDC); + //DeleteDC(hDC); + ReleaseDC(hWnd, hDC); DestroyWindow(hWnd); return -1; } @@ -459,7 +462,8 @@ int vlWin32::choosePixelFormat(const vl::OpenGLContextFormat& fmt, bool verbose) if (!hGLRC) { if (verbose) MessageBox(NULL, L"choosePixelFormat() critical failure: could not create temporary OpenGL context.", L"Visualization Library error", MB_OK); - DeleteDC(hDC); + //DeleteDC(hDC); + ReleaseDC(hWnd, hDC); DestroyWindow(hWnd); return -1; } @@ -469,7 +473,8 @@ int vlWin32::choosePixelFormat(const vl::OpenGLContextFormat& fmt, bool verbose) if (!initializeOpenGL()) { fprintf(stderr, "Error initializing OpenGL!\n"); - DeleteDC(hDC); + //DeleteDC(hDC); + ReleaseDC(hWnd, hDC); DestroyWindow(hWnd); return -1; } @@ -525,7 +530,8 @@ int vlWin32::choosePixelFormat(const vl::OpenGLContextFormat& fmt, bool verbose) // destroy temporary HWND, HDC, HGLRC if ( wglDeleteContext(hGLRC) == FALSE ) if (verbose) MessageBox(NULL, L"Error deleting temporary OpenGL context, wglDeleteContext(hGLRC) failed.", L"Visualization Library error", MB_OK); - DeleteDC(hDC); + //DeleteDC(hDC); + ReleaseDC(hWnd, hDC); DestroyWindow(hWnd); if (verbose) diff --git a/src/vlWin32/Win32Window.cpp b/src/vlWin32/Win32Window.cpp index d833fe5ae..2d55e174f 100644 --- a/src/vlWin32/Win32Window.cpp +++ b/src/vlWin32/Win32Window.cpp @@ -325,7 +325,8 @@ void Win32Window::destroyWin32GLWindow() } if (mHDC) { - DeleteDC(mHDC); + //DeleteDC(mHDC); + ReleaseDC(mHWND, mHDC); mHDC = NULL; } } From 56a194171b58d7c0fadaaf95a2f35cc84d3e074a Mon Sep 17 00:00:00 2001 From: FabienM Date: Mon, 17 Oct 2016 17:01:35 +0200 Subject: [PATCH 2/2] Forgetting data --- data/glsl/simple.fs | 10 +++++++++ data/glsl/simple.vs | 16 ++++++++++++++ data/glsl/simpleColored.fs | 10 +++++++++ data/glsl/simpleColored.vs | 16 ++++++++++++++ data/glsl/transformManipulator.fs | 24 +++++++++++++++++++++ data/glsl/transformManipulator.vs | 27 ++++++++++++++++++++++++ data/glsl/transform_feedback.fs | 10 +++++++++ data/glsl/transform_feedback.gs | 35 +++++++++++++++++++++++++++++++ data/glsl/transform_feedback.vs | 21 +++++++++++++++++++ 9 files changed, 169 insertions(+) create mode 100644 data/glsl/simple.fs create mode 100644 data/glsl/simple.vs create mode 100644 data/glsl/simpleColored.fs create mode 100644 data/glsl/simpleColored.vs create mode 100644 data/glsl/transformManipulator.fs create mode 100644 data/glsl/transformManipulator.vs create mode 100644 data/glsl/transform_feedback.fs create mode 100644 data/glsl/transform_feedback.gs create mode 100644 data/glsl/transform_feedback.vs diff --git a/data/glsl/simple.fs b/data/glsl/simple.fs new file mode 100644 index 000000000..a32d62d8e --- /dev/null +++ b/data/glsl/simple.fs @@ -0,0 +1,10 @@ +#version 330 core + +flat in vec4 FrontColor; + +out vec4 FragColor; + +void main() +{ + FragColor = FrontColor; +} \ No newline at end of file diff --git a/data/glsl/simple.vs b/data/glsl/simple.vs new file mode 100644 index 000000000..15911f0e4 --- /dev/null +++ b/data/glsl/simple.vs @@ -0,0 +1,16 @@ +#version 330 core + +uniform mat4 ModelMatrix; +uniform mat4 ViewMatrix; +uniform mat4 ProjectionMatrix; +uniform vec4 Color; + +in vec4 VertexPosition; + +flat out vec4 FrontColor; + +void main() +{ + gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * VertexPosition; + FrontColor = Color; +} \ No newline at end of file diff --git a/data/glsl/simpleColored.fs b/data/glsl/simpleColored.fs new file mode 100644 index 000000000..a32d62d8e --- /dev/null +++ b/data/glsl/simpleColored.fs @@ -0,0 +1,10 @@ +#version 330 core + +flat in vec4 FrontColor; + +out vec4 FragColor; + +void main() +{ + FragColor = FrontColor; +} \ No newline at end of file diff --git a/data/glsl/simpleColored.vs b/data/glsl/simpleColored.vs new file mode 100644 index 000000000..1c943760a --- /dev/null +++ b/data/glsl/simpleColored.vs @@ -0,0 +1,16 @@ +#version 330 core + +uniform mat4 ModelMatrix; +uniform mat4 ViewMatrix; +uniform mat4 ProjectionMatrix; + +in vec4 VertexPosition; +in vec4 VertexColor; + +flat out vec4 FrontColor; + +void main() +{ + gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * VertexPosition; + FrontColor = VertexColor; +} \ No newline at end of file diff --git a/data/glsl/transformManipulator.fs b/data/glsl/transformManipulator.fs new file mode 100644 index 000000000..0360f985e --- /dev/null +++ b/data/glsl/transformManipulator.fs @@ -0,0 +1,24 @@ +/**************************************************************************************/ +/* */ +/* Copyright (c) 2005-2011, Michele Bosi, Fabien Mathieu. */ +/* All rights reserved. */ +/* */ +/* This file is part of Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Released under the OSI approved Simplified BSD License */ +/* http://www.opensource.org/licenses/bsd-license.php */ +/* */ +/**************************************************************************************/ + +#version 330 core + +uniform vec4 Color; + +out vec4 FragColor; + + +void main(void) +{ + FragColor = Color; +} diff --git a/data/glsl/transformManipulator.vs b/data/glsl/transformManipulator.vs new file mode 100644 index 000000000..812bc454c --- /dev/null +++ b/data/glsl/transformManipulator.vs @@ -0,0 +1,27 @@ +/**************************************************************************************/ +/* */ +/* Copyright (c) 2005-2011, Michele Bosi, Fabien Mathieu. */ +/* All rights reserved. */ +/* */ +/* This file is part of Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Released under the OSI approved Simplified BSD License */ +/* http://www.opensource.org/licenses/bsd-license.php */ +/* */ +/**************************************************************************************/ + +#version 330 core + +uniform mat4 ViewMatrix; +uniform mat4 ModelMatrix; +uniform mat4 ManipulatorPositionMatrix; +uniform mat4 ProjectionMatrix; + +in vec4 VertexPosition; + + +void main(void) +{ + gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * ManipulatorPositionMatrix * VertexPosition; +} diff --git a/data/glsl/transform_feedback.fs b/data/glsl/transform_feedback.fs new file mode 100644 index 000000000..870bea0e2 --- /dev/null +++ b/data/glsl/transform_feedback.fs @@ -0,0 +1,10 @@ +#version 330 core + +uniform vec4 Color; + +out vec4 FragColor; + +void main() +{ + FragColor = Color; +} \ No newline at end of file diff --git a/data/glsl/transform_feedback.gs b/data/glsl/transform_feedback.gs new file mode 100644 index 000000000..81077abce --- /dev/null +++ b/data/glsl/transform_feedback.gs @@ -0,0 +1,35 @@ +/**************************************************************************************/ +/* */ +/* Copyright (c) 2005-2011, Michele Bosi. */ +/* All rights reserved. */ +/* */ +/* This file is part of Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Released under the OSI approved Simplified BSD License */ +/* http://www.opensource.org/licenses/bsd-license.php */ +/* */ +/**************************************************************************************/ + +#version 330 core + +layout(triangles) in; +layout(points, max_vertices = 1) out; + +flat out int normale; + +void main(void) +{ + /*vec3 a = normalize((gl_in[1].gl_Position - gl_in[0].gl_Position).xyz); + vec3 b = normalize((gl_in[2].gl_Position - gl_in[0].gl_Position).xyz); + normale = normalize(cross(a, b));*/ + normale = gl_PrimitiveIDIn; + + //for(int i = 0; i < 3; ++i) + //{ + gl_Position = gl_in[0].gl_Position; + EmitVertex(); + //} + + EndPrimitive(); +} diff --git a/data/glsl/transform_feedback.vs b/data/glsl/transform_feedback.vs new file mode 100644 index 000000000..3738d9d02 --- /dev/null +++ b/data/glsl/transform_feedback.vs @@ -0,0 +1,21 @@ +/**************************************************************************************/ +/* */ +/* Copyright (c) 2005-2011, Michele Bosi, Fabien Mathieu. */ +/* All rights reserved. */ +/* */ +/* This file is part of Visualization Library */ +/* http://www.visualizationlibrary.org */ +/* */ +/* Released under the OSI approved Simplified BSD License */ +/* http://www.opensource.org/licenses/bsd-license.php */ +/* */ +/**************************************************************************************/ + +#version 330 core + +in vec4 VertexPosition; + +void main(void) +{ + gl_Position = VertexPosition; +}