DAESceneEncoder.cpp 76 KB

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