comparison dmmodel.cpp @ 21:1404dfcee7b8

More work on scenefile and model loading support. Can now load PLY models and simple scene definition files. Converted dragon mesh to binary PLY format.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 22 Nov 2019 03:03:52 +0200
parents a329f0216491
children 03b86b9c2f29
comparison
equal deleted inserted replaced
20:294c4c7943b5 21:1404dfcee7b8
1 // 1 //
2 // 2 //
3 // 3 //
4 #include "dmmodel.h" 4 #include "dmmodel.h"
5 #include <SDL_endian.h>
5 6
6 7
7 static bool dmError(DMTextFileInfo &info, const std::string &msg) 8 static bool dmError(DMTextFileInfo &info, const std::string &msg)
8 { 9 {
9 printf("ERROR: %s on line #%d: %s\n", 10 printf("ERROR: %s on line #%d: %s\n",
137 { 138 {
138 size_t nprop = 0, pos = 0; 139 size_t nprop = 0, pos = 0;
139 140
140 // Read one line 141 // Read one line
141 if (!dmReadLine(info)) 142 if (!dmReadLine(info))
142 return false; 143 {
144 return dmError(info,
145 "Unexpected end of file");
146 }
143 147
144 // Skip empty lines 148 // Skip empty lines
145 if (info.line.empty()) 149 if (info.line.empty())
146 return true; 150 return true;
147 151
164 } 168 }
165 169
166 170
167 bool dmPLYReadPropertyValueBIN(DMPLYFileInfo &info, const DMPLYPropType ptype, DMPLYPropValue &pval) 171 bool dmPLYReadPropertyValueBIN(DMPLYFileInfo &info, const DMPLYPropType ptype, DMPLYPropValue &pval)
168 { 172 {
169 uint8_t tmp[8]; 173 uint8_t tmpU8;
174 int8_t tmpS8;
170 uint16_t tmpU16; 175 uint16_t tmpU16;
171 int16_t tmpS16; 176 int16_t tmpS16;
172 uint32_t tmpU32; 177 uint32_t tmpU32;
173 int32_t tmpS32; 178 int32_t tmpS32;
179 float tmpFloat;
174 180
175 switch (ptype) 181 switch (ptype)
176 { 182 {
177 case PLY_TYPE_INT8: 183 case PLY_TYPE_INT8:
178 info.file.read(reinterpret_cast<char *>(&tmp), 1); 184 info.file.read(reinterpret_cast<char *>(&tmpS8), 1);
179 pval.v_int = (int8_t) tmp[0]; 185 pval.v_int = tmpS8;
180 break; 186 break;
181 187
182 case PLY_TYPE_UINT8: 188 case PLY_TYPE_UINT8:
183 info.file.read(reinterpret_cast<char *>(&tmp), 1); 189 info.file.read(reinterpret_cast<char *>(&tmpU8), 1);
184 pval.v_uint = (uint8_t) tmp[0]; 190 pval.v_uint = tmpU8;
185 break; 191 break;
186 192
187 case PLY_TYPE_INT16: 193 case PLY_TYPE_INT16:
188 info.file.read(reinterpret_cast<char *>(&tmp), 2); 194 info.file.read(reinterpret_cast<char *>(&tmpS16), 2);
189 tmpS16 = 195 tmpS16 = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapLE16(tmpS16) : SDL_SwapBE16(tmpS16);
190 (tmp[0] << 8) |
191 (tmp[1]);
192 pval.v_int = tmpS16; 196 pval.v_int = tmpS16;
193 break; 197 break;
194 198
195 case PLY_TYPE_UINT16: 199 case PLY_TYPE_UINT16:
196 info.file.read(reinterpret_cast<char *>(&tmp), 2); 200 info.file.read(reinterpret_cast<char *>(&tmpU16), 2);
197 tmpU16 = 201 tmpU16 = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapLE16(tmpU16) : SDL_SwapBE16(tmpU16);
198 (tmp[0] << 8) |
199 (tmp[1]);
200 pval.v_uint = tmpU16; 202 pval.v_uint = tmpU16;
201 break; 203 break;
202 204
203 case PLY_TYPE_INT32: 205 case PLY_TYPE_INT32:
204 info.file.read(reinterpret_cast<char *>(&tmp), 4); 206 info.file.read(reinterpret_cast<char *>(&tmpS32), 4);
205 tmpS32 = 207 tmpS32 = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapLE32(tmpS32) : SDL_SwapBE32(tmpS32);
206 (tmp[0] << 24) |
207 (tmp[1] << 16) |
208 (tmp[2] << 8) |
209 (tmp[3]);
210
211 pval.v_int = tmpS32; 208 pval.v_int = tmpS32;
212 break; 209 break;
213 210
214 case PLY_TYPE_UINT32: 211 case PLY_TYPE_UINT32:
215 info.file.read(reinterpret_cast<char *>(&tmp), 4); 212 info.file.read(reinterpret_cast<char *>(&tmpU32), 4);
216 tmpU32 = 213 tmpU32 = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapLE32(tmpU32) : SDL_SwapBE32(tmpU32);
217 (tmp[3] << 24) |
218 (tmp[2] << 16) |
219 (tmp[1] << 8) |
220 (tmp[0]);
221
222 pval.v_uint = tmpU32; 214 pval.v_uint = tmpU32;
223 break; 215 break;
224 216
225 case PLY_TYPE_FLOAT: 217 case PLY_TYPE_FLOAT:
226 info.file.read(reinterpret_cast<char *>(&tmp), 4); 218 info.file.read(reinterpret_cast<char *>(&tmpFloat), 4);
227 tmpU32 = 219 pval.v_float = (info.format == PLY_FMT_BIN_LE) ? SDL_SwapFloatLE(tmpFloat) : SDL_SwapFloatBE(tmpFloat);
228 (tmp[0] << 24) |
229 (tmp[1] << 16) |
230 (tmp[2] << 8) |
231 (tmp[3]);
232
233 pval.v_uint = tmpU32;
234 break; 220 break;
235 221
236 default: 222 default:
237 return dmError(info, 223 return dmError(info,
238 "Internal error, unimplemented PLY property type"); 224 "Internal error, unimplemented PLY property type");
546 } 532 }
547 } 533 }
548 else 534 else
549 if (element->name == PLY_ELEM_VERTEX) 535 if (element->name == PLY_ELEM_VERTEX)
550 { 536 {
551 DMVertex vert; 537 DMVector3 vert;
552 vert.x = element->prop_map["x"].value.v_float; 538 vert.x = element->prop_map["x"].value.v_float;
553 vert.y = element->prop_map["y"].value.v_float; 539 vert.y = element->prop_map["y"].value.v_float;
554 vert.z = element->prop_map["z"].value.v_float; 540 vert.z = element->prop_map["z"].value.v_float;
555 541
556 vertices.push_back(vert); 542 vertices.push_back(vert);
557 543
558 if (element->checkProp("nx") && 544 if (element->checkProp("nx") &&
559 element->checkProp("ny") && 545 element->checkProp("ny") &&
560 element->checkProp("nz")) 546 element->checkProp("nz"))
561 { 547 {
562 DMVertex normal; 548 DMVector3 normal;
563 normal.x = element->prop_map["nx"].value.v_float; 549 normal.x = element->prop_map["nx"].value.v_float;
564 normal.y = element->prop_map["ny"].value.v_float; 550 normal.y = element->prop_map["ny"].value.v_float;
565 normal.z = element->prop_map["nz"].value.v_float; 551 normal.z = element->prop_map["nz"].value.v_float;
566 552
567 normals.push_back(normal); 553 normals.push_back(normal);
576 562
577 return true; 563 return true;
578 } 564 }
579 565
580 566
567 bool dmParseVector(DMTextFileInfo &info, const std::vector<std::string> tokens, const size_t offs, DMVector3 &vec)
568 {
569 if (tokens.size() == offs + 1)
570 {
571 vec.x = vec.y = vec.z = std::stof(tokens[offs]);
572 }
573 else
574 if (tokens.size() == offs + 3)
575 {
576 vec.x = std::stof(tokens[offs]);
577 vec.y = std::stof(tokens[offs + 1]);
578 vec.z = std::stof(tokens[offs + 2]);
579 }
580 else
581 {
582 return dmSyntaxError(info,
583 "Expected 1/3 value vector for '"+ *info.key +"'");
584 }
585
586 return true;
587 }
588
589
590 bool dmParseVector(DMTextFileInfo &info, const std::vector<std::string> tokens, const size_t offs, DMVector4 &vec)
591 {
592 vec.w = 1.0f;
593
594 if (tokens.size() == offs + 1)
595 {
596 vec.x = vec.y = vec.z = std::stof(tokens[offs]);
597 }
598 else
599 if (tokens.size() == offs + 3 || tokens.size() == offs + 4)
600 {
601 vec.x = std::stof(tokens[offs]);
602 vec.y = std::stof(tokens[offs + 1]);
603 vec.z = std::stof(tokens[offs + 2]);
604
605 if (tokens.size() == offs + 4)
606 vec.w = std::stof(tokens[offs + 3]);
607 }
608 else
609 {
610 return dmSyntaxError(info,
611 "Expected 1/3/4 value vector for '"+ *info.key +"'");
612 }
613
614 return true;
615 }
616
617
618 bool dmParseColor(DMTextFileInfo &info, const std::vector<std::string> tokens, const size_t offs, DMColor &color)
619 {
620 color.alpha = 0xff;
621
622 if (tokens.size() == offs + 1)
623 {
624 color.r = color.g = color.b = std::stoi(tokens[offs], 0, 0);
625 }
626 else
627 if (tokens.size() == offs + 3 || tokens.size() == offs + 4)
628 {
629 color.r = std::stoi(tokens[offs], 0, 0);
630 color.g = std::stoi(tokens[offs + 1], 0, 0);
631 color.b = std::stoi(tokens[offs + 2], 0, 0);
632
633 if (tokens.size() == offs + 4)
634 color.alpha = std::stoi(tokens[offs + 3], 0, 0);
635 }
636 else
637 {
638 return dmSyntaxError(info,
639 "Expected color values <value> or <red> <green> <blue> [<alpha>] for '"+ *info.key +"'");
640 }
641
642 return true;
643 }
644
645
581 bool DMSimpleScene::loadInfo(const std::string &filename) 646 bool DMSimpleScene::loadInfo(const std::string &filename)
582 { 647 {
583 DMTextFileInfo info; 648 DMTextFileInfo info;
649 DMModel *model = 0;
650 DMLight *light = 0;
651 DMVector3 *ppos = 0, *ppointAt = 0;
584 652
585 info.filename = filename; 653 info.filename = filename;
586 info.nline = info.state = 0; 654 info.nline = info.state = 0;
587 info.file.open(info.filename.c_str(), std::fstream::in | std::fstream::binary); 655 info.file.open(info.filename.c_str(), std::fstream::in | std::fstream::binary);
588 656
611 info.line[0] == ';') 679 info.line[0] == ';')
612 continue; 680 continue;
613 681
614 // Split key and values 682 // Split key and values
615 std::vector<std::string> tokens = dmStrSplit(info.line); 683 std::vector<std::string> tokens = dmStrSplit(info.line);
616 std::string &key = tokens[0]; 684 std::string key = tokens[0];
617 685 info.key = &key;
618 if (key == "color") 686
619 { 687 if (key == "model")
620 DMColor color; 688 {
621 color.alpha = 0xff; 689 DMModel newmodel;
622 690 if (tokens.size() != 2)
623 if (tokens.size() == 2) 691 {
624 { 692 return dmError(info,
625 color.r = color.g = color.b = std::stoi(tokens[1], 0, 0); 693 "Keyword model expects a filename argument");
626 } 694 }
627 else 695
628 if (tokens.size() == 4 || tokens.size() == 5) 696 models.push_back(newmodel);
629 { 697 model = &models.back();
630 color.r = std::stoi(tokens[1], 0, 0); 698 model->modelFile = tokens[1];
631 color.g = std::stoi(tokens[2], 0, 0); 699 info.state = 1;
632 color.b = std::stoi(tokens[3], 0, 0); 700 }
633 701 else
634 if (tokens.size() == 5) 702 if (info.state == 1 && key == "color")
635 color.alpha = std::stoi(tokens[4], 0, 0); 703 {
636 } 704 if (!dmParseColor(info, tokens, 1, model->color))
637 else 705 return false;
638 { 706 }
639 return dmSyntaxError(info, 707 else
640 "Expected color values <value> or <red> <green> <blue> [<alpha>]"); 708 if (info.state == 1 && (key == "translate" || key == "rotate" || key == "scale"))
641 } 709 {
642 710 DMVector3 vec;
643 model.color = color; 711
644 } 712 if (!dmParseVector(info, tokens, 1, vec))
645 else 713 return false;
646 if (key == "translate" || key == "rotate" || key == "scale" || 714
647 key == "camera_pos" || key == "camera_at") 715 if (!model)
648 { 716 return false;
649 DMVertex vec;
650
651 if (tokens.size() == 2)
652 {
653 vec.x = vec.y = vec.z = std::stof(tokens[1]);
654 }
655 else
656 if (tokens.size() == 4)
657 {
658 vec.x = std::stof(tokens[1]);
659 vec.y = std::stof(tokens[2]);
660 vec.z = std::stof(tokens[3]);
661 }
662 else
663 {
664 return dmSyntaxError(info,
665 "Expected vector value for '"+ key +"'");
666 }
667 717
668 if (key == "translate") 718 if (key == "translate")
669 model.translate = vec; 719 model->translate = vec;
670 else 720 else
671 if (key == "rotate") 721 if (key == "rotate")
672 model.rotate = vec; 722 model->rotate = vec;
673 else 723 else
674 if (key == "scale") 724 if (key == "scale")
675 model.scale = vec; 725 model->scale = vec;
726 }
727 else
728 if (key == "light")
729 {
730 DMLight newlight;
731
732 if (lights.size() >= 4)
733 {
734 printf("ERROR: Too many lights defined.\n");
735 return false;
736 }
737 lights.push_back(newlight);
738 light = &lights.back();
739 ppos = &light->pos;
740 ppointAt = &light->pointAt;
741 info.state = 2;
742 }
743 else
744 if (info.state == 2 && (key == "ambient" || key == "diffuse" || key == "specular"))
745 {
746 DMVector4 val;
747
748 if (!dmParseVector(info, tokens, 1, val))
749 return false;
750
751 if (key == "ambient")
752 light->ambient = val;
676 else 753 else
677 if (key == "camera_pos") 754 if (key == "diffuse")
678 camera.pos = vec; 755 light->diffuse = val;
679 else 756 else
680 if (key == "camera_at") 757 if (key == "specular")
681 camera.lookAt = vec; 758 light->specular = val;
682 } 759 }
683 else 760 else
684 if (key == "light") 761 if (key == "camera")
685 { 762 {
686 if (tokens.size() == 4) 763 info.state = 3;
687 { 764
688 DMVertex pos; 765 ppos = &camera.pos;
689 pos.x = std::stof(tokens[1]); 766 ppointAt = &camera.pointAt;
690 pos.y = std::stof(tokens[2]); 767 }
691 pos.z = std::stof(tokens[3]); 768 else
692 } 769 if ((info.state == 3 || info.state == 2) && (key == "pos" || key == "point_at"))
770 {
771 DMVector3 vec;
772
773 if (!dmParseVector(info, tokens, 1, vec))
774 return false;
775
776 if (key == "pos")
777 *ppos = vec;
693 else 778 else
694 { 779 if (key == "point_at")
695 return dmSyntaxError(info, 780 *ppointAt = vec;
696 "Expected light definition as <x> <y> <z> ");
697 }
698 } 781 }
699 else 782 else
700 { 783 {
701 return dmSyntaxError(info, 784 return dmSyntaxError(info,
702 "Unexpected key '"+ key +"'"); 785 "Unexpected key '"+ key +"'");
703 } 786 }
704 } 787 }
705 788
706 model.printInfo(); 789 return true;
707 790 }
708 return true;
709 }