1 #include "Object3D.h"
2 #include <Surface/Surface.h>
3 #define STRINGIFY(...) #__VA_ARGS__
4 #define SHADER(version, shader) "#version " #version "\n" STRINGIFY(shader)
5
6 namespace Upp{
7
8 #define IMAGECLASS TexturesImg
9 #define IMAGEFILE <SurfaceCtrl/textures.iml>
10 #include <Draw/iml.h>
11
12
13 int Object3D::GlobalID = 0;
14
Object3D()15 Object3D::Object3D():ID(++GlobalID){
16 lineColor = Black();
17 lineOpacity = 0.5f;
18 lineWidth = 1.0f;
19
20 normalColor = Red();
21 normalOpacity = 1.0f;
22 normalLength = 1.0f;
23
24 showMesh = true;
25 showMeshLine = false;
26 showMeshNormal = false;
27 showLight = true;
28
29 WhenInit = [&](Object3D& obj){ DefaultInit(obj); };
30 WhenDraw = [&](const glm::mat4& projectionMatrix,const glm::mat4& viewMatrix,const glm::vec3& viewPosition, Object3D& obj){ DefaultDraw(projectionMatrix,viewMatrix,viewPosition,obj); };
31 WhenClear = [&](Object3D& obj){ DefaultClear(obj); };
32 WhenReload = [&](Object3D& obj){ DefaultReload(obj); };
33 }
34
operator =(Object3D && obj)35 Object3D& Object3D::operator=(Object3D&& obj){
36 transform = pick(obj.transform);
37 boundingBox = pick(obj.boundingBox);
38 material = pick(obj.material);
39
40 meshes = pick(obj.meshes);
41 textures = pick(obj.textures);
42 program = pick(obj.program);
43 objectValues = pick(obj.objectValues);
44
45 lineColor = obj.lineColor;
46 lineOpacity = obj.lineOpacity;
47 lineWidth = obj.lineWidth;
48
49 normalColor = obj.normalColor;
50 normalOpacity = obj.normalOpacity;
51 normalLength = obj.normalLength;
52
53 showMesh = obj.showMesh;
54 showMeshLine = obj.showMeshLine;
55 showMeshNormal = obj.showMeshNormal;
56 showLight = obj.showLight;
57
58 WhenInit = obj.WhenInit;
59 WhenDraw = obj.WhenDraw;
60 WhenClear = obj.WhenClear;
61
62 loaded = obj.loaded;
63 moved = obj.moved;
64 visible = obj.visible;
65 showBoundingBox = obj.showBoundingBox;
66
67 programNoLight = obj.programNoLight;
68 programLine = obj.programLine;
69 programNormal = obj.programNormal;
70 programLight = obj.programLight;
71
72 drawType = obj.drawType;
73
74 obj.moved = true;
75 obj.loaded = false;
76 return *this;
77 }
78
operator =(const Object3D & obj)79 Object3D& Object3D::operator=(const Object3D& obj){
80 transform = clone(obj.transform);
81 boundingBox = clone(obj.boundingBox);
82 material = clone(obj.material);
83
84 meshes = clone(obj.meshes);
85 textures = clone(obj.textures);
86 program = clone(obj.program);
87 objectValues = clone(obj.objectValues);
88
89 lineColor = obj.lineColor;
90 lineOpacity = obj.lineOpacity;
91 lineWidth = obj.lineWidth;
92
93 normalColor = obj.normalColor;
94 normalOpacity = obj.normalOpacity;
95 normalLength = obj.normalLength;
96
97 showMesh = obj.showMesh;
98 showMeshLine = obj.showMeshLine;
99 showMeshNormal = obj.showMeshNormal;
100 showLight = obj.showLight;
101
102 WhenInit = obj.WhenInit;
103 WhenDraw = obj.WhenDraw;
104 WhenClear = obj.WhenClear;
105
106 loaded = obj.loaded;
107 moved = obj.moved;
108 visible = obj.visible;
109 showBoundingBox = obj.showBoundingBox;
110
111 programNoLight = obj.programNoLight;
112 programLine = obj.programLine;
113 programNormal = obj.programNormal;
114 programLight = obj.programLight;
115
116 drawType = obj.drawType;
117 return *this;
118 }
119
~Object3D()120 Object3D::~Object3D(){
121 for(const Texture& t : textures){
122 glDeleteTextures(1,&(t.id));
123 }
124 Clear();
125 }
126 /**
127 LoadModel load multiple kind of object file using Assimp lib, you can specify some custom
128 load routine by editing pFlags, if pFlags = 0 then SurfaceCtrl default behavior about
129 assimp will be used
130 **/
LoadModel(const String & Filename,Color color,int alpha,unsigned int pFlags)131 Object3D& Object3D::LoadModel(const String& Filename, Color color, int alpha , unsigned int pFlags ){
132 Clear();
133 if( pFlags == 0){
134 pFlags = aiProcess_JoinIdenticalVertices |// join identical vertices/ optimize indexing
135 aiProcess_ValidateDataStructure | // perform a full validation of the loader's output
136 aiProcess_ImproveCacheLocality | // improve the cache locality of the output vertices
137 aiProcess_RemoveRedundantMaterials |// remove redundant materials
138 aiProcess_GenUVCoords | // convert spherical, cylindrical, box and planar mapping to proper UVs
139 aiProcess_TransformUVCoords | // pre-process UV transformations (scaling, translation ...)
140 aiProcess_FindInstances | // search for instanced meshes and remove them by references to one master
141 aiProcess_LimitBoneWeights | // limit bone weights to 4 per vertex
142 aiProcess_OptimizeMeshes | // join small meshes, if possible;
143 aiProcess_PreTransformVertices |
144 aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing
145 aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into sub-meshes
146 aiProcess_Triangulate | // triangulate polygons with more than 3 edges
147 aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space
148 aiProcess_SortByPType;
149 }
150
151 Assimp::Importer Importer;
152 const aiScene* pScene = Importer.ReadFile(Filename.ToStd().c_str(),pFlags);
153 if(pScene){
154 if(InitFromScene(pScene, Filename)){
155 glm::vec4 col(color.GetR()/255.0f, color.GetG()/255.0f, color.GetB()/255.0f, alpha/255.0f);
156 for(Mesh& m : meshes){
157 Vector<float>& colors = m.GetColors();
158 for(int e = 0; e < (m.GetVertices().GetCount()/3) ; e++){
159 colors << col.x << col.y << col.z << col.w;
160 }
161 }
162 }else{
163 throw Exc(Format("Error initing data from '%s'\n", Filename));
164 }
165 }else {
166 throw Exc(Format("Error parsing '%s': '%s'\n", Filename, String(Importer.GetErrorString())));
167 }
168 return *this;
169 }
LoadTexture(const Image & img,const String & name,int indiceWhereInsert)170 int Object3D::LoadTexture(const Image& img , const String& name, int indiceWhereInsert){
171 Image image = clone(img);
172 String trueName = name;
173 if(IsNull(image)){
174 image = clone(TexturesImg::empty());
175 trueName = AsString(image.GetSerialId());
176 }
177 for(int e = 0; e < textures.GetCount(); e++){
178 if(textures[e].name.IsEqual(trueName)){
179 return e;
180 }
181 }
182
183 Size size = image.GetSize();
184 int indice;
185
186 Texture& t = [&]()-> Texture&{
187 if(indiceWhereInsert == -1){
188 indice = textures.GetCount();
189 return textures.Add();
190 }else{
191 if(indiceWhereInsert < textures.GetCount()){
192 indice = indiceWhereInsert;
193 return textures[indiceWhereInsert];
194 }else{
195 indice = textures.GetCount();
196 return textures.Add();
197 }
198 }
199 }();
200
201 t.name = trueName;
202 glGenTextures(1, &(t.id));
203 glBindTexture(GL_TEXTURE_2D, t.id);
204 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
205 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
207 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
208
209 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.cx , size.cy , 0, GL_BGRA, GL_UNSIGNED_BYTE, ~image);
210 //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.cy , size.cx, 0, GL_RGBA, GL_UNSIGNED_BYTE, ~image);
211 glGenerateMipmap(GL_TEXTURE_2D);
212
213 return indice;
214 }
215 /*
216 Assimp loading function
217 */
InitFromScene(const aiScene * pScene,const String & Filename)218 bool Object3D::InitFromScene(const aiScene* pScene, const String& Filename){
219 meshes.AddN(pScene->mNumMeshes);
220 textures.AddN(pScene->mNumMaterials);
221 //Add Texture vector init here
222
223 // Initialises the scene meshes, one by one
224 for (int i = 0 ; i < meshes.GetCount() ; i++) {
225 const aiMesh* paiMesh = pScene->mMeshes[i];
226 InitMesh(i, paiMesh);
227 }
228 return InitMaterials(pScene, Filename);
229 }
InitMesh(unsigned int Index,const aiMesh * paiMesh)230 void Object3D::InitMesh(unsigned int Index, const aiMesh* paiMesh){
231 //For texture / material data
232 meshes[Index].SetTextureIndice(paiMesh->mMaterialIndex);
233
234 Vector<float>& vertices = meshes[Index].GetVertices();
235 Vector<float>& normals = meshes[Index].GetNormals();
236 Vector<float>& textCoords = meshes[Index].GetTexCoords();
237
238 struct Vertex : public Moveable<Vertex>{
239 float pos[3];
240 float normals[3];
241 float texCoords[2];
242
243 Vertex(float x, float y, float z, float n1 , float n2, float n3, float tc1 , float tc2){
244 pos[0] = x; pos[1] = y; pos[2] = z;
245 normals[0] = n1; normals[1] = n2; normals[2] = n3;
246 texCoords[0] = tc1; texCoords[1] = tc2;
247 }
248 };
249
250 Vector<Vertex> dummyVertices;
251 Vector<int> dummyIndices;
252
253 const aiVector3D Zero3D(0.0f, 0.0f, 0.0f);
254
255 for (unsigned int i = 0 ; i < paiMesh->mNumVertices ; i++) {
256 const aiVector3D* pPos = &(paiMesh->mVertices[i]);
257 const aiVector3D* pNormal = (&(paiMesh->mNormals[i]))? &(paiMesh->mNormals[i]) : &Zero3D;
258
259 glm::vec3 norm(pNormal->x , pNormal->y , pNormal->z);
260 norm = glm::abs(norm) * -1.0f;
261
262 const aiVector3D* pTexCoord = paiMesh->HasTextureCoords(0) ? &(paiMesh->mTextureCoords[0][i]) : &Zero3D;
263
264 //dummyVertices << Vertex( pPos->x , pPos->y , pPos->z , pNormal->x , pNormal->y , pNormal->z , pTexCoord->x , pTexCoord->y);
265 dummyVertices << Vertex( pPos->x , pPos->y , pPos->z , norm.x , norm.y , norm.z , pTexCoord->x , pTexCoord->y);
266 }
267
268 for (unsigned int i = 0 ; i < paiMesh->mNumFaces ; i++) {
269 const aiFace& Face = paiMesh->mFaces[i];
270 ASSERT_(Face.mNumIndices == 3, "Face in Assimp strucure do not contain 3 points !");
271 dummyIndices << Face.mIndices[0] << Face.mIndices[1] << Face.mIndices[2];
272 }
273 for(int i = 0 ; i < dummyIndices.GetCount(); i++){
274 Vertex& vertex = dummyVertices[dummyIndices[i]];
275 vertices << vertex.pos[0] << vertex.pos[1] << vertex.pos[2];
276 normals << vertex.normals[0] << vertex.normals[1] << vertex.normals[2];
277 textCoords << vertex.texCoords[0] << vertex.texCoords[1];
278 }
279 }
InitMaterials(const aiScene * pScene,const String & Filename)280 bool Object3D::InitMaterials(const aiScene* pScene, const String& Filename){
281 aiString Path;
282 for (unsigned int i = 0 ; i < pScene->mNumMaterials ; i++) {
283 const aiMaterial* pMaterial = pScene->mMaterials[i];
284 if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0){
285 if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
286 String FullPath =AppendFileName(GetFileFolder(Filename), String(Path.data));
287 InsertTexture(FullPath,i);
288 }
289 }else if(pMaterial->GetTextureCount(aiTextureType_SPECULAR) > 0){
290 if (pMaterial->GetTexture(aiTextureType_SPECULAR, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
291 LOG("Specular texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
292 }else if(pMaterial->GetTextureCount(aiTextureType_AMBIENT) > 0){
293 if (pMaterial->GetTexture(aiTextureType_AMBIENT, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
294 LOG("Ambient texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
295 }else if(pMaterial->GetTextureCount(aiTextureType_EMISSIVE) > 0){
296 if (pMaterial->GetTexture(aiTextureType_EMISSIVE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
297 LOG("Emissive texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
298 }else if(pMaterial->GetTextureCount(aiTextureType_HEIGHT) > 0){
299 if (pMaterial->GetTexture(aiTextureType_HEIGHT, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
300 LOG("Height texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
301 }else if(pMaterial->GetTextureCount(aiTextureType_NORMALS) > 0){
302 if (pMaterial->GetTexture(aiTextureType_NORMALS, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
303 LOG("Normals texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
304 }else if(pMaterial->GetTextureCount(aiTextureType_SHININESS) > 0){
305 if (pMaterial->GetTexture(aiTextureType_SHININESS, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
306 LOG("Shininess texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
307 }else if(pMaterial->GetTextureCount(aiTextureType_OPACITY) > 0){
308 if (pMaterial->GetTexture(aiTextureType_OPACITY, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
309 LOG("Opacity texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
310 }else if(pMaterial->GetTextureCount(aiTextureType_DISPLACEMENT) > 0){
311 if (pMaterial->GetTexture(aiTextureType_DISPLACEMENT, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
312 LOG("Displacement texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
313 }else if(pMaterial->GetTextureCount(aiTextureType_LIGHTMAP) > 0){
314 if (pMaterial->GetTexture(aiTextureType_LIGHTMAP, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
315 LOG("Lightmap texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
316 }else if(pMaterial->GetTextureCount(aiTextureType_REFLECTION) > 0){
317 if (pMaterial->GetTexture(aiTextureType_REFLECTION, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
318 LOG("Reflection texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
319 }else if(pMaterial->GetTextureCount(aiTextureType_UNKNOWN) > 0){
320 if (pMaterial->GetTexture(aiTextureType_UNKNOWN, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
321 LOG("Unknow texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
322 }else if(pMaterial->GetTextureCount(aiTextureType_NONE) > 0){
323 if (pMaterial->GetTexture(aiTextureType_NONE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
324 LOG("None texture : " + AppendFileName(GetFileFolder(Filename), String(Path.data)));
325 }else{
326 /*for(int e = 0; e < pMaterial->mNumProperties; e++){
327 aiMaterialProperty* aiMp = pMaterial->mProperties[e];
328 LOG("Property number " + AsString(e) +" :");
329 LOG("mKey : " + String((*aiMp).mKey.data));
330 LOG("mSemantic : " + AsString((*aiMp).mSemantic));
331 LOG("mIndex : " + AsString((*aiMp).mIndex));
332 LOG("mDataLength : " + AsString((*aiMp).mDataLength));
333 LOG("aiPropertyTypeInfo : " + AsString((int) (*aiMp).mType));
334 String str = String((*aiMp).mData);
335 LOG("mData count : " + AsString(str.GetCount()));
336 LOG("---------------------------------");
337 }*/
338 }
339 }
340 return true;
341 }
342
LoadSurface(Surface & surface,Color color,int alpha)343 Object3D& Object3D::LoadSurface(Surface& surface, Color color, int alpha){
344 Mesh& mesh = meshes.Create();
345 glm::vec4 col( color.GetR()/255.0f, color.GetG()/255.0f, color.GetB()/255.0f , alpha /255.0f);
346
347 auto& vertices = mesh.GetVertices();
348 auto& normals = mesh.GetNormals();
349 auto& colors = mesh.GetColors();
350
351 for (int ip = 0; ip < surface.panels.GetCount(); ++ip) {
352 const Panel &panel = surface.panels[ip];
353 //ADDING :
354 if(panel.IsTriangle()){
355 for(int e = 0; e < 3; e++){
356 Point3D p = surface.nodes[panel.id[e]];
357 vertices.Add(float(p.x));
358 vertices.Add(float(p.y));
359 vertices.Add(float(p.z));
360 normals.Add(float(panel.normalPaint.x));
361 normals.Add(float(panel.normalPaint.y));
362 normals.Add(float(panel.normalPaint.z));
363 colors.Add(col.x);
364 colors.Add(col.y);
365 colors.Add(col.z);
366 colors.Add(col.w);
367 }
368 }else{//A quad is just 2 triangles
369 Point3D SecondTriangle[3];
370 for(int e = 0; e < 3; e++){
371 Point3D p = surface.nodes[panel.id[e]];
372 if(e == 0) SecondTriangle[2] = p;
373 if(e == 2) SecondTriangle[0] = p;
374 vertices.Add(float(p.x));
375 vertices.Add(float(p.y));
376 vertices.Add(float(p.z));
377
378 normals.Add(float(panel.normalPaint.x));
379 normals.Add(float(panel.normalPaint.y));
380 normals.Add(float(panel.normalPaint.z));
381
382 colors.Add(col.x);
383 colors.Add(col.y);
384 colors.Add(col.z);
385 colors.Add(col.w);
386 }
387 SecondTriangle[1] = surface.nodes[panel.id[3]];
388 for(int e = 0; e < 3; e++){
389 Point3D p = SecondTriangle[e];
390 vertices.Add(float(p.x));
391 vertices.Add(float(p.y));
392 vertices.Add(float(p.z));
393
394 normals.Add(float(panel.normalPaint.x));
395 normals.Add(float(panel.normalPaint.y));
396 normals.Add(float(panel.normalPaint.z));
397
398 colors.Add(col.x);
399 colors.Add(col.y);
400 colors.Add(col.z);
401 colors.Add(col.w);
402 }
403 }
404 }
405 return *this;
406 }
407
GetSurface()408 Surface Object3D::GetSurface(){ //return a surface Objectd
409 Surface surf;
410 for(Mesh& m : meshes){
411 auto& vertices = m.GetVertices();
412 auto& normals = m.GetNormals();
413 for(int e = 0; e < vertices.GetCount(); e = e+9){
414 Panel &panel = surf.panels.Add();
415
416 panel.normalPaint.x = double(normals[e]);
417 panel.normalPaint.y = double(normals[e+1]);
418 panel.normalPaint.z = double(normals[e+2]);
419
420 Point3D &node0 = surf.nodes.Add();
421 node0.x = double(vertices[e]);
422 node0.y = double(vertices[e+1]);
423 node0.z = double(vertices[e+2]);
424 panel.id[0] = surf.nodes.GetCount()-1;
425
426 Point3D &node1 = surf.nodes.Add();
427 node1.x = double(vertices[e+3]);
428 node1.y = double(vertices[e+4]);
429 node1.z = double(vertices[e+5]);
430 panel.id[1] = surf.nodes.GetCount()-1;
431
432 Point3D &node2 = surf.nodes.Add();
433 node2.x = double(vertices[e+6]);
434 node2.y = double(vertices[e+7]);
435 node2.z = double(vertices[e+8]);
436 panel.id[2] = surf.nodes.GetCount()-1;
437 panel.id[3] = panel.id[0];
438 }
439 }
440 return pick(surf);
441 }
442
443 //Check if texture provided is already load, then return the iterator of the texture
444 //object
InsertTexture(const String & filename,int indice,FlipMode flipmode)445 int Object3D::InsertTexture(const String& filename, int indice, FlipMode flipmode)noexcept{ //insert texture in object3D
446 Image m = pick(StreamRaster::LoadFileAny( (IsFullPath(filename))? filename : AppendFileName(GetCurrentDirectory(),filename)));
447 return InsertTexture(m,indice,flipmode);
448 }
InsertTexture(const Image & m,int indice,FlipMode flipmode)449 int Object3D::InsertTexture(const Image& m, int indice, FlipMode flipmode)noexcept{ //insert texture in object3D
450 return LoadTexture(FlipImage(m,flipmode),AsString(m.GetSerialId()),indice);
451 }
452
InsertTexture(const TexturesMaterial & tm,int indice,FlipMode flipmode)453 int Object3D::InsertTexture(const TexturesMaterial& tm, int indice, FlipMode flipmode)noexcept{ //Insert one of SurfaceCtrl provided texture
454 Image m;
455 switch(tm){
456 case TexturesMaterial::BRICK:
457 m = clone(TexturesImg::brick());
458 break;
459 case TexturesMaterial::METAL:
460 m = clone(TexturesImg::metal());
461 break;
462 case TexturesMaterial::STONE:
463 m = clone(TexturesImg::stone());
464 break;
465 case TexturesMaterial::WATER:
466 m = clone(TexturesImg::water());
467 break;
468 case TexturesMaterial::WOOD:
469 m = clone(TexturesImg::wood());
470 break;
471 }
472 return InsertTexture(m,indice,flipmode);
473 }
AttachTexture(int numTexture,int MeshNo,int count)474 Object3D& Object3D::AttachTexture(int numTexture,int MeshNo, int count){//Attach a texture to the range of mes
475 int textNo = numTexture;
476 if(textNo > textures.GetCount()) textNo = 0;
477 if(MeshNo < meshes.GetCount() && count > 0 && (MeshNo + count) <= meshes.GetCount()){
478 for(int e = MeshNo; e < (MeshNo + count); e ++){
479 meshes[e].SetTextureIndice(textNo);
480 }
481 }
482 return *this;
483 }
GenerateTextureCoordinate(int MeshNo,int count,bool CustomTextureCoordinate,const Vector<float> & tc)484 Object3D& Object3D::GenerateTextureCoordinate(int MeshNo, int count , bool CustomTextureCoordinate, const Vector<float>& tc){// Generate new Texture coordinate for the selected range of mesh
485 if(MeshNo < meshes.GetCount() && count > 0 && (MeshNo + count) <= meshes.GetCount()){
486 for(int e = MeshNo; e < (MeshNo + count); e++){
487 Mesh& m = meshes[e];
488 Vector<float>& tex = m.GetTexCoords();
489 tex.Clear();
490 int triangleCpt = (m.GetVertices().GetCount()/3) -1;
491 for(int i = 0; i < triangleCpt; i++){
492 if(CustomTextureCoordinate) tex.Append(tc);
493 else tex << 0.0f << 0.0f << 1.0f << 0.0f << 0.5f << 1.0f;
494 }
495 }
496 }
497 return *this;
498 }
499
CreateBoundingBox()500 void Object3D::CreateBoundingBox(){
501 float minX,minY,minZ;
502 minX = minY = minZ = FLT_MAX;
503 float maxX,maxY,maxZ;
504 maxX = maxY = maxZ = -FLT_MAX;
505 for(Mesh& m : meshes){
506 auto& vertices = m.GetVertices();
507 int cpt = vertices.GetCount() -1;
508 for (int i = 0; i < cpt; i = i + 3) {
509 maxX = max(maxX, vertices[i]);
510 minX = min(minX, vertices[i]);
511 maxY = max(maxY, vertices[i+1]);
512 minY = min(minY, vertices[i+1]);
513 maxZ = max(maxZ, vertices[i+2]);
514 minZ = min(minZ, vertices[i+2]);
515 }
516 }
517 boundingBox.SetBoundingBox(minX,minY,minZ,maxX,maxY,maxZ);
518 }
519
RemoveBoundingBox()520 void Object3D::RemoveBoundingBox(){
521 boundingBox = BoundingBox();
522 }
523
UpdateBuffer(GLuint buffer,int SurfaceCount,int SurfaceNumber,int count,int numberOfElement,const float * data)524 bool Object3D::UpdateBuffer(GLuint buffer, int SurfaceCount ,int SurfaceNumber, int count, int numberOfElement, const float * data)noexcept{
525 glBindBuffer(GL_ARRAY_BUFFER,buffer);
526 float* ptr = (float*) glMapBuffer(GL_ARRAY_BUFFER,GL_WRITE_ONLY);
527 //float* ptr = (float*) glMapNamedBuffer(buffer,GL_WRITE_ONLY);
528 if(ptr){
529 if(SurfaceNumber < SurfaceCount){
530 ptr += SurfaceNumber;
531 for(int i = 0; i < count; i++){
532 for(int e = 0; e < numberOfElement; e++){
533 *(ptr++) = data[e];
534 }
535 }
536 glUnmapBuffer(GL_ARRAY_BUFFER);
537 return true;
538 }
539 glUnmapBuffer(GL_ARRAY_BUFFER);
540 return false;
541 }
542 return false;
543 }
ReadBuffer(GLuint buffer,int SurfaceCount,int SurfaceNumber,int count,int numberOfElement)544 Vector<float> Object3D::ReadBuffer(GLuint buffer, int SurfaceCount , int SurfaceNumber, int count, int numberOfElement)noexcept{
545 // float* ptr = (float*) glMapNamedBuffer(buffer,GL_READ_ONLY);
546 glBindBuffer(GL_ARRAY_BUFFER,buffer);
547 float* ptr = (float*) glMapBuffer(GL_ARRAY_BUFFER,GL_READ_ONLY);
548 Vector<float> data;
549 if(ptr){
550 if(SurfaceNumber < SurfaceCount){
551 ptr += SurfaceNumber;
552 for(int i = 0; i < count; i++){
553 for(int e = 0; e < numberOfElement; e++){
554 data.Add(*ptr);
555 }
556 }
557 }
558 glUnmapBuffer(GL_ARRAY_BUFFER);
559 }
560 return data;
561 }
UpdateColor(int MeshNo,int SurfaceNumber,int r,int g,int b,int alpha)562 bool Object3D::UpdateColor(int MeshNo, int SurfaceNumber, int r, int g, int b, int alpha)noexcept{
563 float data[]= {r/255.0f,g/255.0f,b/255.0f, alpha/255.0f};
564 if(MeshNo < meshes.GetCount()){
565 return UpdateBuffer(meshes[MeshNo].GetColorsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, 1 ,4,data);
566 }else{
567 return false;
568 }
569 }
UpdateColor(int MeshNo,int SurfaceNumber,float r,float g,float b,float alpha)570 bool Object3D::UpdateColor(int MeshNo, int SurfaceNumber, float r, float g, float b, float alpha)noexcept{
571 float data[] = {r,g,b, alpha};
572 if(MeshNo < meshes.GetCount()){
573 return UpdateBuffer(meshes[MeshNo].GetColorsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, 1 ,4,data);
574 }else{
575 return false;
576 }
577 }
UpdateColor(int MeshNo,int SurfaceNumber,glm::vec3 color,float alpha)578 bool Object3D::UpdateColor(int MeshNo, int SurfaceNumber, glm::vec3 color, float alpha)noexcept{
579 if(MeshNo < meshes.GetCount()){
580 float data[]= {color.x,color.y,color.z, alpha};
581 return UpdateBuffer(meshes[MeshNo].GetColorsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, 1 ,4,data);
582 }else{
583 return false;
584 }
585 }
UpdateColor(int MeshNo,int SurfaceNumber,Upp::Color color,int alpha)586 bool Object3D::UpdateColor(int MeshNo, int SurfaceNumber, Upp::Color color, int alpha)noexcept{
587 float data[] = {color.GetR()/255.0f,color.GetG()/255.0f,color.GetB()/255.0f, alpha/255.0f};
588 if(MeshNo < meshes.GetCount()){
589 return UpdateBuffer(meshes[MeshNo].GetColorsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, 1 ,4,data);
590 }else{
591 return false;
592 }
593 }
UpdateColors(int MeshNo,int SurfaceNumber,int Count,const float * data)594 bool Object3D::UpdateColors(int MeshNo, int SurfaceNumber,int Count, const float * data)noexcept{
595 if(MeshNo < meshes.GetCount()){
596 return UpdateBuffer(meshes[MeshNo].GetColorsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, Count ,4,data);
597 }else{
598 return false;
599 }
600 }
UpdateNormal(int MeshNo,int SurfaceNumber,float x,float y,float z)601 bool Object3D::UpdateNormal(int MeshNo, int SurfaceNumber, float x, float y, float z)noexcept{
602 float data[] = {x,y,z};
603 if(MeshNo < meshes.GetCount()){
604 return UpdateBuffer(meshes[MeshNo].GetNormalsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, 1 ,3, data);
605 }else{
606 return false;
607 }
608 }
UpdateNormal(int MeshNo,int SurfaceNumber,glm::vec3 normal)609 bool Object3D::UpdateNormal(int MeshNo, int SurfaceNumber, glm::vec3 normal)noexcept{
610 if(MeshNo < meshes.GetCount()){
611 return UpdateBuffer(meshes[MeshNo].GetNormalsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, 1 ,3, &(normal.x));
612 }else{
613 return false;
614 }
615 }
UpdateNormals(int MeshNo,int SurfaceNumber,int Count,const float * data)616 bool Object3D::UpdateNormals(int MeshNo, int SurfaceNumber,int Count, const float * data)noexcept{
617 if(MeshNo < meshes.GetCount()){
618 return UpdateBuffer(meshes[MeshNo].GetNormalsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, Count ,3, data);
619 }else{
620 return false;
621 }
622 }
UpdateVertice(int MeshNo,int SurfaceNumber,float x,float y,float z)623 bool Object3D::UpdateVertice(int MeshNo, int SurfaceNumber, float x, float y, float z)noexcept{
624 float data[] = {x,y,z};
625 if(MeshNo < meshes.GetCount()){
626 return UpdateBuffer(meshes[MeshNo].GetVerticesVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, 1 ,3, data);
627 }else{
628 return false;
629 }
630 }
UpdateVertice(int MeshNo,int SurfaceNumber,glm::vec3 vertice)631 bool Object3D::UpdateVertice(int MeshNo, int SurfaceNumber, glm::vec3 vertice)noexcept{
632 if(MeshNo < meshes.GetCount()){
633 return UpdateBuffer(meshes[MeshNo].GetVerticesVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber, 1 ,3, &(vertice.x));
634 }else{
635 return false;
636 }
637 }
UpdateVertices(int MeshNo,int SurfaceNumber,int Count,const float * data)638 bool Object3D::UpdateVertices(int MeshNo, int SurfaceNumber,int Count, const float * data)noexcept{
639 if(MeshNo < meshes.GetCount()){
640 return UpdateBuffer(meshes[MeshNo].GetVerticesVBO(), meshes[MeshNo].GetVertices().GetCount()/3 ,SurfaceNumber, Count ,3, data);
641 }else{
642 return false;
643 }
644 }
ReadColors(int MeshNo,int SurfaceNumber,int count)645 Vector<float> Object3D::ReadColors(int MeshNo, int SurfaceNumber, int count){
646 if(MeshNo < meshes.GetCount()){
647 return ReadBuffer(meshes[MeshNo].GetColorsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber,count,4);
648 }else{
649 throw Exc(Format(t_("Object3D '%i' don't have meshes no '%i', colors can't be readed\n"), ID, MeshNo));
650 }
651 }
ReadNormals(int MeshNo,int SurfaceNumber,int count)652 Vector<float> Object3D::ReadNormals(int MeshNo, int SurfaceNumber, int count){
653 if(MeshNo < meshes.GetCount()){
654 return ReadBuffer(meshes[MeshNo].GetNormalsVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber,count,3);
655 }else{
656 throw Exc(Format(t_("Object3D '%i' don't have meshes no '%i', normals can't be readed\n"), ID, MeshNo));
657 }
658 }
ReadVertices(int MeshNo,int SurfaceNumber,int count)659 Vector<float> Object3D::ReadVertices(int MeshNo, int SurfaceNumber, int count){
660 if(MeshNo < meshes.GetCount()){
661 return ReadBuffer(meshes[MeshNo].GetVerticesVBO(), meshes[MeshNo].GetVertices().GetCount()/3,SurfaceNumber,count,3);
662 }else{
663 throw Exc(Format(t_("Object3D '%i' don't have meshes no '%i', vertices can't be readed\n"), ID, MeshNo));
664 }
665 }
666
DefaultInit(Object3D & obj)667 void Object3D::DefaultInit(Object3D& obj){
668 for(Mesh& m : obj.GetMeshes()){
669 m.Init();
670 }
671 obj.CreateBoundingBox();
672
673 }
DefaultDraw(const glm::mat4 & projectionMatrix,const glm::mat4 & viewMatrix,const glm::vec3 & viewPosition,Object3D & obj)674 void Object3D::DefaultDraw(const glm::mat4& projectionMatrix,const glm::mat4& viewMatrix,const glm::vec3& viewPosition,Object3D& obj)noexcept{
675 if(obj.IsLoaded()){
676 if(obj.IsVisible()){
677 if(obj.GetShowMesh()){
678 if(obj.GetProgramNoLight() != -1 && obj.GetProgramLight() != -1 && obj.GetProgram()[obj.GetProgramNoLight()].IsLinked() && obj.GetProgram()[obj.GetProgramLight()].IsLinked()){
679 OpenGLProgram& prog = (obj.GetShowLight())? obj.GetProgram()[obj.GetProgramLight()] : obj.GetProgram()[obj.GetProgramNoLight()];
680 prog.Bind();
681 if(obj.GetShowLight()){
682 prog.SetVec3("viewPos",viewPosition.x,viewPosition.y,viewPosition.z);
683 if(obj.GetMaterial().ShouldBeUpdated()){
684 Material& material = obj.GetMaterial();
685 prog.SetVec3("mat.Diffuse", material.GetDiffuse().x,material.GetDiffuse().y,material.GetDiffuse().z);
686 prog.SetVec3("mat.Specular", material.GetSpecular().x,material.GetSpecular().y,material.GetSpecular().z);
687 prog.SetFloat("mat.Shininess", material.GetShininess());
688 material.HaveBeenUpdated();
689 }
690 }
691 prog.SetMat4("ViewMatrix", viewMatrix);
692 prog.SetMat4("ProjectionMatrix", projectionMatrix);
693 prog.SetMat4("ModelMatrix", obj.GetTransform().GetModelMatrix());
694
695 for(Mesh& m : obj.GetMeshes()){
696 glBindVertexArray(m.GetVAO());
697 if(obj.GetTextures().GetCount()> 0){
698 glActiveTexture(GL_TEXTURE0);
699 glBindTexture(GL_TEXTURE_2D, obj.GetTextures()[m.GetTextureIndice()].id);
700 prog.SetInt("tex", 0);
701 prog.SetInt("useTexture", obj.GetTextures()[m.GetTextureIndice()].id);
702 }else{
703 prog.SetInt("useTexture", 0);
704 }
705 glDrawArrays(((prog.ContainTCS()) ? GL_PATCHES : obj.GetDrawType()), 0, m.GetVertices().GetCount()/3);
706 }
707 }else{
708 ONCELOCK{
709 LOG("no Light/NoLight OpenGL Program have been provided, Object3D No " + AsString(ID) +" Can't be light/nolight draw");
710 }
711 }
712 }
713 if(obj.GetShowMeshLine()){
714 if(obj.GetProgramLine() != -1 && obj.GetProgram()[obj.GetProgramLine()].IsLinked()){
715 OpenGLProgram& prog = obj.GetProgram()[obj.GetProgramLine()];
716 prog.Bind();
717
718 glLineWidth(obj.GetLineWidth());
719 prog.SetMat4("ViewMatrix",viewMatrix);
720 prog.SetMat4("ProjectionMatrix",projectionMatrix);
721 prog.SetMat4("ModelMatrix",obj.GetTransform().GetModelMatrix());
722 Color lineColor = obj.GetLineColor();
723 prog.SetVec4("CustomColor", lineColor.GetR() / 255.0f, lineColor.GetG() / 255.0f, lineColor.GetB() / 255.0f,obj.GetLineOpacity());
724
725 for(Mesh& m : obj.GetMeshes()){
726 glBindVertexArray(m.GetVAO());
727 glDrawArrays(((prog.ContainTCS()) ? GL_PATCHES : GL_TRIANGLES), 0, m.GetVertices().GetCount()/3);
728 }
729 }else{
730 ONCELOCK{
731 LOG("no Line OpenGL Program have been provided, Object3D No " + AsString(ID) +" Can't be line draw");
732 }
733 }
734 }
735 if(obj.GetShowMeshNormal()){
736 if(obj.GetProgramNormal() != -1 && obj.GetProgram()[obj.GetProgramNormal()].IsLinked() ){
737 OpenGLProgram& prog = obj.GetProgram()[obj.GetProgramNormal()];
738 prog.Bind();
739 prog.SetMat4("ViewMatrix", viewMatrix);
740 prog.SetMat4("ProjectionMatrix", projectionMatrix);
741 prog.SetMat4("ModelMatrix", obj.GetTransform().GetModelMatrix());
742 Color normalColor = obj.GetNormalColor();
743 prog.SetVec4("CustomColor",normalColor.GetR() / 255.0f, normalColor.GetG() / 255.0f, normalColor.GetB() / 255.0f, obj.GetNormalOpacity());
744 prog.SetFloat("normal_length",obj.GetNormalLength());
745 for(Mesh& m : obj.GetMeshes()){
746 glBindVertexArray(m.GetVAO());
747 glDrawArrays(GL_TRIANGLES, 0, m.GetVertices().GetCount()/3);
748 }
749 }else{
750 ONCELOCK{
751 LOG("no Normal OpenGL Program have been provided, Object3D No " + AsString(ID) +" Can't be normal draw");
752 }
753 }
754 }
755 if(obj.GetShowBoundingBox()){
756 if(obj.GetProgramLine() != -1 && obj.GetProgram()[obj.GetProgramLine()].IsLinked()){
757 boundingBox.Draw(obj.GetTransform().GetModelMatrix(),viewMatrix,projectionMatrix,obj.GetProgram()[obj.GetProgramLine()]);
758 }else{
759 ONCELOCK{
760 LOG("no Line OpenGL Program have been provided, Object3D No " + AsString(ID) +" Can't have is bounding box draw");
761 }
762 }
763 }
764 }
765 }
766 }
DefaultClear(Object3D & obj)767 void Object3D::DefaultClear(Object3D& obj){
768 if(!moved){
769 for(Mesh& m : obj.GetMeshes()){
770 m.Clear(true);
771 }
772 obj.RemoveBoundingBox();
773 }
774 }
DefaultReload(Object3D & obj)775 void Object3D::DefaultReload(Object3D& obj){
776 obj.Clear();
777 obj.Init();
778 }
779
Init(const Image & skybox_right,const Image & skybox_left,const Image & skybox_top,const Image & skybox_bottom,const Image & skybox_front,const Image & skybox_back)780 Skybox& Skybox::Init(const Image& skybox_right,const Image& skybox_left,const Image& skybox_top,const Image& skybox_bottom,const Image& skybox_front,const Image& skybox_back){
781 auto TestImage = [&](const Image& img) -> Image{
782 if(img){
783 return pick(img);
784 }
785 return TexturesImg::empty();
786 };
787 return Init(Vector<Image>{ TestImage(skybox_right), TestImage(skybox_left), TestImage(skybox_top), TestImage(skybox_bottom),TestImage(skybox_front), TestImage(skybox_back)});
788 }
Init(const Vector<Image> & images)789 Skybox& Skybox::Init(const Vector<Image>& images){
790 glGenTextures(1, &ID);
791 glBindTexture(GL_TEXTURE_CUBE_MAP, ID);
792
793 int i = 0;
794 for(const Image& img : images){
795 if(img){
796 Size size = img.GetSize();
797 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, size.cx , size.cy, 0, GL_BGRA, GL_UNSIGNED_BYTE, ~img);
798 }else{
799 Size size = TexturesImg::empty().GetSize();
800 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, size.cx , size.cy, 0, GL_BGRA, GL_UNSIGNED_BYTE, ~(TexturesImg::empty()));
801 }
802 i++;
803 }
804 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
805 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
806 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
807 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
808 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
809
810 Vector<float> skyboxData;
811 skyboxData << -1.0f << 1.0f << -1.0f << -1.0f << -1.0f << -1.0f << 1.0f << -1.0f << -1.0f << 1.0f << -1.0f << -1.0f << 1.0f << 1.0f << -1.0f << -1.0f << 1.0f << -1.0f <<
812 -1.0f << -1.0f << 1.0f << -1.0f << -1.0f << -1.0f << -1.0f << 1.0f << -1.0f << -1.0f << 1.0f << -1.0f << -1.0f << 1.0f << 1.0f << -1.0f << -1.0f << 1.0f <<
813 1.0f << -1.0f << -1.0f << 1.0f << -1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << -1.0f << 1.0f << -1.0f << -1.0f <<
814 -1.0f << -1.0f << 1.0f << -1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << -1.0f << 1.0f << -1.0f << -1.0f << 1.0f <<
815 -1.0f << 1.0f << -1.0f << 1.0f << 1.0f << -1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << 1.0f << -1.0f << 1.0f << 1.0f << -1.0f << 1.0f << -1.0f <<
816 -1.0f << -1.0f << -1.0f << -1.0f << -1.0f << 1.0f << 1.0f << -1.0f << -1.0f << 1.0f << -1.0f << -1.0f << -1.0f << -1.0f << 1.0f << 1.0f << -1.0f << 1.0f;
817
818
819 glGenVertexArrays(1, &VAO);
820 glGenBuffers(1, &VBO);
821 glBindVertexArray(VAO);
822 glBindBuffer(GL_ARRAY_BUFFER, VBO);
823 glBufferData(GL_ARRAY_BUFFER, skyboxData.GetCount() * sizeof(float), &(skyboxData[0]), GL_STATIC_DRAW);
824 glEnableVertexAttribArray(0);
825 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
826
827 program.AttachShader(OpenGLShader(GL_VERTEX_SHADER,
828 #include "shaders/VertexCubeMap.glsl"
829 )).AttachShader(OpenGLShader(GL_FRAGMENT_SHADER,
830 #include "shaders/FragmentCubeMap.glsl"
831 )).Link();
832 return *this;
833 }
Clear()834 Skybox& Skybox::Clear(){if(ID)glDeleteTextures(1,&ID); return *this;} //Clear the skybox
835
Draw(const glm::mat4 & projectionMatrix,const glm::mat4 & viewMatrix)836 Skybox& Skybox::Draw(const glm::mat4& projectionMatrix,const glm::mat4& viewMatrix){ //Draw the skybox
837 if(show && ID > 0){
838 glDepthFunc(GL_LEQUAL); // change depth function so depth test passes when values are equal to depth buffer's content
839 program.Bind();
840
841 program.SetMat4("ViewMatrix", glm::mat4(glm::mat3(viewMatrix)));// remove translation from the view matrix
842 program.SetMat4("ProjectionMatrix", projectionMatrix);
843 program.SetInt("skybox", 1);
844
845 glBindVertexArray(VAO);
846 glActiveTexture(GL_TEXTURE1);
847 glBindTexture(GL_TEXTURE_CUBE_MAP, ID);
848 glDrawArrays(GL_TRIANGLES, 0, 36);
849 glDepthFunc(GL_LESS); // set depth function back to default
850 }
851 return *this;
852 }
853
854 }