Line data Source code
1 :
2 : /* gltf.cpp: Khronos GL Transmission Format
3 : *
4 : * This is the implementation file for the GL Transmission Format (GLTF) model
5 : * format, version 2.
6 : */
7 :
8 : #include "../libprimis-headers/cube.h"
9 : #include "../../shared/geomexts.h"
10 : #include "../../shared/glemu.h"
11 : #include "../../shared/glexts.h"
12 : #include "../../shared/stream.h"
13 :
14 : #include <optional>
15 : #include <memory>
16 :
17 : #include "render/rendergl.h"
18 : #include "render/rendermodel.h"
19 : #include "render/renderwindow.h"
20 : #include "render/shader.h"
21 : #include "render/shaderparam.h"
22 : #include "render/texture.h"
23 :
24 : #include "interface/console.h"
25 : #include "interface/control.h"
26 : #include "interface/cs.h"
27 :
28 : #include "world/entities.h"
29 : #include "world/octaworld.h"
30 : #include "world/bih.h"
31 :
32 : #include "model.h"
33 : #include "ragdoll.h"
34 : #include "animmodel.h"
35 : #include "skelmodel.h"
36 :
37 : #include "gltf.h"
38 : #include "gltfloader.h"
39 :
40 : skelcommands<gltf> gltf::gltfcommands;
41 :
42 0 : gltf::gltf(std::string name) : skelloader(name)
43 : {
44 0 : }
45 :
46 0 : bool gltf::flipy() const
47 : {
48 0 : return false;
49 : }
50 :
51 0 : int gltf::type() const
52 : {
53 0 : return MDL_GLTF;
54 : }
55 :
56 79 : const char *gltf::formatname()
57 : {
58 79 : return "gltf";
59 : }
60 :
61 0 : gltf::skelmeshgroup *gltf::newmeshes()
62 : {
63 0 : return new gltfmeshgroup;
64 : }
65 :
66 0 : bool gltf::loaddefaultparts()
67 : {
68 0 : skelpart &mdl = addpart();
69 0 : const char *fname = modelname().c_str() + std::strlen(modelname().c_str());
70 : do
71 : {
72 0 : --fname;
73 0 : } while(fname >= modelname() && *fname!='/' && *fname!='\\');
74 0 : fname++;
75 0 : std::string meshname = std::string(modelpath);
76 0 : meshname.append(modelname()).append("/").append(fname).append(".gltfmesh");
77 0 : mdl.meshes = sharemeshes(path(meshname));
78 0 : if(!mdl.meshes)
79 : {
80 0 : return false;
81 : }
82 0 : mdl.initanimparts();
83 0 : mdl.initskins();
84 0 : return true;
85 0 : }
86 :
87 :
88 0 : gltf::gltfmeshgroup::gltfmeshgroup()
89 : {
90 0 : }
91 :
92 0 : bool gltf::gltfmeshgroup::loadmesh(const char *filename, float smooth, part &p)
93 : {
94 : try
95 : {
96 0 : GLTFModelInfo mi(filename);
97 :
98 0 : std::vector<std::string> nodenames = mi.getnodenames(GLTFModelInfo::NodeType_Mesh);
99 0 : for(std::string meshname : nodenames)
100 : {
101 : //get GLTF data from file/binary
102 0 : std::vector<std::array<float, 3>> positions = mi.getpositions(meshname);
103 0 : std::vector<std::array<float, 3>> normals = mi.getnormals(meshname);
104 0 : std::vector<std::array<float, 2>> texcoords = mi.gettexcoords(meshname);
105 0 : std::vector<std::array<uint, 4>> joints = mi.getjoints(meshname);
106 0 : std::vector<std::array<float, 4>> weights = mi.getweights(meshname);
107 0 : std::vector<std::array<uint, 3>> indices = mi.getindices(meshname);
108 : //set skelmodel::vert and skelmodel::tris
109 : vert *verts;
110 : size_t numverts;
111 0 : if(positions.size() == normals.size() && normals.size() == texcoords.size())
112 : {
113 0 : verts = new vert[positions.size()];
114 0 : numverts = positions.size();
115 0 : for(size_t i = 0; i < positions.size(); ++i)
116 : {
117 : //pos, normals are transformed (-z->y, y->z, x->x) from GLTF to Cube coord system
118 0 : verts[i].pos = vec(positions[i][0], -positions[i][2], positions[i][1]);
119 0 : verts[i].norm = vec(normals[i][0], -normals[i][2], normals[i][1]);
120 0 : verts[i].tc = vec2(texcoords[i][0], texcoords[i][1]);
121 0 : blendcombo c;
122 0 : c.addweight(0,0,0);
123 0 : c.finalize(0);
124 0 : verts[i].blend = addblendcombo(c);
125 : }
126 : }
127 : else
128 : {
129 0 : throw std::logic_error("index mismatch: positions/normals/texcoords different sizes");
130 : }
131 0 : tri *tris = new tri[indices.size()];
132 0 : size_t numtris = indices.size();
133 0 : for(size_t i = 0; i < indices.size(); ++i)
134 : {
135 0 : tris[i].vert[0] = indices[i][0];
136 0 : tris[i].vert[1] = indices[i][1];
137 0 : tris[i].vert[2] = indices[i][2];
138 : }
139 : //if able to create the verts/tris arrays without throwing, create new gltfmesh
140 0 : gltfmesh *m = new gltfmesh(newstring(meshname.c_str()), verts, numverts, tris, numtris, this);
141 0 : meshes.push_back(m);
142 0 : p.initskins(notexture, notexture, meshes.size());
143 :
144 0 : }
145 0 : for(uint i = 0; i < meshes.size(); i++)
146 : {
147 0 : gltfmesh &m = *static_cast<gltfmesh *>(meshes[i]);
148 0 : m.buildnorms();
149 0 : m.calctangents();
150 0 : m.cleanup();
151 : }
152 0 : sortblendcombos();
153 0 : return true;
154 0 : }
155 : //catch errors thrown by GLTFModelInfo
156 0 : catch(const std::ios_base::failure &e)
157 : {
158 0 : conoutf("model loading failed: caught %s\n", e.what());
159 0 : return false;
160 0 : }
161 0 : catch(const std::logic_error &e)
162 : {
163 0 : conoutf("invalid model file contents: caught %s\n", e.what());
164 0 : return false;
165 0 : }
166 : }
167 :
168 0 : bool gltf::gltfmeshgroup::load(std::string_view meshfile, float smooth, part &p)
169 : {
170 0 : name = meshfile;
171 :
172 0 : if(!loadmesh(meshfile.data(), smooth, p))
173 : {
174 0 : return false;
175 : }
176 0 : return true;
177 : }
178 :
179 0 : gltf::gltfmesh::gltfmesh(std::string_view name, vert *verts, uint numverts, tri *tris, uint numtris, meshgroup *m) :
180 0 : skelmesh(name, verts, numverts, tris, numtris, m)
181 : {
182 0 : }
183 :
184 0 : gltf::gltfmesh::~gltfmesh()
185 : {
186 0 : cleanup();
187 0 : }
188 :
189 0 : void gltf::gltfmesh::cleanup()
190 : {
191 0 : }
|