52 ~ObjToEggConverter() {
109 if (_egg_data->get_coordinate_system() == CS_default) {
110 _egg_data->set_coordinate_system(CS_zup_right);
113 if (!process(filename)) {
130 _current_vertex_data =
new VertexData(_root_node,
"root");
132 if (!process_node(filename)) {
136 _current_vertex_data->close_geom(
this);
137 delete _current_vertex_data;
149 bool ObjToEggConverter::
153 if (strm ==
nullptr) {
155 <<
"Couldn't read " << filename <<
"\n";
164 _ref_plane_res.set(1.0, 1.0);
170 _egg_data->add_child(_vpool);
172 _egg_data->add_child(_root_group);
173 _current_group = _root_group;
176 string line = sr.readline();
178 while (!line.empty()) {
181 line = sr.readline();
185 while (line[line.length() - 1] ==
'\\') {
187 string line2 = sr.readline();
192 line = line.substr(0, line.length() - 1) +
trim(line2);
195 if (line.substr(0, 15) ==
"#_ref_plane_res") {
196 process_ref_plane_res(line);
197 line = sr.readline();
201 if (line[0] ==
'#') {
202 line = sr.readline();
206 if (!process_line(line)) {
209 line = sr.readline();
214 generate_egg_points();
223 bool ObjToEggConverter::
224 process_line(
const string &line) {
227 nassertr(!words.empty(),
false);
229 string tag = words[0];
231 return process_v(words);
232 }
else if (tag ==
"vt") {
233 return process_vt(words);
234 }
else if (tag ==
"xvt") {
235 return process_xvt(words);
236 }
else if (tag ==
"xvc") {
237 return process_xvc(words);
238 }
else if (tag ==
"vn") {
239 return process_vn(words);
240 }
else if (tag ==
"f") {
241 return process_f(words);
242 }
else if (tag ==
"g") {
243 return process_g(words);
245 bool inserted = _ignored_tags.insert(tag).second;
248 <<
"Ignoring tag " << tag <<
"\n";
258 bool ObjToEggConverter::
259 process_ref_plane_res(
const string &line) {
266 nassertr(!words.empty(),
false);
268 if (words.size() != 3) {
270 <<
"Wrong number of tokens at line " << _line_number <<
"\n";
280 <<
"Invalid number at line " << _line_number <<
":\n";
290 bool ObjToEggConverter::
291 process_v(vector_string &words) {
292 if (words.size() != 4 && words.size() != 5 &&
293 words.size() != 7 && words.size() != 8) {
295 <<
"Wrong number of tokens at line " << _line_number <<
"\n";
304 if (words.size() == 5 || words.size() == 8) {
313 <<
"Invalid number at line " << _line_number <<
"\n";
317 _v_table.push_back(pos);
320 if (words.size() == 7 && words.size() == 8) {
321 size_t si = words.size();
329 <<
"Invalid number at line " << _line_number <<
"\n";
332 while (_rgb_table.size() + 1 < _v_table.size()) {
333 _rgb_table.push_back(LVecBase3d(1.0, 1.0, 1.0));
335 _rgb_table.push_back(rgb);
344 bool ObjToEggConverter::
345 process_vt(vector_string &words) {
346 if (words.size() != 3 && words.size() != 4) {
348 <<
"Wrong number of tokens at line " << _line_number <<
"\n";
356 if (words.size() == 4) {
365 <<
"Invalid number at line " << _line_number <<
"\n";
369 _vt_table.push_back(uvw);
379 bool ObjToEggConverter::
380 process_xvt(vector_string &words) {
381 if (words.size() < 3) {
383 <<
"Wrong number of tokens at line " << _line_number <<
"\n";
394 <<
"Invalid number at line " << _line_number <<
"\n";
398 uv[0] /= _ref_plane_res[0];
399 uv[1] = 1.0 - uv[1] / _ref_plane_res[1];
401 _xvt_table.push_back(uv);
409 bool ObjToEggConverter::
410 process_xvc(vector_string &words) {
417 bool ObjToEggConverter::
418 process_vn(vector_string &words) {
419 if (words.size() != 4) {
421 <<
"Wrong number of tokens at line " << _line_number <<
"\n";
433 <<
"Invalid number at line " << _line_number <<
"\n";
438 _vn_table.push_back(normal);
446 bool ObjToEggConverter::
447 process_f(vector_string &words) {
451 for (
size_t i = 1; i < words.size(); ++i) {
452 EggVertex *vertex = get_face_vertex(words[i]);
453 if (vertex ==
nullptr) {
456 poly->add_vertex(vertex);
466 bool ObjToEggConverter::
467 process_g(vector_string &words) {
475 size_t i = words.size();
479 if (child ==
nullptr || !child->
is_of_type(EggGroup::get_class_type())) {
486 _current_group = group;
495 get_face_vertex(
const string &reference) {
496 VertexEntry entry(
this, reference);
501 if (entry._vi != 0) {
503 synth.
set_pos(LCAST(
double, _v_table[entry._vi - 1]));
505 LPoint4d pos = _v_table[entry._vi - 1];
506 synth.
set_pos(LPoint3d(pos[0], pos[1], pos[2]));
509 if (entry._vi - 1 < (
int)_rgb_table.size()) {
511 LRGBColord rgb = _rgb_table[entry._vi - 1];
512 LColor rgba(rgb[0], rgb[1], rgb[2], 1.0);
513 synth.set_color(rgba);
517 if (entry._vti != 0) {
520 synth.
set_uvw(
"", _vt_table[entry._vti - 1]);
522 LTexCoord3d uvw = _vt_table[entry._vti - 1];
523 synth.
set_uv(
"", LTexCoordd(uvw[0], uvw[1]));
525 }
else if (entry._vi - 1 < (
int)_xvt_table.size()) {
527 synth.
set_uv(
"", _xvt_table[entry._vi - 1]);
530 if (entry._vni != 0) {
532 synth.set_normal(_vn_table[entry._vni - 1]);
535 return _vpool->create_unique_vertex(synth);
542 void ObjToEggConverter::
543 generate_egg_points() {
544 for (
size_t vi = 0; vi < _v_table.size(); ++vi) {
545 const LVecBase4d &p = _v_table[vi];
546 _vpool->make_new_vertex(LVecBase3d(p[0], p[1], p[2]));
554 bool ObjToEggConverter::
555 process_node(
const Filename &filename) {
558 if (strm ==
nullptr) {
560 <<
"Couldn't read " << filename <<
"\n";
569 _ref_plane_res.set(1.0, 1.0);
575 string line = sr.readline();
577 while (!line.empty()) {
580 line = sr.readline();
584 if (line.substr(0, 15) ==
"#_ref_plane_res") {
585 process_ref_plane_res(line);
586 line = sr.readline();
590 if (line[0] ==
'#') {
591 line = sr.readline();
595 if (!process_line_node(line)) {
598 line = sr.readline();
612 bool ObjToEggConverter::
613 process_line_node(
const string &line) {
616 nassertr(!words.empty(),
false);
618 string tag = words[0];
620 return process_v(words);
621 }
else if (tag ==
"vt") {
622 return process_vt(words);
623 }
else if (tag ==
"xvt") {
624 return process_xvt(words);
625 }
else if (tag ==
"xvc") {
626 return process_xvc(words);
627 }
else if (tag ==
"vn") {
628 return process_vn(words);
629 }
else if (tag ==
"f") {
630 return process_f_node(words);
631 }
else if (tag ==
"g") {
632 return process_g_node(words);
634 bool inserted = _ignored_tags.insert(tag).second;
637 <<
"Ignoring tag " << tag <<
"\n";
647 bool ObjToEggConverter::
648 process_f_node(vector_string &words) {
655 verts.reserve(words.size() - 1);
656 for (
size_t i = 1; i < words.size(); ++i) {
657 VertexEntry entry(
this, words[i]);
658 verts.push_back(entry);
659 if (entry._vni == 0) {
665 if (verts.size() < 3) {
668 <<
"Degenerate face at " << _line_number <<
"\n";
675 LNormald normal = LNormald::zero();
676 for (
size_t i = 0; i < verts.size(); ++i) {
677 int vi0 = verts[i]._vi;
678 int vi1 = verts[(i + 1) % verts.size()]._vi;
679 if (vi0 == 0 || vi1 == 0) {
682 const LVecBase4d &p0 = _v_table[vi0 - 1];
683 const LVecBase4d &p1 = _v_table[vi1 - 1];
685 normal[0] += p0[1] * p1[2] - p0[2] * p1[1];
686 normal[1] += p0[2] * p1[0] - p0[0] * p1[2];
687 normal[2] += p0[0] * p1[1] - p0[1] * p1[0];
690 synth_vni = add_synth_normal(normal);
696 if (verts.size() != 3) {
698 for (
size_t i = 0; i < verts.size(); ++i) {
699 const LVecBase4d &p = _v_table[verts[i]._vi - 1];
708 if (_current_vertex_data->_prim->get_num_vertices() + 3 * num_tris > egg_max_indices ||
709 _current_vertex_data->_entries.size() + verts.size() > (
size_t)egg_max_vertices) {
712 _current_vertex_data->close_geom(
this);
715 if (verts.size() == 3) {
717 _current_vertex_data->add_triangle(
this, verts[0], verts[1], verts[2], synth_vni);
721 for (
int ti = 0; ti < num_tris; ++ti) {
725 _current_vertex_data->add_triangle(
this, verts[i0], verts[i1], verts[i2], synth_vni);
735 bool ObjToEggConverter::
736 process_g_node(vector_string &words) {
737 _current_vertex_data->close_geom(
this);
738 delete _current_vertex_data;
739 _current_vertex_data =
nullptr;
748 size_t i = words.size();
765 _current_vertex_data =
new VertexData(np.node(), name);
774 void ObjToEggConverter::
778 vdata->set_num_rows(_v_table.size());
781 for (
size_t vi = 0; vi < _v_table.size(); ++vi) {
782 const LVecBase4d &p = _v_table[vi];
783 vertex_writer.add_data3d(p[0], p[1], p[2]);
787 prim->add_next_vertices(_v_table.size());
788 prim->close_primitive();
791 geom->add_primitive(prim);
794 geom_node->add_geom(geom);
795 _root_node->add_child(geom_node);
802 int ObjToEggConverter::
803 add_synth_normal(
const LVecBase3d &normal) {
804 std::pair<UniqueVec3Table::iterator, bool> result = _unique_synth_vn_table.insert(UniqueVec3Table::value_type(normal, _unique_synth_vn_table.size()));
805 UniqueVec3Table::iterator ni = result.first;
806 int index = (*ni).second;
811 _synth_vn_table.push_back(normal);
821 ObjToEggConverter::VertexEntry::
829 tokenize(obj_vertex, words,
"/",
false);
830 nassertv(!words.empty());
832 for (
size_t i = 0; i < words.size(); ++i) {
834 if (
trim(words[i]).empty()) {
846 _vi = (int)converter->_v_table.size() + _vi;
848 if (_vi < 0 || _vi - 1 >= (
int)converter->_v_table.size()) {
856 _vti = (int)converter->_vt_table.size() + _vti;
858 if (_vti < 0 || _vti - 1 >= (
int)converter->_vt_table.size()) {
866 _vni = (int)converter->_vn_table.size() + _vni;
868 if (_vni < 0 || _vni - 1 >= (
int)converter->_vn_table.size()) {
879 ObjToEggConverter::VertexData::
880 VertexData(
PandaNode *parent,
const string &name) :
881 _parent(parent), _name(name)
883 _geom_node =
nullptr;
898 int ObjToEggConverter::VertexData::
900 std::pair<UniqueVertexEntries::iterator, bool> result;
901 UniqueVertexEntries::iterator ni;
904 if (entry._vni != 0 || entry._synth_vni != 0) {
907 VertexEntry no_normal(entry);
909 no_normal._synth_vni = 0;
910 ni = _unique_entries.find(no_normal);
911 if (ni != _unique_entries.end()) {
914 index = (*ni).second;
915 _unique_entries.erase(ni);
916 result = _unique_entries.insert(UniqueVertexEntries::value_type(entry, index));
917 nassertr(result.second, index);
918 nassertr(_entries[index] == no_normal, index);
919 _entries[index]._vni = entry._vni;
920 _entries[index]._synth_vni = entry._synth_vni;
923 }
else if (entry._vni == 0 && entry._synth_vni == 0) {
926 ni = _unique_entries.lower_bound(entry);
927 if (ni != _unique_entries.end() && (*ni).first.matches_except_normal(entry)) {
929 index = (*ni).second;
936 result = _unique_entries.insert(UniqueVertexEntries::value_type(entry, _entries.size()));
938 index = (*ni).second;
943 _entries.push_back(entry);
945 if (converter->_v4_given) {
948 if (converter->_vt3_given) {
951 if (entry._vti != 0) {
953 }
else if (entry._vi - 1 < (
int)converter->_xvt_table.size()) {
957 if (entry._vi - 1 < (
int)converter->_rgb_table.size()) {
961 if (entry._vni != 0) {
974 void ObjToEggConverter::VertexData::
976 const VertexEntry &v1,
const VertexEntry &v2,
980 v0i = add_vertex(converter, v0);
981 v1i = add_vertex(converter, v1);
983 if (synth_vni != 0) {
985 v2n._synth_vni = synth_vni;
986 v2i = add_vertex(converter, v2n);
988 v2i = add_vertex(converter, v2);
991 _prim->add_vertices(v0i, v1i, v2i);
992 _prim->close_primitive();
999 void ObjToEggConverter::VertexData::
1001 if (_prim->get_num_vertices() != 0) {
1005 aformat->
add_column(InternalName::get_vertex(), 4,
1006 GeomEnums::NT_stdfloat, GeomEnums::C_point);
1008 aformat->add_column(InternalName::get_vertex(), 3,
1009 GeomEnums::NT_stdfloat, GeomEnums::C_point);
1014 aformat->add_column(InternalName::get_normal(), 3,
1015 GeomEnums::NT_stdfloat, GeomEnums::C_vector);
1019 aformat->add_column(InternalName::get_texcoord(), 3,
1020 GeomEnums::NT_stdfloat, GeomEnums::C_texcoord);
1022 aformat->add_column(InternalName::get_texcoord(), 2,
1023 GeomEnums::NT_stdfloat, GeomEnums::C_texcoord);
1028 aformat->add_column(InternalName::get_color(), 4,
1029 GeomEnums::NT_uint8, GeomEnums::C_color);
1041 for (
size_t i = 0; i < _entries.size(); ++i) {
1042 const VertexEntry &entry = _entries[i];
1044 if (entry._vi != 0) {
1045 vertex_writer.set_row(i);
1046 vertex_writer.add_data4d(converter->_v_table[entry._vi - 1]);
1048 if (entry._vti != 0) {
1049 texcoord_writer.set_row(i);
1050 texcoord_writer.add_data3d(converter->_vt_table[entry._vti - 1]);
1051 }
else if (entry._vi - 1 < (
int)converter->_xvt_table.size()) {
1053 texcoord_writer.set_row(i);
1054 texcoord_writer.add_data2d(converter->_xvt_table[entry._vi - 1]);
1056 if (entry._vni != 0) {
1057 normal_writer.set_row(i);
1058 normal_writer.add_data3d(converter->_vn_table[entry._vni - 1]);
1059 }
else if (entry._synth_vni != 0) {
1060 normal_writer.set_row(i);
1061 normal_writer.add_data3d(converter->_synth_vn_table[entry._synth_vni - 1]);
1065 normal_writer.set_row(i);
1066 normal_writer.add_data3d(0, 0, 1);
1069 if (entry._vi - 1 < (
int)converter->_rgb_table.size()) {
1070 color_writer.set_row(i);
1071 color_writer.add_data3d(converter->_rgb_table[entry._vi - 1]);
1077 vdata->transform_vertices(LMatrix4::convert_mat(CS_zup_right, CS_default));
1080 CPT(
RenderState) state = RenderState::make_empty();
1082 state = state->add_attrib(ColorAttrib::make_vertex());
1084 state = state->add_attrib(ColorAttrib::make_flat(LColor(1, 1, 1, 1)));
1088 state = state->add_attrib(ShadeModelAttrib::make(ShadeModelAttrib::M_flat));
1089 _prim->set_shade_model(GeomEnums::SM_flat_last_vertex);
1093 geom->add_primitive(_prim);
1095 if (_geom_node ==
nullptr) {
1097 _parent->add_child(_geom_node);
1100 _geom_node->add_geom(geom, state);
1105 _unique_entries.clear();