DAESceneEncoder.cpp 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928
  1. /*
  2. * DAESceneEncoder.h
  3. */
  4. #include <algorithm>
  5. #include "DAESceneEncoder.h"
  6. #include "DAEOptimizer.h"
  7. //#define ENCODER_PRINT_TIME 1
  8. using namespace gameplay;
  9. DAESceneEncoder::DAESceneEncoder()
  10. : _collada(NULL), _dom(NULL), file(NULL), _vertexBlendWeights(NULL), _vertexBlendIndices(NULL)
  11. {
  12. }
  13. DAESceneEncoder::~DAESceneEncoder()
  14. {
  15. }
  16. std::string getFilenameFromFilePath(const std::string& filepath)
  17. {
  18. if (filepath.find_last_of("/") != std::string::npos)
  19. {
  20. return filepath.substr(filepath.find_last_of("/")+1);
  21. }
  22. return "";
  23. }
  24. std::string getFilenameNoExt(const std::string& filename)
  25. {
  26. if (filename.find_last_of(".") != std::string::npos)
  27. {
  28. return filename.substr(0, filename.find_last_of("."));
  29. }
  30. return filename;
  31. }
  32. unsigned int getMaxOffset(domInputLocalOffset_Array& inputArray)
  33. {
  34. unsigned int maxOffset = 0;
  35. for (unsigned int i = 0; i < (int)inputArray.getCount(); i++ )
  36. {
  37. if ( inputArray[i]->getOffset() > maxOffset )
  38. {
  39. maxOffset = (unsigned int)inputArray[i]->getOffset();
  40. }
  41. }
  42. return maxOffset;
  43. }
  44. void DAESceneEncoder::optimizeCOLLADA(const EncoderArguments& arguments, domCOLLADA* dom)
  45. {
  46. DAEOptimizer optimizer(dom);
  47. const std::vector<std::string>& groupAnimatioNodeIds = arguments.getGroupAnimationNodeId();
  48. const std::vector<std::string>& groupAnimatioIds = arguments.getGroupAnimationAnimationId();
  49. assert(groupAnimatioNodeIds.size() == groupAnimatioIds.size());
  50. size_t size = groupAnimatioNodeIds.size();
  51. if (size > 0)
  52. {
  53. begin();
  54. for (size_t i = 0; i < size; i++)
  55. {
  56. optimizer.combineAnimations(groupAnimatioNodeIds[i], groupAnimatioIds[i]);
  57. }
  58. end("groupAnimation");
  59. }
  60. if (arguments.DAEOutputEnabled())
  61. {
  62. if (!_collada->writeTo(arguments.getFilePath(), arguments.getDAEOutputPath()))
  63. {
  64. fprintf(stderr,"Error: COLLADA failed to write the dom for file:%s\n", arguments.getDAEOutputPath().c_str());
  65. }
  66. }
  67. }
  68. void DAESceneEncoder::triangulate(DAE* dae)
  69. {
  70. daeDatabase* dataBase = dae->getDatabase();
  71. int geometryCount = (int)(dataBase->getElementCount(0, "geometry"));
  72. for (int i = 0; i < geometryCount; i++)
  73. {
  74. // Find the next geometry element.
  75. domGeometry* domGeometry;
  76. dataBase->getElement((daeElement**)&domGeometry, i, 0, "geometry");
  77. // Get the mesh out of the geometry.
  78. const domMeshRef domMesh = domGeometry->getMesh();
  79. if (!domMesh)
  80. {
  81. continue;
  82. }
  83. // Loop over all the polygons elements.
  84. int polygonsCount = (int)(domMesh->getPolygons_array().getCount());
  85. for (int j = 0; j < polygonsCount; j++)
  86. {
  87. // Get the polygons out of the mesh.
  88. domPolygons* domPolygons = domMesh->getPolygons_array()[j];
  89. // Create the triangles from the polygons
  90. createTrianglesFromPolygons(domMesh, domPolygons);
  91. }
  92. while(domMesh->getPolygons_array().getCount() > 0)
  93. {
  94. domPolygons* domPolygons = domMesh->getPolygons_array().get(0);
  95. // Remove the polygons from the mesh.
  96. domMesh->removeChildElement(domPolygons);
  97. }
  98. // Loop over all the polylist elements.
  99. int polylistCount = (int)(domMesh->getPolylist_array().getCount());
  100. for (int j = 0; j < polylistCount; j++)
  101. {
  102. // Get the polylist out of the mesh.
  103. domPolylist* domPolylist = domMesh->getPolylist_array()[j];
  104. // Create the triangles from the polygon list
  105. createTrianglesFromPolylist(domMesh, domPolylist);
  106. }
  107. while(domMesh->getPolylist_array().getCount() > 0)
  108. {
  109. domPolylist* domPolylist = domMesh->getPolylist_array().get(0);
  110. // Remove the polylist from the mesh.
  111. domMesh->removeChildElement(domPolylist);
  112. }
  113. }
  114. }
  115. void DAESceneEncoder::createTrianglesFromPolygons(domMesh* domMesh, domPolygons* domPolygons)
  116. {
  117. // Create a new <triangles> inside the mesh that has the same material as the <polygons>.
  118. domTriangles* triangles = (domTriangles*)domMesh->createAndPlace("triangles");
  119. triangles->setCount(0);
  120. triangles->setMaterial(domPolygons->getMaterial());
  121. domP* domTrianglesP = (domP*)triangles->createAndPlace("p");
  122. // Give the new <triangles> the same <_dae> and <parameters> as the old <polygons>.
  123. for (unsigned int i = 0; i < domPolygons->getInput_array().getCount(); i++)
  124. {
  125. triangles->placeElement(domPolygons->getInput_array()[i]->clone());
  126. }
  127. // Get the number of inputs and primitives for the polygons array.
  128. unsigned int inputCount = getMaxOffset(domPolygons->getInput_array()) + 1;
  129. unsigned int primitiveCount = domPolygons->getP_array().getCount();
  130. // Triangulate all the primitives, this generates all the triangles in a single <p> element.
  131. for (unsigned int j = 0; j < primitiveCount; j++)
  132. {
  133. // Check the polygons for consistancy (some exported files have had the wrong number of indices).
  134. domP* domCurrentP = domPolygons->getP_array()[j];
  135. int elementCount = (int)(domCurrentP->getValue().getCount());
  136. if ( (elementCount % inputCount) != 0 )
  137. {
  138. // Skip this case.
  139. }
  140. else
  141. {
  142. unsigned int triangleCount = (elementCount / inputCount) - 2;
  143. // Write out the primitives as triangles, just fan using the first element as the base.
  144. unsigned int index = inputCount;
  145. for (unsigned int k = 0; k < triangleCount; k++)
  146. {
  147. // First vertex.
  148. for (unsigned int l = 0; l < inputCount; l++)
  149. {
  150. domTrianglesP->getValue().append(domCurrentP->getValue()[l]);
  151. }
  152. // Second vertex.
  153. for (unsigned int l = 0; l < inputCount; l++)
  154. {
  155. domTrianglesP->getValue().append(domCurrentP->getValue()[index + l]);
  156. }
  157. // Third vertex.
  158. index += inputCount;
  159. for (unsigned int l = 0; l < inputCount; l++)
  160. {
  161. domTrianglesP->getValue().append(domCurrentP->getValue()[index + l]);
  162. }
  163. triangles->setCount(triangles->getCount() + 1);
  164. }
  165. }
  166. }
  167. }
  168. void DAESceneEncoder::createTrianglesFromPolylist(domMesh* domMesh, domPolylist* domPolylist)
  169. {
  170. // Create a new <triangles> inside the mesh that has the same material as the <polylist>.
  171. domTriangles* triangles = (domTriangles*)domMesh->createAndPlace("triangles");
  172. triangles->setMaterial(domPolylist->getMaterial());
  173. domP* domTrianglesP = (domP*)triangles->createAndPlace("p");
  174. // Give the new <triangles> the same <_dae> and <parameters> as the old <polylist>.
  175. for (int i = 0; i < (int)(domPolylist->getInput_array().getCount()); i++)
  176. {
  177. triangles->placeElement(domPolylist->getInput_array()[i]->clone());
  178. }
  179. // Get the number of inputs and primitives for the polygons array.
  180. unsigned int inputCount = getMaxOffset(domPolylist->getInput_array()) + 1;
  181. unsigned int primitiveCount = domPolylist->getVcount()->getValue().getCount();
  182. unsigned int offset = 0;
  183. unsigned int trianglesProcessed = 0;
  184. // Triangulate all the primitives, this generates all the triangles in a single <p> element.
  185. for (unsigned int j = 0; j < primitiveCount; j++)
  186. {
  187. unsigned int triangleCount = (unsigned int)domPolylist->getVcount()->getValue()[j] - 2;
  188. // Write out the primitives as triangles, just fan using the first element as the base.
  189. int index = inputCount;
  190. for (unsigned int k = 0; k < triangleCount; k++)
  191. {
  192. // First vertex.
  193. for (unsigned int l = 0; l < inputCount; l++)
  194. {
  195. domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + l]);
  196. }
  197. // Second vertex.
  198. for (unsigned int l = 0; l < inputCount; l++)
  199. {
  200. domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + index + l]);
  201. }
  202. // Third vertex.
  203. index += inputCount;
  204. for (unsigned int l = 0; l < inputCount; l++)
  205. {
  206. domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + index + l]);
  207. }
  208. trianglesProcessed++;
  209. }
  210. offset += (unsigned int)domPolylist->getVcount()->getValue()[j] * inputCount;
  211. }
  212. triangles->setCount(trianglesProcessed);
  213. }
  214. void DAESceneEncoder::write(const std::string& filepath, const EncoderArguments& arguments)
  215. {
  216. _begin = std::clock();
  217. const char* nodeId = arguments.getNodeId();
  218. bool text = arguments.textOutputEnabled();
  219. std::string filenameOnly = getFilenameFromFilePath(filepath);
  220. std::string dstPath = filepath.substr(0, filepath.find_last_of('/'));
  221. // Load the collada document
  222. _collada = new DAE();
  223. begin();
  224. _dom = _collada->open(filepath);
  225. end("Open file");
  226. if (!_dom)
  227. {
  228. fprintf(stderr,"Error: COLLADA failed to open file:%s\n", filepath.c_str());
  229. if (_collada)
  230. {
  231. delete _collada;
  232. _collada = NULL;
  233. }
  234. return;
  235. }
  236. // Run collada conditioners
  237. begin();
  238. triangulate(_collada);
  239. end("triangulate");
  240. // Optimize the dom before encoding
  241. optimizeCOLLADA(arguments, _dom);
  242. // Find the <visual_scene> element within the <scene>
  243. const domCOLLADA::domSceneRef& domScene = _dom->getScene();
  244. daeElement* scene = NULL;
  245. if (domScene && domScene->getInstance_visual_scene())
  246. {
  247. scene = domScene->getInstance_visual_scene()->getUrl().getElement();
  248. if (scene->getElementType() != COLLADA_TYPE::VISUAL_SCENE)
  249. {
  250. // This occured once where Maya exported a Node and Scene element with the same ID.
  251. fprintf(stderr,"Error: instance_visual_scene does not reference visual_scene for file:%s\n", filepath.c_str());
  252. return;
  253. }
  254. if (scene)
  255. {
  256. if (nodeId == NULL)
  257. {
  258. // If the -n <node_id> parameter was not passed then write out the entire scene.
  259. begin();
  260. loadScene((domVisual_scene*)scene);
  261. end("load scene");
  262. }
  263. else
  264. {
  265. // Resolve/Search for the node the user specified with the -n <node_id> parameter.
  266. daeSIDResolver resolver(scene, nodeId);
  267. const domNode* node = daeSafeCast<domNode>(resolver.getElement());
  268. if (node)
  269. {
  270. //createNode(node, NULL);
  271. }
  272. else
  273. {
  274. fprintf(stderr,"COLLADA File loaded to the dom, but node was not found with -n%s.\n", nodeId);
  275. }
  276. }
  277. }
  278. else
  279. {
  280. fprintf(stderr,"COLLADA File loaded to the dom, but query for the dom assets failed.\n");
  281. }
  282. }
  283. else
  284. {
  285. fprintf(stderr, "COLLADA File loaded to the dom, but missing <visual_scene>.\n");
  286. }
  287. // The animations should be loaded last
  288. begin();
  289. loadAnimations(_dom);
  290. end("loadAnimations");
  291. std::string dstFilename = dstPath;
  292. dstFilename.append(1, '/');
  293. dstFilename.append(getFilenameNoExt(filenameOnly));
  294. _gamePlayFile.adjust();
  295. if (text)
  296. {
  297. std::string outFile = dstFilename + ".xml";
  298. fprintf(stderr, "Saving debug file: %s\n", outFile.c_str());
  299. _gamePlayFile.saveText(outFile);
  300. }
  301. else
  302. {
  303. std::string outFile = dstFilename + ".gpb";
  304. fprintf(stderr, "Saving binary file: %s\n", outFile.c_str());
  305. begin();
  306. _gamePlayFile.saveBinary(outFile);
  307. end("save binary");
  308. }
  309. // Cleanup
  310. if (file)
  311. {
  312. fclose(file);
  313. }
  314. if (_collada)
  315. {
  316. delete _collada;
  317. _collada = NULL;
  318. }
  319. }
  320. void DAESceneEncoder::loadAnimations(const domCOLLADA* dom)
  321. {
  322. // Call loadAnimation on all <animation> elements in all <library_animations>
  323. const domLibrary_animations_Array& animationLibrarys = dom->getLibrary_animations_array();
  324. size_t animationLibrarysCount = animationLibrarys.getCount();
  325. for (size_t i = 0; i < animationLibrarysCount; i++)
  326. {
  327. const domLibrary_animationsRef& libraryAnimation = animationLibrarys.get(i);
  328. const domAnimation_Array& animationArray = libraryAnimation->getAnimation_array();
  329. size_t animationCount = animationArray.getCount();
  330. for (size_t j = 0; j < animationCount; j++)
  331. {
  332. const domAnimationRef& animationRef = animationArray.get(j);
  333. loadAnimation(animationRef);
  334. }
  335. }
  336. }
  337. void DAESceneEncoder::loadAnimation(const domAnimationRef animationRef)
  338. {
  339. // <channel> points to one <sampler>
  340. // <sampler> points to multiple <input> elements
  341. Animation* animation = new Animation();
  342. const char* str = animationRef->getId();
  343. if (str)
  344. {
  345. animation->setId(str);
  346. }
  347. // <channel>
  348. const domChannel_Array& channelArray = animationRef->getChannel_array();
  349. size_t channelArrayCount = channelArray.getCount();
  350. for (size_t i = 0; i < channelArrayCount; i++)
  351. {
  352. AnimationChannel* animationChannel = new AnimationChannel();
  353. const domChannelRef& channelRef = channelArray.get(i);
  354. // <sampler>
  355. const domSamplerRef sampler = getSampler(channelRef);
  356. assert(sampler);
  357. // <input>
  358. const domInputLocal_Array& inputArray = sampler->getInput_array();
  359. size_t inputArrayCount = inputArray.getCount();
  360. for (size_t j = 0; j < inputArrayCount; j++)
  361. {
  362. const domInputLocalRef& inputLocal = inputArray.get(j);
  363. // <source>
  364. const domSourceRef source = getSource(inputLocal, animationRef);
  365. std::string semantic = inputLocal->getSemantic();
  366. if (equals(semantic, "INTERPOLATION"))
  367. {
  368. // Interpolation source is a list of strings
  369. loadInterpolation(source, animationChannel);
  370. }
  371. else
  372. {
  373. // The other sources are lists of floats.
  374. std::vector<float> floats;
  375. copyFloats(source->getFloat_array(), &floats);
  376. if (equals(semantic, "INPUT"))
  377. {
  378. // TODO: Ensure param name is TIME?
  379. for (std::vector<float>::iterator k = floats.begin(); k != floats.end(); k++)
  380. {
  381. // Convert seconds to milliseconds
  382. *k = *k * 1000.0f;
  383. }
  384. animationChannel->setKeyTimes(floats);
  385. }
  386. else if (equals(semantic, "OUTPUT"))
  387. {
  388. animationChannel->setKeyValues(floats);
  389. }
  390. else if (equals(semantic, "IN_TANGENT"))
  391. {
  392. animationChannel->setTangentsIn(floats);
  393. }
  394. else if (equals(semantic, "OUT_TANGENT"))
  395. {
  396. animationChannel->setTangentsOut(floats);
  397. }
  398. }
  399. }
  400. // get target attribute enum value
  401. if (loadTarget(channelRef, animationChannel))
  402. {
  403. animation->add(animationChannel);
  404. }
  405. }
  406. if (animation->getAnimationChannelCount() > 0)
  407. {
  408. _gamePlayFile.addAnimation(animation);
  409. }
  410. else
  411. {
  412. delete animation;
  413. }
  414. }
  415. void DAESceneEncoder::loadInterpolation(const domSourceRef source, AnimationChannel* animationChannel)
  416. {
  417. // COLLADA stores the interpolations as a list of strings while GBP uses unsigned int
  418. std::vector<unsigned int> values;
  419. const domName_arrayRef nameArray = getSourceNameArray(source);
  420. assert(nameArray);
  421. const domListOfNames& names = nameArray->getValue();
  422. size_t count = (size_t)names.getCount();
  423. values.resize(count);
  424. if (count > 0)
  425. {
  426. for (size_t i = 0; i < count; i++)
  427. {
  428. values[i] = AnimationChannel::getInterpolationType(names.get(i));
  429. }
  430. // If all of the interpolation types are the same then only store the interpolation once
  431. // instead of storing the same type for each key frame.
  432. unsigned int firstType = values[0];
  433. bool allEqual = true;
  434. for (size_t i = 1; i < count; i++)
  435. {
  436. if (firstType != values[i])
  437. {
  438. allEqual = false;
  439. break;
  440. }
  441. }
  442. if (allEqual)
  443. {
  444. values.resize(1);
  445. }
  446. }
  447. animationChannel->setInterpolations(values);
  448. }
  449. bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChannel* animationChannel)
  450. {
  451. // GamePlay requires that animations are baked. Use "Bake Transforms" in your 3D modeling tool.
  452. // If the target of an animation is not a matrix then an error will be printed.
  453. const static char* TRANSFORM_WARNING_FORMAT = "Warning: Node \"%s\":\n %s %s\n";
  454. const static char* TRANSFORM_MESSAGE = "transform found but not supported.\n Use \"Bake Transforms\" option when exporting.";
  455. unsigned int targetProperty = 0;
  456. DAEChannelTarget channelTarget(channelRef);
  457. const char* targetId = channelTarget.getTargetId().c_str();
  458. // TODO: Do we want to support more than one? If yes then this needs to be fixed.
  459. for (size_t i = 0; i < channelTarget.getTargetAttributeCount(); i++)
  460. {
  461. std::string prop;
  462. channelTarget.getPropertyName(i, &prop);
  463. daeElement* attributeElement = channelTarget.getTargetAttribute(i);
  464. if (attributeElement)
  465. {
  466. daeInt type = attributeElement->typeID();
  467. if (type == domRotate::ID())
  468. {
  469. printf(TRANSFORM_WARNING_FORMAT, targetId, "Rotate", TRANSFORM_MESSAGE);
  470. return false;
  471. /*
  472. // <rotate>
  473. const domRotate* rotate = daeSafeCast<domRotate>(attributeElement);
  474. if (prop.size() > 0)
  475. {
  476. if (equalsIgnoreCase(prop, "ANGLE"))
  477. {
  478. targetProperty = Transform::ANIMATE_ROTATE;
  479. // get the rotation axis
  480. const domFloat4& f = rotate->getValue();
  481. float x = (float)f.get(0);
  482. float y = (float)f.get(1);
  483. float z = (float)f.get(2);
  484. // Get the angle values that were already read
  485. const std::vector<float>& keyValues = animationChannel->getKeyValues();
  486. size_t size = keyValues.size();
  487. assert(size > 0);
  488. // COLLADA only targeted a single prop but GBP requires all 4 rotate values.
  489. // Convert (ANGLE ANGLE ANGLE) to (X Y Z ANGLE X Y Z ANGLE X Y Z ANGLE)
  490. std::vector<float> floats(size * 4);
  491. // Duplicate rotation axis. We will replace only the angle that COLLADA is targeting.
  492. for (size_t j = 0; j < size; j++)
  493. {
  494. size_t k = j * 4;
  495. floats[k+0] = x;
  496. floats[k+1] = y;
  497. floats[k+2] = z;
  498. floats[k+3] = keyValues[j]; // angle
  499. }
  500. animationChannel->setKeyValues(floats);
  501. }
  502. }
  503. */
  504. }
  505. else if (type == domScale::ID())
  506. {
  507. printf(TRANSFORM_WARNING_FORMAT, targetId, "Scale", TRANSFORM_MESSAGE);
  508. return false;
  509. /*
  510. // <scale>
  511. //const domScale* scale = daeSafeCast<domScale>(attributeElement);
  512. if (equalsIgnoreCase(prop, "X"))
  513. {
  514. targetProperty = Transform::ANIMATE_SCALE_X;
  515. }
  516. else if (equalsIgnoreCase(prop, "Y"))
  517. {
  518. targetProperty = Transform::ANIMATE_SCALE_Y;
  519. }
  520. else if (equalsIgnoreCase(prop, "Z"))
  521. {
  522. targetProperty = Transform::ANIMATE_SCALE_Z;
  523. }
  524. else
  525. {
  526. targetProperty = Transform::ANIMATE_SCALE;
  527. }
  528. */
  529. }
  530. else if (type == domTranslate::ID())
  531. {
  532. printf(TRANSFORM_WARNING_FORMAT, targetId, "Translate", TRANSFORM_MESSAGE);
  533. return false;
  534. /*
  535. // <translate>
  536. //const domTranslate* translate = daeSafeCast<domTranslate>(attributeElement);
  537. if (equalsIgnoreCase(prop, "X"))
  538. {
  539. targetProperty = Transform::ANIMATE_TRANSLATE_X;
  540. }
  541. else if (equalsIgnoreCase(prop, "Y"))
  542. {
  543. targetProperty = Transform::ANIMATE_TRANSLATE_Y;
  544. }
  545. else if (equalsIgnoreCase(prop, "Z"))
  546. {
  547. targetProperty = Transform::ANIMATE_TRANSLATE_Z;
  548. }
  549. else
  550. {
  551. targetProperty = Transform::ANIMATE_TRANSLATE;
  552. }
  553. */
  554. }
  555. else if (type == domMatrix::ID())
  556. {
  557. // If the animation is targetting a matrix then convert it into
  558. // a scale, rotate, translate animation by decomposing the matrix.
  559. targetProperty = Transform::ANIMATE_SCALE_ROTATE_TRANSLATE;
  560. const std::vector<float>& keyValues = animationChannel->getKeyValues();
  561. assert(keyValues.size() % 16 == 0);
  562. // The matrix was 16 floats and the new values will be 10 floats
  563. size_t newSize = keyValues.size() / 16 * 10;
  564. std::vector<float> floats(newSize);
  565. size_t matrixCount = keyValues.size() / 16;
  566. for (size_t i = 0; i < matrixCount; i++)
  567. {
  568. size_t j = i * 16;
  569. // COLLADA used row-major but the Matrix class uses column-major
  570. Matrix matrix(
  571. keyValues[j+0], keyValues[j+4], keyValues[j+8], keyValues[j+12],
  572. keyValues[j+1], keyValues[j+5], keyValues[j+9], keyValues[j+13],
  573. keyValues[j+2], keyValues[j+6], keyValues[j+10], keyValues[j+14],
  574. keyValues[j+3], keyValues[j+7], keyValues[j+11], keyValues[j+15]);
  575. Vector3 scale;
  576. Quaternion rotation;
  577. Vector3 translation;
  578. matrix.decompose(&scale, &rotation, &translation);
  579. size_t k = i * 10;
  580. floats[k+0] = scale.x;
  581. floats[k+1] = scale.y;
  582. floats[k+2] = scale.z;
  583. floats[k+3] = rotation.x;
  584. floats[k+4] = rotation.y;
  585. floats[k+5] = rotation.z;
  586. floats[k+6] = rotation.w;
  587. floats[k+7] = translation.x;
  588. floats[k+8] = translation.y;
  589. floats[k+9] = translation.z;
  590. }
  591. animationChannel->setKeyValues(floats);
  592. }
  593. }
  594. }
  595. animationChannel->setTargetAttribute(targetProperty);
  596. animationChannel->setTargetId(channelTarget.getTargetId());
  597. //animationChannel->removeDuplicates();
  598. return true;
  599. }
  600. void DAESceneEncoder::begin()
  601. {
  602. #ifdef ENCODER_PRINT_TIME
  603. _begin = std::clock();
  604. #endif
  605. }
  606. void DAESceneEncoder::end(const char* str)
  607. {
  608. #ifdef ENCODER_PRINT_TIME
  609. clock_t time = std::clock() - _begin;
  610. fprintf(stderr,"%5d %s\n", time, str);
  611. #endif
  612. }
  613. void DAESceneEncoder::copyFloats(const domFloat_array* source, std::vector<float>* target)
  614. {
  615. std::vector<float>& t = *target;
  616. size_t count = (size_t)source->getCount();
  617. t.resize(count);
  618. const domListOfFloats& listOfFloats = source->getValue();
  619. for (size_t i = 0; i < count; i++)
  620. {
  621. t[i] = (float)listOfFloats.get(i);
  622. }
  623. }
  624. void DAESceneEncoder::loadScene(const domVisual_scene* visualScene)
  625. {
  626. Scene* scene = new Scene();
  627. const domNode_Array& nodes = visualScene->getNode_array();
  628. scene->setId(visualScene->getId());
  629. size_t childCount = nodes.getCount();
  630. for (size_t i = 0; i < childCount; i++)
  631. {
  632. scene->add(loadNode(nodes[i], NULL));
  633. }
  634. Node* activeCameraNode = findSceneActiveCameraNode(visualScene, scene);
  635. if (activeCameraNode)
  636. {
  637. scene->setActiveCameraNode(activeCameraNode);
  638. }
  639. _gamePlayFile.addScene(scene);
  640. }
  641. Node* DAESceneEncoder::findSceneActiveCameraNode(const domVisual_scene* visualScene, Scene* scene)
  642. {
  643. // Loops through each evaluate_scene's render until an active camera node is found.
  644. // Returns the first one found.
  645. // Find the active camera
  646. const domVisual_scene::domEvaluate_scene_Array& evaluateScenes = visualScene->getEvaluate_scene_array();
  647. size_t evaluateSceneCount = evaluateScenes.getCount();
  648. for (size_t i = 0; i < evaluateSceneCount; i++)
  649. {
  650. const domVisual_scene::domEvaluate_scene::domRender_Array& renders = evaluateScenes[i]->getRender_array();
  651. size_t renderCount = renders.getCount();
  652. for (size_t j = 0; j < renderCount; j++)
  653. {
  654. xsAnyURI cameraNodeURI = renders[i]->getCamera_node();
  655. domNode* nodeRef = daeSafeCast<domNode>(cameraNodeURI.getElement());
  656. if (nodeRef)
  657. {
  658. std::string id = nodeRef->getId();
  659. Node* node = _gamePlayFile.getNode(id.c_str());
  660. if (node)
  661. {
  662. return node;
  663. }
  664. }
  665. }
  666. }
  667. // Find the first node in the scene that contains a camera.
  668. return scene->getFirstCameraNode();
  669. }
  670. Node* DAESceneEncoder::loadNode(domNode* n, Node* parent)
  671. {
  672. Node* node = NULL;
  673. // Check if this node has already been loaded
  674. const char* id = n->getID();
  675. if (id && strlen(id) > 0)
  676. {
  677. node = _gamePlayFile.getNode(n->getID());
  678. if (node)
  679. {
  680. return node;
  681. }
  682. }
  683. // Load the node
  684. node = new Node();
  685. if (parent)
  686. {
  687. parent->addChild(node);
  688. }
  689. if (n->getType() == NODETYPE_JOINT)
  690. {
  691. node->setIsJoint(true);
  692. }
  693. // Set node id
  694. node->setId(n->getId());
  695. // If this node has an id then add it to the ref table
  696. _gamePlayFile.addNode(node);
  697. transformNode(n, node);
  698. loadControllerInstance(n, node);
  699. loadCameraInstance(n, node);
  700. loadLightInstance(n, node);
  701. loadGeometryInstance(n, node);
  702. // Load child nodes
  703. const domNode_Array& childNodes = n->getNode_array();
  704. size_t childCount = childNodes.getCount();
  705. for (size_t i = 0; i < childCount; i++)
  706. {
  707. loadNode(childNodes.get(i), node);
  708. }
  709. return node;
  710. }
  711. void DAESceneEncoder::transformNode(domNode* domNode, Node* node)
  712. {
  713. // Apply the transform.
  714. // Note that we only honor the first matrix transform specified for the DOM node.
  715. const domMatrix_Array& matrixArray = domNode->getMatrix_array();
  716. if (matrixArray.getCount() > 0)
  717. {
  718. const domMatrixRef& matrix = matrixArray.get(0);
  719. if (!matrix)
  720. {
  721. return;
  722. }
  723. const domFloat4x4& tx = matrix->getValue();
  724. float transform[] = {(float)tx.get(0), (float)tx.get(4), (float)tx.get(8), (float)tx.get(12),
  725. (float)tx.get(1), (float)tx.get(5), (float)tx.get(9), (float)tx.get(13),
  726. (float)tx.get(2), (float)tx.get(6), (float)tx.get(10), (float)tx.get(14),
  727. (float)tx.get(3), (float)tx.get(7), (float)tx.get(11), (float)tx.get(15)};
  728. node->setTransformMatrix(transform);
  729. }
  730. else
  731. {
  732. Matrix transform;
  733. calcTransform(domNode, transform);
  734. node->setTransformMatrix(transform.m);
  735. }
  736. // TODO: Handle transforming by other types (SRT, etc) (see "Node" child elements spec)
  737. /*Vector3 scale;
  738. Quaternion rotation;
  739. Vector3 translation;
  740. localTransform.Decompose(&scale, &rotation, &translation);
  741. node->SetScale(scale);
  742. node->SetRotation(rotation);
  743. node->SetTranslation(translation);*/
  744. }
  745. void DAESceneEncoder::calcTransform(domNode* domNode, Matrix& dstTransform)
  746. {
  747. daeTArray<daeSmartRef<daeElement>> children;
  748. domNode->getChildren(children);
  749. size_t childCount = children.getCount();
  750. for (size_t i = 0; i < childCount; i++)
  751. {
  752. daeElementRef childElement = children[i];
  753. switch (childElement->getElementType())
  754. {
  755. case COLLADA_TYPE::TRANSLATE:
  756. {
  757. domTranslateRef translateNode = daeSafeCast<domTranslate>(childElement);
  758. float x = (float)translateNode->getValue().get(0);
  759. float y = (float)translateNode->getValue().get(1);
  760. float z = (float)translateNode->getValue().get(2);
  761. dstTransform.translate(x, y, z);
  762. break;
  763. }
  764. case COLLADA_TYPE::ROTATE:
  765. {
  766. domRotateRef rotateNode = daeSafeCast<domRotate>(childElement);
  767. float x = (float)rotateNode->getValue().get(0);
  768. float y = (float)rotateNode->getValue().get(1);
  769. float z = (float)rotateNode->getValue().get(2);
  770. float angle = MATH_DEG_TO_RAD((float)rotateNode->getValue().get(3)); // COLLADA uses degrees, gameplay uses radians
  771. if (x == 1.0f && y == 0.0f && z == 0.0f)
  772. {
  773. dstTransform.rotateX(angle);
  774. }
  775. else if (x == 0.0f && y == 1.0f && z == 0.0f)
  776. {
  777. dstTransform.rotateY(angle);
  778. }
  779. else if (x == 0.0f && y == 0.0f && z == 1.0f)
  780. {
  781. dstTransform.rotateZ(angle);
  782. }
  783. else
  784. {
  785. dstTransform.rotate(x, y, z, angle);
  786. }
  787. break;
  788. }
  789. case COLLADA_TYPE::SCALE:
  790. {
  791. domScaleRef scaleNode = daeSafeCast<domScale>(childElement);
  792. float x = (float)scaleNode->getValue().get(0);
  793. float y = (float)scaleNode->getValue().get(1);
  794. float z = (float)scaleNode->getValue().get(2);
  795. dstTransform.scale(x, y, z);
  796. break;
  797. }
  798. case COLLADA_TYPE::SKEW:
  799. warning("Skew transform found but not supported.");
  800. break;
  801. case COLLADA_TYPE::LOOKAT:
  802. warning("Lookat transform found but not supported.");
  803. break;
  804. default:
  805. break;
  806. }
  807. }
  808. }
  809. void DAESceneEncoder::loadCameraInstance(const domNode* n, Node* node)
  810. {
  811. // Does this node have any camera instances?
  812. const domInstance_camera_Array& instanceCameras = n->getInstance_camera_array();
  813. size_t instanceCameraCount = instanceCameras.getCount();
  814. for (size_t i = 0; i < instanceCameraCount; i++)
  815. {
  816. // Get the camrea object
  817. const domInstance_camera* cameraInstanceRef = instanceCameras.get(i);
  818. xsAnyURI cameraURI = cameraInstanceRef->getUrl();
  819. domCamera* cameraRef = daeSafeCast<domCamera>(cameraURI.getElement());
  820. if (cameraRef)
  821. {
  822. CameraInstance* cameraInstance = loadCamera(cameraRef);
  823. if (cameraInstance)
  824. {
  825. node->setCameraInstance(cameraInstance);
  826. }
  827. }
  828. else
  829. {
  830. // warning
  831. }
  832. }
  833. }
  834. void DAESceneEncoder::loadLightInstance(const domNode* n, Node* node)
  835. {
  836. // Does this node have any light instances?
  837. const domInstance_light_Array& instanceLights = n->getInstance_light_array();
  838. size_t instanceLightCount = instanceLights.getCount();
  839. for (size_t i = 0; i < instanceLightCount; i++)
  840. {
  841. // Get the camrea object
  842. const domInstance_light* lightInstanceRef = instanceLights.get(i);
  843. xsAnyURI lightURI = lightInstanceRef->getUrl();
  844. domLight* lightRef = daeSafeCast<domLight>(lightURI.getElement());
  845. if (lightRef)
  846. {
  847. LightInstance* lightInstance = loadLight(lightRef);
  848. if (lightInstance)
  849. {
  850. node->setLightInstance(lightInstance);
  851. }
  852. }
  853. else
  854. {
  855. // warning
  856. }
  857. }
  858. }
  859. void DAESceneEncoder::loadGeometryInstance(const domNode* n, Node* node)
  860. {
  861. // Does this node have any geometry instances?
  862. const domInstance_geometry_Array& instanceGeometries = n->getInstance_geometry_array();
  863. size_t instanceGeometryCount = instanceGeometries.getCount();
  864. for (size_t i = 0; i < instanceGeometryCount; i++)
  865. {
  866. // Get the geometry object
  867. const domInstance_geometryRef geometryInstanceRef = instanceGeometries.get(i);
  868. xsAnyURI geometryURI = geometryInstanceRef->getUrl();
  869. domGeometry* geometry = daeSafeCast<domGeometry>(geometryURI.getElement());
  870. // Load the model from this geometry
  871. if (geometry)
  872. {
  873. Model* model = loadGeometry(geometry, geometryInstanceRef->getBind_material());
  874. if (model)
  875. {
  876. node->setModel(model);
  877. }
  878. }
  879. else
  880. {
  881. warning(std::string("Failed to resolve geometry url: ") + geometryURI.getURI());
  882. }
  883. }
  884. }
  885. void DAESceneEncoder::loadControllerInstance(const domNode* n, Node* node)
  886. {
  887. // Does this node have any controller instances?
  888. const domInstance_controller_Array& instanceControllers = n->getInstance_controller_array();
  889. size_t instanceControllerCount = instanceControllers.getCount();
  890. for (size_t i = 0; i < instanceControllerCount; i++)
  891. {
  892. const domInstance_controllerRef instanceControllerRef = instanceControllers.get(i);
  893. xsAnyURI controllerURI = instanceControllerRef->getUrl();
  894. domController* controllerRef = daeSafeCast<domController>(controllerURI.getElement());
  895. if (controllerRef)
  896. {
  897. const domSkin* skinElement = controllerRef->getSkin();
  898. if (skinElement)
  899. {
  900. Model* model = loadSkin(skinElement);
  901. if (model)
  902. {
  903. domInstance_controller::domSkeleton_Array& skeletons = instanceControllerRef->getSkeleton_array();
  904. if (skeletons.getCount() == 0)
  905. {
  906. warning("No skeletons found for instance controller: ");
  907. delete model;
  908. continue;
  909. }
  910. // Load the skeleton for this skin
  911. domInstance_controller::domSkeletonRef skeleton = getSkeleton(instanceControllerRef);
  912. assert(skeleton);
  913. loadSkeleton(skeleton, model->getSkin());
  914. node->setModel(model);
  915. }
  916. }
  917. }
  918. else
  919. {
  920. // warning
  921. }
  922. _jointLookupTable.clear();
  923. _jointInverseBindPoseMatrices.clear();
  924. }
  925. }
  926. CameraInstance* DAESceneEncoder::loadCamera(const domCamera* cameraRef)
  927. {
  928. ///////////////////////////// CAMERA
  929. // check if camera is already added to gamePlayFile
  930. const char* id = cameraRef->getId();
  931. Camera* camera = _gamePlayFile.getCamera(id);
  932. if (camera == NULL)
  933. {
  934. camera = new Camera();
  935. camera->setId(id);
  936. // Optics
  937. const domCamera::domOpticsRef opticsRef = cameraRef->getOptics();
  938. if (opticsRef.cast())
  939. {
  940. const domCamera::domOptics::domTechnique_commonRef techRef = opticsRef->getTechnique_common();
  941. // Orthographics
  942. const domCamera::domOptics::domTechnique_common::domOrthographicRef orthographicRef = techRef->getOrthographic();
  943. if (orthographicRef.cast())
  944. {
  945. camera->setOrthographic();
  946. camera->setNearPlane((float)orthographicRef->getZnear()->getValue());
  947. camera->setFarPlane((float)orthographicRef->getZfar()->getValue());
  948. const domTargetableFloatRef xmag = orthographicRef->getXmag();
  949. const domTargetableFloatRef ymag = orthographicRef->getYmag();
  950. // Viewport width
  951. if (xmag.cast())
  952. {
  953. camera->setViewportWidth((float)xmag->getValue());
  954. }
  955. // Viewport height
  956. if (ymag.cast())
  957. {
  958. camera->setViewportHeight((float)ymag->getValue());
  959. }
  960. // TODO: Viewport x and y?
  961. }
  962. // Perspective
  963. const domCamera::domOptics::domTechnique_common::domPerspectiveRef perspectiveRef = techRef->getPerspective();
  964. if (perspectiveRef.cast())
  965. {
  966. camera->setPerspective();
  967. camera->setNearPlane((float)perspectiveRef->getZnear()->getValue());
  968. camera->setFarPlane((float)perspectiveRef->getZfar()->getValue());
  969. float aspectRatio = -1.0f;
  970. if (perspectiveRef->getAspect_ratio().cast())
  971. {
  972. aspectRatio = (float)perspectiveRef->getAspect_ratio()->getValue();
  973. camera->setAspectRatio(aspectRatio);
  974. }
  975. if (perspectiveRef->getYfov().cast())
  976. {
  977. camera->setFieldOfView((float)perspectiveRef->getYfov()->getValue());
  978. }
  979. else if (perspectiveRef->getXfov().cast() && aspectRatio > 0.0f)
  980. {
  981. // The gameplaybinary stores the yfov but collada might have specified
  982. // an xfov and an aspect ratio. So use those to calculate the yfov.
  983. float xfov = (float)perspectiveRef->getXfov()->getValue();
  984. float yfov = xfov / aspectRatio;
  985. camera->setFieldOfView(yfov);
  986. }
  987. }
  988. }
  989. _gamePlayFile.addCamera(camera);
  990. }
  991. CameraInstance* cameraInstance = new CameraInstance();
  992. cameraInstance->setCamera(camera);
  993. return cameraInstance;
  994. }
  995. LightInstance* DAESceneEncoder::loadLight(const domLight* lightRef)
  996. {
  997. ///////////////////////////// LIGHT
  998. // check if light is already added to gamePlayFile
  999. const char* id = lightRef->getId();
  1000. Light* light = _gamePlayFile.getLight(id);
  1001. if (light == NULL)
  1002. {
  1003. light = new Light();
  1004. light->setId(lightRef->getId());
  1005. const domLight::domTechnique_commonRef techRef = lightRef->getTechnique_common();
  1006. // Ambient light
  1007. {
  1008. const domLight::domTechnique_common::domAmbientRef ambientRef = techRef->getAmbient();
  1009. if (ambientRef.cast())
  1010. {
  1011. light->setAmbientLight();
  1012. // color
  1013. const domTargetableFloat3Ref float3Ref = ambientRef->getColor();
  1014. const domFloat3& color3 = float3Ref->getValue();
  1015. light->setColor((float)color3.get(0), (float)color3.get(1), (float)color3.get(2));
  1016. }
  1017. }
  1018. // Directional light
  1019. {
  1020. const domLight::domTechnique_common::domDirectionalRef direcitonalRef = techRef->getDirectional();
  1021. if (direcitonalRef.cast())
  1022. {
  1023. light->setDirectionalLight();
  1024. // color
  1025. const domTargetableFloat3Ref float3Ref = direcitonalRef->getColor();
  1026. const domFloat3& color3 = float3Ref->getValue();
  1027. light->setColor((float)color3.get(0), (float)color3.get(1), (float)color3.get(2));
  1028. }
  1029. }
  1030. // Spot light
  1031. {
  1032. const domLight::domTechnique_common::domSpotRef spotRef = techRef->getSpot();
  1033. if (spotRef.cast())
  1034. {
  1035. light->setSpotLight();
  1036. // color
  1037. const domTargetableFloat3Ref float3Ref = spotRef->getColor();
  1038. const domFloat3& color3 = float3Ref->getValue();
  1039. light->setColor((float)color3.get(0), (float)color3.get(1), (float)color3.get(2));
  1040. const domTargetableFloatRef& constAtt = spotRef->getConstant_attenuation();
  1041. if (constAtt.cast())
  1042. {
  1043. light->setConstantAttenuation((float)constAtt->getValue());
  1044. }
  1045. const domTargetableFloatRef& linearAtt = spotRef->getLinear_attenuation();
  1046. if (linearAtt.cast())
  1047. {
  1048. light->setLinearAttenuation((float)linearAtt->getValue());
  1049. }
  1050. const domTargetableFloatRef& quadAtt = spotRef->getQuadratic_attenuation();
  1051. if (quadAtt.cast())
  1052. {
  1053. light->setQuadraticAttenuation((float)quadAtt->getValue());
  1054. }
  1055. const domTargetableFloatRef& falloffAngle = spotRef->getFalloff_angle();
  1056. if (falloffAngle.cast())
  1057. {
  1058. light->setFalloffAngle((float)falloffAngle->getValue());
  1059. }
  1060. const domTargetableFloatRef& falloffExp = spotRef->getFalloff_exponent();
  1061. if (falloffExp.cast())
  1062. {
  1063. light->setFalloffExponent((float)falloffExp->getValue());
  1064. }
  1065. }
  1066. }
  1067. // Point light
  1068. {
  1069. const domLight::domTechnique_common::domPointRef pointRef = techRef->getPoint();
  1070. if (pointRef.cast())
  1071. {
  1072. light->setPointLight();
  1073. // color
  1074. const domTargetableFloat3Ref float3Ref = pointRef->getColor();
  1075. const domFloat3& color3 = float3Ref->getValue();
  1076. light->setColor((float)color3.get(0), (float)color3.get(1), (float)color3.get(2));
  1077. const domTargetableFloatRef& constAtt = pointRef->getConstant_attenuation();
  1078. if (constAtt.cast())
  1079. {
  1080. light->setConstantAttenuation((float)constAtt->getValue());
  1081. }
  1082. const domTargetableFloatRef& linearAtt = pointRef->getLinear_attenuation();
  1083. if (linearAtt.cast())
  1084. {
  1085. light->setLinearAttenuation((float)linearAtt->getValue());
  1086. }
  1087. const domTargetableFloatRef& quadAtt = pointRef->getQuadratic_attenuation();
  1088. if (quadAtt.cast())
  1089. {
  1090. light->setQuadraticAttenuation((float)quadAtt->getValue());
  1091. }
  1092. }
  1093. }
  1094. _gamePlayFile.addLight(light);
  1095. }
  1096. LightInstance* lightInstance = new LightInstance();
  1097. lightInstance->setLight(light);
  1098. return lightInstance;
  1099. }
  1100. void DAESceneEncoder::loadSkeleton(domInstance_controller::domSkeleton* skeletonElement, MeshSkin* skin)
  1101. {
  1102. xsAnyURI skeletonUri = skeletonElement->getValue();
  1103. daeString skeletonId = skeletonUri.getID();
  1104. daeSIDResolver resolver(skeletonUri.getElement(), skeletonId);
  1105. domNode* rootNode = daeSafeCast<domNode>(resolver.getElement());
  1106. // Get the lookup scene id (sid) and joint index.
  1107. std::string id = std::string(skeletonId);
  1108. // Has the skeleton (root joint) been loaded yet?
  1109. Node* skeleton = (Node*)_gamePlayFile.getFromRefTable(id);
  1110. // The skeleton node is not loaded yet, so let's load it now
  1111. if (skeleton == NULL)
  1112. {
  1113. // Find the top most parent of rootNode that has not yet been loaded
  1114. domNode* topLevelParent = rootNode;
  1115. while (
  1116. topLevelParent->getParent() &&
  1117. topLevelParent->getParent()->getElementType() == COLLADA_TYPE::NODE &&
  1118. _gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID()) == NULL)
  1119. {
  1120. topLevelParent = (domNode*)topLevelParent->getParent();
  1121. }
  1122. // Is the parent of this node loaded yet?
  1123. Node* parentNode = NULL;
  1124. if (topLevelParent->getParent() &&
  1125. topLevelParent->getParent()->getElementType() == COLLADA_TYPE::NODE &&
  1126. _gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID()) != NULL)
  1127. {
  1128. parentNode = (Node*)_gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID());
  1129. }
  1130. // Finally, load the node hierarchy that includes the skeleton
  1131. skeleton = loadNode(topLevelParent, parentNode);
  1132. }
  1133. if (skeleton == NULL)
  1134. {
  1135. // This shouldn't really happen..
  1136. skeleton = new Node();
  1137. skeleton->setId(id);
  1138. _gamePlayFile.addNode(skeleton);
  1139. }
  1140. // Resolve and set joints array for skin
  1141. std::list<Node*> _joints;
  1142. const std::list<std::string>& jointNames = skin->getJointNames();
  1143. for (std::list<std::string>::const_iterator i = jointNames.begin(); i != jointNames.end(); i++)
  1144. {
  1145. Object* obj = _gamePlayFile.getFromRefTable(*i);
  1146. if (obj)
  1147. {
  1148. Node* node = (Node*)obj;
  1149. _joints.push_back(node);
  1150. }
  1151. }
  1152. skin->setJoints(_joints);
  1153. }
  1154. Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
  1155. {
  1156. ///////////////////////////// SKIN
  1157. Model* model = new Model();
  1158. MeshSkin* skin = new MeshSkin();
  1159. // Bind Shape Matrix
  1160. const domSkin::domBind_shape_matrix* bindShapeMatrix = skinElement->getBind_shape_matrix();
  1161. if (bindShapeMatrix)
  1162. {
  1163. const domFloat4x4& m = bindShapeMatrix->getValue();
  1164. float transform[] = {(float)m.get(0), (float)m.get(4), (float)m.get(8), (float)m.get(12),
  1165. (float)m.get(1), (float)m.get(5), (float)m.get(9), (float)m.get(13),
  1166. (float)m.get(2), (float)m.get(6), (float)m.get(10), (float)m.get(14),
  1167. (float)m.get(3), (float)m.get(7), (float)m.get(11), (float)m.get(15)};
  1168. skin->setBindShape(transform);
  1169. }
  1170. // Read and set our joints
  1171. domSkin::domJointsRef _joints = skinElement->getJoints();
  1172. domInputLocal_Array& jointInputs = _joints->getInput_array();
  1173. // Process "JOINT" input semantic first (we need to do this to set the joint count)
  1174. unsigned int jointCount = 0;
  1175. for (unsigned int i = 0; i < jointInputs.getCount(); i++)
  1176. {
  1177. domInputLocalRef input = jointInputs.get(i);
  1178. std::string inputSemantic = std::string(input->getSemantic());
  1179. domURIFragmentType* sourceURI = &input->getSource();
  1180. sourceURI->resolveElement();
  1181. const domSourceRef source = (domSource*)(daeElement*)sourceURI->getElement();
  1182. if (equals(inputSemantic, "JOINT"))
  1183. {
  1184. // Get the joint Ids's
  1185. std::list<std::string> list;
  1186. getJointNames(source, list);
  1187. // Go through the joint list and conver them from sid to id because the sid information is
  1188. // lost when converting to the gameplay binary format.
  1189. for (std::list<std::string>::iterator i = list.begin(); i != list.end(); i++)
  1190. {
  1191. daeSIDResolver resolver(source->getDocument()->getDomRoot(), i->c_str());
  1192. daeElement* element = resolver.getElement();
  1193. if (element && element->getElementType() == COLLADA_TYPE::NODE)
  1194. {
  1195. domNodeRef node = daeSafeCast<domNode>(element);
  1196. const char* nodeId = node->getId();
  1197. if (nodeId && !equals(*i, nodeId))
  1198. {
  1199. *i = nodeId;
  1200. }
  1201. }
  1202. }
  1203. // Get the joint count and set the capacities for both the
  1204. jointCount = list.size();
  1205. _jointInverseBindPoseMatrices.reserve(jointCount);
  1206. unsigned int j = 0;
  1207. for (std::list<std::string>::const_iterator i = list.begin(); i != list.end(); i++)
  1208. {
  1209. _jointLookupTable[*i] = j++;
  1210. }
  1211. skin->setJointNames(list);
  1212. }
  1213. }
  1214. // Make sure we have some joints
  1215. if (jointCount == 0)
  1216. {
  1217. warning("No joints found for skin: ");
  1218. return NULL;
  1219. }
  1220. // Process "INV_BIND_MATRIX" next
  1221. for (unsigned int i = 0; i < jointInputs.getCount(); i++)
  1222. {
  1223. domInputLocalRef input = jointInputs.get(i);
  1224. std::string inputSemantic = std::string(input->getSemantic());
  1225. domURIFragmentType* sourceURI = &input->getSource();
  1226. sourceURI->resolveElement();
  1227. domSource* source = (domSource*)(daeElement*)sourceURI->getElement();
  1228. if (equals(inputSemantic, "INV_BIND_MATRIX"))
  1229. {
  1230. domListOfFloats& matrixFloats = source->getFloat_array()->getValue();
  1231. //unsigned int matrixFloatsCount = (unsigned int)source->getFloat_array()->getCount();
  1232. unsigned int jointIndex = 0;
  1233. for (unsigned int j = 0; j < jointCount; j++)
  1234. {
  1235. Matrix matrix((float)matrixFloats.get(jointIndex + 0), (float)matrixFloats.get(jointIndex + 4), (float)matrixFloats.get(jointIndex + 8), (float)matrixFloats.get(jointIndex + 12),
  1236. (float)matrixFloats.get(jointIndex + 1), (float)matrixFloats.get(jointIndex + 5), (float)matrixFloats.get(jointIndex + 9), (float)matrixFloats.get(jointIndex + 13),
  1237. (float)matrixFloats.get(jointIndex + 2), (float)matrixFloats.get(jointIndex + 6), (float)matrixFloats.get(jointIndex + 10), (float)matrixFloats.get(jointIndex + 14),
  1238. (float)matrixFloats.get(jointIndex + 3), (float)matrixFloats.get(jointIndex + 7), (float)matrixFloats.get(jointIndex + 11), (float)matrixFloats.get(jointIndex + 15));
  1239. _jointInverseBindPoseMatrices.push_back(matrix);
  1240. jointIndex += 16;
  1241. }
  1242. }
  1243. }
  1244. skin->setBindPoses(_jointInverseBindPoseMatrices);
  1245. // Get the vertex weights inputs
  1246. domSkin::domVertex_weights* vertexWeights = skinElement->getVertex_weights();
  1247. domInputLocalOffset_Array& vertexWeightsInputs = vertexWeights->getInput_array();
  1248. unsigned int vertexWeightsCount = (unsigned int)vertexWeights->getCount();
  1249. domListOfFloats jointWeights;
  1250. for (unsigned int i = 0; i < jointInputs.getCount(); i++)
  1251. {
  1252. domInputLocalOffsetRef input = vertexWeightsInputs.get(i);
  1253. std::string inputSemantic = std::string(input->getSemantic());
  1254. domURIFragmentType* sourceURI = &input->getSource();
  1255. sourceURI->resolveElement();
  1256. domSource* source = (domSource*)(daeElement*)sourceURI->getElement();
  1257. if (equals(inputSemantic, "WEIGHT"))
  1258. {
  1259. domFloat_array* weights = source->getFloat_array();
  1260. if (weights)
  1261. {
  1262. jointWeights = weights->getValue();
  1263. }
  1264. }
  1265. }
  1266. // Get the number of joint influences per vertex
  1267. domSkin::domVertex_weights::domVcount* vCountElement = vertexWeights->getVcount();
  1268. domListOfUInts skinVertexInfluenceCounts = vCountElement->getValue();
  1269. // Get the joint/weight pair data.
  1270. domSkin::domVertex_weights::domV* vElement = vertexWeights->getV();
  1271. domListOfInts skinVertexJointWeightPairIndices = vElement->getValue();
  1272. // Get the vertex influence count for any given vertex (up to max of 4)
  1273. unsigned int maxVertexInfluencesCount = SCENE_SKIN_VERTEXINFLUENCES_MAX;
  1274. skin->setVertexInfluenceCount(maxVertexInfluencesCount);
  1275. // Get the vertex blend weights and joint indices and
  1276. // allocate our vertex blend weights and blend indices arrays.
  1277. // These will be used and cleaned up later in LoadMesh
  1278. int skinVertexInfluenceCountTotal = skinVertexInfluenceCounts.getCount();
  1279. int totalVertexInfluencesCount = vertexWeightsCount * maxVertexInfluencesCount;
  1280. _vertexBlendWeights = new float[totalVertexInfluencesCount];
  1281. _vertexBlendIndices = new unsigned int[totalVertexInfluencesCount];
  1282. // Preset the default blend weights to 0.0f (no effect) and blend indices to 0 (uses the first which when multiplied
  1283. // will have no effect anyhow.
  1284. memset(_vertexBlendWeights, 0, totalVertexInfluencesCount * sizeof(float));
  1285. memset(_vertexBlendIndices , 0, totalVertexInfluencesCount * sizeof(unsigned int));
  1286. int vOffset = 0;
  1287. int weightOffset = 0;
  1288. // Go through all the skin vertex influence weights from the indexed data.
  1289. for (int i = 0; i < skinVertexInfluenceCountTotal; i++)
  1290. {
  1291. // Get the influence count and directly get the vertext blend weights and indices.
  1292. unsigned int vertexInfluenceCount = (unsigned int)skinVertexInfluenceCounts.get(i);
  1293. float vertexInfluencesTotalWeights = 0.0f;
  1294. std::vector<SkinnedVertexWeightPair> vertexInfluences;
  1295. //vertexInfluences.SetCapacity(vertexInfluenceCount);
  1296. // Get the index/weight pairs and some the weight totals while at it.
  1297. for (unsigned int j = 0; j < vertexInfluenceCount; j++)
  1298. {
  1299. float weight = (float)jointWeights.get((unsigned int)skinVertexJointWeightPairIndices[vOffset + 1]);
  1300. int index = (int)skinVertexJointWeightPairIndices[vOffset];
  1301. // Set invalid index corresponding weights to zero
  1302. if (index < 0 || index > (int)vertexWeightsCount)
  1303. {
  1304. weight = 0.0f;
  1305. index = 0;
  1306. }
  1307. SkinnedVertexWeightPair pair(weight, index);
  1308. vertexInfluences.push_back(pair);
  1309. vertexInfluencesTotalWeights += weight;
  1310. vOffset+=2;
  1311. }
  1312. // Get up the the maximum vertex weight influence count.
  1313. for (unsigned int j = 0; j < maxVertexInfluencesCount; j++)
  1314. {
  1315. if (j < vertexInfluenceCount)
  1316. {
  1317. SkinnedVertexWeightPair pair = vertexInfluences[j];
  1318. _vertexBlendIndices[weightOffset] = pair.BlendIndex;
  1319. if (vertexInfluencesTotalWeights > 0.0f)
  1320. {
  1321. _vertexBlendWeights[weightOffset] = pair.BlendWeight;
  1322. }
  1323. else
  1324. {
  1325. if (j == 0)
  1326. {
  1327. _vertexBlendWeights[weightOffset] = 1.0f;
  1328. }
  1329. else
  1330. {
  1331. _vertexBlendWeights[weightOffset] = 0.0f;
  1332. }
  1333. }
  1334. }
  1335. weightOffset++;
  1336. }
  1337. }
  1338. model->setSkin(skin);
  1339. ///////////////////////////////////////////////////////////
  1340. // get geometry
  1341. xsAnyURI geometryURI = skinElement->getSource();
  1342. domGeometry* geometry = daeSafeCast<domGeometry>(geometryURI.getElement());
  1343. if (geometry)
  1344. {
  1345. const domMesh* meshElement = geometry->getMesh();
  1346. if (meshElement)
  1347. {
  1348. Mesh* mesh = loadMesh(meshElement, geometry->getId());
  1349. if (mesh)
  1350. {
  1351. model->setMesh(mesh);
  1352. }
  1353. }
  1354. }
  1355. ///////////////////////////////////////////////////////////
  1356. return model;
  1357. }
  1358. Model* DAESceneEncoder::loadGeometry(const domGeometry* geometry, const domBind_materialRef bindMaterial)
  1359. {
  1360. // Does this geometry have a valid mesh?
  1361. // Get the mesh for the geometry (if it has one)
  1362. const domMesh* meshElement = geometry->getMesh();
  1363. if (meshElement == NULL)
  1364. {
  1365. warning(std::string("No mesh found for geometry: ") + geometry->getId());
  1366. return NULL;
  1367. }
  1368. ///////////////////////////// GEOMETRY
  1369. // Load the mesh for this model
  1370. Mesh* mesh = loadMesh(meshElement, geometry->getId());
  1371. if (mesh == NULL)
  1372. {
  1373. return NULL;
  1374. }
  1375. // Mesh instance
  1376. Model* model = new Model();
  1377. model->setMesh(mesh);
  1378. return model;
  1379. }
  1380. Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& geometryId)
  1381. {
  1382. const domTriangles_Array& trianglesArray = meshElement->getTriangles_array();
  1383. unsigned int trianglesArrayCount = (unsigned int)trianglesArray.getCount();
  1384. // Ensure the data is exported as triangles.
  1385. if (trianglesArrayCount == 0)
  1386. {
  1387. warning(std::string("Geometry mesh has no triangles: ") + geometryId);
  1388. return NULL;
  1389. }
  1390. // Check if this mesh already exists
  1391. Mesh* mesh = _gamePlayFile.getMesh(geometryId.c_str());
  1392. if (mesh)
  1393. {
  1394. return mesh;
  1395. }
  1396. mesh = new Mesh();
  1397. mesh->setId(geometryId.c_str());
  1398. std::vector<DAEPolygonInput*> polygonInputs;
  1399. // Quickly just go through each triangles array and make sure they have the same number of inputs
  1400. // with the same layout.
  1401. // const domSource_Array& sourceArray = meshElement->getSource_array();
  1402. const domInputLocal_Array& vertexArray = meshElement->getVertices()->getInput_array();
  1403. unsigned int inputCount = (unsigned int)-1;
  1404. // Loop through our set of triangle lists (each list of triangles corresponds to a single MeshPart)
  1405. for (unsigned int i = 0; i < trianglesArrayCount; i++)
  1406. {
  1407. const domTrianglesRef& triangles = trianglesArray.get(i);
  1408. const domInputLocalOffset_Array& inputArray = triangles->getInput_array();
  1409. // If not set then determine the number of input for all the triangles.
  1410. if (inputCount == -1)
  1411. {
  1412. inputCount = (unsigned int)inputArray.getCount();
  1413. for (unsigned int j = 0; j < inputCount; j++)
  1414. {
  1415. const domInputLocalOffsetRef& input = inputArray.get(j);
  1416. std::string inputSemantic = input->getSemantic();
  1417. // If its a vertex first do an extra lookup for the inclusive inputs
  1418. if (equals(inputSemantic, "VERTEX"))
  1419. {
  1420. unsigned int vertexArrayCount = (unsigned int)vertexArray.getCount();
  1421. for (unsigned int k = 0; k < vertexArrayCount; k++)
  1422. {
  1423. const domInputLocalRef& vertexInput = vertexArray.get(k);
  1424. std::string semantic = std::string(vertexInput->getSemantic());
  1425. int type = getVertexUsageType(semantic);
  1426. if (type == -1)
  1427. {
  1428. warning(std::string("Vertex semantic (") + semantic + ") is invalid/unsupported for geometry mesh: " + geometryId);
  1429. }
  1430. DAEPolygonInput* polygonInput = new DAEPolygonInput();
  1431. domURIFragmentType& sourceURI = vertexInput->getSource();
  1432. sourceURI.resolveElement();
  1433. domSource* source = (domSource*)(daeElement*)sourceURI.getElement();
  1434. polygonInput->offset = 0;
  1435. polygonInput->sourceValues = source->getFloat_array()->getValue();
  1436. polygonInput->type = type;
  1437. polygonInputs.push_back(polygonInput);
  1438. }
  1439. }
  1440. else
  1441. {
  1442. std::string semantic = input->getSemantic();
  1443. int type = getVertexUsageType(semantic);
  1444. if (type == -1)
  1445. {
  1446. warning(std::string("Semantic (") + semantic + ") is invalid/unsupported for geometry mesh: " + geometryId);
  1447. }
  1448. DAEPolygonInput* polygonInput = new DAEPolygonInput();
  1449. domURIFragmentType& sourceURI = input->getSource();
  1450. sourceURI.resolveElement();
  1451. domSource* source = (domSource*)(daeElement*)sourceURI.getElement();
  1452. polygonInput->offset = (unsigned int)input->getOffset();
  1453. polygonInput->sourceValues = source->getFloat_array()->getValue();
  1454. polygonInput->type = type;
  1455. // Get the accessor info
  1456. const domSource::domTechnique_commonRef& technique = source->getTechnique_common();
  1457. if (technique.cast())
  1458. {
  1459. const domAccessorRef& accessor = technique->getAccessor();
  1460. polygonInput->accessor = accessor;
  1461. }
  1462. polygonInputs.push_back(polygonInput);
  1463. }
  1464. }
  1465. }
  1466. else
  1467. {
  1468. // If there is a triangle array with a different number of inputs, this is not supported.
  1469. if (inputCount != (unsigned int)inputArray.getCount())
  1470. {
  1471. for (size_t j = 0; j < polygonInputs.size(); j++)
  1472. {
  1473. delete polygonInputs[j];
  1474. }
  1475. warning(std::string("Triangles do not all have the same number of input sources for geometry mesh: ") + geometryId);
  1476. return false;
  1477. }
  1478. else
  1479. {
  1480. // TODO: Check if they are in the same order...
  1481. }
  1482. }
  1483. }
  1484. // Now we have validated that all input in all triangles are the same and in the same input layout.
  1485. // Lets start to read them and build our subsets.
  1486. for (unsigned int i = 0; i < trianglesArrayCount; i++)
  1487. {
  1488. // Subset to be built.
  1489. MeshPart* subset = new MeshPart();
  1490. // All of the information about the triangles and the sources to access the data from.
  1491. domTriangles* triangles = daeSafeCast<domTriangles>(trianglesArray.get(i));
  1492. // Parse the material for this subset
  1493. //std::string materialName = triangles->getMaterial() == NULL ? _T("") : triangles->getMaterial();
  1494. //if (materialName.size() > 0)
  1495. /// subset->material = ParseMaterial(bindMaterial, materialName);
  1496. //const domInputLocalOffset_Array& inputArray = triangles->getInput_array();
  1497. const domListOfUInts& polyInts = triangles->getP()->getValue();
  1498. unsigned int polyIntsCount = (unsigned int)polyInts.getCount();
  1499. unsigned int poly = 0;
  1500. unsigned int inputSourceCount = (unsigned int)polygonInputs.size();
  1501. unsigned int maxOffset = 0;
  1502. // Go through the polygon indices for each input source retrieve the values
  1503. // and iterate by its offset.
  1504. Vertex vertex;
  1505. for (unsigned int k = 0; k < inputSourceCount && poly < polyIntsCount;)
  1506. {
  1507. const domListOfFloats& source = polygonInputs[k]->sourceValues;
  1508. unsigned int offset = polygonInputs[k]->offset;
  1509. if (offset > maxOffset)
  1510. {
  1511. maxOffset = offset;
  1512. }
  1513. int type = polygonInputs[k]->type;
  1514. unsigned int polyIndex = (unsigned int) polyInts.get(poly + offset);
  1515. switch (type)
  1516. {
  1517. case POSITION:
  1518. vertex = Vertex(); // TODO
  1519. if (_vertexBlendWeights && _vertexBlendIndices)
  1520. {
  1521. vertex.hasWeights = true;
  1522. vertex.blendWeights.x = _vertexBlendWeights[polyIndex * 4];
  1523. vertex.blendWeights.y = _vertexBlendWeights[polyIndex * 4 + 1];
  1524. vertex.blendWeights.z = _vertexBlendWeights[polyIndex * 4 + 2];
  1525. vertex.blendWeights.w = _vertexBlendWeights[polyIndex * 4 + 3];
  1526. vertex.blendIndices.x = (float)_vertexBlendIndices[polyIndex * 4];
  1527. vertex.blendIndices.y = (float)_vertexBlendIndices[polyIndex * 4 + 1];
  1528. vertex.blendIndices.z = (float)_vertexBlendIndices[polyIndex * 4 + 2];
  1529. vertex.blendIndices.w = (float)_vertexBlendIndices[polyIndex * 4 + 3];
  1530. }
  1531. vertex.position.x = (float)source.get(polyIndex * 3);
  1532. vertex.position.y = (float)source.get(polyIndex * 3 + 1);
  1533. vertex.position.z = (float)source.get(polyIndex * 3 + 2);
  1534. break;
  1535. case NORMAL:
  1536. vertex.hasNormal = true;
  1537. vertex.normal.x = (float)source.get(polyIndex * 3);
  1538. vertex.normal.y = (float)source.get(polyIndex * 3 + 1);
  1539. vertex.normal.z = (float)source.get(polyIndex * 3 + 2);
  1540. break;
  1541. // TODO: Handle reading of per-vertex colors.
  1542. // HOW do we know how many color components to read?
  1543. // We must examine the Collada input accessor and read the stride/count to verify this - not ONLY for Color, but we should be doing this for ALL components (i.e. Position, Normal, etc).
  1544. // case Color:
  1545. // vertex.hasColor = true;
  1546. // vertex.Diffuse.R = (float)source.get(polyIndex * 3);
  1547. // vertex.Diffuse.G = (float)source.get(polyIndex * 3 + 1);
  1548. // vertex.Diffuse.B = (float)source.get(polyIndex * 3 + 2);
  1549. // vertex.Diffuse.A = (float)source.get(polyIndex * 3 + 3);
  1550. // break;
  1551. case TANGENT:
  1552. vertex.hasTangent = true;
  1553. vertex.tangent.x = (float)source.get(polyIndex * 3);
  1554. vertex.tangent.y = (float)source.get(polyIndex * 3 + 1);
  1555. vertex.tangent.z = (float)source.get(polyIndex * 3 + 2);
  1556. break;
  1557. case BINORMAL:
  1558. vertex.hasBinormal = true;
  1559. vertex.binormal.x = (float)source.get(polyIndex * 3);
  1560. vertex.binormal.y = (float)source.get(polyIndex * 3 + 1);
  1561. vertex.binormal.z = (float)source.get(polyIndex * 3 + 2);
  1562. break;
  1563. case TEXCOORD0:
  1564. vertex.hasTexCoord = true;
  1565. if (polygonInputs[k]->accessor)
  1566. {
  1567. // TODO: This assumes (s, t) are first
  1568. unsigned int stride = (unsigned int)polygonInputs[k]->accessor->getStride();
  1569. vertex.texCoord.x = (float)source.get(polyIndex * stride);
  1570. vertex.texCoord.y = (float)source.get(polyIndex * stride + 1);
  1571. }
  1572. else
  1573. {
  1574. vertex.texCoord.x = (float)source.get(polyIndex * 2);
  1575. vertex.texCoord.y = (float)source.get(polyIndex * 2 + 1);
  1576. }
  1577. break;
  1578. default:
  1579. break;
  1580. }
  1581. // On the last input source attempt to add the vertex or index an existing one.
  1582. if (k == (inputSourceCount - 1))
  1583. {
  1584. // Only add unique vertices, use a hashtable and compare the hash functions of the
  1585. // vertices. If they exist simply lookup the index of the existing ones.
  1586. // otherwise add and new one and index it.
  1587. unsigned int index;
  1588. if (mesh->contains(vertex))
  1589. {
  1590. index = mesh->getVertexIndex(vertex);
  1591. }
  1592. else
  1593. {
  1594. index = mesh->addVertex(vertex);
  1595. }
  1596. subset->addIndex(index);
  1597. poly += (maxOffset+1);
  1598. k = 0;
  1599. }
  1600. else
  1601. {
  1602. k++;
  1603. }
  1604. }
  1605. // Add our new subset for the mesh.
  1606. mesh->addMeshPart(subset);
  1607. }
  1608. bool hasNormals = mesh->vertices[0].hasNormal;
  1609. bool hasColors = mesh->vertices[0].hasColor;
  1610. bool hasTangents = mesh->vertices[0].hasTangent;
  1611. bool hasBinormals = mesh->vertices[0].hasBinormal;
  1612. bool hasTexCoords = mesh->vertices[0].hasTexCoord;
  1613. bool hasWeights = mesh->vertices[0].hasWeights;
  1614. // The order that the vertex elements are add to the list matters.
  1615. // It should be the same order as how the Vertex data is written.
  1616. // Position
  1617. mesh->addVetexAttribute(POSITION, 3);
  1618. // Normals
  1619. if (hasNormals)
  1620. {
  1621. mesh->addVetexAttribute(NORMAL, 3);
  1622. }
  1623. // Tangents
  1624. if (hasTangents)
  1625. {
  1626. mesh->addVetexAttribute(TANGENT, 3);
  1627. }
  1628. // Binormals
  1629. if (hasBinormals)
  1630. {
  1631. mesh->addVetexAttribute(BINORMAL, 3);
  1632. }
  1633. // Texture Coordinates
  1634. if (hasTexCoords)
  1635. {
  1636. mesh->addVetexAttribute(TEXCOORD0, 2);
  1637. }
  1638. // Diffuse Color
  1639. if (hasColors)
  1640. {
  1641. mesh->addVetexAttribute(COLOR, 3);
  1642. }
  1643. // Skinning BlendWeights BlendIndices
  1644. if (hasWeights /*_vertexBlendWeights && _vertexBlendIndices*/)
  1645. {
  1646. mesh->addVetexAttribute(BLENDWEIGHTS, 4);
  1647. mesh->addVetexAttribute(BLENDINDICES, 4);
  1648. }
  1649. _gamePlayFile.addMesh(mesh);
  1650. return mesh;
  1651. }
  1652. void DAESceneEncoder::warning(const std::string& message)
  1653. {
  1654. printf("Warning: %s\n", message.c_str());
  1655. }
  1656. void DAESceneEncoder::warning(const char* message)
  1657. {
  1658. printf("Warning: %s\n", message);
  1659. }
  1660. int DAESceneEncoder::getVertexUsageType(const std::string& semantic)
  1661. {
  1662. int type = -1;
  1663. if (semantic.length() > 0)
  1664. {
  1665. switch (semantic[0])
  1666. {
  1667. case 'P':
  1668. if (equals(semantic, "POSITION"))
  1669. {
  1670. type = POSITION;
  1671. }
  1672. break;
  1673. case 'N':
  1674. if (equals(semantic, "NORMAL"))
  1675. {
  1676. type = NORMAL;
  1677. }
  1678. case 'C':
  1679. if (equals(semantic, "COLOR"))
  1680. {
  1681. type = COLOR;
  1682. }
  1683. case 'T':
  1684. if (equals(semantic, "TANGENT"))
  1685. {
  1686. type = TANGENT;
  1687. }
  1688. else if (equals(semantic, "TEXCOORD"))
  1689. {
  1690. type = TEXCOORD0;
  1691. }
  1692. else if (equals(semantic, "TEXTANGENT"))
  1693. {
  1694. // Treat TEXTANGENT as TANGENT
  1695. type = TANGENT;
  1696. }
  1697. else if (equals(semantic, "TEXBINORMAL"))
  1698. {
  1699. // Treat TEXBINORMAL as BINORMAL
  1700. type = BINORMAL;
  1701. }
  1702. case 'B':
  1703. if (equals(semantic, "BINORMAL"))
  1704. {
  1705. type = BINORMAL;
  1706. }
  1707. default:
  1708. break;
  1709. }
  1710. }
  1711. return type;
  1712. }
  1713. DAESceneEncoder::DAEPolygonInput::DAEPolygonInput(void) :
  1714. offset(0),
  1715. type(0),
  1716. accessor(NULL)
  1717. {
  1718. }
  1719. DAESceneEncoder::DAEPolygonInput::~DAEPolygonInput(void)
  1720. {
  1721. }