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 }