123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610 |
- /*************************************************************************/
- /* collada.cpp */
- /*************************************************************************/
- /* This file is part of: */
- /* GODOT ENGINE */
- /* https://godotengine.org */
- /*************************************************************************/
- /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
- /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
- /* */
- /* Permission is hereby granted, free of charge, to any person obtaining */
- /* a copy of this software and associated documentation files (the */
- /* "Software"), to deal in the Software without restriction, including */
- /* without limitation the rights to use, copy, modify, merge, publish, */
- /* distribute, sublicense, and/or sell copies of the Software, and to */
- /* permit persons to whom the Software is furnished to do so, subject to */
- /* the following conditions: */
- /* */
- /* The above copyright notice and this permission notice shall be */
- /* included in all copies or substantial portions of the Software. */
- /* */
- /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
- /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
- /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
- /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
- /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
- /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
- /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- /*************************************************************************/
- #ifdef TOOLS_ENABLED
- #include "collada.h"
- #include "stdio.h"
- //#define DEBUG_DEFAULT_ANIMATION
- //#define DEBUG_COLLADA
- #ifdef DEBUG_COLLADA
- #define COLLADA_PRINT(m_what) print_line(m_what)
- #else
- #define COLLADA_PRINT(m_what)
- #endif
- #define COLLADA_IMPORT_SCALE_SCENE
- /* HELPERS */
- String Collada::Effect::get_texture_path(const String &p_source, Collada &state) const {
- String image = p_source;
- ERR_FAIL_COND_V(!state.state.image_map.has(image), "");
- return state.state.image_map[image].path;
- }
- Transform Collada::get_root_transform() const {
- Transform unit_scale_transform;
- #ifndef COLLADA_IMPORT_SCALE_SCENE
- unit_scale_transform.scale(Vector3(state.unit_scale, state.unit_scale, state.unit_scale));
- #endif
- return unit_scale_transform;
- }
- void Collada::Vertex::fix_unit_scale(Collada &state) {
- #ifdef COLLADA_IMPORT_SCALE_SCENE
- vertex *= state.state.unit_scale;
- #endif
- }
- static String _uri_to_id(const String &p_uri) {
- if (p_uri.begins_with("#"))
- return p_uri.substr(1, p_uri.size() - 1);
- else
- return p_uri;
- }
- /** HELPER FUNCTIONS **/
- Transform Collada::fix_transform(const Transform &p_transform) {
- Transform tr = p_transform;
- #ifndef NO_UP_AXIS_SWAP
- if (state.up_axis != Vector3::AXIS_Y) {
- for (int i = 0; i < 3; i++)
- SWAP(tr.basis[1][i], tr.basis[state.up_axis][i]);
- for (int i = 0; i < 3; i++)
- SWAP(tr.basis[i][1], tr.basis[i][state.up_axis]);
- SWAP(tr.origin[1], tr.origin[state.up_axis]);
- tr.basis[state.up_axis][0] = -tr.basis[state.up_axis][0];
- tr.basis[state.up_axis][1] = -tr.basis[state.up_axis][1];
- tr.basis[0][state.up_axis] = -tr.basis[0][state.up_axis];
- tr.basis[1][state.up_axis] = -tr.basis[1][state.up_axis];
- tr.origin[state.up_axis] = -tr.origin[state.up_axis];
- }
- #endif
- // tr.scale(Vector3(state.unit_scale.unit_scale.unit_scale));
- return tr;
- //return state.matrix_fix * p_transform;
- }
- static Transform _read_transform_from_array(const Vector<float> &array, int ofs = 0) {
- Transform tr;
- // i wonder why collada matrices are transposed, given that's opposed to opengl..
- tr.basis.elements[0][0] = array[0 + ofs];
- tr.basis.elements[0][1] = array[1 + ofs];
- tr.basis.elements[0][2] = array[2 + ofs];
- tr.basis.elements[1][0] = array[4 + ofs];
- tr.basis.elements[1][1] = array[5 + ofs];
- tr.basis.elements[1][2] = array[6 + ofs];
- tr.basis.elements[2][0] = array[8 + ofs];
- tr.basis.elements[2][1] = array[9 + ofs];
- tr.basis.elements[2][2] = array[10 + ofs];
- tr.origin.x = array[3 + ofs];
- tr.origin.y = array[7 + ofs];
- tr.origin.z = array[11 + ofs];
- return tr;
- }
- /* STRUCTURES */
- Transform Collada::Node::compute_transform(Collada &state) const {
- Transform xform;
- for (int i = 0; i < xform_list.size(); i++) {
- Transform xform_step;
- const XForm &xf = xform_list[i];
- switch (xf.op) {
- case XForm::OP_ROTATE: {
- if (xf.data.size() >= 4) {
- xform_step.rotate(Vector3(xf.data[0], xf.data[1], xf.data[2]), -Math::deg2rad(xf.data[3]));
- }
- } break;
- case XForm::OP_SCALE: {
- if (xf.data.size() >= 3) {
- xform_step.scale(Vector3(xf.data[0], xf.data[1], xf.data[2]));
- }
- } break;
- case XForm::OP_TRANSLATE: {
- if (xf.data.size() >= 3) {
- xform_step.origin = Vector3(xf.data[0], xf.data[1], xf.data[2]);
- }
- } break;
- case XForm::OP_MATRIX: {
- if (xf.data.size() >= 16) {
- xform_step = _read_transform_from_array(xf.data, 0);
- }
- } break;
- default: {
- }
- }
- xform = xform * xform_step;
- }
- #ifdef COLLADA_IMPORT_SCALE_SCENE
- xform.origin *= state.state.unit_scale;
- #endif
- return xform;
- }
- Transform Collada::Node::get_transform() const {
- return default_transform;
- }
- Transform Collada::Node::get_global_transform() const {
- if (parent)
- return parent->get_global_transform() * default_transform;
- else
- return default_transform;
- }
- Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) {
- ERR_FAIL_COND_V(keys.size() == 0, Vector<float>());
- int i = 0;
- for (i = 0; i < keys.size(); i++) {
- if (keys[i].time > p_time)
- break;
- }
- if (i == 0)
- return keys[0].data;
- if (i == keys.size())
- return keys[keys.size() - 1].data;
- switch (keys[i].interp_type) {
- case INTERP_BEZIER: //wait for bezier
- case INTERP_LINEAR: {
- float c = (p_time - keys[i - 1].time) / (keys[i].time - keys[i - 1].time);
- if (keys[i].data.size() == 16) {
- //interpolate a matrix
- Transform src = _read_transform_from_array(keys[i - 1].data);
- Transform dst = _read_transform_from_array(keys[i].data);
- Transform interp = c < 0.001 ? src : src.interpolate_with(dst, c);
- Vector<float> ret;
- ret.resize(16);
- Transform tr;
- // i wonder why collada matrices are transposed, given that's opposed to opengl..
- ret[0] = interp.basis.elements[0][0];
- ret[1] = interp.basis.elements[0][1];
- ret[2] = interp.basis.elements[0][2];
- ret[4] = interp.basis.elements[1][0];
- ret[5] = interp.basis.elements[1][1];
- ret[6] = interp.basis.elements[1][2];
- ret[8] = interp.basis.elements[2][0];
- ret[9] = interp.basis.elements[2][1];
- ret[10] = interp.basis.elements[2][2];
- ret[3] = interp.origin.x;
- ret[7] = interp.origin.y;
- ret[11] = interp.origin.z;
- ret[12] = 0;
- ret[13] = 0;
- ret[14] = 0;
- ret[15] = 1;
- return ret;
- } else {
- Vector<float> dest;
- dest.resize(keys[i].data.size());
- for (int j = 0; j < dest.size(); j++) {
- dest[j] = keys[i].data[j] * c + keys[i - 1].data[j] * (1.0 - c);
- }
- return dest;
- //interpolate one by one
- }
- } break;
- }
- ERR_FAIL_V(Vector<float>());
- }
- void Collada::_parse_asset(XMLParser &parser) {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
- if (name == "up_axis") {
- parser.read();
- if (parser.get_node_data() == "X_UP")
- state.up_axis = Vector3::AXIS_X;
- if (parser.get_node_data() == "Y_UP")
- state.up_axis = Vector3::AXIS_Y;
- if (parser.get_node_data() == "Z_UP")
- state.up_axis = Vector3::AXIS_Z;
- COLLADA_PRINT("up axis: " + parser.get_node_data());
- } else if (name == "unit") {
- state.unit_scale = parser.get_attribute_value("meter").to_double();
- COLLADA_PRINT("unit scale: " + rtos(state.unit_scale));
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "asset")
- break; //end of <asset>
- }
- }
- void Collada::_parse_image(XMLParser &parser) {
- String id = parser.get_attribute_value("id");
- if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- Image image;
- if (state.version < State::Version(1, 4, 0)) {
- /* <1.4 */
- String path = parser.get_attribute_value("source").strip_edges();
- if (path.find("://") == -1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- image.path = Globals::get_singleton()->localize_path(state.local_path.get_base_dir() + "/" + path.percent_decode());
- }
- } else {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
- if (name == "init_from") {
- parser.read();
- String path = parser.get_node_data().strip_edges().percent_decode();
- if (path.find("://") == -1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- path = Globals::get_singleton()->localize_path(state.local_path.get_base_dir() + "/" + path);
- } else if (path.find("file:///") == 0) {
- path = path.replace_first("file:///", "");
- path = Globals::get_singleton()->localize_path(path);
- }
- image.path = path;
- }
- if (name == "data") {
- ERR_PRINT("COLLADA Embedded image data not supported!");
- } else if (name == "extra" && !parser.is_empty())
- parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "image")
- break; //end of <asset>
- }
- }
- state.image_map[id] = image;
- }
- void Collada::_parse_material(XMLParser &parser) {
- if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- Material material;
- String id = parser.get_attribute_value("id");
- if (parser.has_attribute("name"))
- material.name = parser.get_attribute_value("name");
- if (state.version < State::Version(1, 4, 0)) {
- /* <1.4 */
- ERR_PRINT("Collada Materials < 1.4 are not supported (yet)");
- } else {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT && parser.get_node_name() == "instance_effect") {
- material.instance_effect = _uri_to_id(parser.get_attribute_value("url"));
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "material")
- break; //end of <asset>
- }
- }
- state.material_map[id] = material;
- }
- //! reads floats from inside of xml element until end of xml element
- Vector<float> Collada::_read_float_array(XMLParser &parser) {
- if (parser.is_empty())
- return Vector<float>();
- Vector<String> splitters;
- splitters.push_back(" ");
- splitters.push_back("\n");
- splitters.push_back("\r");
- splitters.push_back("\t");
- Vector<float> array;
- while (parser.read() == OK) {
- // TODO: check for comments inside the element
- // and ignore them.
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- // parse float data
- String str = parser.get_node_data();
- array = str.split_floats_mk(splitters, false);
- //array=str.split_floats(" ",false);
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
- break; // end parsing text
- }
- return array;
- }
- Vector<String> Collada::_read_string_array(XMLParser &parser) {
- if (parser.is_empty())
- return Vector<String>();
- Vector<String> array;
- while (parser.read() == OK) {
- // TODO: check for comments inside the element
- // and ignore them.
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- // parse String data
- String str = parser.get_node_data();
- array = str.split_spaces();
- //for(int i=0;i<array.size();i++) {
- // print_line(itos(i)+": "+array[i]);
- //}
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
- break; // end parsing text
- }
- return array;
- }
- Transform Collada::_read_transform(XMLParser &parser) {
- if (parser.is_empty())
- return Transform();
- Vector<float> array;
- while (parser.read() == OK) {
- // TODO: check for comments inside the element
- // and ignore them.
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- // parse float data
- String str = parser.get_node_data();
- array = str.split_floats(" ", false);
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
- break; // end parsing text
- }
- ERR_FAIL_COND_V(array.size() != 16, Transform());
- return _read_transform_from_array(array);
- }
- String Collada::_read_empty_draw_type(XMLParser &parser) {
- String empty_draw_type = "";
- if (parser.is_empty())
- return empty_draw_type;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- empty_draw_type = parser.get_node_data();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
- break; // end parsing text
- }
- return empty_draw_type;
- }
- Variant Collada::_parse_param(XMLParser &parser) {
- if (parser.is_empty())
- return Variant();
- String from = parser.get_node_name();
- Variant data;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "float") {
- parser.read();
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- data = parser.get_node_data().to_double();
- }
- } else if (parser.get_node_name() == "float2") {
- Vector<float> v2 = _read_float_array(parser);
- if (v2.size() >= 2) {
- data = Vector2(v2[0], v2[1]);
- }
- } else if (parser.get_node_name() == "float3") {
- Vector<float> v3 = _read_float_array(parser);
- if (v3.size() >= 3) {
- data = Vector3(v3[0], v3[1], v3[2]);
- }
- } else if (parser.get_node_name() == "float4") {
- Vector<float> v4 = _read_float_array(parser);
- if (v4.size() >= 4) {
- data = Color(v4[0], v4[1], v4[2], v4[3]);
- }
- } else if (parser.get_node_name() == "sampler2D") {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "source") {
- parser.read();
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- data = parser.get_node_data();
- }
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "sampler2D")
- break;
- }
- } else if (parser.get_node_name() == "surface") {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "init_from") {
- parser.read();
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- data = parser.get_node_data();
- }
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "surface")
- break;
- }
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == from)
- break;
- }
- COLLADA_PRINT("newparam ending " + parser.get_node_name());
- return data;
- }
- void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String &id) {
- if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- // first come the tags we descend, but ignore the top-levels
- COLLADA_PRINT("node name: " + parser.get_node_name());
- if (!parser.is_empty() && (parser.get_node_name() == "profile_COMMON" || parser.get_node_name() == "technique" || parser.get_node_name() == "extra")) {
- _parse_effect_material(parser, effect, id); // try again
- } else if (parser.get_node_name() == "newparam") {
- String name = parser.get_attribute_value("sid");
- Variant value = _parse_param(parser);
- effect.params[name] = value;
- COLLADA_PRINT("param: " + name + " value:" + String(value));
- } else if (parser.get_node_name() == "constant" ||
- parser.get_node_name() == "lambert" ||
- parser.get_node_name() == "phong" ||
- parser.get_node_name() == "blinn") {
- COLLADA_PRINT("shade model: " + parser.get_node_name());
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String what = parser.get_node_name();
- if (what == "emission" ||
- what == "diffuse" ||
- what == "specular" ||
- what == "reflective") {
- // color or texture types
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "color") {
- Vector<float> colorarr = _read_float_array(parser);
- COLLADA_PRINT("colorarr size: " + rtos(colorarr.size()));
- if (colorarr.size() >= 3) {
- // alpha strangely not allright? maybe it needs to be multiplied by value as a channel intensity
- Color color(colorarr[0], colorarr[1], colorarr[2], 1.0);
- if (what == "diffuse")
- effect.diffuse.color = color;
- if (what == "specular")
- effect.specular.color = color;
- if (what == "emission")
- effect.emission.color = color;
- COLLADA_PRINT(what + " color: " + color);
- }
- } else if (parser.get_node_name() == "texture") {
- String sampler = parser.get_attribute_value("texture");
- if (!effect.params.has(sampler)) {
- ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data());
- } else {
- String surface = effect.params[sampler];
- if (!effect.params.has(surface)) {
- ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + id).utf8().get_data());
- } else {
- String uri = effect.params[surface];
- if (what == "diffuse") {
- effect.diffuse.texture = uri;
- } else if (what == "specular") {
- effect.specular.texture = uri;
- } else if (what == "emission") {
- effect.emission.texture = uri;
- } else if (what == "bump") {
- if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") {
- WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.")
- }
- effect.bump.texture = uri;
- }
- COLLADA_PRINT(what + " texture: " + uri);
- }
- }
- } else if (!parser.is_empty())
- parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == what)
- break;
- }
- } else if (what == "shininess") {
- #if 1
- effect.shininess = _parse_param(parser);
- #else
- parser.read();
- float shininess = parser.get_node_data().to_double();
- effect.shininess = shininess;
- COLLADA_PRINT("shininess: " + rtos(shininess));
- #endif
- }
- }
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && (parser.get_node_name() == "constant" ||
- parser.get_node_name() == "lambert" ||
- parser.get_node_name() == "phong" ||
- parser.get_node_name() == "blinn"))
- break;
- }
- } else if (parser.get_node_name() == "double_sided" || parser.get_node_name() == "show_double_sided") { // colladamax / google earth
- // 3DS Max / Google Earth double sided extension
- parser.read();
- effect.found_double_sided = true;
- effect.double_sided = parser.get_node_data().to_int();
- COLLADA_PRINT("double sided: " + itos(parser.get_node_data().to_int()));
- } else if (parser.get_node_name() == "unshaded") {
- parser.read();
- effect.unshaded = parser.get_node_data().to_int();
- } else if (parser.get_node_name() == "bump") {
- // color or texture types
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "texture") {
- String sampler = parser.get_attribute_value("texture");
- if (!effect.params.has(sampler)) {
- ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data());
- } else {
- String surface = effect.params[sampler];
- if (!effect.params.has(surface)) {
- ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + id).utf8().get_data());
- } else {
- String uri = effect.params[surface];
- if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") {
- WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.")
- }
- effect.bump.texture = uri;
- COLLADA_PRINT(" bump: " + uri);
- }
- }
- } else if (!parser.is_empty())
- parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "bump")
- break;
- }
- } else if (!parser.is_empty())
- parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END &&
- (parser.get_node_name() == "effect" ||
- parser.get_node_name() == "profile_COMMON" ||
- parser.get_node_name() == "technique" ||
- parser.get_node_name() == "extra"))
- break;
- }
- }
- void Collada::_parse_effect(XMLParser &parser) {
- if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- String id = parser.get_attribute_value("id");
- Effect effect;
- if (parser.has_attribute("name"))
- effect.name = parser.get_attribute_value("name");
- _parse_effect_material(parser, effect, id);
- state.effect_map[id] = effect;
- COLLADA_PRINT("Effect ID:" + id);
- }
- void Collada::_parse_camera(XMLParser &parser) {
- if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- String id = parser.get_attribute_value("id");
- state.camera_data_map[id] = CameraData();
- CameraData &camera = state.camera_data_map[id];
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
- if (name == "perspective") {
- camera.mode = CameraData::MODE_PERSPECTIVE;
- } else if (name == "orthographic") {
- camera.mode = CameraData::MODE_ORTHOGONAL;
- } else if (name == "xfov") {
- parser.read();
- camera.perspective.x_fov = parser.get_node_data().to_double();
- } else if (name == "yfov") {
- parser.read();
- camera.perspective.y_fov = parser.get_node_data().to_double();
- } else if (name == "xmag") {
- parser.read();
- camera.orthogonal.x_mag = parser.get_node_data().to_double();
- } else if (name == "ymag") {
- parser.read();
- camera.orthogonal.y_mag = parser.get_node_data().to_double();
- } else if (name == "aspect_ratio") {
- parser.read();
- camera.aspect = parser.get_node_data().to_double();
- } else if (name == "znear") {
- parser.read();
- camera.z_near = parser.get_node_data().to_double();
- } else if (name == "zfar") {
- parser.read();
- camera.z_far = parser.get_node_data().to_double();
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "camera")
- break; //end of <asset>
- }
- COLLADA_PRINT("Camera ID:" + id);
- }
- void Collada::_parse_light(XMLParser &parser) {
- if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- String id = parser.get_attribute_value("id");
- state.light_data_map[id] = LightData();
- LightData &light = state.light_data_map[id];
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
- if (name == "ambient") {
- light.mode = LightData::MODE_AMBIENT;
- } else if (name == "directional") {
- light.mode = LightData::MODE_DIRECTIONAL;
- } else if (name == "point") {
- light.mode = LightData::MODE_OMNI;
- } else if (name == "spot") {
- light.mode = LightData::MODE_SPOT;
- } else if (name == "color") {
- parser.read();
- Vector<float> colorarr = _read_float_array(parser);
- COLLADA_PRINT("colorarr size: " + rtos(colorarr.size()));
- if (colorarr.size() >= 4) {
- // alpha strangely not allright? maybe it needs to be multiplied by value as a channel intensity
- Color color(colorarr[0], colorarr[1], colorarr[2], 1.0);
- light.color = color;
- }
- } else if (name == "constant_attenuation") {
- parser.read();
- light.constant_att = parser.get_node_data().to_double();
- } else if (name == "linear_attenuation") {
- parser.read();
- light.linear_att = parser.get_node_data().to_double();
- } else if (name == "quadratic_attenuation") {
- parser.read();
- light.quad_att = parser.get_node_data().to_double();
- } else if (name == "falloff_angle") {
- parser.read();
- light.spot_angle = parser.get_node_data().to_double();
- } else if (name == "falloff_exponent") {
- parser.read();
- light.spot_exp = parser.get_node_data().to_double();
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "light")
- break; //end of <asset>
- }
- COLLADA_PRINT("Light ID:" + id);
- }
- void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_name) {
- if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- //load everything into a pre dictionary
- state.curve_data_map[p_id] = CurveData();
- CurveData &curvedata = state.curve_data_map[p_id];
- curvedata.name = p_name;
- COLLADA_PRINT("curve name: " + p_name);
- String current_source;
- // handles geometry node and the curve childs in this loop
- // read sources with arrays and accessor for each curve
- if (parser.is_empty()) {
- return;
- }
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
- if (section == "source") {
- String id = parser.get_attribute_value("id");
- curvedata.sources[id] = CurveData::Source();
- current_source = id;
- COLLADA_PRINT("source data: " + id);
- } else if (section == "float_array" || section == "array") {
- // create a new array and read it.
- if (curvedata.sources.has(current_source)) {
- curvedata.sources[current_source].array = _read_float_array(parser);
- COLLADA_PRINT("section: " + current_source + " read " + itos(curvedata.sources[current_source].array.size()) + " values.");
- }
- } else if (section == "Name_array") {
- // create a new array and read it.
- if (curvedata.sources.has(current_source)) {
- curvedata.sources[current_source].sarray = _read_string_array(parser);
- COLLADA_PRINT("section: " + current_source + " read " + itos(curvedata.sources[current_source].array.size()) + " values.");
- }
- } else if (section == "technique_common") {
- //skip it
- } else if (section == "accessor") { // child of source (below a technique tag)
- if (curvedata.sources.has(current_source)) {
- curvedata.sources[current_source].stride = parser.get_attribute_value("stride").to_int();
- COLLADA_PRINT("section: " + current_source + " stride " + itos(curvedata.sources[current_source].stride));
- }
- } else if (section == "control_vertices") {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_attribute_value("semantic");
- String source = _uri_to_id(parser.get_attribute_value("source"));
- curvedata.control_vertices[semantic] = source;
- COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
- break;
- }
- } else if (!parser.is_empty()) {
- parser.skip_section();
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "spline")
- break;
- }
- }
- void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name) {
- if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- //load everything into a pre dictionary
- state.mesh_data_map[p_id] = MeshData();
- MeshData &meshdata = state.mesh_data_map[p_id];
- meshdata.name = p_name;
- COLLADA_PRINT("mesh name: " + p_name);
- String current_source;
- // handles geometry node and the mesh childs in this loop
- // read sources with arrays and accessor for each mesh
- if (parser.is_empty()) {
- return;
- }
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
- if (section == "source") {
- String id = parser.get_attribute_value("id");
- meshdata.sources[id] = MeshData::Source();
- current_source = id;
- COLLADA_PRINT("source data: " + id);
- } else if (section == "float_array" || section == "array" || section == "float_array") {
- // create a new array and read it.
- if (meshdata.sources.has(current_source)) {
- meshdata.sources[current_source].array = _read_float_array(parser);
- COLLADA_PRINT("section: " + current_source + " read " + itos(meshdata.sources[current_source].array.size()) + " values.");
- }
- } else if (section == "technique_common") {
- //skip it
- } else if (section == "accessor") { // child of source (below a technique tag)
- if (meshdata.sources.has(current_source)) {
- meshdata.sources[current_source].stride = parser.get_attribute_value("stride").to_int();
- COLLADA_PRINT("section: " + current_source + " stride " + itos(meshdata.sources[current_source].stride));
- }
- } else if (section == "vertices") {
- MeshData::Vertices vert;
- String id = parser.get_attribute_value("id");
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_attribute_value("semantic");
- String source = _uri_to_id(parser.get_attribute_value("source"));
- vert.sources[semantic] = source;
- COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
- break;
- }
- meshdata.vertices[id] = vert;
- } else if (section == "triangles" || section == "polylist" || section == "polygons") {
- bool polygons = (section == "polygons");
- if (polygons) {
- WARN_PRINT("Primitive type \"polygons\" is not well supported (concave shapes may fail). To ensure that the geometry is properly imported, please re-export using \"triangles\" or \"polylist\".");
- }
- MeshData::Primitives prim;
- if (parser.has_attribute("material"))
- prim.material = parser.get_attribute_value("material");
- prim.count = parser.get_attribute_value("count").to_int();
- prim.vertex_size = 0;
- int last_ref = 0;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_attribute_value("semantic");
- String source = _uri_to_id(parser.get_attribute_value("source"));
- if (semantic == "TEXCOORD") {
- /*
- if (parser.has_attribute("set"))// a texcoord
- semantic+=parser.get_attribute_value("set");
- else
- semantic="TEXCOORD0";*/
- semantic = "TEXCOORD" + itos(last_ref++);
- }
- int offset = parser.get_attribute_value("offset").to_int();
- MeshData::Primitives::SourceRef sref;
- sref.source = source;
- sref.offset = offset;
- prim.sources[semantic] = sref;
- prim.vertex_size = MAX(prim.vertex_size, offset + 1);
- COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source + " offset: " + itos(offset));
- } else if (parser.get_node_name() == "p") { //indices
- Vector<float> values = _read_float_array(parser);
- if (polygons) {
- prim.polygons.push_back(values.size() / prim.vertex_size);
- int from = prim.indices.size();
- prim.indices.resize(from + values.size());
- for (int i = 0; i < values.size(); i++)
- prim.indices[from + i] = values[i];
- } else if (prim.vertex_size > 0) {
- prim.indices = values;
- }
- COLLADA_PRINT("read " + itos(values.size()) + " index values");
- } else if (parser.get_node_name() == "vcount") { // primitive
- Vector<float> values = _read_float_array(parser);
- prim.polygons = values;
- COLLADA_PRINT("read " + itos(values.size()) + " polygon values");
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
- break;
- }
- meshdata.primitives.push_back(prim);
- } else if (parser.get_node_name() == "double_sided") {
- parser.read();
- meshdata.found_double_sided = true;
- meshdata.double_sided = parser.get_node_data().to_int();
- } else if (parser.get_node_name() == "polygons") {
- ERR_PRINT("Primitive type \"polygons\" not supported, re-export using \"polylist\" or \"triangles\".");
- } else if (!parser.is_empty()) {
- parser.skip_section();
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "mesh")
- break;
- }
- }
- void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
- state.skin_controller_data_map[p_id] = SkinControllerData();
- SkinControllerData &skindata = state.skin_controller_data_map[p_id];
- skindata.base = _uri_to_id(parser.get_attribute_value("source"));
- String current_source;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
- if (section == "bind_shape_matrix") {
- skindata.bind_shape = _read_transform(parser);
- #ifdef COLLADA_IMPORT_SCALE_SCENE
- skindata.bind_shape.origin *= state.unit_scale;
- #endif
- COLLADA_PRINT("skeleton bind shape transform: " + skindata.bind_shape);
- } else if (section == "source") {
- String id = parser.get_attribute_value("id");
- skindata.sources[id] = SkinControllerData::Source();
- current_source = id;
- COLLADA_PRINT("source data: " + id);
- } else if (section == "float_array" || section == "array") {
- // create a new array and read it.
- if (skindata.sources.has(current_source)) {
- skindata.sources[current_source].array = _read_float_array(parser);
- COLLADA_PRINT("section: " + current_source + " read " + itos(skindata.sources[current_source].array.size()) + " values.");
- }
- } else if (section == "Name_array" || section == "IDREF_array") {
- // create a new array and read it.
- if (section == "IDREF_array")
- skindata.use_idrefs = true;
- if (skindata.sources.has(current_source)) {
- skindata.sources[current_source].sarray = _read_string_array(parser);
- if (section == "IDREF_array") {
- Vector<String> sa = skindata.sources[current_source].sarray;
- for (int i = 0; i < sa.size(); i++)
- state.idref_joints.insert(sa[i]);
- }
- COLLADA_PRINT("section: " + current_source + " read " + itos(skindata.sources[current_source].array.size()) + " values.");
- }
- } else if (section == "technique_common") {
- //skip it
- } else if (section == "accessor") { // child of source (below a technique tag)
- if (skindata.sources.has(current_source)) {
- int stride = 1;
- if (parser.has_attribute("stride"))
- stride = parser.get_attribute_value("stride").to_int();
- skindata.sources[current_source].stride = stride;
- COLLADA_PRINT("section: " + current_source + " stride " + itos(skindata.sources[current_source].stride));
- }
- } else if (section == "joints") {
- SkinControllerData::Joints joint;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_attribute_value("semantic");
- String source = _uri_to_id(parser.get_attribute_value("source"));
- joint.sources[semantic] = source;
- COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
- break;
- }
- skindata.joints = joint;
- } else if (section == "vertex_weights") {
- SkinControllerData::Weights weights;
- weights.count = parser.get_attribute_value("count").to_int();
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_attribute_value("semantic");
- String source = _uri_to_id(parser.get_attribute_value("source"));
- int offset = parser.get_attribute_value("offset").to_int();
- SkinControllerData::Weights::SourceRef sref;
- sref.source = source;
- sref.offset = offset;
- weights.sources[semantic] = sref;
- COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source + " offset: " + itos(offset));
- } else if (parser.get_node_name() == "v") { //indices
- Vector<float> values = _read_float_array(parser);
- weights.indices = values;
- COLLADA_PRINT("read " + itos(values.size()) + " index values");
- } else if (parser.get_node_name() == "vcount") { // weightsitive
- Vector<float> values = _read_float_array(parser);
- weights.sets = values;
- COLLADA_PRINT("read " + itos(values.size()) + " polygon values");
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
- break;
- }
- skindata.weights = weights;
- } // else if (!parser.is_empty())
- // parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "skin")
- break;
- }
- /* STORE REST MATRICES */
- Vector<Transform> rests;
- ERR_FAIL_COND(!skindata.joints.sources.has("JOINT"));
- ERR_FAIL_COND(!skindata.joints.sources.has("INV_BIND_MATRIX"));
- String joint_arr = skindata.joints.sources["JOINT"];
- String ibm = skindata.joints.sources["INV_BIND_MATRIX"];
- ERR_FAIL_COND(!skindata.sources.has(joint_arr));
- ERR_FAIL_COND(!skindata.sources.has(ibm));
- SkinControllerData::Source &joint_source = skindata.sources[joint_arr];
- SkinControllerData::Source &ibm_source = skindata.sources[ibm];
- ERR_FAIL_COND(joint_source.sarray.size() != ibm_source.array.size() / 16);
- for (int i = 0; i < joint_source.sarray.size(); i++) {
- String name = joint_source.sarray[i];
- Transform xform = _read_transform_from_array(ibm_source.array, i * 16); // <- this is a mistake, it must be applied to vertices
- xform.affine_invert(); // inverse for rest, because it's an inverse
- #ifdef COLLADA_IMPORT_SCALE_SCENE
- xform.origin *= state.unit_scale;
- #endif
- skindata.bone_rest_map[name] = xform;
- }
- }
- void Collada::_parse_morph_controller(XMLParser &parser, String p_id) {
- state.morph_controller_data_map[p_id] = MorphControllerData();
- MorphControllerData &morphdata = state.morph_controller_data_map[p_id];
- print_line("morph source: " + parser.get_attribute_value("source") + " id: " + p_id);
- morphdata.mesh = _uri_to_id(parser.get_attribute_value("source"));
- print_line("morph source2: " + morphdata.mesh);
- morphdata.mode = parser.get_attribute_value("method");
- printf("JJmorph: %p\n", &morphdata);
- String current_source;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
- if (section == "source") {
- String id = parser.get_attribute_value("id");
- morphdata.sources[id] = MorphControllerData::Source();
- current_source = id;
- COLLADA_PRINT("source data: " + id);
- } else if (section == "float_array" || section == "array") {
- // create a new array and read it.
- if (morphdata.sources.has(current_source)) {
- morphdata.sources[current_source].array = _read_float_array(parser);
- COLLADA_PRINT("section: " + current_source + " read " + itos(morphdata.sources[current_source].array.size()) + " values.");
- }
- } else if (section == "Name_array" || section == "IDREF_array") {
- // create a new array and read it.
- //if (section=="IDREF_array")
- // morphdata.use_idrefs=true;
- if (morphdata.sources.has(current_source)) {
- morphdata.sources[current_source].sarray = _read_string_array(parser);
- /*
- if (section=="IDREF_array") {
- Vector<String> sa = morphdata.sources[current_source].sarray;
- for(int i=0;i<sa.size();i++)
- state.idref_joints.insert(sa[i]);
- }*/
- COLLADA_PRINT("section: " + current_source + " read " + itos(morphdata.sources[current_source].array.size()) + " values.");
- }
- } else if (section == "technique_common") {
- //skip it
- } else if (section == "accessor") { // child of source (below a technique tag)
- if (morphdata.sources.has(current_source)) {
- int stride = 1;
- if (parser.has_attribute("stride"))
- stride = parser.get_attribute_value("stride").to_int();
- morphdata.sources[current_source].stride = stride;
- COLLADA_PRINT("section: " + current_source + " stride " + itos(morphdata.sources[current_source].stride));
- }
- } else if (section == "targets") {
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "input") {
- String semantic = parser.get_attribute_value("semantic");
- String source = _uri_to_id(parser.get_attribute_value("source"));
- morphdata.targets[semantic] = source;
- COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
- break;
- }
- }
- // else if (!parser.is_empty())
- // parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "morph")
- break;
- }
- if (morphdata.targets.has("MORPH_WEIGHT")) {
- state.morph_name_map[morphdata.targets["MORPH_WEIGHT"]] = p_id;
- }
- }
- void Collada::_parse_controller(XMLParser &parser) {
- String id = parser.get_attribute_value("id");
- if (parser.is_empty()) {
- return;
- }
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
- if (section == "skin") {
- _parse_skin_controller(parser, id);
- } else if (section == "morph") {
- _parse_morph_controller(parser, id);
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "controller")
- break;
- }
- }
- Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) {
- String type = parser.get_node_name();
- NodeGeometry *geom = memnew(NodeGeometry);
- geom->controller = type == "instance_controller";
- geom->source = _uri_to_id(parser.get_attribute_value_safe("url"));
- if (parser.is_empty()) //nothing else to parse...
- return geom;
- // try to find also many materials and skeletons!
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "instance_material") {
- String symbol = parser.get_attribute_value("symbol");
- String target = _uri_to_id(parser.get_attribute_value("target"));
- NodeGeometry::Material mat;
- mat.target = target;
- geom->material_map[symbol] = mat;
- COLLADA_PRINT("uses material: '" + target + "' on primitive'" + symbol + "'");
- } else if (parser.get_node_name() == "skeleton") {
- parser.read();
- String uri = _uri_to_id(parser.get_node_data());
- if (uri != "") {
- geom->skeletons.push_back(uri);
- }
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == type)
- break;
- }
- if (geom->controller) {
- if (geom->skeletons.empty()) {
- //XSI style
- if (state.skin_controller_data_map.has(geom->source)) {
- SkinControllerData *skin = &state.skin_controller_data_map[geom->source];
- //case where skeletons reference bones with IDREF (XSI)
- ERR_FAIL_COND_V(!skin->joints.sources.has("JOINT"), geom);
- String joint_arr = skin->joints.sources["JOINT"];
- ERR_FAIL_COND_V(!skin->sources.has(joint_arr), geom);
- Collada::SkinControllerData::Source &joint_source = skin->sources[joint_arr];
- geom->skeletons = joint_source.sarray; //quite crazy, but should work.
- }
- }
- }
- return geom;
- }
- Collada::Node *Collada::_parse_visual_instance_camera(XMLParser &parser) {
- String type = parser.get_node_name();
- NodeCamera *cam = memnew(NodeCamera);
- cam->camera = _uri_to_id(parser.get_attribute_value_safe("url"));
- if (state.up_axis == Vector3::AXIS_Z) //collada weirdness
- cam->post_transform.basis.rotate(Vector3(1, 0, 0), Math_PI * 0.5);
- if (parser.is_empty()) //nothing else to parse...
- return cam;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "instance_camera")
- break;
- }
- return cam;
- }
- Collada::Node *Collada::_parse_visual_instance_light(XMLParser &parser) {
- String type = parser.get_node_name();
- NodeLight *cam = memnew(NodeLight);
- cam->light = _uri_to_id(parser.get_attribute_value_safe("url"));
- if (state.up_axis == Vector3::AXIS_Z) //collada weirdness
- cam->post_transform.basis.rotate(Vector3(1, 0, 0), Math_PI * 0.5);
- if (parser.is_empty()) //nothing else to parse...
- return cam;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "instance_light")
- break;
- }
- return cam;
- }
- Collada::Node *Collada::_parse_visual_node_instance_data(XMLParser &parser) {
- String instance_type = parser.get_node_name();
- if (instance_type == "instance_geometry" || instance_type == "instance_controller") {
- return _parse_visual_instance_geometry(parser);
- } else if (instance_type == "instance_camera") {
- return _parse_visual_instance_camera(parser);
- } else if (instance_type == "instance_light") {
- return _parse_visual_instance_light(parser);
- }
- if (parser.is_empty()) //nothing else to parse...
- return NULL;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == instance_type)
- break;
- }
- return NULL;
- }
- Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
- String name;
- String id = parser.get_attribute_value_safe("id");
- bool found_name = false;
- if (id == "") {
- id = "%NODEID%" + itos(Math::rand());
- } else {
- found_name = true;
- }
- Vector<Node::XForm> xform_list;
- Vector<Node *> children;
- String empty_draw_type = "";
- Node *node = NULL;
- name = parser.has_attribute("name") ? parser.get_attribute_value_safe("name") : parser.get_attribute_value_safe("id");
- if (name == "") {
- name = id;
- } else {
- found_name = true;
- }
- if ((parser.has_attribute("type") && parser.get_attribute_value("type") == "JOINT") || state.idref_joints.has(name)) {
- // handle a bone
- NodeJoint *joint = memnew(NodeJoint);
- if (parser.has_attribute("sid")) { //bones may not have sid
- joint->sid = parser.get_attribute_value("sid");
- // state.bone_map[joint->sid]=joint;
- } else if (state.idref_joints.has(name)) {
- joint->sid = name; //kind of a cheat but..
- } else if (parser.has_attribute("name")) {
- joint->sid = parser.get_attribute_value_safe("name");
- }
- if (joint->sid != "") {
- state.sid_to_node_map[joint->sid] = id;
- }
- node = joint;
- }
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
- if (section == "translate") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_attribute_value("sid");
- }
- xf.op = Node::XForm::OP_TRANSLATE;
- Vector<float> xlt = _read_float_array(parser);
- xf.data = xlt;
- xform_list.push_back(xf);
- } else if (section == "rotate") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_attribute_value("sid");
- }
- xf.op = Node::XForm::OP_ROTATE;
- Vector<float> rot = _read_float_array(parser);
- xf.data = rot;
- xform_list.push_back(xf);
- } else if (section == "scale") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_attribute_value("sid");
- }
- xf.op = Node::XForm::OP_SCALE;
- Vector<float> scale = _read_float_array(parser);
- xf.data = scale;
- xform_list.push_back(xf);
- } else if (section == "matrix") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_attribute_value("sid");
- }
- xf.op = Node::XForm::OP_MATRIX;
- Vector<float> matrix = _read_float_array(parser);
- xf.data = matrix;
- String mtx;
- for (int i = 0; i < matrix.size(); i++)
- mtx += " " + rtos(matrix[i]);
- xform_list.push_back(xf);
- } else if (section == "visibility") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id = parser.get_attribute_value("sid");
- }
- xf.op = Node::XForm::OP_VISIBILITY;
- Vector<float> visible = _read_float_array(parser);
- xf.data = visible;
- xform_list.push_back(xf);
- } else if (section == "empty_draw_type") {
- empty_draw_type = _read_empty_draw_type(parser);
- } else if (section == "technique" || section == "extra") {
- } else if (section != "node") {
- //usually what defines the type of node
- //print_line(" dont know what to do with "+section);
- if (section.begins_with("instance_")) {
- if (!node) {
- node = _parse_visual_node_instance_data(parser);
- } else {
- ERR_PRINT("Multiple instance_* not supported.");
- }
- }
- } else if (section == "node") {
- /* Found a child node!! what to do..*/
- Node *child = _parse_visual_scene_node(parser);
- children.push_back(child);
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "node")
- break;
- }
- if (!node) {
- node = memnew(Node); //generic node, nothing of relevance found
- }
- node->noname = !found_name;
- node->xform_list = xform_list;
- node->children = children;
- for (int i = 0; i < children.size(); i++) {
- node->children[i]->parent = node;
- }
- node->name = name;
- node->id = id;
- node->empty_draw_type = empty_draw_type;
- if (node->children.size() == 1) {
- if (node->children[0]->noname && !node->noname) {
- node->children[0]->name = node->name;
- node->name = node->name + "-base";
- }
- }
- node->default_transform = node->compute_transform(*this);
- state.scene_map[id] = node;
- return node;
- }
- void Collada::_parse_visual_scene(XMLParser &parser) {
- String id = parser.get_attribute_value("id");
- if (parser.is_empty()) {
- return;
- }
- state.visual_scene_map[id] = VisualScene();
- VisualScene &vscene = state.visual_scene_map[id];
- if (parser.has_attribute("name"))
- vscene.name = parser.get_attribute_value("name");
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String section = parser.get_node_name();
- if (section == "node") {
- vscene.root_nodes.push_back(_parse_visual_scene_node(parser));
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "visual_scene")
- break;
- }
- COLLADA_PRINT("Scene ID:" + id);
- }
- void Collada::_parse_animation(XMLParser &parser) {
- if (!(state.import_flags & IMPORT_FLAG_ANIMATION)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- Map<String, Vector<float> > float_sources;
- Map<String, Vector<String> > string_sources;
- Map<String, int> source_strides;
- Map<String, Map<String, String> > samplers;
- Map<String, Vector<String> > source_param_names;
- Map<String, Vector<String> > source_param_types;
- String id = "";
- if (parser.has_attribute("id"))
- id = parser.get_attribute_value("id");
- String current_source;
- String current_sampler;
- Vector<String> channel_sources;
- Vector<String> channel_targets;
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
- if (name == "source") {
- current_source = parser.get_attribute_value("id");
- source_param_names[current_source] = Vector<String>();
- source_param_types[current_source] = Vector<String>();
- } else if (name == "float_array") {
- if (current_source != "") {
- float_sources[current_source] = _read_float_array(parser);
- }
- } else if (name == "Name_array") {
- if (current_source != "") {
- string_sources[current_source] = _read_string_array(parser);
- }
- } else if (name == "accessor") {
- if (current_source != "" && parser.has_attribute("stride")) {
- source_strides[current_source] = parser.get_attribute_value("stride").to_int();
- }
- } else if (name == "sampler") {
- current_sampler = parser.get_attribute_value("id");
- samplers[current_sampler] = Map<String, String>();
- } else if (name == "param") {
- if (parser.has_attribute("name"))
- source_param_names[current_source].push_back(parser.get_attribute_value("name"));
- else
- source_param_names[current_source].push_back("");
- if (parser.has_attribute("type"))
- source_param_types[current_source].push_back(parser.get_attribute_value("type"));
- else
- source_param_types[current_source].push_back("");
- } else if (name == "input") {
- if (current_sampler != "") {
- samplers[current_sampler][parser.get_attribute_value("semantic")] = parser.get_attribute_value("source");
- }
- } else if (name == "channel") {
- channel_sources.push_back(parser.get_attribute_value("source"));
- channel_targets.push_back(parser.get_attribute_value("target"));
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation")
- break; //end of <asset>
- }
- for (int i = 0; i < channel_sources.size(); i++) {
- String source = _uri_to_id(channel_sources[i]);
- String target = channel_targets[i];
- if (!samplers.has(source)) {
- print_line("channel lacks source: " + source);
- }
- ERR_CONTINUE(!samplers.has(source));
- Map<String, String> &sampler = samplers[source];
- ERR_CONTINUE(!sampler.has("INPUT")); //no input semantic? wtf?
- String input_id = _uri_to_id(sampler["INPUT"]);
- COLLADA_PRINT("input id is " + input_id);
- ERR_CONTINUE(!float_sources.has(input_id));
- ERR_CONTINUE(!sampler.has("OUTPUT"));
- String output_id = _uri_to_id(sampler["OUTPUT"]);
- ERR_CONTINUE(!float_sources.has(output_id));
- ERR_CONTINUE(!source_param_names.has(output_id));
- Vector<String> &names = source_param_names[output_id];
- for (int l = 0; l < names.size(); l++) {
- String name = names[l];
- Vector<float> &time_keys = float_sources[input_id];
- int key_count = time_keys.size();
- AnimationTrack track; //begin crating track
- track.id = id;
- track.keys.resize(key_count);
- for (int j = 0; j < key_count; j++) {
- track.keys[j].time = time_keys[j];
- state.animation_length = MAX(state.animation_length, time_keys[j]);
- }
- //now read actual values
- int stride = 1;
- if (source_strides.has(output_id))
- stride = source_strides[output_id];
- int output_len = stride / names.size();
- ERR_CONTINUE(output_len == 0);
- ERR_CONTINUE(!float_sources.has(output_id));
- Vector<float> &output = float_sources[output_id];
- ERR_EXPLAIN("Wrong number of keys in output");
- ERR_CONTINUE((output.size() / stride) != key_count);
- for (int j = 0; j < key_count; j++) {
- track.keys[j].data.resize(output_len);
- for (int k = 0; k < output_len; k++)
- track.keys[j].data[k] = output[l + j * stride + k]; //super weird but should work
- }
- if (sampler.has("INTERPOLATION")) {
- String interp_id = _uri_to_id(sampler["INTERPOLATION"]);
- ERR_CONTINUE(!string_sources.has(interp_id));
- Vector<String> &interps = string_sources[interp_id];
- ERR_CONTINUE(interps.size() != key_count);
- for (int j = 0; j < key_count; j++) {
- if (interps[j] == "BEZIER")
- track.keys[j].interp_type = AnimationTrack::INTERP_BEZIER;
- else
- track.keys[j].interp_type = AnimationTrack::INTERP_LINEAR;
- }
- }
- if (sampler.has("IN_TANGENT") && sampler.has("OUT_TANGENT")) {
- //bezier control points..
- String intangent_id = _uri_to_id(sampler["IN_TANGENT"]);
- ERR_CONTINUE(!float_sources.has(intangent_id));
- Vector<float> &intangents = float_sources[intangent_id];
- ERR_CONTINUE(intangents.size() != key_count * 2 * names.size());
- String outangent_id = _uri_to_id(sampler["OUT_TANGENT"]);
- ERR_CONTINUE(!float_sources.has(outangent_id));
- Vector<float> &outangents = float_sources[outangent_id];
- ERR_CONTINUE(outangents.size() != key_count * 2 * names.size());
- for (int j = 0; j < key_count; j++) {
- track.keys[j].in_tangent = Vector2(intangents[j * 2 * names.size() + 0 + l * 2], intangents[j * 2 * names.size() + 1 + l * 2]);
- track.keys[j].out_tangent = Vector2(outangents[j * 2 * names.size() + 0 + l * 2], outangents[j * 2 * names.size() + 1 + l * 2]);
- }
- }
- if (target.find("/") != -1) { //transform component
- track.target = target.get_slicec('/', 0);
- track.param = target.get_slicec('/', 1);
- if (track.param.find(".") != -1)
- track.component = track.param.get_slice(".", 1).to_upper();
- track.param = track.param.get_slice(".", 0);
- if (names.size() > 1 && track.component == "") {
- //this is a guess because the collada spec is ambiguous here...
- //i suppose if you have many names (outputs) you can't use a component and i should abide to that.
- track.component = name;
- }
- } else {
- track.target = target;
- }
- print_line("TARGET: " + track.target);
- state.animation_tracks.push_back(track);
- if (!state.referenced_tracks.has(target))
- state.referenced_tracks[target] = Vector<int>();
- state.referenced_tracks[target].push_back(state.animation_tracks.size() - 1);
- if (id != "") {
- if (!state.by_id_tracks.has(id))
- state.by_id_tracks[id] = Vector<int>();
- state.by_id_tracks[id].push_back(state.animation_tracks.size() - 1);
- }
- COLLADA_PRINT("loaded animation with " + itos(key_count) + " keys");
- }
- }
- }
- void Collada::_parse_animation_clip(XMLParser &parser) {
- if (!(state.import_flags & IMPORT_FLAG_ANIMATION)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
- AnimationClip clip;
- if (parser.has_attribute("name"))
- clip.name = parser.get_attribute_value("name");
- else if (parser.has_attribute("id"))
- clip.name = parser.get_attribute_value("id");
- if (parser.has_attribute("start"))
- clip.begin = parser.get_attribute_value("start").to_double();
- if (parser.has_attribute("end"))
- clip.end = parser.get_attribute_value("end").to_double();
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
- if (name == "instance_animation") {
- String url = _uri_to_id(parser.get_attribute_value("url"));
- clip.tracks.push_back(url);
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation_clip")
- break; //end of <asset>
- }
- state.animation_clips.push_back(clip);
- print_line("found anim clip: " + clip.name);
- }
- void Collada::_parse_scene(XMLParser &parser) {
- if (parser.is_empty()) {
- return;
- }
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
- if (name == "instance_visual_scene") {
- state.root_visual_scene = _uri_to_id(parser.get_attribute_value("url"));
- print_line("***ROOT VISUAL SCENE: " + state.root_visual_scene);
- }
- if (name == "instance_physics_scene") {
- state.root_physics_scene = _uri_to_id(parser.get_attribute_value("url"));
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "scene")
- break; //end of <asset>
- }
- }
- void Collada::_parse_library(XMLParser &parser) {
- if (parser.is_empty()) {
- return;
- }
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- String name = parser.get_node_name();
- COLLADA_PRINT("library name is: " + name);
- if (name == "image") {
- _parse_image(parser);
- } else if (name == "material") {
- _parse_material(parser);
- } else if (name == "effect") {
- _parse_effect(parser);
- } else if (name == "camera") {
- _parse_camera(parser);
- } else if (name == "light") {
- _parse_light(parser);
- } else if (name == "geometry") {
- String id = parser.get_attribute_value("id");
- String name = parser.get_attribute_value_safe("name");
- while (parser.read() == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "mesh") {
- state.mesh_name_map[id] = (name != "") ? name : id;
- _parse_mesh_geometry(parser, id, name);
- } else if (parser.get_node_name() == "spline") {
- state.mesh_name_map[id] = (name != "") ? name : id;
- _parse_curve_geometry(parser, id, name);
- } else if (!parser.is_empty())
- parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "geometry")
- break;
- }
- } else if (name == "controller") {
- _parse_controller(parser);
- } else if (name == "animation") {
- _parse_animation(parser);
- } else if (name == "animation_clip") {
- _parse_animation_clip(parser);
- } else if (name == "visual_scene") {
- COLLADA_PRINT("visual scene");
- _parse_visual_scene(parser);
- } else if (!parser.is_empty())
- parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name().begins_with("library_"))
- break; //end of <asset>
- }
- }
- void Collada::_joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner) {
- if (p_node->type == Node::TYPE_JOINT) {
- NodeJoint *nj = static_cast<NodeJoint *>(p_node);
- nj->owner = p_owner;
- for (int i = 0; i < nj->children.size(); i++) {
- _joint_set_owner(nj->children[i], p_owner);
- }
- }
- }
- void Collada::_create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton) {
- Node *node = *p_node;
- if (node->type == Node::TYPE_JOINT) {
- if (!p_skeleton) {
- // ohohohoohoo it's a joint node, time to work!
- NodeSkeleton *sk = memnew(NodeSkeleton);
- *p_node = sk;
- sk->children.push_back(node);
- sk->parent = node->parent;
- node->parent = sk;
- p_skeleton = sk;
- }
- NodeJoint *nj = static_cast<NodeJoint *>(node);
- nj->owner = p_skeleton;
- } else {
- p_skeleton = NULL;
- }
- for (int i = 0; i < node->children.size(); i++) {
- _create_skeletons(&node->children[i], p_skeleton);
- }
- }
- bool Collada::_remove_node(Node *p_parent, Node *p_node) {
- for (int i = 0; i < p_parent->children.size(); i++) {
- if (p_parent->children[i] == p_node) {
- p_parent->children.remove(i);
- return true;
- }
- if (_remove_node(p_parent->children[i], p_node))
- return true;
- }
- return false;
- }
- void Collada::_remove_node(VisualScene *p_vscene, Node *p_node) {
- for (int i = 0; i < p_vscene->root_nodes.size(); i++) {
- if (p_vscene->root_nodes[i] == p_node) {
- p_vscene->root_nodes.remove(i);
- return;
- }
- if (_remove_node(p_vscene->root_nodes[i], p_node))
- return;
- }
- ERR_PRINT("ERROR: Not found node to remove?");
- }
- void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) {
- if (p_node->type == Node::TYPE_GEOMETRY) {
- NodeGeometry *gnode = static_cast<NodeGeometry *>(p_node);
- if (gnode->controller) {
- // recount skeletons used
- Set<NodeSkeleton *> skeletons;
- for (int i = 0; i < gnode->skeletons.size(); i++) {
- String nodeid = gnode->skeletons[i];
- ERR_CONTINUE(!state.scene_map.has(nodeid)); //weird, it should have it...
- NodeJoint *nj = SAFE_CAST<NodeJoint *>(state.scene_map[nodeid]);
- ERR_CONTINUE(!nj); //broken collada
- if (!nj->owner) {
- print_line("no owner for: " + String(nodeid));
- }
- ERR_CONTINUE(!nj->owner); //weird, node should have a skeleton owner
- skeletons.insert(nj->owner);
- }
- if (skeletons.size() > 1) {
- //do the merger!!
- Set<NodeSkeleton *>::Element *E = skeletons.front();
- NodeSkeleton *base = E->get();
- for (E = E->next(); E; E = E->next()) {
- NodeSkeleton *merged = E->get();
- _remove_node(p_vscene, merged);
- for (int i = 0; i < merged->children.size(); i++) {
- _joint_set_owner(merged->children[i], base);
- base->children.push_back(merged->children[i]);
- merged->children[i]->parent = base;
- }
- merged->children.clear(); //take children from it
- memdelete(merged);
- }
- }
- }
- }
- for (int i = 0; i < p_node->children.size(); i++) {
- _merge_skeletons(p_vscene, p_node->children[i]);
- }
- }
- void Collada::_merge_skeletons2(VisualScene *p_vscene) {
- for (Map<String, SkinControllerData>::Element *E = state.skin_controller_data_map.front(); E; E = E->next()) {
- SkinControllerData &cd = E->get();
- NodeSkeleton *skeleton = NULL;
- for (Map<String, Transform>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) {
- String name;
- if (!state.sid_to_node_map.has(F->key())) {
- continue;
- }
- name = state.sid_to_node_map[F->key()];
- if (!state.scene_map.has(name)) {
- print_line("no foundie node for: " + name);
- }
- ERR_CONTINUE(!state.scene_map.has(name));
- Node *node = state.scene_map[name];
- ERR_CONTINUE(node->type != Node::TYPE_JOINT);
- if (node->type != Node::TYPE_JOINT)
- continue;
- NodeSkeleton *sk = NULL;
- while (node && !sk) {
- if (node->type == Node::TYPE_SKELETON) {
- sk = static_cast<NodeSkeleton *>(node);
- }
- node = node->parent;
- }
- ERR_CONTINUE(!sk);
- if (!sk)
- continue; //bleh
- if (!skeleton) {
- skeleton = sk;
- continue;
- }
- if (skeleton != sk) {
- //whoa.. wtf, merge.
- print_line("MERGED BONES!!");
- //NodeSkeleton *merged = E->get();
- _remove_node(p_vscene, sk);
- for (int i = 0; i < sk->children.size(); i++) {
- _joint_set_owner(sk->children[i], skeleton);
- skeleton->children.push_back(sk->children[i]);
- sk->children[i]->parent = skeleton;
- }
- sk->children.clear(); //take children from it
- memdelete(sk);
- }
- }
- }
- }
- bool Collada::_optimize_skeletons(VisualScene *p_vscene, Node *p_node) {
- Node *node = p_node;
- if (node->type == Node::TYPE_SKELETON && node->parent && node->parent->type == Node::TYPE_NODE && node->parent->children.size() == 1) {
- //replace parent by this...
- Node *parent = node->parent;
- //i wonder if this is allright.. i think it is since created skeleton (first joint) is already animated by bone..
- node->id = parent->id;
- node->name = parent->name;
- node->xform_list = parent->xform_list;
- node->default_transform = parent->default_transform;
- state.scene_map[node->id] = node;
- node->parent = parent->parent;
- if (parent->parent) {
- Node *gp = parent->parent;
- bool found = false;
- for (int i = 0; i < gp->children.size(); i++) {
- if (gp->children[i] == parent) {
- gp->children[i] = node;
- found = true;
- break;
- }
- }
- if (!found) {
- ERR_PRINT("BUG");
- }
- } else {
- bool found = false;
- for (int i = 0; i < p_vscene->root_nodes.size(); i++) {
- if (p_vscene->root_nodes[i] == parent) {
- p_vscene->root_nodes[i] = node;
- found = true;
- break;
- }
- }
- if (!found) {
- ERR_PRINT("BUG");
- }
- }
- parent->children.clear();
- memdelete(parent);
- return true;
- }
- for (int i = 0; i < node->children.size(); i++) {
- if (_optimize_skeletons(p_vscene, node->children[i]))
- return false; //stop processing, go up
- }
- return false;
- }
- bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, List<Node *> *p_mgeom) {
- // bind shape matrix escala los huesos y los hace gigantes, asi la matriz despues achica
- // al modelo?
- // solucion: aplicarle la bind shape matrix a los VERTICES, y si el objeto viene con escala, se la dejo me parece!
- if (p_node->type == Node::TYPE_GEOMETRY) {
- NodeGeometry *ng = static_cast<NodeGeometry *>(p_node);
- if (ng->ignore_anim)
- return false; //already made child of skeleton and processeg
- if (ng->controller && ng->skeletons.size()) {
- String nodeid = ng->skeletons[0];
- ERR_FAIL_COND_V(!state.scene_map.has(nodeid), false); //weird, it should have it...
- NodeJoint *nj = SAFE_CAST<NodeJoint *>(state.scene_map[nodeid]);
- ERR_FAIL_COND_V(!nj, false);
- if (!nj->owner) {
- print_line("Has no owner: " + nj->name);
- }
- ERR_FAIL_COND_V(!nj->owner, false); //weird, node should have a skeleton owner
- NodeSkeleton *sk = nj->owner;
- Node *p = sk->parent;
- bool node_is_parent_of_skeleton = false;
- while (p) {
- if (p == p_node) {
- node_is_parent_of_skeleton = true;
- break;
- }
- p = p->parent; // try again
- }
- ERR_FAIL_COND_V(node_is_parent_of_skeleton, false);
- //this should be correct
- ERR_FAIL_COND_V(!state.skin_controller_data_map.has(ng->source), false);
- SkinControllerData &skin = state.skin_controller_data_map[ng->source];
- Transform skel_inv = sk->get_global_transform().affine_inverse();
- p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it
- //make rests relative to the skeleton (they seem to be always relative to world)
- for (Map<String, Transform>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) {
- E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton
- state.bone_rest_map[E->key()] = E->get(); // make it remember where the bone is globally, now that it's relative
- }
- //but most exporters seem to work only if i do this..
- //p_node->default_transform = p_node->get_global_transform();
- //p_node->default_transform=Transform(); //this seems to be correct, because bind shape makes the object local to the skeleton
- p_node->ignore_anim = true; // collada may animate this later, if it does, then this is not supported (redo your original asset and don't animate the base mesh)
- p_node->parent = sk;
- //sk->children.push_back(0,p_node); //avoid INFINIT loop
- p_mgeom->push_back(p_node);
- return true;
- }
- }
- for (int i = 0; i < p_node->children.size(); i++) {
- if (_move_geometry_to_skeletons(p_vscene, p_node->children[i], p_mgeom)) {
- p_node->children.remove(i);
- i--;
- }
- }
- return false;
- }
- void Collada::_find_morph_nodes(VisualScene *p_vscene, Node *p_node) {
- if (p_node->type == Node::TYPE_GEOMETRY) {
- NodeGeometry *nj = static_cast<NodeGeometry *>(p_node);
- if (nj->controller) {
- String base = nj->source;
- while (base != "" && !state.mesh_data_map.has(base)) {
- if (state.skin_controller_data_map.has(base)) {
- SkinControllerData &sk = state.skin_controller_data_map[base];
- base = sk.base;
- } else if (state.morph_controller_data_map.has(base)) {
- state.morph_ownership_map[base] = nj->id;
- break;
- } else {
- ERR_EXPLAIN("Invalid scene");
- ERR_FAIL();
- }
- }
- }
- }
- for (int i = 0; i < p_node->children.size(); i++) {
- _find_morph_nodes(p_vscene, p_node->children[i]);
- }
- }
- void Collada::_optimize() {
- for (Map<String, VisualScene>::Element *E = state.visual_scene_map.front(); E; E = E->next()) {
- VisualScene &vs = E->get();
- for (int i = 0; i < vs.root_nodes.size(); i++) {
- _create_skeletons(&vs.root_nodes[i]);
- }
- #if 1
- for (int i = 0; i < vs.root_nodes.size(); i++) {
- _merge_skeletons(&vs, vs.root_nodes[i]);
- }
- _merge_skeletons2(&vs);
- for (int i = 0; i < vs.root_nodes.size(); i++) {
- _optimize_skeletons(&vs, vs.root_nodes[i]);
- }
- for (int i = 0; i < vs.root_nodes.size(); i++) {
- List<Node *> mgeom;
- if (_move_geometry_to_skeletons(&vs, vs.root_nodes[i], &mgeom)) {
- vs.root_nodes.remove(i);
- i--;
- }
- while (!mgeom.empty()) {
- Node *n = mgeom.front()->get();
- n->parent->children.push_back(n);
- mgeom.pop_front();
- }
- }
- #endif
- for (int i = 0; i < vs.root_nodes.size(); i++) {
- _find_morph_nodes(&vs, vs.root_nodes[i]);
- }
- }
- }
- int Collada::get_uv_channel(String p_name) {
- if (!channel_map.has(p_name)) {
- ERR_FAIL_COND_V(channel_map.size() == 2, 0);
- channel_map[p_name] = channel_map.size();
- }
- return channel_map[p_name];
- }
- Error Collada::load(const String &p_path, int p_flags) {
- Ref<XMLParser> parserr = memnew(XMLParser);
- XMLParser &parser = *parserr.ptr();
- Error err = parser.open(p_path);
- ERR_FAIL_COND_V(err, err);
- state.local_path = Globals::get_singleton()->localize_path(p_path);
- state.import_flags = p_flags;
- /* Skip headers */
- err = OK;
- while ((err = parser.read()) == OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
- if (parser.get_node_name() == "COLLADA") {
- break;
- } else if (!parser.is_empty())
- parser.skip_section(); // unknown section, likely headers
- }
- }
- ERR_FAIL_COND_V(err != OK, ERR_FILE_CORRUPT);
- /* Start loading Collada */
- {
- //version
- String version = parser.get_attribute_value("version");
- state.version.major = version.get_slice(".", 0).to_int();
- state.version.minor = version.get_slice(".", 1).to_int();
- state.version.rev = version.get_slice(".", 2).to_int();
- COLLADA_PRINT("Collada VERSION: " + version);
- }
- while ((err = parser.read()) == OK) {
- /* Read all the main sections.. */
- if (parser.get_node_type() != XMLParser::NODE_ELEMENT)
- continue; //no idea what this may be, but skipping anyway
- String section = parser.get_node_name();
- COLLADA_PRINT("section: " + section);
- if (section == "asset") {
- _parse_asset(parser);
- } else if (section.begins_with("library_")) {
- _parse_library(parser);
- } else if (section == "scene") {
- _parse_scene(parser);
- } else if (!parser.is_empty()) {
- parser.skip_section(); // unknown section, likely headers
- }
- }
- _optimize();
- return OK;
- }
- Collada::Collada() {
- }
- #endif
|