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