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