Commits

Frederic De Groef committed 4cc7a52 Merge

Merge

Comments (0)

Files changed (9)

Debug/resources.cfg

+Zip=../media/OgreCore.zip
+
+FileSystem=../media/
+FileSystem=../media/Grid
+FileSystem=../media/samples
+FileSystem=../media/celshading
+FileSystem=../media/stanford
+FileSystem=../media/npr
+FileSystem=../media2/auralias
+FileSystem=../media/ulb_building

Release/resources.cfg

+Zip=../media/OgreCore.zip
+
+FileSystem=../media/
+FileSystem=../media/Grid
+FileSystem=../media/samples
+FileSystem=../media/celshading
+FileSystem=../media/npr
+FileSystem=../media/titanic
+FileSystem=../media/ulb_building
     float EdotN = dot(E,N);
     float EdotT = dot(E,T);
  
-    float extend =  0.1 * (length(E)/75.0f);
+
     float3 newPos;
 
     // extend everything by default

media/npr/gooch.material

 		{
 			vertex_program_ref Shading/PerVertex/GoochVP
 			{
-				param_named KCool float3	0.05  0.05  0.6
-				param_named KWarm float3 	0.5   0.4   0.05
+				param_named KCool float3	1.0   1.0   1.0
+				param_named KWarm float3 	0.0   0.0   0.5
 				param_named Ks 	  float3 	0.5   0.5   0.5
-	    			param_named ns 	  float 	50.0
+	    		param_named ns 	  float 	50.0
 			}
 			fragment_program_ref Shading/PerVertex/GoochFP
 			{
 			}
 			fragment_program_ref Shading/PerPixel/GoochFP
 			{
-				param_named KCool float3	0.05  0.05  0.6
-				param_named KWarm float3 	0.5   0.4   0.05
+				param_named KCool float3	1.0   1.0   1.0
+				param_named KWarm float3 	0.0   0.0   0.5
 				param_named Ks 	  float3 	0.0  0.0   0.0
 	    			param_named ns 	  float 	50.0
 			}

ogre-npr/EdgeGeometryBuilder.cpp

+#include "precompiled.h"
+#include "EdgeGeometryBuilder.hpp"
+
+
+//-----------------------------------------------------------------------------
+EdgeGeometryBuilder::EdgeGeometryBuilder(const Ogre::String &_name, Ogre::Log *_log, Ogre::SceneManager *_sceneMgr)
+    :mName(_name)
+    ,mLog(_log)
+    ,mSceneMgr(_sceneMgr)
+    ,mIsBuilding(false)
+    ,mEdges(NULL)
+    ,mRidgeThreshold(40.0f)
+{
+}
+//-----------------------------------------------------------------------------
+EdgeGeometryBuilder::~EdgeGeometryBuilder()
+{
+}
+//-----------------------------------------------------------------------------
+void EdgeGeometryBuilder::attachToSceneNode(Ogre::SceneNode *_node)
+{
+    _node->attachObject(mEdges);
+}
+//-----------------------------------------------------------------------------
+void EdgeGeometryBuilder::setVisible(bool _visible)
+{
+#ifdef _DEBUG
+    assert(mEdges);
+#endif
+
+    mEdges->setVisible(_visible);
+}
+//-----------------------------------------------------------------------------
+void EdgeGeometryBuilder::begin()
+{
+    mIsBuilding = true;
+
+    mEdges = mSceneMgr->createManualObject(mName);
+    mEdges->begin("NPR/EdgeOutliner", Ogre::RenderOperation::OT_TRIANGLE_LIST);
+    mIndex = 0;
+
+}
+//-----------------------------------------------------------------------------
+void EdgeGeometryBuilder::end()
+{
+    mEdges->end();
+    mIsBuilding = false;
+}
+//-----------------------------------------------------------------------------
+void EdgeGeometryBuilder::addEdgesForEntity(Ogre::Entity *_ent)
+{
+    if(mIsBuilding)
+    {
+
+        mLog->logMessage("Creating edges for entity : " + _ent->getName());
+        Ogre::MeshPtr mesh = _ent->getMesh();
+
+        {
+            boost::format fmt("Mesh has %d submeshes");
+            fmt % mesh->getNumSubMeshes();
+            mLog->logMessage(fmt.str());
+        }
+
+        mesh->buildEdgeList();
+
+        Ogre::EdgeData *edgeData = mesh->getEdgeList();
+
+        {
+            boost::format fmt("Generating %d edgegroups");
+            fmt % edgeData->edgeGroups.size();
+            mLog->logMessage(fmt.str());
+        }
+    
+        for(int edgeGroupIdx = 0 ; edgeGroupIdx < edgeData->edgeGroups.size() ; edgeGroupIdx++)
+        {
+            {
+                boost::format fmt("Adding edges for edgegroup[%d]");
+                fmt % edgeGroupIdx ;
+                mLog->logMessage(fmt.str());
+            }
+
+            Ogre::EdgeData::EdgeGroup &currentEdgeGroup = edgeData->edgeGroups[edgeGroupIdx];
+            _addEdgesForEdgeGroup(currentEdgeGroup, *edgeData);
+
+            {
+                boost::format fmt("%s : Added %d edges (%d tris, %d vertices)");
+                fmt % mEdges->getName() % (mIndex/6) % (mIndex/3) % (mIndex);
+                mLog->logMessage(fmt.str());
+            }
+
+        }
+    }
+    else
+    {
+        throw new Ogre::RuntimeAssertionException(Ogre::Exception::ERR_RT_ASSERTION_FAILED
+            , "EdgeGeometryBuilder::addEdgesForEntity() was called before EdgeGeometryBuilder::begin() was"
+            , "EdgeGeometryBuilder::addEdgesForEntity()"
+            , __FILE__
+            , __LINE__);
+    }
+}
+//-----------------------------------------------------------------------------
+void EdgeGeometryBuilder::_addEdgesForEdgeGroup(const Ogre::EdgeData::EdgeGroup &_edgeGroup, const Ogre::EdgeData &edgeData)
+{
+    std::vector<Ogre::Vector3> vertices;
+    vertices.resize(_edgeGroup.vertexData->vertexCount);
+
+    const Ogre::VertexElement* posElem =
+        _edgeGroup.vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
+
+    Ogre::HardwareVertexBufferSharedPtr vbuf =
+        _edgeGroup.vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
+
+    unsigned char* vertex =
+        static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
+
+    // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
+    //  as second argument. So make it float, to avoid trouble when Ogre::Real will
+    //  be comiled/typedefed as double:
+    //      Ogre::Real* pReal;
+    float* pReal;
+
+    for( size_t j = 0; j < _edgeGroup.vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize())
+    {
+        posElem->baseVertexPointerToElement(vertex, &pReal);
+
+        Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
+
+        vertices[j] = pt;
+    }
+    vbuf->unlock();
+
+
+
+
+
+
+    int edgeCount = _edgeGroup.edges.size();
+                                                            
+    for(int i=0; i<edgeCount ; i++)
+    {
+        Ogre::EdgeData::Edge e = _edgeGroup.edges[i];
+
+        Ogre::Vector3 v0, v1;
+        Ogre::Vector4 nA, nB ;
+        Ogre::Real markedEdge;
+
+        if(e.degenerate)
+        {
+            
+            v0 =  vertices[e.vertIndex[0]];
+            v1 =  vertices[e.vertIndex[1]];
+
+            nA = edgeData.triangleFaceNormals[e.triIndex[0]];
+            nB = -nA;
+            markedEdge = 2.0f;
+        }
+        else
+        {
+            v0 =  vertices[e.vertIndex[0]];
+            v1 =  vertices[e.vertIndex[1]];
+
+            nA = edgeData.triangleFaceNormals[e.triIndex[0]];
+            nB = edgeData.triangleFaceNormals[e.triIndex[1]];
+
+            Ogre::Real ridgeThreshold = Ogre::Degree(mRidgeThreshold).valueRadians();
+            Ogre::Real valleyThreshold = Ogre::Degree(mRidgeThreshold).valueRadians();
+
+
+            bool isRidge = _isEdgeARidge(Ogre::Vector3(nA.x, nA.y, nA.z)
+                                        ,Ogre::Vector3(nB.x, nB.y, nB.z)
+                                        ,ridgeThreshold);
+
+            bool isValley = _isEdgeAValley(Ogre::Vector3(nA.x, nA.y, nA.z)
+                                          ,Ogre::Vector3(nB.x, nB.y, nB.z)
+                                          ,valleyThreshold);
+
+            markedEdge = (isRidge || isValley) ? 1.0f : 0.0f;
+        }
+
+        {
+            boost::format fmt("Adding new edge for position : (%.2f, %.2f, %.2f)  (%.2f, %.2f, %.2f)");
+            fmt % v0.x % v0.y % v0.z % v1.x % v1.y % v0.z; 
+            mLog->logMessage(fmt.str());
+        }
+
+        _buildEdgeQuad(v0, v1, nA, nB, markedEdge, mIndex);
+        mIndex += 6;
+    }
+}
+//-----------------------------------------------------------------------------
+void EdgeGeometryBuilder::_buildEdgeQuad(  const Ogre::Vector3 &_v0, const Ogre::Vector3 &_v1
+                                         , const Ogre::Vector4 &_nA,const Ogre::Vector4 &_nB
+                                         , const Ogre::Real _markedEdge,unsigned int _idx)
+{
+    Ogre::Vector3 nA = Ogre::Vector3(_nA.x, _nA.y, _nA.z).normalisedCopy();
+    Ogre::Vector3 nB = Ogre::Vector3(_nB.x, _nB.y, _nB.z).normalisedCopy();
+
+    /* 1st tri
+    1 __ 2
+    | /
+    |/
+    3
+    */
+    mEdges->position(_v0);
+    mEdges->normal(nA);
+    mEdges->textureCoord(nB);
+    mEdges->textureCoord(_markedEdge);
+
+    mEdges->index(_idx++);
+
+    mEdges->position(_v0);
+    mEdges->normal(nB);
+    mEdges->textureCoord(nA);
+    mEdges->textureCoord(_markedEdge);
+
+    mEdges->index(_idx++);
+
+    mEdges->position(_v1);
+    mEdges->normal(nA);
+    mEdges->textureCoord(nB);
+    mEdges->textureCoord(_markedEdge);
+
+    mEdges->index(_idx++);
+
+    /* 2nd tri
+       6
+      /|
+     /_|
+    4   5
+    */
+    mEdges->position(_v1);
+    mEdges->normal(nA);
+    mEdges->textureCoord(nB);
+    mEdges->textureCoord(_markedEdge);
+
+    mEdges->index(_idx++);
+
+    mEdges->position(_v0);
+    mEdges->normal(nB);
+    mEdges->textureCoord(nA);
+    mEdges->textureCoord(_markedEdge);
+
+    mEdges->index(_idx++);
+
+    mEdges->position(_v1);
+    mEdges->normal(nB);
+    mEdges->textureCoord(nA);
+    mEdges->textureCoord(_markedEdge);
+
+    mEdges->index(_idx++);
+}
+
+//-----------------------------------------------------------------------------
+bool EdgeGeometryBuilder::_isEdgeARidge(const Ogre::Vector3 &_nA, const Ogre::Vector3 &_nB, const Ogre::Real &_threshold)
+{
+    Ogre::Vector3 nA_norm = Ogre::Vector3(_nA.x, _nA.y, _nA.z).normalisedCopy();
+    Ogre::Vector3 nB_norm = Ogre::Vector3(_nB.x, _nB.y, _nB.z).normalisedCopy();
+
+    return nA_norm.dotProduct(nB_norm) < Ogre::Math::Cos(_threshold);
+}
+//-----------------------------------------------------------------------------
+bool EdgeGeometryBuilder::_isEdgeAValley(const Ogre::Vector3 &_nA, const Ogre::Vector3 &_nB, const Ogre::Real &_threshold)
+{
+    Ogre::Vector3 nA_norm = Ogre::Vector3(_nA.x, _nA.y, _nA.z).normalisedCopy();
+    Ogre::Vector3 nB_norm = Ogre::Vector3(_nB.x, _nB.y, _nB.z).normalisedCopy();
+
+    return nA_norm.dotProduct(nB_norm) < Ogre::Math::Cos(_threshold);
+}

ogre-npr/EdgeGeometryBuilder.hpp

+#pragma once
+#ifndef __041010_EDGEGEOMETRYBUILDER_HPP__
+#define __041010_EDGEGEOMETRYBUILDER_HPP__
+
+#include <Ogre.h>
+
+class EdgeGeometryBuilder
+{
+public:
+    EdgeGeometryBuilder(const Ogre::String &_name, Ogre::Log *_log, Ogre::SceneManager *_sceneMgr);
+    ~EdgeGeometryBuilder();
+    void begin();
+    void addEdgesForEntity(Ogre::Entity *_ent);
+    void end();
+    void attachToSceneNode(Ogre::SceneNode*);
+    void setVisible(bool _visible);
+    bool isVisible(){return mEdges->isVisible();};
+
+
+protected:
+    void _addEdgesForEdgeGroup(const Ogre::EdgeData::EdgeGroup &_edgeGroup
+                              ,const Ogre::EdgeData &edgeData);
+    void _buildEdgeQuad(const Ogre::Vector3 &_v0, const Ogre::Vector3 &_v1
+                       ,const Ogre::Vector4 &_nA, const Ogre::Vector4 &_nB
+                       ,const Ogre::Real _markedEdge, unsigned int _idx);
+
+    inline bool _isEdgeARidge(const Ogre::Vector3&, const Ogre::Vector3&, const Ogre::Real&);
+    inline bool _isEdgeAValley(const Ogre::Vector3&, const Ogre::Vector3&, const Ogre::Real&);
+
+
+private:
+    EdgeGeometryBuilder(){};
+
+
+protected:
+    Ogre::String mName;
+    bool mIsBuilding;
+    Ogre::ManualObject *mEdges;
+    Ogre::Log *mLog;
+    Ogre::SceneManager *mSceneMgr;
+    Ogre::Real mRidgeThreshold;
+
+    int mIndex;
+};
+
+#endif 

ogre-npr/NPRDemoApp.cpp

+/* This program is free software. It comes without any warranty, to
+* the extent permitted by applicable law. You can redistribute it
+* and/or modify it under the terms of the Do What The Fuck You Want
+* To Public License, Version 2, as published by Sam Hocevar. See
+* http://sam.zoy.org/wtfpl/COPYING for more details. */
+
+#include "precompiled.h"
+
+#include "NPRDemoApp.h"
+
+#include <sstream>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+
+//-----------------------------------------------------------------------------
+NPRDemoApp::NPRDemoApp()
+    :OgreApplication("NPR Sandbox")
+    ,mBBset(NULL)
+    ,mLightFlare(NULL)
+    ,mLight(NULL)
+    ,mLightNode(NULL)
+    ,mDebugText(NULL)
+    ,mAnimState(NULL)
+    ,mEdgesVisible(true)
+{
+}
+//-----------------------------------------------------------------------------
+void NPRDemoApp::createScene()
+{
+    mLog  = LogManager::getSingleton().createLog("NPR.log");
+
+    const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
+    if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM)))
+    {
+        OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your card does not support vertex and fragment programs, so cannot "
+            "run this application. Sorry!", 
+            "createScene");
+    }
+
+
+    mSceneMgr->setNormaliseNormalsOnScale(true);
+    _createGrid(500);
+    _createLight();
+    _populate();
+
+    _createDebugOverlay();
+}
+//-----------------------------------------------------------------------------
+bool NPRDemoApp::frameStarted(const FrameEvent& evt)
+{
+    _updateDebugOverlay();
+    return OgreApplication::frameStarted(evt);
+}
+//-----------------------------------------------------------------------------
+bool NPRDemoApp::keyPressed (const OIS::KeyEvent &e )
+{
+    if(mKeyboard->isKeyDown(OIS::KC_E))
+    {
+        mStaticEdges->setVisible(!mStaticEdges->isVisible());
+    }
+    return OgreApplication::keyPressed(e);
+}
+//-----------------------------------------------------------------------------
+void NPRDemoApp::_createDebugOverlay()
+{
+    new TextRenderer();
+
+    mDebugText = TextRenderer::getSingletonPtr();
+
+    int x_offset=100, y_offset=18, w=100, h=18;
+
+    mDebugText->addTextBox("Batches_", "#Batches : "
+                            , 10, 10, w, h
+                            , ColourValue(0.7,0.7,0.7));
+    mDebugText->addTextBox("Batches", "0"
+                            , x_offset, 10, w, h
+                            , ColourValue(1.0,1.0,1.0));
+    mDebugText->addTextBox("FPS_", "#FPS : "
+                            , 10, 10+y_offset, w, h
+                            , ColourValue(0.7,0.7,0.7));
+    mDebugText->addTextBox("FPS", "0"
+                            , x_offset, 10+y_offset, w, h
+                            , ColourValue(1.0,1.0,1.0));
+
+    mDebugText->addTextBox("Triangles_", "#tris : "
+                            , 10, 10+y_offset*2, w, h
+                            , ColourValue(0.7,0.7,0.7));
+    mDebugText->addTextBox("Triangles", "0"
+                            , x_offset, 10+y_offset*2, w, h
+                            , ColourValue(1.0,1.0,1.0));
+
+
+
+}
+//-----------------------------------------------------------------------------
+void NPRDemoApp::_updateDebugOverlay()
+{
+    mDebugText->setText("Batches", StringConverter::toString(mWindow->getBatchCount()));
+    mDebugText->setText("FPS", StringConverter::toString(mWindow->getLastFPS()));
+    mDebugText->setText("Triangles", StringConverter::toString(mWindow->getTriangleCount()));
+}
+
+//-----------------------------------------------------------------------------
+void NPRDemoApp::_populate()
+{
+    //_loadMesh("TorusKnot01", Vector3(-50, 0, 0));
+    //_loadMesh("Teapot01",    Vector3(50, 0, 0));
+    //_loadMesh("Gengon01",   Vector3(-50, 0, 50));
+    //_loadMesh("Cone01",     Vector3(50, 0, 50));
+    //_loadMesh("Box01",      Vector3(-50, 0, -50));
+
+	//_loadMesh("sphere2", Vector3(500, 0, 0));
+	//
+    //_loadMesh("Rectangle01", Vector3(0, 0, 0));
+
+    // stanford models
+
+ //   SceneNode *bunny = _loadMesh("bunny", Vector3::ZERO);
+    
+	//bunny->scale(100, 100, 100);
+	//bunny->pitch(Degree(-90));
+	//bunny->translate(0, 20, 0);
+
+	//SceneNode *dragon = _loadMesh("dragon", Vector3(50, 0, 100));
+    
+ //   SceneNode *dragon = _loadMesh("dragon", Vector3::ZERO);
+
+	//dragon->scale(50, 50, 50);
+	//dragon->pitch(Degree(180));
+	//dragon->translate(0, 15, 0);
+
+    //_loadMesh("math_back wall", Vector3(0, 0, 0));
+    //_loadMesh("math_front wall", Vector3(0, 0, 0));
+    //_loadMesh("math_left wall", Vector3(0, 0, 0));
+    //_loadMesh("math_right wall", Vector3(0, 0, 0));
+    //_loadMesh("math_roof", Vector3(0, 0, 0));
+    //_loadMesh("math_ground", Vector3(0, 0, 0));
+    //_loadMesh("math_chairs", Vector3(0, 0, 0));
+
+    // loading a .scene scene
+    //SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("titanic_root");
+    //_loadScene("titanic", node);
+
+
+
+
+    _loadMesh("ulb_building_BATIMENTS_EST", Vector3(-1300, 0, 0));
+
+    _loadMesh("ulb_building_bat_C", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_ASCENCEUR", Vector3(-1300, 0, 0));
+
+ 
+    _loadMesh("ulb_building_BAT_NEXT", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_BAT_PRINCIPAL", Vector3(-1300, 0, 0));
+    //_loadMesh("ulb_building_bat_projet_broullion", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_bat_S_W", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_batiment_plus", Vector3(-1300, 0, 0));
+
+
+    _loadMesh("ulb_building_BATIMENTS_PROJET", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_BATIMENTS_TOUT", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_Calque1", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_Calque2", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_COURBES", Vector3(-1300, 0, 0));
+
+    _loadMesh("ulb_building_galleries", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_Layer0", Vector3(-1300, 0, 0));
+
+    _loadMesh("ulb_building_Le_Batiment", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_route_relief", Vector3(-1300, 0, 0));
+
+    _loadMesh("ulb_building_tour", Vector3(-1300, 0, 0));
+    _loadMesh("ulb_building_Z_LAYOUT", Vector3(-1300, 0, 0));
+
+    _buildStaticEdges();
+
+
+
+}
+//-----------------------------------------------------------------------------
+void NPRDemoApp::_loadScene(const String &_name, SceneNode* _node)
+{
+    OgreMax::OgreMaxScene sceneLoader;
+
+    sceneLoader.Load("../media/"+_name+"/"+_name+".scene", mWindow
+        , OgreMax::OgreMaxScene::SKIP_ENVIRONMENT |
+        OgreMax::OgreMaxScene::SKIP_SKY |
+        OgreMax::OgreMaxScene::SKIP_TERRAIN|
+        OgreMax::OgreMaxScene::SKIP_EXTERNALS
+                    ,mSceneMgr,_node, this);
+}
+//-----------------------------------------------------------------------------
+SceneNode* NPRDemoApp::_loadMesh(const Ogre::String &_name, const Ogre::Vector3 &_pos)
+{
+    Entity *ent = mSceneMgr->createEntity(_name, _name+".mesh");
+    SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode(_name+"Node", _pos);
+
+	ent->setMaterialName("Shading/PerPixel/Gooch");
+    node->attachObject(ent);
+
+    mScenePairs.push_back(NPRDemoApp::ScenePair(ent, node));
+
+    return node;
+}
+//-----------------------------------------------------------------------------
+void NPRDemoApp::_buildStaticEdges()
+{
+    mStaticEdges = new EdgeGeometryBuilder("ULB static edges", mLog, mSceneMgr);
+    mStaticEdges->begin();
+
+    BOOST_FOREACH(NPRDemoApp::ScenePair pair, mScenePairs)
+    {
+        mStaticEdges->addEdgesForEntity(pair.first);
+
+    }
+    mStaticEdges->end();
+
+    mStaticEdges->setVisible(true);
+    Ogre::SceneNode *edgesNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("edges node", Ogre::Vector3(-1300, 0, 0));
+    mStaticEdges->attachToSceneNode(edgesNode);
+}
+//-----------------------------------------------------------------------------
+void NPRDemoApp::_setCelShadingMaterial(Entity *_ent)
+{
+    _ent->getSubEntity(0)->setMaterialName("Examples/CelShading");
+
+    _ent->getSubEntity(0)->setCustomParameter(0, Vector4(10.0f, 0.0f, 0.0f, 0.0f));
+    _ent->getSubEntity(0)->setCustomParameter(1, Vector4(0.0f, 0.5f, 0.0f, 1.0f));
+    _ent->getSubEntity(0)->setCustomParameter(2, Vector4(0.3f, 0.5f, 0.3f, 1.0f));
+}
+//-----------------------------------------------------------------------------
+void NPRDemoApp::_createLight()
+{
+    mBBset = mSceneMgr->createBillboardSet("Light BB");
+    mBBset->setMaterialName("Objects/Flare");
+    mLightFlare = mBBset->createBillboard(Vector3::ZERO);
+
+    mLight = mSceneMgr->createLight("main light");
+    mLight->setType(Light::LT_POINT);
+    mLight->setDiffuseColour(ColourValue::White);
+    mLight->setSpecularColour(ColourValue::White);
+
+    mLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("light node");
+    mLightNode->attachObject(mLight);
+    mLightNode->attachObject(mBBset);
+
+    mLightNode->setPosition(Ogre::Vector3(0, 500, 500));
+
+}
+//-----------------------------------------------------------------------------
+
+////-----------------------------------------------------------------------------
+//void NPRDemoApp::CreatedEntity(const OgreMax::OgreMaxScene* scene
+//                                 ,Ogre::Entity* entity)
+//{
+//    entity->setMaterialName("NPR/Face");
+//    ManualObject *edges = _createQuadFinGeometry(entity);
+//    edges->setVisible(true);
+//
+//    SceneNode *node = entity->getParentSceneNode();
+//
+//    if (node)
+//    {
+//        node->attachObject(edges);
+//        node->setVisible(true); 
+//    }
+//}
+////-----------------------------------------------------------------------------
+//void NPRDemoApp::_setEdgesVisible(EdgeGeometryItem &_item, bool _visible)
+//{
+//    ManualObject *edges = _item.first;
+//    SceneNode    *node  = _item.second;
+//    
+//    node->setVisible(_visible);
+//    edges->setVisible(_visible);
+//}
+////-----------------------------------------------------------------------------

ogre-npr/NPRDemoApp.h

+/* This program is free software. It comes without any warranty, to
+* the extent permitted by applicable law. You can redistribute it
+* and/or modify it under the terms of the Do What The Fuck You Want
+* To Public License, Version 2, as published by Sam Hocevar. See
+* http://sam.zoy.org/wtfpl/COPYING for more details. */
+
+#ifndef _NPRDEMOAPP__H_
+#define _NPRDEMOAPP__H_
+
+#include <vector>
+#include <list>
+#include <utility>
+#include "OgreApplication.h"
+#include "TextRenderer.h"
+
+#include "EdgeGeometryBuilder.hpp"
+#include <OgreMaxScene.hpp>
+
+class NPRDemoApp : public OgreApplication, public OgreMax::OgreMaxSceneCallback
+{
+protected:
+    typedef std::pair<Ogre::Entity*, Ogre::SceneNode*> ScenePair;
+    typedef std::vector<ScenePair> ScenePairs;
+public:
+    NPRDemoApp();
+    void createScene();
+    Ogre::ManualObject*   _createQuadFinGeometry(Entity*);
+
+    bool frameStarted(const FrameEvent& evt);
+    bool keyPressed( const OIS::KeyEvent &e );
+protected:
+    // Scene generation
+    void _populate();
+    void _createLight();
+    SceneNode* _loadMesh(const String&, const Vector3&);
+    void _setCelShadingMaterial(Entity*);
+    void _loadScene(const String&, SceneNode*);
+    void _buildStaticEdges();
+
+    // overlay
+    void _createDebugOverlay();
+    void _updateDebugOverlay();
+
+    // OgreMaxSceneCallback
+    void CreatedEntity(const OgreMax::OgreMaxScene*, Ogre::Entity*){};
+
+
+protected:
+    BillboardSet *mBBset;
+    Billboard *mLightFlare;
+    Light *mLight;
+    SceneNode *mLightNode;
+    TextRenderer *mDebugText;
+
+    AnimationState *mAnimState;
+    bool mEdgesVisible;
+
+    Log *mLog;
+    EdgeGeometryBuilder* mStaticEdges;
+    ScenePairs mScenePairs;
+};
+
+
+#endif _NPRDEMOAPP__H_

ogre-npr/ogre-npr.vcproj

+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9,00"
+	Name="ogre-npr"
+	ProjectGUID="{315EFB01-99A5-4C7E-8DB1-9E329966BD44}"
+	RootNamespace="ogrenpr"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/Zm200"
+				Optimization="0"
+				AdditionalIncludeDirectories="&quot;$(BOOST136_HOME)&quot;;&quot;$(OGRE16_HOME)\include&quot;;..\Dependencies\OgreMax\tinyxml;..\Dependencies\OgreMax"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;TIXML_USE_STL"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="precompiled.h"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="OgreMain_d.lib OIS_d.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="&quot;$(OGRE16_HOME)\lib&quot;"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/Zm200"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="&quot;$(BOOST136_HOME)&quot;;&quot;$(OGRE16_HOME)\include&quot;;..\Dependencies\OgreMax\tinyxml;..\Dependencies\OgreMax"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;TIXML_USE_STL"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="OgreMain.lib OIS.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="&quot;$(OGRE16_HOME)\lib&quot;"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\EdgeGeometryBuilder.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\NPRDemoApp.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\ogre-npr.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\OgreApplication.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\precompiled.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\TextRenderer.cpp"
+				>
+			</File>
+			<Filter
+				Name="Dep/OgreMax"
+				>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxModel.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxScene.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxUtilities.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgrePlugins.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\ProgressCalculator.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\Version.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+			</Filter>
+			<Filter
+				Name="Dep/tinyxml"
+				>
+				<File
+					RelativePath="..\Dependencies\OgreMax\tinyxml\tinyxml.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\tinyxml\tinyxmlerror.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\tinyxml\tinyxmlparser.cpp"
+					>
+					<FileConfiguration
+						Name="Debug|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release|Win32"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+							UsePrecompiledHeader="0"
+						/>
+					</FileConfiguration>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\EdgeGeometryBuilder.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\NPRDemoApp.h"
+				>
+			</File>
+			<File
+				RelativePath=".\OgreApplication.h"
+				>
+			</File>
+			<File
+				RelativePath=".\precompiled.h"
+				>
+			</File>
+			<File
+				RelativePath=".\TextRenderer.h"
+				>
+			</File>
+			<Filter
+				Name="Dep/tinyxml"
+				>
+				<File
+					RelativePath="..\Dependencies\OgreMax\tinyxml\tinyxml.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="Dep/OgreMax"
+				>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxModel.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxPlatform.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxRenderWindowIterator.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxScene.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxTypes.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgreMaxUtilities.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\OgrePlugins.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\ProgressCalculator.hpp"
+					>
+				</File>
+				<File
+					RelativePath="..\Dependencies\OgreMax\Version.hpp"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="Dep/tinyxml"
+				>
+				<File
+					RelativePath="..\Dependencies\OgreMax\tinyxml\tinyxml.h"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>