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