1 #include "pch.h"
2 #include "RenderConst.h"
3 #include "Def_Str.h"
4 #include "../common/data/SceneXml.h"
5 #include "../common/CScene.h"
6 #include "../common/Axes.h"
7 #include "../../vdrift/pathmanager.h"
8 #include "../../btOgre/BtOgreGP.h"
9 #include "../../road/Road.h"
10 #include "../common/ShapeData.h"
11 #ifdef SR_EDITOR
12 	#include "../../editor/CApp.h"
13 	#include "../../editor/CGui.h"
14 #else
15 	#include "../CGame.h"
16 	#include "../../vdrift/game.h"
17 #endif
18 #include <BulletCollision/CollisionDispatch/btCollisionObject.h>
19 #include <BulletCollision/CollisionShapes/btCollisionShape.h>
20 #include <LinearMath/btDefaultMotionState.h>
21 #include <BulletDynamics/Dynamics/btRigidBody.h>
22 #include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
23 #include <LinearMath/btSerializer.h>
24 #include <BulletFileLoader/btBulletFile.h>
25 #include <BulletWorldImporter/btBulletWorldImporter.h>
26 
27 #include <OgreManualObject.h>
28 #include <OgreMeshManager.h>
29 #include <OgreMaterialManager.h>
30 #include <OgreEntity.h>
31 #include <OgreSceneManager.h>
32 #include <OgreSceneNode.h>
33 #include <OgreRenderWindow.h>
34 #include <OgreSubEntity.h>
35 #include <OgreCamera.h>
36 #include <MyGUI.h>
37 #include <MyGUI_InputManager.h>
38 using namespace Ogre;
39 using namespace MyGUI;
40 using namespace std;
41 
42 
43 
44 ///  Objects  ... .. . . .
45 //----------------------------------------------------------------------------------------------------------------------
46 class BulletWorldOffset : public btBulletWorldImporter
47 {
48 public:
49 	btTransform mTrOfs;  // in offset
50 	btDefaultMotionState* ms;  // out
51 	btRigidBody* rb;  // out
52 
BulletWorldOffset(btDynamicsWorld * world=0)53 	BulletWorldOffset(btDynamicsWorld* world=0)
54 		: btBulletWorldImporter(world), ms(0), rb(0)
55 	{
56 		mTrOfs.setIdentity();
57 	}
58 
59 	//todo: shape->setUserPointer((void*)SU_ObjectDynamic);  // mark shapes..
60 
createCollisionObject(const btTransform & startTransform,btCollisionShape * shape,const char * bodyName)61 	btCollisionObject* createCollisionObject(const btTransform& startTransform,btCollisionShape* shape, const char* bodyName)
62 	{
63 		return createRigidBody(false,0,startTransform,shape,bodyName);
64 	}
65 
createRigidBody(bool isDynamic,btScalar mass,const btTransform & startTransform,btCollisionShape * shape,const char * bodyName)66 	btRigidBody* createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform,
67 								btCollisionShape* shape, const char* bodyName)
68 	{
69 		btVector3 localInertia;
70 		localInertia.setZero();
71 
72 		if (mass)
73 			shape->calculateLocalInertia(mass,localInertia);
74 
75 		ms = new btDefaultMotionState();
76 		ms->setWorldTransform(mTrOfs);
77 		btRigidBody* body = new btRigidBody(mass,ms,shape,localInertia);
78 		body->setDamping(0.1f, 0.3f);
79 		//body->setFriction(0.5f);
80 		rb = body;
81 
82 		#ifdef SR_EDITOR
83 		//body->setActivationState(DISABLE_DEACTIVATION);
84 		#else
85 		body->setActivationState(WANTS_DEACTIVATION);  // game creates deactivated (sleeping)
86 		#endif
87 
88 		if (m_dynamicsWorld)
89 			m_dynamicsWorld->addRigidBody(body);
90 
91 		/*if (bodyName)
92 		{
93 			char* newname = duplicateName(bodyName);
94 			m_objectNameMap.insert(body,newname);
95 			m_nameBodyMap.insert(newname,body);
96 		}*/
97 		m_allocatedRigidBodies.push_back(body);
98 		return body;
99 	}
100 };
101 
102 
103 //  Create
104 //-------------------------------------------------------------------------------------------------------
CreateObjects()105 void App::CreateObjects()
106 {
107 	//  maps for file exist (optimize)
108 	using std::map;  using std::string;
109 	map<string,bool> objExists, objHasBlt;
110 
111 	for (int i=0; i < scn->sc->objects.size(); ++i)
112 	{
113 		const string& s = scn->sc->objects[i].name;
114 		objExists[s] = false;  objHasBlt[s] = false;
115 	}
116 	for (map<string,bool>::iterator it = objExists.begin(); it != objExists.end(); ++it)
117 	{
118 		bool ex = PATHMANAGER::FileExists(PATHMANAGER::Data()+"/objects/"+ (*it).first + ".mesh");
119 		bool ex0 = PATHMANAGER::FileExists(PATHMANAGER::Data()+"/objects0/"+ (*it).first + ".mesh");
120 		bool exC = PATHMANAGER::FileExists(PATHMANAGER::Data()+"/objectsC/"+ (*it).first + ".mesh");
121 		(*it).second = ex || ex0 || exC;
122 		if (!ex)  LogO("Warning: CreateObjects mesh doesn't exist: " + (*it).first + ".mesh");
123 	}
124 	for (map<string,bool>::iterator it = objHasBlt.begin(); it != objHasBlt.end(); ++it)
125 		(*it).second = PATHMANAGER::FileExists(PATHMANAGER::Data()+"/objects/"+ (*it).first + ".bullet");
126 
127 	//  loader
128 	#ifndef SR_EDITOR
129 	btDiscreteDynamicsWorld* world = pGame->collision.world;
130 	#endif
131 	BulletWorldOffset* fileLoader = new BulletWorldOffset(world);
132 
133 	///  create  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
134 	for (int i=0; i < scn->sc->objects.size(); ++i)
135 	{
136 		Object& o = scn->sc->objects[i];
137 		String s = toStr(i);  // counter for names
138 		o.dyn = objHasBlt[o.name];
139 		#ifndef SR_EDITOR
140 		if (o.dyn && !pSet->game.dyn_objects)  continue;
141 		#endif
142 
143 		//  add to ogre
144 		bool no = !objExists[o.name];
145 		o.ent = mSceneMgr->createEntity("oE"+s, (no ? "sphere" : o.name) + ".mesh");
146 		o.nd = mSceneMgr->getRootSceneNode()->createChildSceneNode("oN"+s);
147 		o.SetFromBlt();
148 		o.nd->attachObject(o.ent);  o.ent->setVisibilityFlags(RV_Objects);
149 		o.nd->setScale(o.scale);
150 		if (no)  continue;
151 
152 		//  add to bullet world (in game)
153 		if (!o.dyn)
154 		{
155 			///  static  . . . . . . . . . . . .
156 			Vector3 posO = Axes::toOgre(o.pos);
157 			Quaternion rotO = Axes::toOgreW(o.rot);
158 
159 			Matrix4 tre;  tre.makeTransform(posO,o.scale,rotO);
160 			BtOgre::StaticMeshToShapeConverter converter(o.ent, tre);
161 			btCollisionShape* shape = converter.createTrimesh();  //=new x2 todo:del?...
162 			shape->setUserPointer((void*)SU_ObjectStatic);  // mark
163 
164 			btCollisionObject* bco = new btCollisionObject();
165 			btTransform tr;  tr.setIdentity();  //tr.setOrigin(btVector3(pos.x,-pos.z,pos.y));
166 			bco->setActivationState(DISABLE_SIMULATION);  // WANTS_DEACTIVATION
167 			bco->setCollisionShape(shape);	bco->setWorldTransform(tr);
168 			bco->setFriction(0.7f);   //+
169 			bco->setRestitution(0.f);
170 			bco->setCollisionFlags(bco->getCollisionFlags() |
171 				btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT/**/);
172 			world->addCollisionObject(bco);
173 			#ifndef SR_EDITOR
174 			o.co = bco;  o.ms = 0;  o.rb = 0;
175 			pGame->collision.shapes.push_back(shape);
176 			#endif
177 		}
178 		else  ///  dynamic  . . . . . . . . . . . .
179 		{
180 			// .bullet load
181 			fileLoader->mTrOfs.setOrigin(btVector3(o.pos[0],o.pos[1],o.pos[2]));
182 			fileLoader->mTrOfs.setRotation(btQuaternion(o.rot[0],o.rot[1],o.rot[2],o.rot[3]));
183 			//fileLoader->setVerboseMode(true);//
184 			std::string file = PATHMANAGER::Data()+"/objects/"+o.name+".bullet";
185 
186 			if (fileLoader->loadFile(file.c_str()))
187 			{
188 				o.ms = fileLoader->ms;  // 1 only
189 				o.rb = fileLoader->rb;  // 1 only
190 
191 				/*int nshp = fileLoader->getNumCollisionShapes();
192 				for (int i=0; i < nshp; ++i)
193 					pGame->collision.shapes.push_back(
194 						fileLoader->getCollisionShapeByIndex(i));/**/
195 
196 				#ifndef SR_EDITOR
197 				btTransform t1;  // save 1st pos for reset
198 				o.ms->getWorldTransform(t1);
199 				o.tr1 = new btTransform(t1);
200 				#endif
201 				#if 0
202 				LogO(".bullet: "+o.name+
203 					"  shapes:"+toStr(fileLoader->getNumCollisionShapes())+
204 					"  bodies:"+toStr(fileLoader->getNumRigidBodies())+
205 					"  constr:"+toStr(fileLoader->getNumConstraints())); /**/
206 				#endif
207 			}else
208 				LogO(".bullet: Load Error: "+o.name);
209 		}
210 	}
211 	delete fileLoader;
212 
213 	#ifdef SR_EDITOR
214 	iObjLast = scn->sc->objects.size();
215 	#endif
216 }
217 
218 ///  destroy
DestroyObjects(bool clear)219 void App::DestroyObjects(bool clear)
220 {
221 	for (int i=0; i < scn->sc->objects.size(); ++i)
222 	{
223 		Object& o = scn->sc->objects[i];
224 		delete o.tr1;  o.tr1 = 0;
225 
226 		// ogre
227 		if (o.nd)  mSceneMgr->destroySceneNode(o.nd);  o.nd = 0;
228 		#ifdef SR_EDITOR  // game has destroyAll
229 		if (o.ent)  mSceneMgr->destroyEntity(o.ent);  o.ent = 0;
230 		#endif
231 
232 		#ifdef SR_EDITOR
233 		// bullet
234 		if (o.co)
235 		{	delete o.co->getCollisionShape();
236 			#ifdef SR_EDITOR
237 			world->removeCollisionObject(o.co);
238 			#else
239 			pGame->collision.world->removeCollisionObject(o.co);
240 			#endif
241 			delete o.co;  o.co = 0;
242 		}
243 		if (o.rb)
244 		{	delete o.rb->getCollisionShape();
245 			delete o.ms;  o.ms = 0;
246 			#ifdef SR_EDITOR
247 			world->removeRigidBody(o.rb);
248 			#else
249 			pGame->collision.world->removeCollisionObject(o.rb);
250 			#endif
251 			delete o.rb;  o.rb = 0;
252 		}
253 		#endif
254 	}
255 	if (clear)
256 		scn->sc->objects.clear();
257 }
258 
ResetObjects()259 void App::ResetObjects()
260 {
261 	for (int i=0; i < scn->sc->objects.size(); ++i)
262 	{
263 		Object& o = scn->sc->objects[i];
264 		if (o.dyn && o.ms && o.tr1)
265 		{
266 			o.rb->clearForces();
267 			o.rb->setHitFraction(0.f);
268 			o.rb->setLinearVelocity(btVector3(0,0,0));
269 			o.rb->setAngularVelocity(btVector3(0,0,0));
270 			o.rb->setActivationState(WANTS_DEACTIVATION);
271 			o.rb->setWorldTransform(*o.tr1);
272 			o.ms->setWorldTransform(*o.tr1);
273 			o.SetFromBlt();
274 	}	}
275 }
276 
277 
278 //  Pick
279 //-------------------------------------------------------------------------------------------------------
280 
281 #ifdef SR_EDITOR
UpdObjPick()282 void App::UpdObjPick()
283 {
284 	if (ndStBox)
285 		ndStBox->setVisible(edMode == ED_Start && !bMoveCam);
286 
287 	int objs = scn->sc->objects.size();
288 	bool bObjects = edMode == ED_Objects && !bMoveCam && objs > 0 && iObjCur >= 0;
289 	if (objs > 0)
290 		iObjCur = std::min(iObjCur, objs-1);
291 
292 	if (!ndObjBox)  return;
293 	ndObjBox->setVisible(bObjects);
294 	if (!bObjects)  return;
295 
296 	const Object& o = scn->sc->objects[iObjCur];
297 	const AxisAlignedBox& ab = o.nd->getAttachedObject(0)->getBoundingBox();
298 	Vector3 s = o.scale * ab.getSize();  // * sel obj's node aabb
299 
300 	Vector3 posO = Axes::toOgre(o.pos);
301 	Quaternion rotO = Axes::toOgreW(o.rot);
302 
303 	Vector3 scaledCenter = ab.getCenter() * o.scale;
304 	posO += (rotO * scaledCenter);
305 
306 	ndObjBox->setPosition(posO);
307 	ndObjBox->setOrientation(rotO);
308 	ndObjBox->setScale(s);
309 }
310 
PickObject()311 void App::PickObject()
312 {
313 	if (scn->sc->objects.empty())  return;
314 
315 	iObjCur = -1;
316 	const MyGUI::IntPoint& mp = MyGUI::InputManager::getInstance().getMousePosition();
317 	Real mx = Real(mp.left)/mWindow->getWidth(), my = Real(mp.top)/mWindow->getHeight();
318 	Ray ray = mCamera->getCameraToViewportRay(mx,my);  // 0..1
319 	const Vector3& pos = mCamera->getDerivedPosition(), dir = ray.getDirection();
320 
321 	//  query scene (aabbs are enough)
322 	RaySceneQuery* rq = mSceneMgr->createRayQuery(ray);
323 	rq->setSortByDistance(true);
324 	RaySceneQueryResult& res = rq->execute();
325 
326 	Real distC = 100000.f;
327 	int io = -1;
328 	for (RaySceneQueryResult::iterator it = res.begin(); it != res.end(); ++it)
329 	{
330 		const String& s = (*it).movable->getName();
331 		if (StringUtil::startsWith(s,"oE",false))
332 		{
333 			//LogO("RAY "+s+" "+fToStr((*it).distance,2,4)+"  n "+toStr(n)+"  nn "+toStr(nn));
334 			int i = -1;
335 			//  find obj with same ent name
336 			for (int o=0; o < scn->sc->objects.size(); ++o)
337 				if (s == scn->sc->objects[o].ent->getName())
338 				{	i = o;  break;  }
339 
340 			//  pick
341 			if (i != -1)
342 			{
343 				//AxisAlignedBox ab = sc->objects[i].ent->getBoundingBox();
344 				//ab.getCenter();  ab.getSize();
345 
346 				//  closest to obj center
347 				const Vector3 posSph = scn->sc->objects[i].nd->getPosition();
348 				const Vector3 ps = pos - posSph;
349 				Vector3 crs = ps.crossProduct(dir);
350 				Real dC = crs.length() / dir.length();
351 
352 				//if ((*it).distance < dist)  // closest aabb
353 				if (dC < distC)  // closest center
354 				{
355 					io = i;
356 					//dist = (*it).distance;
357 					distC = dC;
358 			}	}
359 	}	}
360 
361 	if (io != -1)  //  if none picked
362 	if (iObjCur == -1)
363 		iObjCur = io;
364 
365 	//rq->clearResults();
366 	mSceneMgr->destroyQuery(rq);
367 }
368 
369 //  upd obj selected glow
UpdObjSel()370 void App::UpdObjSel()
371 {
372 	int objs = scn->sc->objects.size();
373 	for (int i=0; i < objs; ++i)
374 	{	bool bSel = vObjSel.find(i) != vObjSel.end();
375 		scn->sc->objects[i].ent->getSubEntity(0)->setCustomParameter(1, Vector4(bSel ? 1 : 0, 0,0,0));
376 	}
377 }
378 
379 //  selection center pos, or picked pos for multi rotate and scale
GetObjPos0()380 Vector3 App::GetObjPos0()
381 {
382 	Vector3 pos0(0,0,0);
383 	if (iObjCur>=0)
384 	{
385 		MATHVECTOR<float,3> p = scn->sc->objects[iObjCur].pos;
386 		pos0 = Vector3(p[0],p[2],-p[1]);
387 	}
388 	else if (!vObjSel.empty())
389 	{
390 		for (std::set<int>::iterator it = vObjSel.begin(); it != vObjSel.end(); ++it)
391 		{
392 			MATHVECTOR<float,3> p = scn->sc->objects[(*it)].pos;
393 			pos0 += Vector3(p[0],p[2],-p[1]);
394 		}
395 		pos0 /= Real(vObjSel.size());
396 	}
397 	return pos0;
398 }
399 
400 
401 ///  toggle objects simulation (bullet world)
402 //-------------------------------------------------------------------------------------------------------
ToggleObjSim()403 void App::ToggleObjSim()
404 {
405 	if (gui->objPan)  gui->objPan->setVisible(objSim);
406 
407 	DestroyObjects(false);
408 
409 	if (!objSim)  // off sim
410 	{
411 		//  Destroy blt world
412 		for(int i = world->getNumCollisionObjects() - 1; i >= 0; i--)
413 		{
414 			btCollisionObject* obj = world->getCollisionObjectArray()[i];
415 			delete obj->getCollisionShape();
416 
417 			btRigidBody* body = btRigidBody::upcast(obj);
418 			if (body && body->getMotionState())
419 				delete body->getMotionState();
420 
421 			if (obj->getUserPointer() != (void*)111)
422 			{
423 				ShapeData* sd = static_cast<ShapeData*>(obj->getUserPointer());
424 				delete sd;
425 			}
426 			world->removeCollisionObject(obj);
427 			delete obj;
428 		}
429 	}
430 	else  // on sim
431 	{
432 		//  Create blt world
433 		scn->CreateBltTerrain();
434 		scn->road->RebuildRoadInt(false,true);
435 	}
436 	CreateObjects();
437 	UpdObjPick();
438 }
439 
440 
441 ///  add new object
AddNewObj(bool getName)442 void App::AddNewObj(bool getName)  //App..
443 {
444 	::Object o = objNew;
445 	if (getName)
446 		o.name = vObjNames[iObjTNew];
447 	++iObjLast;
448 	String s = toStr(iObjLast);  // counter for names
449 	///TODO: ?dyn objs size, !?get center,size, rmb height..
450 
451 	//  pos, rot
452 	if (getName)
453 	{	// one new
454 		const Vector3& v = scn->road->posHit;
455 		o.pos[0] = v.x;  o.pos[1] =-v.z;  o.pos[2] = v.y + objNew.pos[2];
456 	}else  // many
457 	{	// offset for cursor pos..
458 		//o.pos[0] = v.x;  o.pos[1] =-v.z;  o.pos[2] = v.y + objNew.pos[2];
459 	}
460 
461 	//  create object
462 	o.ent = mSceneMgr->createEntity("oE"+s, o.name + ".mesh");
463 	o.nd = mSceneMgr->getRootSceneNode()->createChildSceneNode("oN"+s);
464 	o.SetFromBlt();
465 	o.nd->setScale(o.scale);
466 	o.nd->attachObject(o.ent);  o.ent->setVisibilityFlags(RV_Vegetation);
467 
468 	o.dyn = PATHMANAGER::FileExists(PATHMANAGER::Data()+"/objects/"+ o.name + ".bullet");
469 	scn->sc->objects.push_back(o);
470 }
471 
472 
473 //  change obj to insert
listObjsChng(MyGUI::List * l,size_t t)474 void CGui::listObjsChng(MyGUI::List* l, size_t t)
475 {
476 	//  unselect other
477 	if (l != objListDyn)  objListDyn->setIndexSelected(ITEM_NONE);
478 	if (l != objListSt)	  objListSt->setIndexSelected(ITEM_NONE);
479 	if (l != objListRck)  objListRck->setIndexSelected(ITEM_NONE);
480 	if (l != objListBld)  objListBld->setIndexSelected(ITEM_NONE);
481 
482 	if (t == ITEM_NONE)  //  sel default
483 	{	/*l = objListDyn;*/  t = 0;  l->setIndexSelected(t);  }
484 
485 	std::string s = l->getItemNameAt(t).substr(7);
486 	for (int i=0; i < app->vObjNames.size(); ++i)
487 		if (s == app->vObjNames[i])
488 		{
489 			app->SetObjNewType(i);
490 			Upd3DView(s+".mesh");
491 			return;
492 		}
493 }
494 
listObjsNext(int rel)495 void CGui::listObjsNext(int rel)
496 {
497 	Li li = 0;
498 	if (objListDyn->getIndexSelected()!= ITEM_NONE)  li = objListDyn; //else
499 	if (objListSt->getIndexSelected() != ITEM_NONE)  li = objListSt;
500 	if (objListRck->getIndexSelected()!= ITEM_NONE)  li = objListRck;
501 	if (objListBld->getIndexSelected()!= ITEM_NONE)  li = objListBld;
502 	if (li)
503 	{
504 		size_t cnt = li->getItemCount();
505 		if (cnt == 0)  return;
506 		int i = std::max(0, std::min((int)cnt-1, (int)li->getIndexSelected()+rel ));
507 		li->setIndexSelected(i);
508 		li->beginToItemAt(std::max(0, i-11));  // center
509 		listObjsChng(li, li->getIndexSelected());
510 	}
511 }
512 
513 
514 //  change category, fill buildings list
listObjsCatChng(Li li,size_t id)515 void CGui::listObjsCatChng(Li li, size_t id)
516 {
517 	if (id == ITEM_NONE || id >= li->getItemCount())  id = 0;
518 	if (li->getItemCount()==0)  return;
519 	string cat = li->getItemNameAt(id).substr(7);
520 
521 	objListBld->removeAllItems();
522 	for (size_t i=0; i < app->vBuildings.size(); ++i)
523 	{
524 		const string& s = app->vBuildings[i];
525 		if (//id == 0 ||/*all*/
526 			s.length() > 4 && s.substr(0,4) == cat)
527 			objListBld->addItem("#E0E080"+s);
528 	}
529 }
530 
531 
532 //  preview model for insert
SetObjNewType(int tnew)533 void App::SetObjNewType(int tnew)
534 {
535 	iObjTNew = tnew;
536 	if (objNew.nd)	{	mSceneMgr->destroySceneNode(objNew.nd);  objNew.nd = 0;  }
537 	if (objNew.ent)	{	mSceneMgr->destroyEntity(objNew.ent);  objNew.ent = 0;  }
538 
539 	String name = vObjNames[iObjTNew];
540 	objNew.dyn = PATHMANAGER::FileExists(PATHMANAGER::Data()+"/objects/"+ name + ".bullet");
541 	if (objNew.dyn)  objNew.scale = Vector3::UNIT_SCALE;  // dyn no scale
542 	objNew.ent = mSceneMgr->createEntity("-oE", name + ".mesh");
543 	objNew.nd = mSceneMgr->getRootSceneNode()->createChildSceneNode("-oN");
544 	objNew.nd->attachObject(objNew.ent);  objNew.ent->setVisibilityFlags(RV_Vegetation);
545 	UpdObjNewNode();
546 }
547 
UpdObjNewNode()548 void App::UpdObjNewNode()
549 {
550 	if (!scn->road || !objNew.nd)  return;
551 
552 	bool vis = scn->road->bHitTer && bEdit() && iObjCur == -1 && edMode == ED_Objects;
553 	objNew.nd->setVisible(vis);
554 	if (!vis)  return;
555 
556 	Vector3 p = scn->road->posHit;  p.y += objNew.pos[2];
557 	objNew.SetFromBlt();
558 	objNew.nd->setPosition(p);
559 	objNew.nd->setScale(objNew.scale);
560 }
561 
562 #endif
563