Main.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This program is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU General Public License as published by the Free  *
00007 * Software Foundation; either version 2 of the License, or (at your option)   *
00008 * any later version.                                                          *
00009 *                                                                             *
00010 * This program is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
00013 * more details.                                                               *
00014 *                                                                             *
00015 * You should have received a copy of the GNU General Public License along     *
00016 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
00017 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
00018 *******************************************************************************
00019 *                            SOFA :: Applications                             *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include <iostream>
00028 #include <fstream>
00029 #include <stack>
00030 
00031 #include <flowvr/module.h>
00032 #include <flowvr/render/chunkwriter.h>
00033 //#include <flowvr/interact/chunkwriter.h>
00034 
00035 #include <sofa/simulation/tree/Simulation.h>
00036 #include <sofa/simulation/common/Visitor.h>
00037 #include <sofa/core/ObjectFactory.h>
00038 #include <sofa/defaulttype/Vec3Types.h>
00039 #include <sofa/defaulttype/Mat.h>
00040 #include <sofa/helper/ArgumentParser.h>
00041 #include <sofa/helper/BackTrace.h>
00042 #include <sofa/helper/system/thread/CTime.h>
00043 #include <sofa/helper/system/FileRepository.h>
00044 #include <sofa/core/objectmodel/Event.h>
00045 #include <sofa/simulation/common/AnimateBeginEvent.h>
00046 #include <sofa/simulation/common/AnimateEndEvent.h>
00047 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00048 
00049 #include <sofa/simulation/common/Node.h>
00050 #include <sofa/simulation/common/InitVisitor.h>
00051 #include <sofa/simulation/tree/DeleteVisitor.h>
00052 #include <sofa/component/MechanicalObject.h>
00053 #include <sofa/component/collision/PointModel.h>
00054 #include <sofa/component/collision/MinProximityIntersection.h>
00055 #include <sofa/component/collision/BruteForceDetection.h>
00056 #include <sofa/component/init.h>
00057 
00058 #include <sofa/component/visualmodel/VisualModelImpl.h>
00059 #include <sofa/component/visualmodel/OglModel.h>
00060 
00061 #ifdef SOFA_GPU_CUDA
00062 #include <sofa/gpu/cuda/CudaDistanceGridCollisionModel.h>
00063 #endif
00064 
00065 #include <sofa/gui/SofaGUI.h>
00066 #include <sofa/helper/system/gl.h> 
00067 #include <sofa/helper/system/glut.h>
00068   
00069 using sofa::helper::system::thread::CTime;
00070 using sofa::helper::system::thread::ctime_t;
00071 using namespace sofa::simulation::tree;
00072 
00073 
00074 //#define VERBOSE
00075 
00076 // ---------------------------------------------------------------------
00077 // --- SOFA+FLOWVR integration
00078 // ---------------------------------------------------------------------
00079 
00080 namespace ftl
00081 {
00082 
00083 namespace Type
00084 {
00085 
00086 template<int N, typename real>
00087 Type get(const sofa::defaulttype::Vec<N,real>&)
00088 {
00089     return (Type)vector(get(real()),N);
00090 }
00091 
00092 template<int L, int C, typename real>
00093 Type get(const sofa::defaulttype::Mat<L,C,real>&)
00094 {
00095     return (Type)matrix(get(real()),L,C);
00096 }
00097 
00098 }
00099 
00100 }
00101 
00102 namespace SofaFlowVR
00103 {
00104 
00105 //flowvr::ModuleAPI* module = NULL;
00106 
00107 //using namespace flowvr::render;
00108 //using namespace flowvr::interact;
00109 
00110 //using namespace Sofa::Abstract;
00111 //using namespace Sofa::Components;
00112 using namespace sofa::defaulttype;
00113 using namespace sofa::simulation;
00114 
00115 class FlowVRModule;
00116 
00117 class FlowVREvent : public sofa::core::objectmodel::Event
00118 {
00119 public:
00120     FlowVREvent() : from(NULL) {}
00121     virtual ~FlowVREvent() {}
00122     FlowVRModule* from;
00123 };
00124 
00125 class FlowVRPreInitEvent : public FlowVREvent
00126 {
00127 public:
00128     virtual ~FlowVRPreInitEvent() {}
00129     std::set<flowvr::Port*>* ports;
00130 };
00131 
00132 class FlowVRInitEvent : public FlowVREvent
00133 {
00134 public:
00135     virtual ~FlowVRInitEvent() {}
00136     flowvr::ModuleAPI* module;
00137 };
00138 
00139 class FlowVRBeginIterationEvent : public FlowVREvent
00140 {
00141 public:
00142     virtual ~FlowVRBeginIterationEvent() {}
00143     flowvr::ModuleAPI* module;
00144 };
00145 
00146 class FlowVREndIterationEvent : public FlowVREvent
00147 {
00148 public:
00149     virtual ~FlowVREndIterationEvent() {}
00150     flowvr::ModuleAPI* module;
00151 };
00152 
00153 class FlowVRObject : public virtual sofa::core::objectmodel::BaseObject
00154 {
00155 public:
00156     Data<std::string> modName;
00157     FlowVRModule* mod;
00158 
00159 
00160     FlowVRObject()
00161     : modName(initData(&modName, "module", "Name of FlowVR Module"))
00162     , mod(NULL)
00163     {
00164         f_listening.setValue(true);
00165     }
00166     
00167     virtual ~FlowVRObject()
00168     {
00169     }
00170     
00171     virtual void animateBegin(double /*dt*/)
00172     {
00173     }
00174     
00175     virtual void animateEnd(double /*dt*/)
00176     {
00177     }
00178     
00179     virtual void flowvrPreInit(std::set<flowvr::Port*>* /*ports*/)
00180     {
00181     }
00182     
00183     virtual void flowvrInit(flowvr::ModuleAPI* /*module*/)
00184     {
00185     }
00186     
00187     virtual void flowvrBeginIteration(flowvr::ModuleAPI* /*module*/)
00188     {
00189     }
00190     
00191     virtual void flowvrEndIteration(flowvr::ModuleAPI* /*module*/)
00192     {
00193     }
00194 
00195     virtual void handleEvent(sofa::core::objectmodel::Event* event);
00196 
00197 };
00198 
00199 std::map<std::string, flowvr::ModuleAPI*> moduleMap;
00200 std::map<std::string, flowvr::InputPort*> inputPortMap;
00201 std::map<std::string, flowvr::OutputPort*> outputPortMap;
00202 std::map<std::string, flowvr::render::SceneOutputPort*> sceneOutputPortMap;
00203 
00204 flowvr::ModuleAPI* createModule(const std::vector<flowvr::Port*>& ports, const char* name="")
00205 {
00206     flowvr::ModuleAPI*& module = moduleMap[name];
00207     if (module==NULL)
00208     {
00209         std::cout << "SofaFlowVR: Creating module "<<name<<std::endl;
00210         module = flowvr::initModule(ports);
00211     }
00212     else
00213     {
00214         std::cout << "SofaFlowVR: Reusing module "<<name<<std::endl;
00215     }
00216     return module;
00217 }
00218 
00219 flowvr::InputPort* createInputPort(const char* name)
00220 {
00221     flowvr::InputPort*& port = inputPortMap[name];
00222     if (port==NULL)
00223     {
00224       std::cout << "SofaFlowVR: Creating port "<<name<<std::endl;
00225         port = new flowvr::InputPort(name);
00226     }
00227     else
00228       std::cout << "SofaFlowVR: Reusing port "<<name<<std::endl;
00229     return port;
00230 }
00231 
00232 flowvr::OutputPort* createOutputPort(const char* name)
00233 {
00234     flowvr::OutputPort*& port = outputPortMap[name];
00235     if (port==NULL)
00236     {
00237         std::cout << "SofaFlowVR: Creating port "<<name<<std::endl;
00238         port = new flowvr::OutputPort(name);
00239     }
00240     else
00241       std::cout << "SofaFlowVR: Reusing port "<<name<<std::endl;
00242     return port;
00243 }
00244 
00245 flowvr::render::SceneOutputPort* createSceneOutputPort(const char* name="scene")
00246 {
00247     flowvr::render::SceneOutputPort*& port = sceneOutputPortMap[name];
00248     if (port==NULL)
00249     {
00250       std::cout << "SofaFlowVR: Creating port "<<name<<std::endl;
00251       port = new flowvr::render::SceneOutputPort(name);
00252     }
00253     else
00254       std::cout << "SofaFlowVR: Reusing port "<<name<<std::endl;
00255 
00256     return port;
00257 }
00258 
00259 class FlowVRModule : public FlowVRObject
00260 {
00261 public:
00262     flowvr::ModuleAPI* module;
00263     Data<double> f_dt;
00264     Data<float> f_scale;
00265     Data<Vec3f> f_trans;
00266     Data< vector<std::string> > f_inputPorts;
00267     Data< vector<std::string> > f_outputPorts;
00268     int it;
00269     double lasttime;
00270     bool step;
00271     FlowVRModule()
00272     : module(NULL)
00273     , f_dt(initData(&f_dt,0.0,"dt","simulation time interval between flowvr iteration"))
00274     , f_scale(initData(&f_scale,1.0f,"scale","scale"))
00275     , f_trans(initData(&f_trans,Vec3f(0,0,0),"translation","translation"))
00276     , f_inputPorts(initData(&f_inputPorts,"inputPorts","additional input ports to be defined"))
00277     , f_outputPorts(initData(&f_outputPorts,"outputPorts","additional output ports to be defined"))
00278     , it(-1)
00279     , lasttime(0.0), step(false)
00280     {
00281     mod = this;
00282     }
00283     
00284     virtual void init()
00285     {
00286         if (module!=NULL) return;
00287         std::set<flowvr::Port*> ports;
00288         std::cout << "Sending FlowVRPreInit"<<std::endl;
00289         FlowVRPreInitEvent ev;
00290     ev.from = this;
00291         ev.ports = &ports;
00292         getContext()->propagateEvent(&ev);
00293         const vector<std::string>& inputPorts = f_inputPorts.getValue();
00294         for (vector<std::string>::const_iterator it = inputPorts.begin(); it != inputPorts.end(); ++it)
00295             ports.insert(createInputPort(it->c_str()));
00296         const vector<std::string>& outputPorts = f_outputPorts.getValue();
00297         for (vector<std::string>::const_iterator it = outputPorts.begin(); it != outputPorts.end(); ++it)
00298             ports.insert(createOutputPort(it->c_str()));
00299         std::vector<flowvr::Port*> vports;
00300         vports.insert(vports.end(), ports.begin(), ports.end());
00301         //module = flowvr::initModule(vports);
00302         module = createModule(vports);
00303         if (module == NULL)
00304         {
00305         std::cerr << "SofaFlowVR: module creation failed. Exit."<<std::endl;
00306             std::exit(1);
00307         }
00308         std::cout << "Sending FlowVRInit"<<std::endl;
00309         FlowVRInitEvent ev2;
00310     ev2.from = this;
00311         ev2.module = module;
00312         getContext()->propagateEvent(&ev2);
00313     }
00314     
00315     virtual void animateBegin(double /*dt*/)
00316     {
00317         if (module==NULL) return;
00318         if (it!=-1 && f_dt.getValue()>0 && getContext()->getTime()<lasttime+f_dt.getValue() && getContext()->getTime()>=lasttime) return;
00319         if (!module->wait())
00320         {
00321         std::cerr << "SofaFlowVR: module wait method returned 0. Exit."<<std::endl;
00322             std::exit(1);
00323         }
00324         ++it; step = true;
00325         lasttime = getContext()->getTime();
00326         //std::cout << "Sending FlowVRBeginIteration"<<std::endl;
00327         FlowVRBeginIterationEvent ev;
00328     ev.from = this;
00329         ev.module = module;
00330         getContext()->propagateEvent(&ev);
00331     }
00332     
00333     virtual void animateEnd(double /*dt*/)
00334     {
00335         if (module==NULL) return;
00336         if (!step) return;
00337         step = false;
00338         //std::cout << "Sending FlowVREndIteration"<<std::endl;
00339         FlowVREndIterationEvent ev;
00340     ev.from = this;
00341         ev.module = module;
00342         getContext()->propagateEvent(&ev);
00343     }
00344 };
00345 
00346 SOFA_DECL_CLASS(FlowVRModule)
00347 int FlowVRModuleClass = sofa::core::RegisterObject("FlowVR main module")
00348 .add<FlowVRModule>()
00349 ;
00350 
00351 
00352 void FlowVRObject::handleEvent(sofa::core::objectmodel::Event* event)
00353 {
00354     if (AnimateBeginEvent* ev = dynamic_cast<AnimateBeginEvent*>(event))
00355     animateBegin(ev->getDt());
00356     if (AnimateEndEvent* ev = dynamic_cast<AnimateEndEvent*>(event))
00357     animateEnd(ev->getDt());
00358     if (FlowVREvent* flev = dynamic_cast<FlowVREvent*>(event))
00359     {
00360     if (!mod)
00361     {
00362         if (modName.getValue().empty() || modName.getValue() == flev->from->modName.getValue())
00363         mod = flev->from;
00364         else
00365         return; // event for another module
00366     }
00367     else if (flev->from != mod)
00368         return; // event for another module
00369     if (FlowVRPreInitEvent* ev = dynamic_cast<FlowVRPreInitEvent*>(event))
00370         flowvrPreInit(ev->ports);
00371     if (FlowVRInitEvent* ev = dynamic_cast<FlowVRInitEvent*>(event))
00372         flowvrInit(ev->module);
00373     if (FlowVRBeginIterationEvent* ev = dynamic_cast<FlowVRBeginIterationEvent*>(event))
00374         flowvrBeginIteration(ev->module);
00375     if (FlowVREndIterationEvent* ev = dynamic_cast<FlowVREndIterationEvent*>(event))
00376         flowvrEndIteration(ev->module);
00377     }
00378 }
00379 
00380 //flowvr::interact::ObjectsOutputPort pObjectsOut("objects");
00381 //flowvr::interact::ChunkInteractWriter objects;
00382 
00383 class FlowVRInputMesh : public FlowVRObject
00384 {
00385 public:
00386 
00387     flowvr::InputPort* pInFacets;
00388     flowvr::InputPort* pInPoints;
00389     flowvr::InputPort* pInMatrix;
00390 
00391     Data<bool> computeV;
00392     Data<double> maxVDist;
00393 
00394     // Velocity is estimated by searching the nearest primitive from each new point
00395     // To do it we need to create an additionnal PointModel collision model, as well as a Detection and Intersection class
00396     sofa::simulation::tree::GNode * newPointsNode;
00397     typedef sofa::simulation::tree::GNode::Sequence<sofa::core::CollisionModel>::iterator CMIterator;
00398     sofa::component::MechanicalObject<Vec3Types> * newPoints;
00399     sofa::component::collision::PointModel * newPointsCM;
00400     sofa::component::collision::MinProximityIntersection * intersection;
00401     sofa::component::collision::BruteForceDetection * detection;
00402     sofa::helper::vector<double> newPointsDist;
00403     
00404     Mat4x4f matrix;
00405     int facetsLastIt;
00406     int pointsLastIt;
00407     int matrixLastIt;
00408     double motionLastTime;
00409     
00410     FlowVRInputMesh()
00411     : pInFacets(createInputPort("facets")), pInPoints(createInputPort("points")), pInMatrix(createInputPort("matrix"))
00412     , computeV( initData(&computeV, false, "computeV", "estimate velocity by detecting nearest primitive of previous model") )
00413     , maxVDist( initData(&maxVDist,   1.0, "maxVDist", "maximum distance to use for velocity estimation") )
00414     , newPointsNode(NULL), newPointsCM(NULL), intersection(NULL), detection(NULL)
00415     , facetsLastIt(-20), pointsLastIt(-20), matrixLastIt(-20), motionLastTime(-1000)
00416     {
00417         matrix.identity();
00418     }
00419 
00420     ~FlowVRInputMesh()
00421     {
00422     if (newPointsNode != NULL)
00423     {
00424         newPointsNode->execute<sofa::simulation::tree::DeleteVisitor>();
00425         delete newPointsNode;
00426     }
00427     }
00428     
00429     virtual void flowvrPreInit(std::set<flowvr::Port*>* ports)
00430     {
00431         std::cout << "Received FlowVRPreInit"<<std::endl;
00432         ports->insert(pInFacets);
00433         ports->insert(pInPoints);
00434         ports->insert(pInMatrix);
00435     }
00436 
00437     virtual void init()
00438     {
00439     this->FlowVRObject::init();
00440     if (computeV.getValue())
00441     {
00442         newPointsNode = new sofa::simulation::tree::GNode("newPoints");
00443         newPointsNode->addObject ( newPoints = new sofa::component::MechanicalObject<Vec3Types> );
00444         newPointsNode->addObject ( newPointsCM = new sofa::component::collision::PointModel );
00445 
00446         newPointsNode->addObject ( intersection = new sofa::component::collision::MinProximityIntersection );
00447         intersection->setAlarmDistance(maxVDist.getValue());
00448         intersection->setContactDistance(0); //maxVDist.getValue());
00449         
00450         newPointsNode->addObject ( detection = new sofa::component::collision::BruteForceDetection );
00451         detection->setIntersectionMethod(intersection);
00452         
00453         newPointsNode->execute<sofa::simulation::InitVisitor>();
00454     }
00455     }
00456     
00457     virtual void flowvrBeginIteration(flowvr::ModuleAPI* module)
00458     {
00459         //std::cout << "Received FlowVRBeginIteration"<<std::endl;
00460         flowvr::Message points, facets;
00461 //  double time = getContext()->getTime();
00462         
00463         module->get(pInPoints, points);
00464         module->get(pInFacets, facets);
00465     
00466         bool newmatrix = false;
00467         if (pInMatrix->isConnected())
00468         {
00469             flowvr::Message msgmatrix;
00470             module->get(pInMatrix,msgmatrix);
00471             int matrixIt = -1;
00472             msgmatrix.stamps.read(pInMatrix->stamps->it,matrixIt);
00473             if (matrixIt != matrixLastIt && msgmatrix.data.getSize()>=(int)sizeof(Mat4x4f))
00474             {
00475                 matrix = *msgmatrix.data.getRead<Mat4x4f>(0);
00476                 matrixLastIt = matrixIt;
00477                 newmatrix = true;
00478             }
00479         }
00480         
00481         int pointsIt = -1;
00482         points.stamps.read(pInPoints->stamps->it,pointsIt);
00483         const unsigned int nbv = points.data.getSize()/sizeof(Vec3f);
00484         if (pointsIt != pointsLastIt || newmatrix)
00485         {
00486             pointsLastIt = pointsIt;
00487             const Vec3f* vertices = points.data.getRead<Vec3f>(0);
00488             const Vec3f trans = mod->f_trans.getValue();
00489             const float scale = mod->f_scale.getValue();
00490             
00491             BaseObject* mmodel = getContext()->getMechanicalState();
00492 #ifndef SOFA_FLOAT
00493         sofa::core::componentmodel::behavior::MechanicalState<Vec3dTypes>* mmodel3d;
00494         if ((mmodel3d = dynamic_cast<sofa::core::componentmodel::behavior::MechanicalState<Vec3dTypes>*>(mmodel))!=NULL)
00495         {
00496           bool doComputeV = (computeV.getValue() && newPoints != NULL && motionLastTime != -1000);
00497         
00498           sofa::core::componentmodel::behavior::MechanicalState<Vec3dTypes>* mm;
00499           if (doComputeV)
00500           {
00501             //std::cout << "Copying "<<nbv<<" vertices and estimate velocity"<<std::endl;
00502         mm = newPoints; // put new data in newPoints state
00503           }
00504           else
00505           {
00506             //std::cout << "Copying "<<nbv<<" vertices to mmodel3d"<<std::endl;
00507         mm = mmodel3d;
00508           }
00509           mm->resize(nbv);
00510           Vec3dTypes::VecCoord& x = *mm->getX();
00511 
00512           if (matrixLastIt==-20)
00513           {
00514         for (unsigned int i=0;i<nbv;i++)
00515         {
00516           x[i] = vertices[i]*scale;
00517           x[i] += trans;
00518         }
00519           }
00520           else
00521           {
00522         float scale2 = 1.0;
00523         if (matrix[3][3] != 0) scale2 = 1/matrix[3][3];
00524         for (unsigned int i=0;i<nbv;i++)
00525         {
00526           Vec3f v = vertices[i]*scale;
00527           v += trans;
00528           Vec4f tv = matrix * Vec4f(v[0],v[1],v[2],1.0f);
00529           x[i] = Vec3d(tv[0],tv[1],tv[2])*scale2;
00530         }
00531           }
00532 #if 0
00533           if (doComputeV)
00534           {
00535           sofa::simulation::tree::GNode* node = dynamic_cast<sofa::simulation::tree::GNode*>(getContext());
00536           Vec3dTypes::VecDeriv& v = *newPoints->getV();
00537           const double dmax = maxVDist.getValue();
00538           newPointsDist.resize(nbv);
00539           for (unsigned int i=0;i<nbv;i++)
00540           {
00541           v[i] = Vec3dTypes::Deriv();
00542           newPointsDist[i] = dmax;
00543         }
00544           intersection->setAlarmDistance(dmax); // make sure the distance is up-to-date
00545           intersection->setContactDistance(0);
00546           newPointsCM->computeBoundingTree( 6 ); // compute a bbox tree of depth 6
00547             //std::cout << "computeV: "<<newPointsCM->end().getIndex()<<" points"<<std::endl;
00548           detection->beginNarrowPhase();
00549           for (CMIterator it = node->collisionModel.begin(), itend = node->collisionModel.end(); it != itend ; ++it)
00550           {
00551           sofa::core::CollisionModel* cm2 = *it;
00552           std::cout << "computeV: narrow phase detection with "<<cm2->getClassName()<<std::endl;
00553                    detection->addCollisionPair(std::make_pair(newPointsCM->getFirst(), cm2->getFirst()));
00554             //detection->addCollisionPair(std::make_pair(cm2, newPointsCM));
00555         }
00556                {
00557                    sofa::core::componentmodel::collision::NarrowPhaseDetection::DetectionOutputMap& contactMap = detection->getDetectionOutputs();
00558                    int ncollisions = 0;
00559                    for (sofa::core::componentmodel::collision::NarrowPhaseDetection::DetectionOutputMap::iterator it1 = contactMap.begin(); it1 != contactMap.end(); ++it1)
00560                {
00561                    sofa::core::componentmodel::collision::NarrowPhaseDetection::DetectionOutputVector& contacts = it1->second;
00562                    if (contacts.empty()) continue;
00563                    int newPointsCMIndex = (contacts[0].elem.second.getCollisionModel()==newPointsCM)?1:0;
00564                    for (sofa::core::componentmodel::collision::NarrowPhaseDetection::DetectionOutputVector::iterator it2 = contacts.begin(); it2 != contacts.end(); ++it2)
00565                {
00566                    sofa::core::componentmodel::collision::DetectionOutput* detection = &*it2;
00567                    ++ncollisions;
00568                    int index = (&(detection->elem.first))[newPointsCMIndex].getIndex();
00569                    double d = detection->distance;
00570                    if ((unsigned)index >= nbv)
00571                {
00572                    std::cerr << "computeV: invalid point index "<<index<<std::endl;
00573         }
00574                    else if (d < newPointsDist[index])
00575                {
00576                    newPointsDist[index] = d;
00577                    v[index] = detection->point[newPointsCMIndex] - detection->point[1-newPointsCMIndex];
00578         }
00579         }
00580         }
00581                    std::cout << "computeV: "<<ncollisions<<" collisions detected"<<std::endl;
00582         }
00583             // then we finalize the results
00584                    const double vscale = (time > motionLastTime) ? 1.0/(time-motionLastTime) : 1.0;
00585                    for (unsigned int i=0;i<nbv;i++)
00586                {
00587                    v[i] *= vscale;
00588         }
00589                    mmodel3d->resize(nbv);
00590                    Vec3dTypes::VecCoord& x2 = *mmodel3d->getX();
00591                    Vec3dTypes::VecDeriv& v2 = *mmodel3d->getV();
00592                    x2.swap(x);
00593                    v2.swap(v);
00594         }
00595 #endif
00596                    motionLastTime = time;
00597         }
00598     
00599 #endif
00600 #ifndef SOFA_DOUBLE
00601         sofa::core::componentmodel::behavior::MechanicalState<Vec3fTypes>* mmodel3f;
00602             
00603         if ((mmodel3f = dynamic_cast<sofa::core::componentmodel::behavior::MechanicalState<Vec3fTypes>*>(mmodel))!=NULL)
00604         {
00605                 //std::cout << "Copying "<<nbv<<" vertices to mmodel3f"<<std::endl;
00606           mmodel3f->resize(nbv);
00607           Vec3fTypes::VecCoord& x = *mmodel3f->getX();
00608           if (matrixLastIt==-20)
00609           {
00610         for (unsigned int i=0;i<nbv;i++)
00611         {
00612           x[i] = vertices[i]*scale;
00613           x[i] += trans;
00614         }
00615           }
00616           else
00617           {
00618         float scale2 = 1.0;
00619         if (matrix[3][3] != 0) scale2 = 1/matrix[3][3];
00620         for (unsigned int i=0;i<nbv;i++)
00621         {
00622           Vec3f v = vertices[i]*scale;
00623           v += trans;
00624           Vec4f tv = matrix * Vec4f(v[0],v[1],v[2],1.0f);
00625           x[i] = Vec3f(tv[0],tv[1],tv[2])*scale2;
00626         }
00627           }
00628         }
00629 #endif
00630     }
00631         int facetsIt = -1;
00632         facets.stamps.read(pInFacets->stamps->it,facetsIt);
00633         if (facetsIt != facetsLastIt)
00634         {
00635             facetsLastIt = facetsIt;
00636             const unsigned int nbi = facets.data.getSize()/sizeof(unsigned short);
00637             const unsigned short* indices = facets.data.getRead<unsigned short>(0);
00638             
00639             // check indices
00640             bool valid = true;
00641             for (unsigned int i=0;i<nbi;i++)
00642             {
00643                 if (indices[i] >= nbv)
00644                 {
00645                     std::cerr << "ERROR: invalid indice "<<i<<" ("<<indices[i]<<">="<<nbv<<") it="<<facetsIt<<std::endl;
00646                     valid = false;
00647                 }
00648             }
00649             BaseObject* topology = getContext()->getTopology();
00650             sofa::core::componentmodel::topology::BaseMeshTopology* mesh;
00651             if ((mesh = dynamic_cast<sofa::core::componentmodel::topology::BaseMeshTopology*>(topology))!=NULL)
00652             {
00653                 mesh->clear();
00654                 if (valid)
00655                 {
00656                     //std::cout << "Copying "<<nbi/3<<" triangles to mesh"<<std::endl;
00657                     for (unsigned int i=0;i<nbi;i+=3)
00658                     {
00659                         mesh->addTriangle(indices[i  ],indices[i+1],indices[i+2]);
00660                         // must create edges too
00661                         if (indices[i  ] < indices[i+1])
00662                             mesh->addLine(indices[i  ],indices[i+1]);
00663                         if (indices[i+1] < indices[i+2])
00664                             mesh->addLine(indices[i+1],indices[i+2]);
00665                         if (indices[i+2] < indices[i  ])
00666                             mesh->addLine(indices[i+2],indices[i  ]);
00667                     }
00668                     //std::cout << "Copying "<<mesh->getNbLines()<<" edges to mesh"<<std::endl;
00669                 }
00670             }
00671         }
00672     }
00673 };
00674 
00675 SOFA_DECL_CLASS(FlowVRInputMesh)
00676 int FlowVRInputMeshClass = sofa::core::RegisterObject("Import a mesh from a FlowVR InputPort")
00677 .add< FlowVRInputMesh >()
00678 ;
00679 
00680 template<class T>
00681 class SofaFlowVRAllocator : public sofa::defaulttype::ExtVectorAllocator<T>
00682 {
00683 public:
00684     typedef typename sofa::defaulttype::ExtVectorAllocator<T>::value_type value_type;
00685     typedef typename sofa::defaulttype::ExtVectorAllocator<T>::size_type size_type;
00686     virtual void close(value_type* /*data*/)
00687     {
00688         delete this;
00689     }
00690     virtual void resize(value_type*& data, size_type size, size_type& maxsize, size_type& cursize)
00691     {
00692         if (size > maxsize)
00693         {
00694             if (size > (size_type)bRead.getSize()) size = bRead.getSize();
00695             maxsize = bRead.getSize();
00696             data = const_cast<value_type*>(bRead.getRead<value_type>());
00697         }
00698         cursize = size;
00699     }
00700     flowvr::Buffer bRead;
00701     SofaFlowVRAllocator(flowvr::Buffer& data) : bRead(data) {}
00702 };
00703 
00704 //using sofa::component::collision::DistanceGrid;
00705 
00706 template<class DistanceGridModel, class DistanceGrid>
00707 class FlowVRInputDistanceGrid : public FlowVRObject
00708 {
00709 public:
00710  
00711   
00712 
00713     flowvr::InputPort* pInDistance;
00714     flowvr::InputPort* pInMatrix;
00715     flowvr::StampInfo stampSizes, stampP0, stampDP, stampBB;
00716 
00717     Data<bool> computeV;
00718     Data<double> maxVDist;
00719 
00720     Mat4x4f matrix, lastMatrix;
00721     float mscale; 
00722     int distanceLastIt;
00723     int matrixLastIt;
00724     double motionLastTime;
00725     DistanceGrid* curDistGrid;
00726     DistanceGrid* emptyGrid;
00727     //flowvr::Message curDistance, lastDistance;
00728 
00729     DistanceGridModel* grid;
00730     //sofa::core::componentmodel::behavior::MechanicalState<RigidTypes>* rigid;
00731 
00732     FlowVRInputDistanceGrid()
00733     : pInDistance(createInputPort("distance")), pInMatrix(createInputPort("matrix"))
00734     , stampSizes("Sizes", flowvr::TypeArray::create(3, flowvr::TypeInt::create()))
00735     , stampP0("P0", flowvr::TypeArray::create(3, flowvr::TypeFloat::create()))
00736     , stampDP("DP", flowvr::TypeArray::create(3, flowvr::TypeFloat::create()))
00737     , stampBB("BB", flowvr::TypeArray::create(6, flowvr::TypeInt::create()))
00738     , computeV( initData(&computeV, false, "computeV", "estimate velocity by detecting nearest primitive of previous model") )
00739     , maxVDist( initData(&maxVDist,   1.0, "maxVDist", "maximum distance to use for velocity estimation") )
00740     , mscale(1.0f), distanceLastIt(-20), matrixLastIt(-20), motionLastTime(-1000), curDistGrid(NULL), emptyGrid(NULL)
00741     , grid(NULL) //, rigid(NULL)
00742     {
00743         pInDistance->stamps->add(&stampSizes);
00744         pInDistance->stamps->add(&stampP0);
00745         pInDistance->stamps->add(&stampDP);
00746         pInDistance->stamps->add(&stampBB);
00747         matrix.identity();
00748     }
00749 
00750     ~FlowVRInputDistanceGrid()
00751     {
00752         if (emptyGrid!=NULL)
00753         {
00754             emptyGrid->release();
00755         }
00756         if (curDistGrid!=NULL)
00757         {
00758             curDistGrid->release();
00759         }
00760     }
00761 
00762     virtual void flowvrPreInit(std::set<flowvr::Port*>* ports)
00763     {
00764         std::cout << "Received FlowVRPreInit"<<std::endl;
00765         ports->insert(pInDistance);
00766         ports->insert(pInMatrix);
00767     }
00768 
00769     virtual void init()
00770     {
00771         this->FlowVRObject::init();
00772         sofa::simulation::tree::GNode* node = dynamic_cast<sofa::simulation::tree::GNode*>(this->getContext());
00773         if (node)
00774         {
00775             node->getNodeObject(grid);
00776             if (grid)
00777             {
00778                 //rigid = grid->getRigidModel();
00779                 
00780                 // just create a dummy distance grid for now
00781                 emptyGrid = new DistanceGrid(2,2,2,typename DistanceGrid::Coord(0,0,-100),typename DistanceGrid::Coord(0.001f,0.001f,-99.999f));
00782                 for (int i=0;i<emptyGrid->size();i++)
00783                     (*emptyGrid)[i] = emptyGrid->maxDist();
00784                 grid->resize(1);
00785                 curDistGrid = emptyGrid->addRef();
00786                 grid->setGrid(curDistGrid,0);
00787                 grid->setActive(false);
00788             }
00789         }
00790         if (computeV.getValue())
00791         {
00792         }
00793     }
00794 
00795     virtual void flowvrBeginIteration(flowvr::ModuleAPI* module)
00796     {
00797         //std::cout << "Received FlowVRBeginIteration"<<std::endl;
00798         flowvr::Message distance;
00799         double time = getContext()->getTime();
00800 
00801         bool newmotion = false;
00802         bool newscale = false;
00803         if (pInMatrix->isConnected())
00804         {
00805             flowvr::Message msgmatrix;
00806             module->get(pInMatrix,msgmatrix);
00807             int matrixIt = -1;
00808             msgmatrix.stamps.read(pInMatrix->stamps->it,matrixIt);
00809             if (matrixIt != matrixLastIt && msgmatrix.data.getSize()>=(int)sizeof(Mat4x4f))
00810             {
00811                 lastMatrix = matrix;
00812                 matrix = *msgmatrix.data.getRead<Mat4x4f>(0);
00813 
00814                 // remove scale component
00815                 float newmscale = 0.0f;
00816                 for(int j=0;j<3;j++)
00817                     for(int i=0;i<3;i++)
00818                         newmscale += matrix[j][i]*matrix[j][i];
00819                 newmscale = sqrt(newmscale/3);
00820                 for(int j=0;j<3;j++)
00821                     for(int i=0;i<3;i++)
00822                         matrix[j][i] /= newmscale;
00823                 if (matrix[3][3] != 0 && matrix[3][3] != 1)
00824                 {
00825                     for(int i=0;i<3;i++)
00826                         matrix[i][3] /= matrix[3][3];
00827                     newmscale /= matrix[3][3];
00828                     matrix[3][3] = 1;
00829                 }
00830                 if (newmscale != mscale)
00831                     newscale = true;
00832                 mscale = newmscale;
00833 
00834                 matrixLastIt = matrixIt;
00835                 if (lastMatrix != matrix || newscale)
00836                     newmotion = true;
00837                 
00838                 //if(rigid)
00839                 //    (*rigid->getX())[0].fromMatrix(matrix);
00840             }
00841         }
00842 
00843         if (pInDistance->isConnected())
00844         {
00845             module->get(pInDistance, distance);
00846 
00847             int distanceIt = -1;
00848             distance.stamps.read(pInDistance->stamps->it,distanceIt);
00849         //const unsigned int nbv = points.data.getSize()/sizeof(Vec3f);
00850         if (distanceIt != distanceLastIt || newscale)
00851         {
00852             distanceLastIt = distanceIt;
00853             //const Vec3f* vertices = points.data.getRead<Vec3f>(0);
00854             const Vec3f trans = mod->f_trans.getValue();
00855             const float scale = mod->f_scale.getValue()*mscale;
00856             
00857             int nz = 0;
00858             int ny = 0;
00859             int nx = 0;
00860             Vec3f p0, dp;
00861             int bbox[6] = {-1,-1,-1,-1,-1,-1};
00862             distance.stamps.read(stampSizes[0], nz);
00863             distance.stamps.read(stampSizes[1], ny);
00864             distance.stamps.read(stampSizes[2], nx);
00865             distance.stamps.read(stampP0[0], p0[0]);
00866             distance.stamps.read(stampP0[1], p0[1]);
00867             distance.stamps.read(stampP0[2], p0[2]);
00868             distance.stamps.read(stampDP[0], dp[0]);
00869             distance.stamps.read(stampDP[1], dp[1]);
00870             distance.stamps.read(stampDP[2], dp[2]);
00871             for (int i=0;i<6;i++)
00872                 distance.stamps.read(stampBB[i], bbox[i]);
00873             
00874             if (!nx || !ny || !nz || bbox[0] > bbox[3])
00875             { // empty grid
00876                 curDistGrid->release();
00877                 curDistGrid = emptyGrid->addRef();
00878                 grid->setActive(false);
00879             }
00880             else
00881             {
00882                 typename DistanceGrid::Coord pmin = trans + p0*scale;
00883                 typename DistanceGrid::Coord pmax = pmin + Vec3f(dp[0]*(nx-1),dp[1]*(ny-1),dp[2]*(ny-2))*scale;
00884                 typename DistanceGrid::Coord bbmin = pmin + Vec3f(dp[0]*bbox[0],dp[1]*bbox[1],dp[2]*bbox[2])*scale;
00885                 typename DistanceGrid::Coord bbmax = pmin + Vec3f(dp[0]*bbox[3],dp[1]*bbox[4],dp[2]*bbox[5])*scale;
00886                 
00887                 /*if (scale==1.0f)
00888                 {
00889                     curDistGrid->release();
00890                     curDistGrid = new DistanceGrid(nx,ny,nz, pmin, pmax, new SofaFlowVRAllocator<typename DistanceGrid::Real>(distance.data));
00891                 }
00892                 else*/
00893                 {
00894                     curDistGrid->release();
00895                     curDistGrid = new DistanceGrid(nx,ny,nz, pmin, pmax);
00896                     const float* in = distance.data.getRead<float>();
00897                     for (int i=0;i<curDistGrid->size();i++)
00898                         (*curDistGrid)[i] = in[i]*scale;
00899                 }
00900                 curDistGrid->setBBMin(bbmin);
00901                 curDistGrid->setBBMax(bbmax);
00902                 grid->setActive(true);
00903             }
00904             newmotion = true;
00905         }
00906         }
00907         
00908         if (newmotion)
00909         {
00910             Mat3x3f rotation;
00911             Vec3f translation;
00912             if (matrixLastIt != -20)
00913             {
00914                 rotation = matrix;
00915                 translation = matrix.col(3);
00916             }
00917             else rotation.identity();
00918             double dt = 0;
00919             if (computeV.getValue() && grid->getGrid(0) != emptyGrid)
00920                 dt = (motionLastTime == -1000 || motionLastTime >= time) ? 1 : time-motionLastTime;
00921             grid->setNewState(0,dt,curDistGrid, rotation, translation);
00922             motionLastTime = time;
00923         }
00924     }
00925 };
00926 
00927 SOFA_DECL_CLASS(FlowVRInputDistanceGrid)
00928 int FlowVRInputDistanceGridClass = sofa::core::RegisterObject("Import a distance field from a FlowVR InputPort")
00929 .add< FlowVRInputDistanceGrid<sofa::component::collision::RigidDistanceGridCollisionModel,sofa::component::collision::DistanceGrid> >()
00930 #ifdef SOFA_GPU_CUDA
00931 .add< FlowVRInputDistanceGrid<sofa::gpu::cuda::CudaRigidDistanceGridCollisionModel,sofa::gpu::cuda::CudaDistanceGrid> >()
00932 #endif
00933 ;
00934 
00935 class FlowVRRenderEvent : public FlowVREvent
00936 {
00937 public:
00938     virtual ~FlowVRRenderEvent() {}
00939 };
00940 
00941 class FlowVRRenderInitEvent : public FlowVRRenderEvent
00942 {
00943 public:
00944     virtual ~FlowVRRenderInitEvent() {}
00945     flowvr::render::ChunkRenderWriter* scene;
00946     bool* scratch;
00947 };
00948 
00949 class FlowVRRenderUpdateEvent : public FlowVRRenderEvent
00950 {
00951 public:
00952     virtual ~FlowVRRenderUpdateEvent() {}
00953     flowvr::render::ChunkRenderWriter* scene;
00954     bool* scratch;
00955 };
00956 
00957 std::vector<flowvr::ID> prevP;
00958 std::map<std::string,flowvr::ID> prevVS;
00959 std::map<std::string,flowvr::ID> prevPS;
00960 std::map<std::string,flowvr::ID> prevVB;
00961 std::map<std::string,flowvr::ID> prevIB;
00962 std::map<std::string,flowvr::ID> prevT;
00963 std::map<std::string,flowvr::ID> prevNM;
00964 
00965 class FlowVRRenderObject : public FlowVRObject
00966 {
00967 public:
00968 void clearSharedResources(flowvr::render::ChunkRenderWriter* scene)
00969 {
00970     for(std::vector<flowvr::ID>::const_iterator it = prevP.begin(), itend = prevP.end(); it != itend; ++it)
00971         scene->delPrimitive(*it);
00972     prevP.clear();
00973     for(std::map<std::string,flowvr::ID>::const_iterator it = prevVS.begin(), itend = prevVS.end(); it != itend; ++it)
00974         scene->delVertexShader(it->second);
00975     prevVS.clear();
00976     for(std::map<std::string,flowvr::ID>::const_iterator it = prevPS.begin(), itend = prevPS.end(); it != itend; ++it)
00977         scene->delPixelShader(it->second);
00978     prevPS.clear();
00979     for(std::map<std::string,flowvr::ID>::const_iterator it = prevVB.begin(), itend = prevVB.end(); it != itend; ++it)
00980         scene->delVertexBuffer(it->second);
00981     prevVB.clear();
00982     for(std::map<std::string,flowvr::ID>::const_iterator it = prevIB.begin(), itend = prevIB.end(); it != itend; ++it)
00983         scene->delIndexBuffer(it->second);
00984     prevIB.clear();
00985     for(std::map<std::string,flowvr::ID>::const_iterator it = prevT.begin(), itend = prevT.end(); it != itend; ++it)
00986         scene->delTexture(it->second);
00987     prevT.clear();
00988     for(std::map<std::string,flowvr::ID>::const_iterator it = prevNM.begin(), itend = prevNM.end(); it != itend; ++it)
00989         scene->delTexture(it->second);
00990     prevNM.clear();
00991 }
00992 
00993 flowvr::ID loadSharedTexture(flowvr::render::ChunkRenderWriter* scene, const char* filename)
00994 {
00995     flowvr::ID& id = prevT[filename];
00996     if (!id)
00997     {
00998         id = mod->module->generateID();
00999         flowvr::render::ChunkTexture* t = scene->loadTexture(id, filename);
01000         if (t)
01001             std::cout << "FlowVR Render: loaded " << t->nx << "x" << t->ny << "x" << ftl::Type::nx(t->pixelType)*(ftl::Type::elemSize(t->pixelType)==0?1:8*ftl::Type::elemSize(t->pixelType)) << " texture " << filename << std::endl;
01002     }
01003     return id;
01004 }
01005 
01006 flowvr::ID loadSharedTextureNormalMap(flowvr::render::ChunkRenderWriter* scene, const char* filename)
01007 {
01008     flowvr::ID& id = prevNM[filename];
01009     if (!id)
01010     {
01011         id = mod->module->generateID();
01012         flowvr::render::ChunkTexture* t = scene->loadTextureNormalMap(id, filename);
01013         if (t)
01014         {
01015             std::cout << "FlowVR Render: loaded " << t->nx << "x" << t->ny << "x" << ftl::Type::nx(t->pixelType)*(ftl::Type::elemSize(t->pixelType)==0?1:8*ftl::Type::elemSize(t->pixelType)) << " normal map " << filename << std::endl;
01016             std::string outname(filename,strrchr(filename,'.')?strrchr(filename,'.'):filename+strlen(filename));
01017             outname+="-NM.png";
01018             scene->saveTexture(t,outname.c_str());
01019         }
01020     }
01021     return id;
01022 }
01023 
01024 flowvr::ID loadSharedVertexShader(flowvr::render::ChunkRenderWriter* scene, const std::string& filename, const std::string& predefs="")
01025 {
01026     flowvr::ID& id = prevVS[filename+"\n"+predefs];
01027     if (!id)
01028     {
01029         id = mod->module->generateID();
01030         scene->loadVertexShader(id, filename, (predefs.empty()?NULL:predefs.c_str()));
01031     }
01032     return id;
01033 }
01034 
01035 flowvr::ID loadSharedPixelShader(flowvr::render::ChunkRenderWriter* scene, const std::string& filename, const std::string& predefs="")
01036 {
01037     flowvr::ID& id = prevPS[filename+"\n"+predefs];
01038     if (!id)
01039     {
01040         id = mod->module->generateID();
01041         scene->loadPixelShader(id, filename, (predefs.empty()?NULL:predefs.c_str()));
01042     }
01043     return id;
01044 }
01045 
01046 flowvr::ID addVertexBuffer(flowvr::render::ChunkRenderWriter* /*scene*/)
01047 {
01048     static int count = 0;
01049     char buf[16];
01050     sprintf(buf,"default%d",count);
01051     ++count;
01052     flowvr::ID& id = prevVB[buf];
01053     if (!id)
01054     {
01055         id = mod->module->generateID();
01056     }
01057     return id;
01058 }
01059 
01060 flowvr::ID addIndexBuffer(flowvr::render::ChunkRenderWriter* /*scene*/)
01061 {
01062     static int count = 0;
01063     char buf[16];
01064     sprintf(buf,"default%d",count);
01065     ++count;
01066     flowvr::ID& id = prevIB[buf];
01067     if (!id)
01068     {
01069         id = mod->module->generateID();
01070     }
01071     return id;
01072 }
01073 
01074 flowvr::ID addPrimitive(flowvr::render::ChunkRenderWriter* scene, const char* name)
01075 {
01076     flowvr::ID id = mod->module->generateID();
01077     prevP.push_back(id);
01078     scene->addPrimitive(id, name);
01079     return id;
01080 }
01081 
01082 
01083 
01084 
01085 
01086     virtual void flowvrRenderInit(flowvr::render::ChunkRenderWriter* /*scene*/, bool* /*scratch*/)
01087     {
01088     }
01089 
01090     virtual void flowvrRenderUpdate(flowvr::render::ChunkRenderWriter* /*scene*/, bool* /*scratch*/)
01091     {
01092     }
01093 
01094     virtual void handleEvent(sofa::core::objectmodel::Event* event)
01095     {
01096         FlowVRObject::handleEvent(event);
01097         if (dynamic_cast<FlowVRRenderEvent*>(event))
01098         {
01099             if (FlowVRRenderInitEvent* ev = dynamic_cast<FlowVRRenderInitEvent*>(event))
01100           flowvrRenderInit(ev->scene, ev->scratch);
01101             if (FlowVRRenderUpdateEvent* ev = dynamic_cast<FlowVRRenderUpdateEvent*>(event))
01102                 flowvrRenderUpdate(ev->scene, ev->scratch);
01103         }
01104     }
01105 };
01106 
01107 class FlowVRRenderWriter : public FlowVRRenderObject
01108 {
01109 public:
01110     flowvr::render::SceneOutputPort* pOutScene;
01111     flowvr::render::ChunkRenderWriter scene;
01112     bool init;
01113     bool scratch;
01114     FlowVRRenderWriter()
01115     : pOutScene(createSceneOutputPort()), init(false), scratch(false)
01116     {
01117         clearSharedResources(&scene);
01118     }
01119     
01120     virtual void flowvrPreInit(std::set<flowvr::Port*>* ports)
01121     {
01122         std::cout << "Received FlowVRPreInit"<<std::endl;
01123         ports->insert(pOutScene);
01124     }
01125     
01126     virtual void flowvrBeginIteration(flowvr::ModuleAPI* /*module*/)
01127     {
01128         if (!init)
01129         {
01130             FlowVRRenderInitEvent ev;
01131         ev.from = mod;
01132             ev.scene = &scene;
01133         ev.scratch = &scratch;
01134             getContext()->propagateEvent(&ev);
01135             init = true;
01136         }
01137     }
01138     
01139     virtual void flowvrEndIteration(flowvr::ModuleAPI* /*module*/)
01140     {
01141         FlowVRRenderUpdateEvent ev;
01142     ev.from = mod;
01143         ev.scene = &scene;
01144     ev.scratch = &scratch;
01145         getContext()->propagateEvent(&ev);
01146         scene.put(pOutScene, scratch);
01147     scratch = true;
01148     }
01149 
01150     virtual void flowvrInit(flowvr::ModuleAPI* module)
01151     {
01152         FlowVRRenderObject::flowvrInit(module);
01153         if (!init)
01154         {
01155         //FlowVRRenderInitEvent ev;
01156         //ev.from = mod;
01157             //ev.scene = &scene;
01158             //getContext()->propagateEvent(&ev);
01159         scene.put(pOutScene);
01160             //init = true;
01161         }
01162     }
01163     
01164 };
01165 
01166 SOFA_DECL_CLASS(FlowVRRenderWriter)
01167 int FlowVRRenderWriterClass = sofa::core::RegisterObject("FlowVRRender scene manager")
01168 .add<FlowVRRenderWriter>()
01169 ;
01170 
01171 class FlowVRRenderVisualModel : public FlowVRRenderObject//, public sofa::core::VisualModel
01172 {
01173 protected:
01174     flowvr::render::ChunkRenderWriter* scene;
01175     bool *scratch;
01176     flowvr::ModuleAPI* module;
01177 public:
01178     FlowVRRenderVisualModel()
01179     : scene(NULL), scratch(NULL), module(NULL)
01180     {
01181     }
01182     
01183     virtual void renderInit() = 0;
01184     virtual void renderUpdate()= 0;
01185     
01186     void flowvrInit(flowvr::ModuleAPI* module)
01187     {
01188         this->module = module;
01189     if (this->scene!=NULL)
01190             renderInit();
01191     }
01192     //void flowvrRenderInit(flowvr::render::ChunkRenderWriter* scene)
01193     void flowvrRenderInit(flowvr::render::ChunkRenderWriter* scene, bool* scratch)
01194     {
01195         this->scene = scene;
01196         this->scratch = scratch;
01197     if (this->module!=NULL)
01198             renderInit();
01199     }
01200     void flowvrRenderUpdate(flowvr::render::ChunkRenderWriter* scene, bool* scratch)
01201     {
01202     if (this->scene == NULL)
01203     {
01204         std::cout << "LIVE creation of FlowVRRenderVisualModel detected."<<std::endl;
01205         this->module = mod->module;
01206         flowvrRenderInit(scene, scratch);
01207     }
01208         renderUpdate();
01209     }
01210     
01211     /*
01212     void initTextures()
01213     {
01214     }
01215     
01216     void update()
01217     {
01218         //if (scene!=NULL)
01219         //    renderUpdate();
01220     }
01221     
01222     void draw()
01223     {
01224     }
01225     */
01226 };
01227 
01228 class FlowVRRenderMesh : public FlowVRRenderVisualModel, public sofa::component::visualmodel::OglModel //VisualModelImpl
01229 {
01230 public:
01231     typedef sofa::component::visualmodel::OglModel Inherit;
01232     typedef Inherit::VecCoord VecCoord;
01233     typedef Inherit::Coord Coord;
01234 
01235     Data<std::string> vShader;
01236     Data<std::string> pShader;
01237     Data<bool> useTangent;
01238     std::string texture;
01239     
01240     std::map<std::string,std::string> paramT;
01241     std::map<std::string,std::string> paramNM;
01242     std::map<std::string,std::string> paramVS;
01243     std::map<std::string,std::string> paramPS;
01244 
01245     flowvr::ID idP;
01246     flowvr::ID idVB;
01247     flowvr::ID idVBN;
01248     flowvr::ID idVBT;
01249     flowvr::ID idVBTangent;
01250     flowvr::ID idIB;
01251     flowvr::ID idVS;
01252     flowvr::ID idPS;
01253     flowvr::ID idTex;
01254     
01255     bool posModified;
01256     bool normModified;
01257     bool meshModified;
01258 
01259     int lastPosRev;
01260     int lastNormRev;
01261 
01262     FlowVRRenderMesh()
01263     : vShader(initData(&vShader, std::string(""), "vshader", "vertex shader name"))
01264     , pShader(initData(&pShader, std::string(""), "pshader", "pixel shader name"))
01265     , useTangent(initData(&useTangent, false, "useTangent", "enable computation of texture tangent space vectors (for normal mapping)"))
01266 //    , color(initData(&color, Vec4f(1, 1, 1, 0.5f), "color", "RGBA color value"))
01267 //    , topology(NULL)
01268 //    , mmodel(NULL)
01269     , idP(0)
01270     , idVB(0)
01271     , idVBN(0)
01272     , idVBT(0)
01273     , idVBTangent(0)
01274     , idIB(0)
01275     , idVS(0)
01276     , idPS(0)
01277     , idTex(0)
01278     , posModified(true)
01279     , meshModified(true)
01280 //    , lastMeshRev(-1)
01281     , lastPosRev(-1)
01282     {
01283     }
01284 
01285     void parse(sofa::core::objectmodel::BaseObjectDescription* arg)
01286     {
01287         this->sofa::component::visualmodel::OglModel::parse(arg);
01288         std::vector<std::string> params;
01289         arg->getAttributeList(params);
01290         for (unsigned int i=0; i<params.size(); ++i)
01291         {
01292             const char* name = params[i].c_str();
01293             if (!strncmp(name,"tex_",4))
01294             {
01295                 std::string filename = arg->getAttribute(name);
01296                 sofa::helper::system::DataRepository.findFile(filename);
01297                 paramT[name+4] = filename;
01298             }
01299             if (!strncmp(name,"bump_",5))
01300             {
01301                 std::string filename = arg->getAttribute(name);
01302                 sofa::helper::system::DataRepository.findFile(filename);
01303                 paramNM[name+5] = filename;
01304                 useTangent.setValue(true);
01305             }
01306             else if (!strncmp(name,"ps_",3))
01307             {
01308                 paramPS[name+3] = arg->getAttribute(name);
01309             }
01310             else if (!strncmp(name,"vs_",3))
01311             {
01312                 paramVS[name+3] = arg->getAttribute(name);
01313             }
01314         }
01315     }
01316     
01317     virtual bool loadTexture(const std::string& filename)
01318     {
01319         texture = filename;
01320         sofa::helper::system::DataRepository.findFile(texture);
01321         Inherit::loadTexture(filename);
01322         return true;
01323     }
01324 
01325     void renderInit()
01326     {
01327     }
01328 
01329     void init()
01330     {
01331         VisualModelImpl::init();
01332     }
01333 
01334     void computePositions()
01335     {
01336         Inherit::computePositions();
01337         posModified = true;
01338     }
01339 
01340     void computeNormals()
01341     {
01342         Inherit::computeNormals();
01343         //normModified = true;
01344     }
01345 
01346     void computeMesh(sofa::core::componentmodel::topology::BaseMeshTopology* topology)
01347     {
01348         Inherit::computeMesh(topology);
01349         meshModified = true;
01350     }
01351 
01352     void renderUpdate()
01353     {
01354         if (!idP)
01355     {
01356             *scratch = false;
01357             idP = addPrimitive(scene, getName().c_str());
01358 
01359             std::string predefs;
01360             bool useSpecular = material.getValue().useSpecular && material.getValue().shininess > 0.0001 && (material.getValue().specular[0] > 0.0001 || material.getValue().specular[1] > 0.0001 || material.getValue().specular[2] > 0.0001);
01361             if (useSpecular)
01362                 predefs += "#define SPECULAR 1\n";
01363 
01364             const char* vshader;
01365             if (!vShader.getValue().empty())
01366                 vshader = vShader.getValue().c_str();
01367             else if (!texture.empty() && useTangent.getValue())
01368                 vshader = "shaders/obj_color_tangent_v.cg";
01369             else if (!texture.empty())
01370                 vshader = "shaders/obj_color_v.cg";
01371             else
01372                 vshader = "shaders/obj_v.cg";
01373 
01374             idVS = loadSharedVertexShader(scene, vshader, predefs);
01375             scene->addParamID(idP, flowvr::render::ChunkPrimParam::VSHADER, "", idVS);
01376 
01377             const char* pshader;
01378             if (!pShader.getValue().empty())
01379                 pshader = pShader.getValue().c_str();
01380             else if (!texture.empty() && useTangent.getValue())
01381                 pshader = "shaders/obj_mat_color_tangent_p.cg";
01382             else if (!texture.empty())
01383                 pshader = "shaders/obj_mat_color_p.cg";
01384             else
01385                 pshader = "shaders/obj_mat_p.cg";
01386 
01387             idPS = loadSharedPixelShader(scene, pshader, predefs);
01388             scene->addParamID(idP, flowvr::render::ChunkPrimParam::PSHADER, "", idPS);
01389 
01390             if (!texture.empty())
01391             {
01392                 idTex = loadSharedTexture(scene,texture.c_str());
01393                 scene->addParamID(idP, flowvr::render::ChunkPrimParam::TEXTURE, "texcolor", idTex);
01394             }
01395             ftl::Vec4f ambient  ( 0.3f, 0.3f, 0.3f, 1.0f);
01396             ftl::Vec3f diffuse  ( 0.6f, 0.6f, 0.6f);
01397             ftl::Vec4f specular ( 0.9f, 0.9f, 0.9f, 16.0f);
01398             if (material.getValue().useAmbient) for (int i=0;i<3;i++) ambient[i] = (float)material.getValue().ambient[i] * 0.5f;
01399             ambient[3] = material.getValue().diffuse[3]; // alpha
01400             if (material.getValue().useDiffuse) for (int i=0;i<3;i++) diffuse[i] = (float)material.getValue().diffuse[i];
01401             if (material.getValue().useSpecular) for (int i=0;i<3;i++) specular[i] = (float)material.getValue().specular[i];
01402             specular[3] = material.getValue().shininess;
01403             //scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMVSHADER, "color", color); //ftl::Vec4f(1, 1, 1, 0.5));
01404             scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMPSHADER, "mat_ambient" , ambient );
01405             scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMPSHADER, "mat_diffuse" , diffuse );
01406             if (useSpecular)
01407                 scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMPSHADER, "mat_specular", specular);
01408 
01409         if (ambient[3] < 1.0)
01410         { // enable alpha blending
01411         scene->addParam(idP,flowvr::render::ChunkPrimParam::PARAMOPENGL,"Blend",true);
01412         scene->addParam(idP,flowvr::render::ChunkPrimParam::ORDER,"",1);
01413         scene->addParam(idP,flowvr::render::ChunkPrimParam::PARAMOPENGL,"DepthWrite",false);        
01414         }
01415 
01416             // add user-defined textures
01417             for (std::map<std::string,std::string>::const_iterator it = paramT.begin(), itend = paramT.end(); it != itend; ++it)
01418             {
01419                 scene->addParamID(idP, flowvr::render::ChunkPrimParam::TEXTURE, it->first.c_str(), loadSharedTexture(scene,it->second.c_str()));
01420             }
01421             for (std::map<std::string,std::string>::const_iterator it = paramNM.begin(), itend = paramNM.end(); it != itend; ++it)
01422             {
01423                 scene->addParamID(idP, flowvr::render::ChunkPrimParam::TEXTURE, it->first.c_str(), loadSharedTextureNormalMap(scene,it->second.c_str()));
01424             }
01425 
01426             // add user-defined params
01427 
01428             for (std::map<std::string,std::string>::const_iterator it = paramVS.begin(), itend = paramVS.end(); it != itend; ++it)
01429             {
01430                 float vals[4] = {0,0,0,0};
01431                 int n = sscanf(it->second.c_str(),"%f %f %f %f",&vals[0],&vals[1],&vals[2],&vals[3]);
01432                 if (n==4)
01433                     scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMVSHADER, it->first.c_str(), ftl::Vec4f(vals));
01434                 else if (n==3)
01435                     scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMVSHADER, it->first.c_str(), ftl::Vec3f(vals));
01436                 else if (n==2)
01437                     scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMVSHADER, it->first.c_str(), ftl::Vec2f(vals));
01438                 else if (n==1)
01439                     scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMVSHADER, it->first.c_str(), vals[0]);
01440                 else
01441                 {
01442                     std::cerr << "ERROR: vertex shader parameter "<<it->first<<": cannot parse value "<<it->second<<std::endl;
01443                 }
01444             }
01445 
01446             for (std::map<std::string,std::string>::const_iterator it = paramPS.begin(), itend = paramPS.end(); it != itend; ++it)
01447             {
01448                 float vals[4] = {0,0,0,0};
01449                 int n = sscanf(it->second.c_str(),"%f %f %f %f",&vals[0],&vals[1],&vals[2],&vals[3]);
01450                 if (n==4)
01451                     scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMPSHADER, it->first.c_str(), ftl::Vec4f(vals));
01452                 else if (n==3)
01453                     scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMPSHADER, it->first.c_str(), ftl::Vec3f(vals));
01454                 else if (n==2)
01455                     scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMPSHADER, it->first.c_str(), ftl::Vec2f(vals));
01456                 else if (n==1)
01457                     scene->addParam(idP, flowvr::render::ChunkPrimParam::PARAMPSHADER, it->first.c_str(), vals[0]);
01458                 else
01459                 {
01460                     std::cerr << "ERROR: vertex shader parameter "<<it->first<<": cannot parse value "<<it->second<<std::endl;
01461                 }
01462             }
01463 
01464         // SOFA = trans + scale * FLOWVR
01465         // FLOWVR = SOFA * 1/scale - trans * 1/scale
01466 
01467             const Vec3f trans = mod->f_trans.getValue();
01468             const float scale = mod->f_scale.getValue();
01469         const float inv_scale = 1/scale;
01470 
01471         scene->addParam(idP, flowvr::render::ChunkPrimParam::TRANSFORM_POSITION, "", ftl::Vec3f(trans.ptr())*(-inv_scale));
01472         scene->addParam(idP, flowvr::render::ChunkPrimParam::TRANSFORM_SCALE, "", ftl::Vec3f(inv_scale,inv_scale,inv_scale));
01473         }
01474         if (posModified)
01475         {
01476             if (!idVB)
01477             {
01478                 *scratch = false;
01479                 idVB = addVertexBuffer(scene);
01480                 scene->addParamID(idP, flowvr::render::ChunkPrimParam::VBUFFER_ID, "position", idVB);
01481                 scene->addParam(idP, flowvr::render::ChunkPrimParam::VBUFFER_NUMDATA, "position", 0);
01482             }
01483             const VecCoord& x = vertices;
01484             int types[1] = { ftl::Type::get(x[0]) };
01485             flowvr::render::BBox bb(ftl::Vec3f(bbox[0].ptr()),ftl::Vec3f(bbox[1].ptr()));
01486             flowvr::render::ChunkVertexBuffer* vb = scene->addVertexBuffer(idVB, x.size(), 1, types, bb);
01487             vb->gen = ++lastPosRev;
01488             memcpy(vb->data(), &(x[0]), vb->dataSize());
01489             posModified = false;
01490 
01491             const VecCoord& n = vnormals;
01492             if (!n.empty())
01493             {
01494                 if (!idVBN)
01495                 {
01496                     *scratch = false;
01497                     //idVBN = module->generateID();
01498                     idVBN = addVertexBuffer(scene);
01499                     scene->addParamID(idP, flowvr::render::ChunkPrimParam::VBUFFER_ID, "normal", idVBN);
01500                     scene->addParam(idP, flowvr::render::ChunkPrimParam::VBUFFER_NUMDATA, "normal", 0);
01501                 }
01502                 int types[1] = { ftl::Type::get(n[0]) };
01503                 flowvr::render::ChunkVertexBuffer* vb = scene->addVertexBuffer(idVBN, n.size(), 1, types, bb);
01504                 vb->gen = lastPosRev;
01505                 memcpy(vb->data(), &(n[0]), vb->dataSize());
01506             }
01507 
01508             const ResizableExtVector<TexCoord>& t = vtexcoords;
01509             if (!t.empty() && !idVBT) // only send texcoords once
01510             {
01511                 if (!idVBT)
01512                 {
01513                     *scratch = false;
01514                     //idVBT = module->generateID();
01515                     idVBT = addVertexBuffer(scene);
01516                     scene->addParamID(idP, flowvr::render::ChunkPrimParam::VBUFFER_ID, "texcoord0", idVBT);
01517                     scene->addParam(idP, flowvr::render::ChunkPrimParam::VBUFFER_NUMDATA, "texcoord0", 0);
01518                 }
01519                 int types[1] = { ftl::Type::get(t[0]) };
01520                 flowvr::render::ChunkVertexBuffer* vb = scene->addVertexBuffer(idVBT, n.size(), 1, types, bb);
01521                 //vb->gen = lastPosRev;
01522                 memcpy(vb->data(), &(t[0]), vb->dataSize());
01523             }
01524 
01525             if (!n.empty() && !t.empty() && useTangent.getValue())
01526             {
01527                 if (!idVBTangent)
01528                 {
01529                     *scratch = false;
01530                     idVBTangent = addVertexBuffer(scene);
01531                     scene->addParamID(idP, flowvr::render::ChunkPrimParam::VBUFFER_ID, "tangent", idVBTangent);
01532                     scene->addParam(idP, flowvr::render::ChunkPrimParam::VBUFFER_NUMDATA, "tangent", 0);
01533                 }
01534 
01535                 ResizableExtVector<Vec4f> tangent; tangent.resize(t.size());
01536                 ResizableExtVector<Coord> tangent1; tangent1.resize(t.size());
01537                 ResizableExtVector<Coord> tangent2; tangent2.resize(t.size());
01538                 
01539                 // see http://www.terathon.com/code/tangent.php
01540                 
01541                 for (unsigned int i=0;i<triangles.size();i++)
01542                 {
01543                     int i1 = triangles[i][0];
01544                     int i2 = triangles[i][1];
01545                     int i3 = triangles[i][2];
01546                     
01547                     const Coord& v1 = x[i1];
01548                     const Coord& v2 = x[i2];
01549                     const Coord& v3 = x[i3];
01550                     
01551                     const TexCoord& w1 = t[i1];
01552                     const TexCoord& w2 = t[i2];
01553                     const TexCoord& w3 = t[i3];
01554                     
01555                     float x1 = v2[0] - v1[0];
01556                     float x2 = v3[0] - v1[0];
01557                     float y1 = v2[1] - v1[1];
01558                     float y2 = v3[1] - v1[1];
01559                     float z1 = v2[2] - v1[2];
01560                     float z2 = v3[2] - v1[2];
01561                     
01562                     float s1 = w2[0] - w1[0];
01563                     float s2 = w3[0] - w1[0];
01564                     float t1 = w2[1] - w1[1];
01565                     float t2 = w3[1] - w1[1];
01566                     
01567                     float r = 1.0f / (s1 * t2 - s2 * t1);
01568                     Coord sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
01569                     Coord tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
01570                     
01571                     tangent1[i1] += sdir;
01572                     tangent1[i2] += sdir;
01573                     tangent1[i3] += sdir;
01574                     
01575                     tangent2[i1] += tdir;
01576                     tangent2[i2] += tdir;
01577                     tangent2[i3] += tdir;
01578                 }
01579                 
01580                 for (unsigned int i=0;i<quads.size();i++)
01581                 {
01582                     int i1 = quads[i][0];
01583                     int i2 = quads[i][1];
01584                     int i3 = quads[i][2];
01585                     int i4 = quads[i][3];
01586                     
01587                     const Coord& v1 = x[i1];
01588                     const Coord& v2 = x[i2];
01589                     const Coord& v3 = x[i3];
01590                     const Coord& v4 = x[i4];
01591                     
01592                     const TexCoord& w1 = t[i1];
01593                     const TexCoord& w2 = t[i2];
01594                     const TexCoord& w3 = t[i3];
01595                     const TexCoord& w4 = t[i4];
01596                     
01597                     // triangle i1 i2 i3
01598                     {
01599                         float x1 = v2[0] - v1[0];
01600                         float x2 = v3[0] - v1[0];
01601                         float y1 = v2[1] - v1[1];
01602                         float y2 = v3[1] - v1[1];
01603                         float z1 = v2[2] - v1[2];
01604                         float z2 = v3[2] - v1[2];
01605                         
01606                         float s1 = w2[0] - w1[0];
01607                         float s2 = w3[0] - w1[0];
01608                         float t1 = w2[1] - w1[1];
01609                         float t2 = w3[1] - w1[1];
01610                         
01611                         float r = 1.0f / (s1 * t2 - s2 * t1);
01612                         Coord sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
01613                         Coord tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
01614                         
01615                         tangent1[i1] += sdir;
01616                         tangent1[i2] += sdir;
01617                         tangent1[i3] += sdir;
01618                         
01619                         tangent2[i1] += tdir;
01620                         tangent2[i2] += tdir;
01621                         tangent2[i3] += tdir;
01622                     }
01623                     
01624                     // triangle i1 i3 i4
01625                     {
01626                         float x1 = v3[0] - v1[0];
01627                         float x2 = v4[0] - v1[0];
01628                         float y1 = v3[1] - v1[1];
01629                         float y2 = v4[1] - v1[1];
01630                         float z1 = v3[2] - v1[2];
01631                         float z2 = v4[2] - v1[2];
01632                         
01633                         float s1 = w3[0] - w1[0];
01634                         float s2 = w4[0] - w1[0];
01635                         float t1 = w3[1] - w1[1];
01636                         float t2 = w4[1] - w1[1];
01637                         
01638                         float r = 1.0f / (s1 * t2 - s2 * t1);
01639                         Coord sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
01640                         Coord tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
01641                         
01642                         tangent1[i1] += sdir;
01643                         tangent1[i3] += sdir;
01644                         tangent1[i4] += sdir;
01645                         
01646                         tangent2[i1] += tdir;
01647                         tangent2[i3] += tdir;
01648                         tangent2[i4] += tdir;
01649                     }
01650                 }
01651                 
01652                 for (unsigned int i=0;i<tangent.size();i++)
01653                 {
01654                     const Coord& normal = n[i];
01655                     Coord t1 = tangent1[i];
01656                     // Gram-Schmidt orthogonalize
01657                     t1 -= normal * ( normal * t1 );
01658                     t1.normalize();
01659                     tangent[i] = t1;
01660                     // Calculate handedness
01661                     tangent[i][3] = ((normal.cross(t1) * tangent2[i]) < 0.0f) ? -1.0f : 1.0f;
01662                 }
01663                 
01664                 int types[1] = { ftl::Type::get(tangent[0]) };
01665                 flowvr::render::ChunkVertexBuffer* vb = scene->addVertexBuffer(idVBTangent, tangent.size(), 1, types, bb);
01666                 vb->gen = lastPosRev;
01667                 memcpy(vb->data(), &(tangent[0]), vb->dataSize());
01668             }
01669         }
01670         if (meshModified)
01671         {
01672             if (!idIB)
01673             {
01674                 *scratch = false;
01675                 //idIB = module->generateID();
01676                 idIB = addIndexBuffer(scene);
01677                 scene->addParamID(idP, flowvr::render::ChunkPrimParam::IBUFFER_ID, "", idIB);
01678             }
01679             if (quads.empty())
01680             { // only triangles
01681                 flowvr::render::ChunkIndexBuffer* ib = scene->addIndexBuffer(idIB, triangles.size()*3, ftl::Type::Int, flowvr::render::ChunkIndexBuffer::Triangle);
01682                 ib->gen = lastMeshRev;
01683                 memcpy(ib->data(), &(triangles[0]), ib->dataSize());
01684             }
01685             else if (triangles.empty())
01686             { // only quads
01687                 flowvr::render::ChunkIndexBuffer* ib = scene->addIndexBuffer(idIB, quads.size()*4, ftl::Type::Int, flowvr::render::ChunkIndexBuffer::Quad);
01688                 ib->gen = lastMeshRev;
01689                 memcpy(ib->data(), &(quads[0]), ib->dataSize());
01690             }
01691             else
01692             { // both triangles and quads -> convert all to triangles
01693                 flowvr::render::ChunkIndexBuffer* ib = scene->addIndexBuffer(idIB, triangles.size()*3 + quads.size()*6, ftl::Type::Int, flowvr::render::ChunkIndexBuffer::Triangle);
01694                 ib->gen = lastMeshRev;
01695                 memcpy(ib->data(), &(triangles[0]), triangles.size()*3*sizeof(int));
01696                 int* dest = ((int*)ib->data()) + triangles.size()*3;
01697                 for (unsigned int i=0;i<quads.size();i++)
01698                 {
01699                     *(dest++) = quads[i][0];
01700                     *(dest++) = quads[i][1];
01701                     *(dest++) = quads[i][2];
01702                     *(dest++) = quads[i][0];
01703                     *(dest++) = quads[i][2];
01704                     *(dest++) = quads[i][3];
01705                 }
01706             }
01707             meshModified = false;
01708         }
01709         if (xformsModified)
01710         {
01711             Vec3f position = xforms[0].getCenter();
01712             Quatf rotation = xforms[0].getOrientation();
01713 
01714             Mat4x4f matrix;
01715             matrix.identity();
01716             rotation.toMatrix(matrix);
01717             matrix[0][3] = position[0];
01718             matrix[1][3] = position[1];
01719             matrix[2][3] = position[2];
01720 
01721             // SOFA = trans + scale * FLOWVR
01722             // FLOWVR = (SOFA - trans) * 1/scale
01723             // FLOWVR = SOFA * 1/scale - trans * 1/scale
01724 
01725             Vec3f trans = mod->f_trans.getValue();
01726             const float scale = mod->f_scale.getValue();
01727             const float inv_scale = 1/scale;
01728 
01729             matrix[0][3] -= trans[0];
01730             matrix[1][3] -= trans[1];
01731             matrix[2][3] -= trans[2];
01732 
01733             matrix *= inv_scale;
01734 
01735             // TODO: use xforms
01736             //scene->addParam(idP, flowvr::render::ChunkPrimParam::TRANSFORM_POSITION, "", ftl::Vec3f(trans.ptr())*(-inv_scale));
01737             //scene->addParam(idP, flowvr::render::ChunkPrimParam::TRANSFORM_SCALE, "", ftl::Vec3f(inv_scale,inv_scale,inv_scale));
01738             scene->addParam(idP, flowvr::render::ChunkPrimParam::TRANSFORM, "", ftl::Mat4x4f(matrix.ptr()));
01739 
01740             xformsModified = false;
01741         }
01742     }
01743 };
01744 
01745 SOFA_DECL_CLASS(FlowVRRenderMesh)
01746 int FlowVRRenderMeshClass = sofa::core::RegisterObject("FlowVRRender Visual Model")
01747 .add< FlowVRRenderMesh >()
01748 ;
01749 
01750 } // namespace SofaFlowVR
01751 
01752 
01753 #ifndef WIN32
01754 #include <dlfcn.h>
01755 bool loadPlugin(const char* filename)
01756 {
01757   void *handle;
01758   handle=dlopen(filename, RTLD_LAZY);
01759   if (!handle)
01760   { 
01761     std::cerr<<"Error loading plugin "<<filename<<": "<<dlerror()<<std::endl; 
01762     return false;
01763   } 
01764   std::cerr<<"Plugin "<<filename<<" loaded."<<std::endl;
01765   return true;
01766 }
01767 #else
01768 bool loadPlugin(const char* filename)
01769 {
01770     std::cerr << "Plugin loading not supported on this platform.\n";
01771     return false;
01772 }
01773 #endif
01774 
01775 
01776 int main(int argc, char** argv)
01777 {
01778     sofa::helper::BackTrace::autodump();
01779 
01780     glutInit(&argc,argv);
01781 
01782     sofa::gui::SofaGUI::SetProgramName(argv[0]);
01783     std::string fileName ;
01784     bool        startAnim = false;
01785     bool        printFactory = false;
01786     std::string gui = sofa::gui::SofaGUI::GetGUIName();
01787     std::vector<std::string> plugins;
01788     std::vector<std::string> files; 
01789     
01790     std::string gui_help = "choose the UI (";
01791     gui_help += sofa::gui::SofaGUI::ListSupportedGUI('|');
01792     gui_help += ")";
01793 
01794     sofa::helper::parse(&files, "This is a SOFA application. Here are the command line arguments")
01795 //  .option(&fileName,'f',"file","scene file")
01796     .option(&startAnim,'s',"start","start the animation loop")
01797     .option(&printFactory,'p',"factory","print factory logs")
01798     //.option(&nogui,'g',"nogui","use no gui, run a number of iterations and exit")
01799     .option(&gui,'g',"gui",gui_help.c_str())
01800     .option(&plugins,'l',"load","load given plugins")
01801     (argc,argv);
01802 
01803     sofa::component::init();
01804 
01805     if (!files.empty()) fileName = files[0];
01806 
01807     for (unsigned int i=0;i<plugins.size();i++)
01808         loadPlugin(plugins[i].c_str());
01809 
01810     if (printFactory)
01811     {
01812         std::cout << "////////// FACTORY //////////" << std::endl;
01813         sofa::helper::printFactoryLog();
01814         std::cout << "//////// END FACTORY ////////" << std::endl;  
01815     }
01816 
01817     if (int err=sofa::gui::SofaGUI::Init(argv[0],gui.c_str()))
01818         return err;
01819 
01820     sofa::simulation::tree::GNode* groot = NULL; 
01821 
01822     if (fileName.empty())
01823     {
01824         fileName = "liver.scn"; 
01825         sofa::helper::system::DataRepository.findFile(fileName);
01826     }
01827 
01828     sofa::core::ObjectFactory::ClassEntry* classVisualModel;
01829     sofa::core::ObjectFactory::AddAlias("VisualModel", "FlowVRRenderMesh", true, &classVisualModel); 
01830     groot = sofa::simulation::tree::getSimulation()->load(fileName.c_str());
01831 
01832     if (groot==NULL)
01833     {
01834         groot = new sofa::simulation::tree::GNode;
01835         //return 1; 
01836     }
01837 
01838     if (startAnim)
01839         groot->setAnimate(true);
01840 
01841     
01842 
01843     //=======================================
01844     // Run the main loop
01845   
01846     if (gui=="batch")
01847     {
01848         if (groot==NULL)
01849         {
01850             std::cerr<<"Could not load file "<<fileName<<std::endl;
01851             return 1;
01852         }
01853         for (int i=0;true;i++)
01854         {
01855             sofa::simulation::tree::getSimulation()->animate(groot);
01856         }
01857         std::cout << "FlowVR has sent stop" << std::endl;
01858     }
01859     else
01860     {
01861         if (int err=sofa::gui::SofaGUI::MainLoop(groot,fileName.c_str()))
01862             return err;
01863         groot = (GNode *)sofa::gui::SofaGUI::CurrentSimulation();
01864     }
01865 
01866     if (groot!=NULL)
01867         sofa::simulation::tree::getSimulation()->unload(groot);
01868     return 0;
01869 }

Generated on Sun Nov 23 02:28:34 2008 for Sofa by  doxygen 1.5.7.1