00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <iostream>
00028 #include <fstream>
00029 #include <stack>
00030
00031 #include <flowvr/module.h>
00032 #include <flowvr/render/chunkwriter.h>
00033
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
00075
00076
00077
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
00106
00107
00108
00109
00110
00111
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 )
00172 {
00173 }
00174
00175 virtual void animateEnd(double )
00176 {
00177 }
00178
00179 virtual void flowvrPreInit(std::set<flowvr::Port*>* )
00180 {
00181 }
00182
00183 virtual void flowvrInit(flowvr::ModuleAPI* )
00184 {
00185 }
00186
00187 virtual void flowvrBeginIteration(flowvr::ModuleAPI* )
00188 {
00189 }
00190
00191 virtual void flowvrEndIteration(flowvr::ModuleAPI* )
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
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 )
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
00327 FlowVRBeginIterationEvent ev;
00328 ev.from = this;
00329 ev.module = module;
00330 getContext()->propagateEvent(&ev);
00331 }
00332
00333 virtual void animateEnd(double )
00334 {
00335 if (module==NULL) return;
00336 if (!step) return;
00337 step = false;
00338
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;
00366 }
00367 else if (flev->from != mod)
00368 return;
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
00381
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
00395
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);
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
00460 flowvr::Message points, facets;
00461
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
00502 mm = newPoints;
00503 }
00504 else
00505 {
00506
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);
00545 intersection->setContactDistance(0);
00546 newPointsCM->computeBoundingTree( 6 );
00547
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
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
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
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
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
00657 for (unsigned int i=0;i<nbi;i+=3)
00658 {
00659 mesh->addTriangle(indices[i ],indices[i+1],indices[i+2]);
00660
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
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* )
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
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
00728
00729 DistanceGridModel* grid;
00730
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)
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
00779
00780
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
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
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
00839
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
00850 if (distanceIt != distanceLastIt || newscale)
00851 {
00852 distanceLastIt = distanceIt;
00853
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 {
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
00888
00889
00890
00891
00892
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* )
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* )
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* , bool* )
01087 {
01088 }
01089
01090 virtual void flowvrRenderUpdate(flowvr::render::ChunkRenderWriter* , bool* )
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* )
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* )
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
01156
01157
01158
01159 scene.put(pOutScene);
01160
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
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
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
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 };
01227
01228 class FlowVRRenderMesh : public FlowVRRenderVisualModel, public sofa::component::visualmodel::OglModel
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
01267
01268
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
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
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];
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
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 {
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
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
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
01465
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
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)
01510 {
01511 if (!idVBT)
01512 {
01513 *scratch = false;
01514
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
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
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
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
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
01657 t1 -= normal * ( normal * t1 );
01658 t1.normalize();
01659 tangent[i] = t1;
01660
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
01676 idIB = addIndexBuffer(scene);
01677 scene->addParamID(idP, flowvr::render::ChunkPrimParam::IBUFFER_ID, "", idIB);
01678 }
01679 if (quads.empty())
01680 {
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 {
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 {
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
01722
01723
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
01736
01737
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 }
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
01796 .option(&startAnim,'s',"start","start the animation loop")
01797 .option(&printFactory,'p',"factory","print factory logs")
01798
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
01836 }
01837
01838 if (startAnim)
01839 groot->setAnimate(true);
01840
01841
01842
01843
01844
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 }