DAESceneEncoder.cpp 75 KB

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