DAESceneEncoder.cpp 76 KB

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