查看: 3209|回复: 11

3Dmax导出3DS文件的坐标问题

[复制链接]

该用户从未签到

发表于 2011-3-21 10:20:39 | 显示全部楼层 |阅读模式
做了一个模型,使用的是3DS文件,画出物体的包围盒。但是不知道怎么回事,在OSG中直接渲染的节点和它的包围盒有很大的偏差。

截图

截图

两个圆柱体的模型的包围盒是那个长方体,利用的lib3ds库读入的3ds的TriMesh,然后确定的包围盒,请高手指点

该用户从未签到

 楼主| 发表于 2011-3-21 13:37:31 | 显示全部楼层
没人知道么?

该用户从未签到

发表于 2011-3-21 15:23:03 | 显示全部楼层
我无法得知您到底对模型和程序都做了什么

该用户从未签到

 楼主| 发表于 2011-3-21 15:57:08 | 显示全部楼层

  1. #define min(a,b) (((a)<(b))?(a):(b))
  2. extern int MeshCount;
  3. //ODE的错误消减参数,值在0-1之间,默认值为0.2

  4. const double ERP = 0.8;
  5. //ODE的约束力混合参数
  6. const double CFM = 0.1;
  7. const double MAX_STEP = 0.01;
  8. const int MAX_CONTACTS = 10;
  9. #define NUM 200                        // 最大的物体数量

  10. dWorldID World;              //ODE世界
  11. dJointGroupID ContactGroup;   //接触点容器
  12. dSpaceID Space;              //ODE冲突检测空间

  13. dBodyID testBody;            //主动运动的盒子刚体体积数据句柄,用于物理交互

  14. dGeomID testGeom;            //主动运动的盒子刚体几何体数据句柄,用于碰撞交互

  15. dGeomID GroundGeom[6];          //地形刚体几何体数据句柄,用于碰撞交互

  16. bool peng=false;             //碰撞检测函数
  17. typedef struct MyTrimesh
  18. {
  19.         float* vertices;
  20.         unsigned int vertexcount;
  21.         int* indices;
  22.         unsigned int indexcount;
  23. } MyTrimesh;              //三角形数据TriMesh

  24. typedef struct MyObiect
  25. {
  26.         dBodyID body;
  27.         dGeomID geom;
  28.         dReal   matrix_dblbuff[16*2];
  29.         int     last_matrix_index;
  30. } MyObiect;                //模型节点

  31. static dTriMeshDataID TriData;
  32. dTriMeshDataID TriData1;
  33. dGeomID geom;
  34. MyTrimesh* trimesh;
  35. static MyObiect model;

  36. osg::ref_ptr<osg::Node> testnode = new osg::Node;
  37. osg::ref_ptr<osg::Node> testnode1 = new osg::Node;
  38. osg::ref_ptr<osg::PositionAttitudeTransform> testPAT = new osg::PositionAttitudeTransform;
  39. osg::ref_ptr<osg::PositionAttitudeTransform> testPAT1 = new osg::PositionAttitudeTransform;
  40. osg::ref_ptr<osg::Group> root = new osg::Group;
  41. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
  42. osg::ref_ptr<osg::Geode> sphereGeode = new osg::Geode;
  43. osg::ref_ptr<osg::Box> groundBox;
  44. osg::ref_ptr<osg::Geode> groundGeode = new osg::Geode();

  45. osg::ref_ptr<osgManipulator::Selection> sel= new osgManipulator::Selection; //初始化拖拽器
  46. osg::ref_ptr<osgManipulator::TranslateAxisDragger> dra= new osgManipulator::TranslateAxisDragger;
  47. osg::ref_ptr<osgManipulator::CommandManager> cmd= new osgManipulator::CommandManager;
  48. osg::ref_ptr<osg::Group> gr= new osg::Group;
  49. //GUI事件
  50. class ODEController: public osgGA::GUIEventHandler
  51. {
  52. public:
  53.         ODEController()
  54.         {
  55.                 m_isForceOn = 0;
  56.         }

  57.         virtual bool handle (const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter &aa)
  58.         {
  59.                 switch (ea.getEventType())
  60.                 {
  61.                 case osgGA::GUIEventAdapter::KEYDOWN:
  62.                         if (ea.getKey() == 'w' || ea.getKey() == 'W')
  63.                         {
  64.                                 m_isForceOn = 1;
  65.                                 return true;
  66.                         }
  67.                         if (ea.getKey() == 's' || ea.getKey() == 'S')
  68.                         {
  69.                                 m_isForceOn = 2;
  70.                                 return true;
  71.                         }
  72.                 case osgGA::GUIEventAdapter::KEYUP:
  73.                         //if (ea.getKey() == 'f' || ea.getKey() == 'F')
  74.                         {
  75.                                 m_isForceOn = 0;
  76.                                 return true;
  77.                         }
  78.                 default:
  79.                         break;
  80.                 }

  81.                 return false;
  82.         }

  83.         int isForceOn()
  84.         {
  85.                 return m_isForceOn;
  86.         }

  87. private:
  88.         int m_isForceOn;
  89. };
  90. //创建物理学世界

  91. void setCurrentTransform(dGeomID geom)
  92. {
  93.         const dReal* Pos = dGeomGetPosition(geom);
  94.         const dReal* Rot = dGeomGetRotation(geom);

  95.         const

  96. dReal Transform[16] =
  97.         {
  98.                 Rot[0], Rot[4], Rot[8],  0,
  99.                 Rot[1], Rot[5], Rot[9],  0,
  100.                 Rot[2], Rot[6], Rot[10], 0,
  101.                

  102. Pos[0], Pos[1], Pos[2],  1
  103.         };

  104.         dGeomTriMeshSetLastTransform( geom, *(dMatrix4*)(&Transform) );

  105. }
  106. void makeModel(const char* filename)
  107. {
  108.         dMass m;
  109.         static float weigth=50.0;
  110.         dReal x0 = 0, y0 = 0, z0 = 5.0;
  111.         load3dsModel(filename);

  112.         for (int i = 0; i < MeshCount; i++) {

  113.                 //memset(&model[i],0,sizeof(model[i]));
  114.                 // rigid body
  115.                 model.body = dBodyCreate(World);
  116.                 dBodySetPosition(model.body, x0, y0, z0);
  117.        dBodySetData(model.body,&i);

  118.                 // for a trimesh object
  119.                 TriData = dGeomTriMeshDataCreate();          

  120.                 dGeomTriMeshDataBuildSingle(TriData, trimesh[i].vertices, 3 * sizeof(float),
  121.                         trimesh[i].vertexcount, trimesh[i].indices, trimesh[i].indexcount * 3, 3 * sizeof(int));

  122.                 model.geom = dCreateTriMesh(Space, TriData, 0, 0, 0);


  123.                 dGeomSetPosition(model.geom,0,0,0);
  124.                 dMatrix3 RI;
  125.                 dRSetIdentity (RI);
  126.                 dGeomSetRotation(model.geom,RI);

  127.         }

  128. }
  129. void createODEWorld()
  130. {
  131.         //初始化ODE引擎
  132.         dInitODE2(0);   
  133.         World = dWorldCreate();
  134.         //设置地球重力,如果设置为正数,则被操作物体将漂浮
  135.         dWorldSetGravity(World, 0.0, 0.0, -0.5);
  136.         //设置全局ERP
  137.         dWorldSetERP (World, 0.8);
  138.         dWorldSetCFM (World,1e-5);
  139.         //创建冲突世界和几何对象
  140.         Space = dSimpleSpaceCreate(0);
  141.         //GroundGeom[0]=dCreatePlane(Space, 0.0, 0.0, 1.0, -40.0);

  142.         ContactGroup = dJointGroupCreate(0);
  143. }

  144. void updateOSGWorld()
  145. {

  146.         //const dReal *testQuat = dBodyGetQuaternion(model.body);
  147.         //testPAT->setAttitude(osg::Quat(testQuat[1], testQuat[2], testQuat[3], testQuat[0]));

  148.         //const dReal *testVec = dGeomGetPosition(model.geom);
  149.         //testPAT->setPosition(osg::Vec3(testVec[0], testVec[1], testVec[2]));

  150. }


  151. //用于ODE冲突检测子系统的回调函数
  152. void nearCallback (void *, dGeomID o1, dGeomID o2)
  153. {
  154.         int i;
  155. // if (o1->body && o2->body) return;

  156. // exit without doing anything if the two bodies are connected by a joint
  157. dBodyID b1 = dGeomGetBody

  158. (o1);
  159. dBodyID b2 = dGeomGetBody(o2);
  160. if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;

  161. dContact contact[MAX_CONTACTS];   // up to

  162. MAX_CONTACTS contacts per box-box
  163. for (i=0; i<MAX_CONTACTS; i++) {
  164.         contact[i].surface.mode = dContactBounce | dContactSoftCFM;
  165.         contact

  166. [i].surface.mu = dInfinity;
  167.         contact[i].surface.mu2 = 0;
  168.         contact[i].surface.bounce = 0.1;
  169.         contact[i].surface.bounce_vel = 0.1;
  170.         contact

  171. [i].surface.soft_cfm = 0.01;
  172. }
  173. if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
  174.         sizeof(dContact)))
  175.        
  176. {
  177.             

  178. std::cout<<"peng="<<numc<<std::endl;
  179.             peng=true;
  180.                 //dMatrix3 RI;
  181.                 //dRSetIdentity (RI);
  182.                 //const dReal ss[3] =

  183. {0.02,0.02,0.02};
  184.                 //for (i=0; i<numc; i++) {
  185.                 //        osg::ref_ptr<osg::Box> groundBox = new osg::Box(osg::Vec3(contact

  186. [i].geom.pos[0],contact[i].geom.pos[1],contact[i].geom.pos[2]), 1.0, 1.0, 1.0);
  187.                 //        groundGeode->addDrawable(new osg::ShapeDrawable(groundBox.get()));
  188.                 ////        dJointID c = dJointCreateContact

  189. (World,ContactGroup,contact+i);
  190.                 ////        dJointAttach (c,b1,b2);
  191.                 ////        //if (show_contacts) dsDrawBox (contact

  192. [i].geom.pos,RI,ss);
  193.                 //}
  194. }
  195. }

  196. //销毁ODE世界
  197. void destroyODEWorld()
  198. {
  199.         dSpaceDestroy(Space);
  200.         dWorldDestroy(World);
  201. }
  202. class keybordHandle:public osgGA::GUIEventHandler
  203. {
  204. public:

  205.         enum modes
  206.         {
  207.                 VIEW=0,
  208.                 PICK
  209.         };
  210.         keybordHandle():_mx(0.0f),_my(0.0f),_activedrgger(0),_mode(VIEW),m_isForceOn(0)
  211.         {

  212.         }
  213.         ~keybordHandle()
  214.         {

  215.         }
  216.         bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
  217.         {
  218.                 osgViewer::Viewer* viewer=dynamic_cast<osgViewer::Viewer*>(&aa);
  219.                 if(!viewer)
  220.                         return false;
  221.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Tab &&
  222.                         ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN &&
  223.                         _activedrgger == 0)
  224.                 {
  225.                         _mode = ! _mode;
  226.                 }
  227.                 if (VIEW == _mode) return false;
  228.                 switch(ea.getEventType())
  229.                 {
  230.                 case osgGA::GUIEventAdapter::KEYDOWN:
  231.                         if(ea.getKey()==osgGA::GUIEventAdapter::KEY_Space)
  232.                         {
  233.                                 int width=ea.getWindowHeight();
  234.                                 int height=ea.getWindowWidth();
  235.                                 viewer->requestWarpPointer(width*0.5,height*0.5);
  236.                         }
  237.                         else
  238.                         {
  239.                                 osg::ref_ptr<osg::Switch> root=dynamic_cast<osg::Switch*>(viewer->getSceneData());
  240.                                 if(!root)return false;
  241.                                 if(ea.getKey()=='1')
  242.                                 {
  243.                                         root->setValue(0,false);
  244.                                         root->setValue(1,true);

  245.                                 }
  246.                                 else if (ea.getKey()=='2')
  247.                                 {
  248.                                         root->setValue(0,true);
  249.                                         root->setValue(1,false);
  250.                                 }
  251.                                 return true;
  252.                         }
  253.                         break;
  254.                 case osgGA::GUIEventAdapter::PUSH:
  255.                         //case(osgGA::GUIEventAdapter::MOVE):
  256.                         {
  257.                                 _mx=ea.getX();
  258.                                 _my=ea.getY();
  259.                                 _pointinfo.reset();
  260.                                 osgUtil::LineSegmentIntersector::Intersections inter;
  261.                                 if(viewer->computeIntersections(ea.getX(),ea.getY(),inter))
  262.                                 {
  263.                                         _pointinfo.setCamera(viewer->getCamera());
  264.                                         _pointinfo.setMousePosition(_mx,_my);
  265.                                         osgUtil::LineSegmentIntersector::Intersections::iterator hitr;
  266.                                         for(hitr=inter.begin();hitr!=inter.end();++hitr)
  267.                                         {
  268.                                                 _pointinfo.addIntersection(hitr->nodePath,hitr->getLocalIntersectPoint());
  269.                                         }
  270.                                         osg::NodePath::iterator it;
  271.                                         for(it=_pointinfo._hitList.front().first.begin();
  272.                                                 it!=_pointinfo._hitList.front().first.end();it++)
  273.                                         {
  274.                                                 osgManipulator::Dragger* dragger=dynamic_cast<osgManipulator::Dragger*>(*it);
  275.                                                 if(dragger)
  276.                                                 {
  277.                                                         dragger->handle(_pointinfo,ea,aa);
  278.                                                         _activedrgger=dragger;
  279.                                                         break;
  280.                                                 }
  281.                                         }
  282.                                 }
  283.                                 break;
  284.                         }
  285.                 case osgGA::GUIEventAdapter::DRAG:
  286.                 case osgGA::GUIEventAdapter::RELEASE:
  287.                         {
  288.                                 if(_activedrgger)
  289.                                 {
  290.                                         m_isForceOn=1;
  291.                                         osg::Matrix dra_command=_activedrgger->getMatrix();//之前的变换
  292.                   osg::Matrix sel_command=sel->getMatrix();//之前的变换
  293.                                     const dReal *testVec = dGeomGetPosition(model.geom);
  294.                   printf("center at %f %f %f\n", testVec[0], testVec[1], testVec[2]);

  295.                                         _pointinfo._hitIter=_pointinfo._hitList.begin();
  296.                                         _pointinfo.setCamera(viewer->getCamera());
  297.                                         _pointinfo.setMousePosition(ea.getX(),ea.getY());
  298.                                         _activedrgger->handle(_pointinfo,ea,aa);

  299.                                         osg::Vec3d vec=_activedrgger->getMatrix().getTrans();//处理临时的变换
  300.                                         dGeomSetPosition(model.geom,vec[0],vec[1],vec[2]);
  301.                                         dSpaceCollide(Space, 0, nearCallback);
  302.                                         dJointGroupEmpty(ContactGroup);
  303.                                         if (peng)
  304.                                         {
  305.                                                 dGeomSetPosition(model.geom,testVec[0],testVec[1],testVec[2]);
  306.                                                 dra->setMatrix(dra_command);
  307.                                                 sel->setMatrix(sel_command);
  308.                                                 peng=false;
  309.                                                 //std::cout<<"改变1"<<std::endl;
  310.                                         }

  311.                                         }
  312.                                         break;
  313.                                 }

  314.                 default: break;
  315.                         }
  316.                         if(ea.getEventType()==osgGA::GUIEventAdapter::RELEASE)
  317.                         {
  318.                                 m_isForceOn=0;
  319.                                 _activedrgger=0;
  320.                                 _pointinfo.reset();
  321.                         }
  322.                         return true;
  323.                 }
  324.        
  325.         int isForceOn()
  326.         {
  327.                 return m_isForceOn;
  328.         }
  329. public:       
  330.         //得到鼠标的位置
  331.         float _mx;
  332.         float _my;
  333.         unsigned int _mode;
  334.         int m_isForceOn;
  335.         osgManipulator::Dragger* _activedrgger;
  336.         osgManipulator::PointerInfo _pointinfo;
  337. };
  338. int main()
  339. {
  340.         double x = -5.0;

  341.         groundBox = new osg::Box(osg::Vec3(0.0,0.0,0.0), 50.0, 50.0, 0.1);
  342.         groundGeode->addDrawable(new osg::ShapeDrawable(groundBox.get()));
  343.         root->addChild(groundGeode.get());


  344.         testnode = osgDB::readNodeFile("lun2.3ds");

  345.         testnode1 = osgDB::readNodeFile("lun4.3ds");
  346.         testPAT->addChild(testnode1.get());
  347.         root->addChild(testPAT.get());

  348.         sel->addChild(testnode.get());
  349.         dra->setupDefaultGeometry();
  350.         gr->addChild(dra.get());       
  351.         gr->addChild(sel.get());
  352.         float scale=testnode->getBound().radius()*1.1;
  353.         dra->setMatrix(osg::Matrix::scale(scale,scale,scale)*osg::Matrix::translate(testnode->getBound().center()));
  354.         cmd->connect(*dra.get(),*sel.get());
  355.         root->addChild(gr.get());


  356.         keybordHandle* eh= new keybordHandle;
  357.         viewer->addEventHandler(eh);

  358.         viewer->setCameraManipulator(new osgGA::TrackballManipulator);
  359.         viewer->setSceneData(root.get());

  360.         osg::ref_ptr<osg::GraphicsContext::Traits> trait= new osg::GraphicsContext::Traits;
  361.         trait->x=100;
  362.         trait->y=100;
  363.         trait->width=900;
  364.         trait->height=700;
  365.         trait->windowDecoration=true;
  366.         trait->doubleBuffer=true;
  367.         trait->sharedContext=0;
  368.         osg::ref_ptr<osg::GraphicsContext> gc=osg::GraphicsContext::createGraphicsContext(trait);
  369.         osg::ref_ptr<osg::Camera>camera=viewer->getCamera();
  370.         camera->setGraphicsContext(gc);
  371.         camera->setViewport(new osg::Viewport(0,0,trait->width,trait->height));
  372.         GLenum buffer=trait->doubleBuffer?GL_BACK:GL_FRONT;
  373.         camera->setDrawBuffer(buffer);
  374.         camera->setReadBuffer(buffer);

  375.         createODEWorld();
  376.         makeModel("lun2.3ds");
  377.        
  378.         load3dsModel("lun4.3ds");
  379.         TriData1 = dGeomTriMeshDataCreate();          
  380.         dGeomTriMeshDataBuildSingle(TriData1, trimesh[0].vertices, 3 * sizeof(float),
  381.                 trimesh[0].vertexcount, trimesh[0].indices, trimesh[0].indexcount * 3, 3 * sizeof(int));
  382.     geom = dCreateTriMesh(Space, TriData1, 0, 0, 0);
  383.         dGeomSetPosition(geom,50,0,0);
  384.         dMatrix3 RI;
  385.        
  386.     dRSetIdentity (RI);
  387.     dGeomSetRotation(geom,RI);

  388.          testPAT->setPosition(osg::Vec3(50.0, 0.0, 0.0));
  389.        
  390.         updateOSGWorld();

  391.         osg::Timer_t prevTime = osg::Timer::instance()->tick();

  392.         while (!viewer->done())
  393.         {
  394.                 viewer->frame();

  395.                 const osg::Timer_t now = osg::Timer::instance()->tick();
  396.                 double deltaSecs = osg::Timer::instance()->delta_s(prevTime, now);
  397.                 prevTime = now;

  398.                 while (deltaSecs > 0.0)
  399.                 {

  400.                         const double step = min(MAX_STEP, deltaSecs);
  401.                         deltaSecs -= MAX_STEP;

  402.                         dWorldStep(World, step);

  403.                         dJointGroupEmpty(ContactGroup);
  404.                 }

  405.                 updateOSGWorld();
  406.         }

  407.         destroyODEWorld();

  408.         return 0;
  409. }
复制代码

该用户从未签到

 楼主| 发表于 2011-3-21 16:05:59 | 显示全部楼层
回复 3# array
O]$QPD`08RT55`N3YEUZU2F.jpg
上面的代码实现的是这个场景,但是有的时候从3Dmax中读入的模型 跟用ODE算出的包围盒有位置上的差异,
换做其他的模型的图片是这样的(这个模型也是在3Dmax原点导出的3DS文件)
MJ}1K[F12TH@%K6TZ1)X6SL.jpg
那个会的的长方体是那个车架的包围盒(使用lib3DS读取的3ds文件)使用ODE中GetAABB算出的包围盒。

该用户从未签到

发表于 2011-3-22 08:20:57 | 显示全部楼层
能否请您把您的代码简化到一目了然的程度,同时给出自己经过一定分析和测试后的解释。没有人愿意专门抽时间为您调试这么冗长的代码,而且是缺少对您的构架的了解和相应资源的条件下。我看不到您说的GetAABB在哪里;您是在什么地方绘制这个长方体的,我也无从得知

该用户从未签到

 楼主| 发表于 2011-3-22 09:10:39 | 显示全部楼层
回复 6# array

load3dsModel("lun5.3ds");            //使用lib3ds加载3ds文件,然后使用ODE的TriMesh生成碰撞检测的三角曲面
TriData1 = dGeomTriMeshDataCreate(); //同上          
dGeomTriMeshDataBuildSingle(TriData1, trimesh[0].vertices, 3 * sizeof(float),
                trimesh[0].vertexcount, trimesh[0].indices, trimesh[0].indexcount * 3, 3 * sizeof(int));
geom = dCreateTriMesh(Space, TriData1, 0, 0, 0);

dMass m;
static float weigth=1.0;
dMassSetTrimesh(&m, weigth, geom);
//碰撞检测空间的初始化设置
dGeomSetPosition(geom,0,0,0);
dMatrix3 RI;
dRSetIdentity (RI);
dGeomSetRotation(geom,RI);

//下面是计算这个Geom的包围盒
dReal aabb[6];
dGeomGetAABB (geom,aabb);
dVector3 bbpos;               
for (int i=0; i<3; i++) bbpos = 0.5*(aabb[i*2] + aabb[i*2+1]);//这里是计算包围盒(使用ODE中的Trimesh)
dVector3 bbsides;               
for (int j=0; j<3; j++) bbsides[j] = aabb[j*2+1] - aabb[j*2];//这里是计算包围盒的各个边长
//显示包围盒
groundBox = new osg::Box(osg::Vec3(bbpos[0],bbpos[1],bbpos[2]), bbsides[0], bbsides[1] ,bbsides[2]);
groundGeode->addDrawable(new osg::ShapeDrawable(groundBox.get()));


testnode1 = osgDB::readNodeFile("lun5.3ds");
//直接利用OSG读取要渲染的模型节点

(******************************************************************************)
但是上面的那个画出的包围盒 不能包住这个node节点。
奇怪的是如果我把模型手动的移动到世界坐标的中心,这个包围盒就可以把这个模型包住了,如果模型的中心不在世界坐标的中心,则这个包围盒 和 这个模型就有一定的偏差。
想问一下OSG中渲染3ds文件时,坐标是怎么设置的?

该用户从未签到

 楼主| 发表于 2011-3-22 09:15:33 | 显示全部楼层
US){]R(%[QYC_3EPBN_WRM8.jpg


上面的灰色盒子使用ODE直接算出的TriMes的包围盒,那个轮胎是用OSG直接渲染出来的,但是包围盒没有把轮胎包住。
(轮胎在3Dmax中不是在世界坐标的原点导出的,如果移动到原点,那么这个包围盒就可以把他包住,而且就在OSG的世界坐标的中心)

该用户从未签到

发表于 2011-3-22 09:19:45 | 显示全部楼层
OSG会忠实地将物体建模时的实际坐标读取出来并渲染在场景中。而您可以打印物理引擎ode计算得到的包围体的值并判断它的中心是否为物体中心,我想应该是这里的问题

该用户从未签到

 楼主| 发表于 2011-3-22 09:28:26 | 显示全部楼层
回复 9# array

用ODE的TriMesh算出的物理的包围盒的中心和OSG的node节点的中心不一致,有些偏差。
难道是我使用的lib3ds读取3ds文件的时候,里面的三角面数据出现了篡改?导致这个最后的包围盒有一定的偏差。
应该不会有这样的问题吧

该用户从未签到

发表于 2011-3-22 12:45:22 | 显示全部楼层
应该是中心不一致导致的,你模型导出的时候中心跟原点重合,然后包围盒跟模型放在一个MatrixTransform下试试

该用户从未签到

 楼主| 发表于 2011-3-22 13:03:02 | 显示全部楼层
回复 11# tianxiao888

果断是3Dmax中的问题,我找了那个模型经过了什么变换,搞不懂。
所以先找一个最简单的代替。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表