Browse Source

Update to OpenB3D 0.9.

woollybah 11 years ago
parent
commit
e46b4e3808
33 changed files with 8192 additions and 5672 deletions
  1. 1 0
      openb3d.mod/examples/CreateTexture2.bmx
  2. 14 0
      openb3dlib.mod/openb3d/license.txt
  3. 129 3
      openb3dlib.mod/openb3d/src/animation.cpp
  4. 1 0
      openb3dlib.mod/openb3d/src/animation.h
  5. 33 10
      openb3dlib.mod/openb3d/src/camera.cpp
  6. 1 1
      openb3dlib.mod/openb3d/src/entity.cpp
  7. 20 7
      openb3dlib.mod/openb3d/src/functions.cpp
  8. 1192 1192
      openb3dlib.mod/openb3d/src/functions.h
  9. 1364 1253
      openb3dlib.mod/openb3d/src/geosphere.cpp
  10. 1 1
      openb3dlib.mod/openb3d/src/geosphere.h
  11. 16 0
      openb3dlib.mod/openb3d/src/global.cpp
  12. 7 0
      openb3dlib.mod/openb3d/src/global.h
  13. 1719 1719
      openb3dlib.mod/openb3d/src/material.cpp
  14. 294 0
      openb3dlib.mod/openb3d/src/md2.cpp
  15. 3 0
      openb3dlib.mod/openb3d/src/md2.h
  16. 61 28
      openb3dlib.mod/openb3d/src/mesh.cpp
  17. 1496 0
      openb3dlib.mod/openb3d/src/metaball.cpp
  18. 64 0
      openb3dlib.mod/openb3d/src/metaball.h
  19. 2 2
      openb3dlib.mod/openb3d/src/model.cpp
  20. 13 11
      openb3dlib.mod/openb3d/src/octree.cpp
  21. 159 0
      openb3dlib.mod/openb3d/src/particle.cpp
  22. 115 0
      openb3dlib.mod/openb3d/src/particle.h
  23. 556 542
      openb3dlib.mod/openb3d/src/shadow.cpp
  24. 3 0
      openb3dlib.mod/openb3d/src/sprite_batch.h
  25. 1 0
      openb3dlib.mod/openb3d/src/stb_image.c
  26. 216 202
      openb3dlib.mod/openb3d/src/stencil.cpp
  27. 65 75
      openb3dlib.mod/openb3d/src/terrain.cpp
  28. 3 0
      openb3dlib.mod/openb3d/src/texture.cpp
  29. 0 3
      openb3dlib.mod/openb3d/src/turn.cpp
  30. 1 1
      openb3dlib.mod/openb3d/src/voxel.cpp
  31. 622 622
      openb3dlib.mod/openb3d/src/x.cpp
  32. 17 0
      openb3dlib.mod/openb3d/whatsnew.txt
  33. 3 0
      openb3dlib.mod/source.bmx

+ 1 - 0
openb3d.mod/examples/CreateTexture2.bmx

@@ -4,6 +4,7 @@ Strict
 
 
 Framework b3d.b3dglgraphics
+Import brl.random
 
 Graphics3D 800,600,0,2
 

+ 14 - 0
openb3dlib.mod/openb3d/license.txt

@@ -0,0 +1,14 @@
+    The OpenB3D library is licensed under the GNU LGPLv2 or later, 
+    with this exception to allow linking to it statically:
+
+        As a special exception, the copyright holders of this library give
+        you permission to link this library with independent modules to
+        produce an executable, regardless of the license terms of these
+        independent modules, and to copy and distribute the resulting
+        executable under terms of your choice, provided that you also meet,
+        for each linked independent module, the terms and conditions of the
+        license of that module. An independent module is a module which is
+        not derived from or based on this library. If you modify this library,
+        you may extend this exception to your version of the library, but
+        you are not obligated to do so. If you do not wish to do so, delete
+        this exception statement from your version.

+ 129 - 3
openb3dlib.mod/openb3d/src/animation.cpp

@@ -20,10 +20,95 @@ using namespace std;
 
 void Animation::AnimateMesh(Mesh* ent1,float framef,int start_frame,int end_frame){
 	//if(dynamic_cast<Mesh*>(ent1)!=NULL){
-	if(ent1->anim==false) return; // mesh contains no anim data
+	if(ent1->anim!=1) {			//Not a bone based animation
+
+		if(ent1->anim<=0) return; // mesh contains no anim data
+
+		if(ent1->anim==64) { // repeated mesh: every frame has its own surface
+			ent1->anim_render=true;
+			//ent1->surf_list.size();
+			list<Surface*>::iterator dst_surf_it;
+			dst_surf_it=ent1->anim_surf_list.begin();
+
+			list<Surface*>::iterator src_surf_it;
+			src_surf_it=ent1->anim_surf_list.begin();
+
+			//Locate correct frame
+			for(unsigned int i=0;i<(int)framef*ent1->surf_list.size();i++){
+				src_surf_it++;
+			}
+
+			list<Surface*>::iterator surf_it;
+			surf_it=ent1->surf_list.begin();
+
+			// cycle through all surfs
+			for(surf_it=ent1->surf_list.begin();surf_it!=ent1->surf_list.end();surf_it++){
+
+				*dst_surf_it=*src_surf_it;
+				src_surf_it++;
+				dst_surf_it++;
+			}
+			
+
+
+			
+			return;
+		}
+
+
+		//Vertex deform animation
+		ent1->anim_render=true;
+
+		list<Surface*>::iterator surf_it;
+		surf_it=ent1->surf_list.begin();
+
+		list<Surface*>::iterator anim_surf_it;
+
+
+		// cycle through all surfs
+		for(anim_surf_it=ent1->anim_surf_list.begin();anim_surf_it!=ent1->anim_surf_list.end();anim_surf_it++){
+
+			Surface& anim_surf=**anim_surf_it;
+
+			Surface& surf=**surf_it;
+
+			anim_surf.reset_vbo=anim_surf.reset_vbo|1;
+
+			int t0, t1;
+			t0=0;
+			for(unsigned int i=0;i<=anim_surf.vert_weight4.size();i++){
+				if (anim_surf.vert_weight4[i]>=framef){
+					t1=i; t0=i-1;
+					break;
+				}
+			}
+			float m1=(framef-anim_surf.vert_weight4[t0])/(anim_surf.vert_weight4[t1]-anim_surf.vert_weight4[t0]);
+			float m0=1.0-m1;
+
+			t0*=anim_surf.no_verts*3;
+			t1*=anim_surf.no_verts*3;
+
+
+			for(int i=0;i<=anim_surf.no_verts*3;i++){
+				anim_surf.vert_coords[i]=surf.vert_coords[i+t0]*m0+surf.vert_coords[i+t1]*m1;
+
+			}
+
+
+
+
+			surf_it++;
+
+		}
+		
+		return;
+
+
+	}
+
 	ent1->anim_render=true;
 
-  // cap framef values
+	// cap framef values
 	if(framef>end_frame) framef=end_frame;
 	if(framef<start_frame) framef=start_frame;
 
@@ -276,7 +361,7 @@ void Animation::AnimateMesh2(Mesh* ent1,float framef,int start_frame,int end_fra
 
 	//if(dynamic_cast<Mesh*>(ent1)!=NULL){
 
-	if(ent1->anim==false) return; // mesh contains no anim data
+	if(ent1->anim!=1) return; // mesh contains no anim data
 
 		ent1->anim_render=true;
 
@@ -474,6 +559,47 @@ void Animation::AnimateMesh2(Mesh* ent1,float framef,int start_frame,int end_fra
 
 }
 
+void Animation::AnimateMesh3(Mesh* ent1){
+	if(ent1->anim!=1) return; // mesh contains no anim data
+
+		ent1->anim_render=true;
+
+		//int frame=framef; // float to int
+
+		vector<Bone*>::iterator it;
+
+		for(it=ent1->bones.begin();it!=ent1->bones.end();it++){
+
+			Bone& bent=**it;
+
+			// set mat2 to equal mat
+			bent.mat2.Overwrite(bent.mat);
+
+			bent.mat2.grid[3][0]-=ent1->mat.grid[3][0];
+			bent.mat2.grid[3][1]-=ent1->mat.grid[3][1];
+			bent.mat2.grid[3][2]-=ent1->mat.grid[3][2];
+
+
+			// mat2 is used to store local bone positions, and is needed for vertex deform
+
+			// set tform mat
+			// A tform mat is needed to transform vertices, and is basically the bone mat multiplied by the inverse reference pose mat
+			bent.tform_mat.Overwrite(bent.mat2);
+
+			bent.tform_mat.Multiply(bent.inv_mat);
+
+
+		}
+
+		ent1->MQ_Update();
+
+		// --- vertex deform ---
+		VertexDeform(ent1);
+
+	//}
+
+}
+
 void Animation::VertexDeform(Mesh* ent){
 
 	float ovx=0.0,ovy=0.0,ovz=0.0; // original vertex positions

+ 1 - 0
openb3dlib.mod/openb3d/src/animation.h

@@ -21,6 +21,7 @@ public:
 
 	static void AnimateMesh(Mesh* ent1,float framef,int start_frame,int end_frame);
 	static void AnimateMesh2(Mesh* ent1,float framef,int start_frame,int end_frame);
+	static void AnimateMesh3(Mesh* ent1);
 	static void VertexDeform(Mesh* ent);
 	//static void NormaliseWeights(Mesh* mesh);
 	

+ 33 - 10
openb3dlib.mod/openb3d/src/camera.cpp

@@ -13,6 +13,7 @@
 #include "light.h"
 #include "sprite.h"
 #include "sprite_batch.h"
+#include "particle.h"
 #include "pick.h"
 #include "project.h"
 //#include "misc.h"
@@ -472,12 +473,12 @@ void Camera::Update(){
 
 	if(fog_mode>0){
 	
-		//if(fog!=true){
+		if(fog!=true){
 			glEnable(GL_FOG); // enable if disabled
 			if(fog==-1) glFogf(GL_FOG_MODE,GL_LINEAR); // once only
 			fog=true;
 			Global::fog_enabled=true; // used in mesh render
-		//}
+		}
 		
 		if(abs(fog_near-fog_range_near)>0.0001){
 			glFogf(GL_FOG_START,fog_range_near);
@@ -499,11 +500,11 @@ void Camera::Update(){
 		
 	}else{
 		
-		//if(fog!=false){
+		if(fog!=false){
 			glDisable(GL_FOG);
 			fog=false;
 			Global::fog_enabled=false; // used in mesh render
-		//}
+		}
 		
 	}
 	
@@ -632,17 +633,39 @@ void UpdateEntityRender(Entity* ent,Entity* cam){
 		
 			if(sprite){
 	
-				dynamic_cast<Camera*>(cam)->UpdateSprite(*sprite);
+				switch (sprite->render_mode){
+					case (1):{
+						dynamic_cast<Camera*>(cam)->UpdateSprite(*sprite);
+						break;}
+
 			
-				if(sprite->render_mode==2){ // sprite batch rendering
+					case (2):{ // sprite batch rendering
+						dynamic_cast<Camera*>(cam)->UpdateSprite(*sprite);
+
+						Surface* surf=SpriteBatch::GetSpriteBatchSurface(sprite->brush.tex[0],sprite->brush.blend,sprite->order);
 			
-					Surface* surf=SpriteBatch::GetSpriteBatchSurface(sprite->brush.tex[0],sprite->brush.blend,sprite->order);
+						dynamic_cast<Camera*>(cam)->AddTransformedSpriteToSurface(*sprite,surf);
+				
+						return;}
+					case (3):{
+						Surface* surf=ParticleBatch::GetParticleBatchSurface(sprite->brush.tex[0],sprite->brush.blend,sprite->order);
 			
-					dynamic_cast<Camera*>(cam)->AddTransformedSpriteToSurface(*sprite,surf);
+						surf->no_verts++;
+
+						surf->vert_coords.push_back(sprite->mat.grid[3][0]);
+						surf->vert_coords.push_back(sprite->mat.grid[3][1]);
+						surf->vert_coords.push_back(sprite->mat.grid[3][2]);
+
+						surf->vert_col.push_back(1.0);
+						surf->vert_col.push_back(1.0);
+						surf->vert_col.push_back(1.0);
+						surf->vert_col.push_back(1.0);
+
 				
-					return;
+						return;}
 					
-				}
+					
+				}  
 				
 			}
 		

+ 1 - 1
openb3dlib.mod/openb3d/src/entity.cpp

@@ -738,7 +738,7 @@ int Entity::AddAnimSeq(int length){
 
 			Mesh* mesh=dynamic_cast<Mesh*>(this);
 
-			anim=true;
+			anim=2;
 			anim_render=true;
 
 			//mesh->frames=a_frames

+ 20 - 7
openb3dlib.mod/openb3d/src/functions.cpp

@@ -11,6 +11,7 @@
 #include "voxel.h"
 #include "octree.h"
 #include "geosphere.h"
+#include "metaball.h"
 
 extern "C" {
 
@@ -403,6 +404,10 @@ int CountVertices(Surface* surf){
 	return surf->CountVertices();
 }
 
+Blob* CreateBlob(Fluid* fluid, float radius, Entity* parent_ent){
+	return Blob::CreateBlob(fluid, radius, parent_ent);
+}
+
 /*
 bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateBrush">Online Help</a>
 */
@@ -861,13 +866,13 @@ void Graphics3D(int width,int height,int depth,int mode,int rate){
 }
 
 /*
-*/
-void GraphicsResize(int width,int height){
-	Global::width=width;
-	Global::height=height;
-}
-
-/*
+*/
+void GraphicsResize(int width,int height){
+	Global::width=width;
+	Global::height=height;
+}
+
+/*
 bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=HandleSprite">Online Help</a>
 */
 void HandleSprite(Sprite* sprite,float h_x,float h_y){
@@ -1273,6 +1278,10 @@ void ShowEntity(Entity* ent){
 	ent->ShowEntity();
 }
 
+void SpriteRenderMode(Sprite* sprite,int mode){
+	sprite->SpriteRenderMode(mode);
+}
+
 /*
 bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SpriteViewMode">Online Help</a>
 */
@@ -1798,6 +1807,10 @@ void OctreeMesh(OcTree* octree, Mesh* mesh, int level, float X, float Y, float Z
 	octree->OctreeMesh(mesh, level, X, Y, Z, Near, Far);
 }
 
+Fluid* CreateFluid(){
+	return Fluid::CreateFluid();
+}
+
 /*void SetParameter1S(Shader* material, char* name, float v1){
 	material->SetParameter1S(name, v1);
 }

+ 1192 - 1192
openb3dlib.mod/openb3d/src/functions.h

@@ -1,1192 +1,1192 @@
-#ifndef __functions_h__
-#define __functions_h__
-
-// functions
-extern "C" {
-
-void BufferToTex(Texture* tex,unsigned char* buffer, int frame);
-void BackBufferToTex(Texture* tex,int frame);
-void TexToBuffer(Texture* tex,unsigned char* buffer, int frame);
-
-
-/*
-bbdoc: Minib3d Only
-about:
-This command is the equivalent of Blitz3D's MeshCullBox command.
-
-It is used to set the radius of a mesh's 'cull sphere' - if the 'cull sphere' is not inside the viewing area, the mesh will not
-be rendered.
-
-A mesh's cull radius is set automatically, therefore in most cases you will not have to use this command.
-
-One time you may have to use it is for animated meshes where the default cull radius may not take into account all animation
-positions, resulting in the mesh being wrongly culled at extreme positions.
-*/
-void MeshCullRadius(Entity* ent, float radius);
-// Blitz3D functions, A-Z
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AddAnimSeq">Online Help</a>
-*/
-int AddAnimSeq(Entity* ent,int length);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AddMesh">Online Help</a>
-*/
-void AddMesh(Mesh* mesh1,Mesh* mesh2);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AddTriangle">Online Help</a>
-*/
-int AddTriangle(Surface* surf,int v0,int v1,int v2);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AddVertex">Online Help</a>
-*/
-int AddVertex(Surface* surf,float x, float y,float z,float u, float v,float w);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AmbientLight">Online Help</a>
-*/
-void AmbientLight(float r,float g,float b);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AntiAlias">Online Help</a>
-*/
-void AntiAlias(int samples);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Animate">Online Help</a>
-*/
-void Animate(Entity* ent,int mode,float speed,int seq,int trans);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Animating">Online Help</a>
-*/
-int Animating(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AnimLength">Online Help</a>
-*/
-int AnimLength(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AnimSeq">Online Help</a>
-*/
-int AnimSeq(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AnimTime">Online Help</a>
-*/
-float AnimTime(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushAlpha">Online Help</a>
-*/
-void BrushAlpha(Brush* brush, float a);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushBlend">Online Help</a>
-*/
-void BrushBlend(Brush* brush,int blend);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushColor">Online Help</a>
-*/
-void BrushColor(Brush* brush,float r,float g,float b);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushFX">Online Help</a>
-*/
-void BrushFX(Brush* brush,int fx);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushShininess">Online Help</a>
-*/
-void BrushShininess(Brush* brush,float s);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushTexture">Online Help</a>
-*/
-void BrushTexture(Brush* brush,Texture* tex,int frame,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraClsColor">Online Help</a>
-*/
-void CameraClsColor(Camera* cam, float r,float g,float b);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraClsMode">Online Help</a>
-*/
-void CameraClsMode(Camera* cam,int cls_depth,int cls_zbuffer);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraFogColor">Online Help</a>
-*/
-void CameraFogColor(Camera* cam,float r,float g,float b);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraFogMode">Online Help</a>
-*/
-void CameraFogMode(Camera* cam,int mode);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraFogRange">Online Help</a>
-*/
-void CameraFogRange(Camera* cam,float nnear,float nfar);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraPick">Online Help</a>
-*/
-Entity* CameraPick(Camera* cam,float x,float y);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraProject">Online Help</a>
-*/
-void CameraProject(Camera* cam,float x,float y,float z);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraProjMode">Online Help</a>
-*/
-void  CameraProjMode(Camera* cam,int mode);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraRange">Online Help</a>
-*/
-void  CameraRange(Camera* cam,float nnear,float nfar);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraViewport">Online Help</a>
-*/
-void  CameraViewport(Camera* cam,int x,int y,int width,int height);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraZoom">Online Help</a>
-*/
-void  CameraZoom(Camera* cam,float zoom);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ClearCollisions">Online Help</a>
-int ClearCollisions(){
-	Global::ClearCollisions();
-}
-*/
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ClearSurface">Online Help</a>
-*/
-void ClearSurface(Surface* surf,bool clear_verts,bool clear_tris);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ClearTextureFilters">Online Help</a>
-*/
-void ClearTextureFilters();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ClearWorld">Online Help</a>
-*/
-void ClearWorld(bool entities,bool brushes,bool textures);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionEntity">Online Help</a>
-*/
-Entity* CollisionEntity(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Collisions">Online Help</a>
-*/
-void Collisions(int src_no,int dest_no,int method_no,int response_no);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionNX">Online Help</a>
-*/
-float CollisionNX(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionNY">Online Help</a>
-*/
-float CollisionNY(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionNZ">Online Help</a>
-*/
-float CollisionNZ(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionSurface">Online Help</a>
-*/
-Surface* CollisionSurface(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionTime">Online Help</a>
-*/
-float CollisionTime(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionTriangle">Online Help</a>
-*/
-int CollisionTriangle(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionX">Online Help</a>
-*/
-float CollisionX(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionY">Online Help</a>
-*/
-float CollisionY(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionZ">Online Help</a>
-*/
-float CollisionZ(Entity* ent,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountChildren">Online Help</a>
-*/
-int CountChildren(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountCollisions">Online Help</a>
-*/
-int CountCollisions(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CopyEntity">Online Help</a>
-*/
-Entity* CopyEntity(Entity* ent,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CopyMesh">Online Help</a>
-*/
-Mesh* CopyMesh(Mesh* mesh,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountSurfaces">Online Help</a>
-*/
-int CountSurfaces(Mesh* mesh);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountTriangles">Online Help</a>
-*/
-int CountTriangles(Surface* surf);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountVertices">Online Help</a>
-*/
-int CountVertices(Surface* surf);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateBrush">Online Help</a>
-*/
-Brush* CreateBrush(float r,float g,float b);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateCamera">Online Help</a>
-*/
-Camera* CreateCamera(Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateCone">Online Help</a>
-*/
-Mesh* CreateCone(int segments,bool solid,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateCylinder">Online Help</a>
-*/
-Mesh* CreateCylinder(int segments,bool solid,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateCube">Online Help</a>
-*/
-Mesh* CreateCube(Entity* parent);
-
-Terrain* CreateGeosphere(int size, Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateMesh">Online Help</a>
-*/
-Mesh* CreateMesh(Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateLight">Online Help</a>
-*/
-Light* CreateLight(int light_type,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreatePivot">Online Help</a>
-*/
-Pivot* CreatePivot(Entity* parent);
-
-Mesh* CreatePlane(int divisions,Entity* parent);
-
-Mesh* CreateQuad(Entity* parent);
-
-ShadowObject* CreateShadow(Mesh* parent, char Static);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateSphere">Online Help</a>
-*/
-Mesh* CreateSphere(int segments,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateSprite">Online Help</a>
-*/
-Sprite* CreateSprite(Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateSurface">Online Help</a>
-*/
-Surface* CreateSurface(Mesh* mesh,Brush* brush);
-
-/*
-*/
-Stencil* CreateStencil();
-
-/*
-*/
-Terrain* CreateTerrain(int size, Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateTexture">Online Help</a>
-*/
-Texture* CreateTexture(int width,int height,int flags,int frames);
-
-/*
-*/
-VoxelSprite* CreateVoxelSprite(int slices, Entity* parent);
-
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=DeltaPitch">Online Help</a>
-*/
-float DeltaPitch(Entity* ent1,Entity* ent2);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=DeltaYaw">Online Help</a>
-*/
-float DeltaYaw(Entity* ent1,Entity* ent2);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityAlpha">Online Help</a>
-*/
-void EntityAlpha(Entity* ent,float alpha);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityAutoFade">Online Help</a>
-*/
-void EntityAutoFade(Entity* ent,float near,float far);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityBlend">Online Help</a>
-*/
-void EntityBlend(Entity* ent, int blend);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityBox">Online Help</a>
-*/
-void EntityBox(Entity* ent,float x,float y,float z,float w,float h,float d);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityClass">Online Help</a>
-*/
-const char* EntityClass(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityCollided">Online Help</a>
-*/
-Entity* EntityCollided(Entity* ent,int type_no);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityColor">Online Help</a>
-*/
-void EntityColor(Entity* ent,float red,float green,float blue);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityDistance">Online Help</a>
-*/
-float EntityDistance(Entity* ent1,Entity* ent2);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityFX">Online Help</a>
-*/
-void EntityFX(Entity* ent,int fx);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityInView">Online Help</a>
-*/
-int EntityInView(Entity* ent,Camera* cam);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityName">Online Help</a>
-*/
-const char* EntityName(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityOrder">Online Help</a>
-*/
-void EntityOrder(Entity* ent,int order);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityParent">Online Help</a>
-
-
-
-
-*/
-void EntityParent(Entity* ent,Entity* parent_ent,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityPick">Online Help</a>
-*/
-Entity* EntityPick(Entity* ent,float range);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityPickMode">Online Help</a>
-*/
-void EntityPickMode(Entity* ent,int pick_mode,bool obscurer);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityPitch">Online Help</a>
-*/
-float EntityPitch(Entity* ent,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityRadius">Online Help</a>
-*/
-void EntityRadius(Entity* ent,float radius_x,float radius_y);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityRoll">Online Help</a>
-*/
-float EntityRoll(Entity* ent,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityShininess">Online Help</a>
-*/
-void EntityShininess(Entity* ent,float shine);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityTexture">Online Help</a>
-*/
-void EntityTexture(Entity* ent,Texture* tex,int frame,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityType">Online Help</a>
-*/
-void EntityType(Entity* ent,int type_no,bool recursive);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityVisible">Online Help</a>
-*/
-int EntityVisible(Entity* src_ent,Entity* dest_ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityX">Online Help</a>
-*/
-float EntityX(Entity* ent,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityY">Online Help</a>
-*/
-float EntityY(Entity* ent,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityYaw">Online Help</a>
-*/
-float EntityYaw(Entity* ent,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityZ">Online Help</a>
-*/
-float EntityZ(Entity* ent,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ExtractAnimSeq">Online Help</a>
-*/
-int ExtractAnimSeq(Entity* ent,int first_frame,int last_frame,int seq);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FindChild">Online Help</a>
-*/
-Entity* FindChild(Entity* ent,char* child_name);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FindSurface">Online Help</a>
-*/
-Surface* FindSurface(Mesh* mesh,Brush* brush);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FitMesh">Online Help</a><p>
-*/
-void FitMesh(Mesh* mesh,float x,float y,float z,float width,float height,float depth,bool uniform);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FlipMesh">Online Help</a>
-*/
-void FlipMesh(Mesh* mesh);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FreeBrush">Online Help</a>
-*/
-void  FreeBrush(Brush* brush);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FreeEntity">Online Help</a>
-*/
-void FreeEntity(Entity* ent);
-
-void FreeShadow(ShadowObject* shad);
-
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FreeTexture">Online Help</a>
-*/
-void FreeTexture(Texture* tex);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetBrushTexture">Online Help</a>
-*/
-Texture* GetBrushTexture(Brush* brush,int index);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetChild">Online Help</a>
-*/
-Entity* GetChild(Entity* ent,int child_no);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetEntityBrush">Online Help</a>
-*/
-Brush* GetEntityBrush(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetEntityType">Online Help</a>
-*/
-int GetEntityType(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ResetEntity">Online Help</a>
-*/
-float GetMatElement(Entity* ent,int row,int col);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetParent">Online Help</a>
-*/
-Entity* GetParentEntity(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetSurface">Online Help</a>
-*/
-Surface* GetSurface(Mesh* mesh,int surf_no);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetSurfaceBrush">Online Help</a>
-*/
-Brush* GetSurfaceBrush(Surface* surf);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Graphics3D">Online Help</a>
-*/
-void Graphics3D(int width,int height,int depth,int mode,int rate);
-
-/*
-*/
-void GraphicsResize(int width,int height);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=HandleSprite">Online Help</a>
-*/
-void HandleSprite(Sprite* sprite,float h_x,float h_y);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=HideEntity">Online Help</a>
-*/
-void HideEntity(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LightColor">Online Help</a>
-*/
-void LightColor(Light* light,float red,float green,float blue);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LightConeAngles">Online Help</a>
-*/
-void LightConeAngles(Light* light,float inner_ang,float outer_ang);
-
-/*
-
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LightRange">Online Help</a>
-*/
-void LightRange(Light* light,float range);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LinePick">Online Help</a>
-*/
-Entity* LinePick(float x,float y,float z,float dx,float dy,float dz,float radius);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadAnimMesh">Online Help</a>
-*/
-Mesh* LoadAnimMesh(char* file,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadAnimTexture">Online Help</a>
-*/
-Texture* LoadAnimTexture(char* file,int flags,int frame_width,int frame_height,int first_frame,int frame_count);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadBrush">Online Help</a>
-*/
-Brush* LoadBrush(char *file,int flags,float u_scale,float v_scale);
-
-Terrain* LoadGeosphere(char* file,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadMesh">Online Help</a>
-*/
-Mesh* LoadMesh(char* file,Entity* parent);
-
-
-Terrain* LoadTerrain(char* file,Entity* parent);
-
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadTexture">Online Help</a>
-*/
-Texture* LoadTexture(char* file,int flags);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadSprite">Online Help</a>
-*/
-Sprite* LoadSprite(char* tex_file,int tex_flag,Entity* parent);
-
-/*
-*/
-Mesh* MeshCSG(Mesh* m1, Mesh* m2, int method = 1);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MeshDepth">Online Help</a>
-*/
-float MeshDepth(Mesh* mesh);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MeshesIntersect">Online Help</a>
-*/
-int MeshesIntersect(Mesh* mesh1,Mesh* mesh2);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MeshHeight">Online Help</a>
-*/
-float MeshHeight(Mesh* mesh);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MeshWidth">Online Help</a>
-*/
-float MeshWidth(Mesh* mesh);
-
-void ModifyGeosphere(Geosphere* geo, int x, int z, float new_height);
-
-void ModifyTerrain(Terrain* terr, int x, int z, float new_height);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MoveEntity">Online Help</a>
-*/
-void MoveEntity(Entity* ent,float x,float y,float z);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=NameEntity">Online Help</a>
-*/
-void NameEntity(Entity* ent,char* name);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PaintEntity">Online Help</a>
-*/
-void PaintEntity(Entity* ent,Brush* brush);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PaintMesh">Online Help</a>
-*/
-void PaintMesh(Mesh* mesh,Brush* brush);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PaintSurface">Online Help</a>
-*/
-void PaintSurface(Surface* surf,Brush* brush);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedEntity">Online Help</a>
-*/
-Entity* PickedEntity();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedNX">Online Help</a>
-*/
-float PickedNX();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedNY">Online Help</a>
-*/
-float PickedNY();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedNZ">Online Help</a>
-*/
-float PickedNZ();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedSurface">Online Help</a>
-*/
-Surface* PickedSurface();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedTime">Online Help</a>
-*/
-float PickedTime();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedTriangle">Online Help</a>
-*/
-int PickedTriangle();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedX">Online Help</a>
-*/
-float PickedX();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedY">Online Help</a>
-*/
-float PickedY();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedZ">Online Help</a>
-*/
-float PickedZ();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PointEntity">Online Help</a>
-*/
-void PointEntity(Entity* ent,Entity* target_ent,float roll);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PositionEntity">Online Help</a>
-*/
-void PositionEntity(Entity* ent,float x,float y,float z,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PositionMesh">Online Help</a>
-*/
-void PositionMesh(Mesh* mesh,float px,float py,float pz);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PositionTexture">Online Help</a>
-*/
-void PositionTexture(Texture* tex,float u_pos,float v_pos);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ProjectedX">Online Help</a>
-*/
-float ProjectedX();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ProjectedY">Online Help</a>
-*/
-float ProjectedY();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ProjectedZ">Online Help</a>
-*/
-float ProjectedZ();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RenderWorld">Online Help</a>
-*/
-void RenderWorld();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RepeatMesh">Online Help</a>
-*/
-Mesh* RepeatMesh(Mesh* mesh,Entity* parent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ResetEntity">Online Help</a>
-*/
-void ResetEntity(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RotateEntity">Online Help</a>
-*/
-void RotateEntity(Entity* ent,float x,float y,float z,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RotateMesh">Online Help</a>
-*/
-void RotateMesh(Mesh* mesh,float pitch,float yaw,float roll);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RotateSprite">Online Help</a>
-*/
-void RotateSprite(Sprite* sprite,float ang);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RotateTexture">Online Help</a>
-*/
-void RotateTexture(Texture* tex,float ang);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ScaleEntity">Online Help</a>
-*/
-void ScaleEntity(Entity* ent,float x,float y,float z,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ScaleMesh">Online Help</a>
-*/
-void ScaleMesh(Mesh* mesh,float sx,float sy,float sz);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ScaleSprite">Online Help</a>
-*/
-void ScaleSprite(Sprite* sprite,float s_x,float s_y);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ScaleTexture">Online Help</a>
-*/
-void ScaleTexture(Texture* tex,float u_scale,float v_scale);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SetAnimTime">Online Help</a>
-*/
-void SetAnimTime(Entity* ent,float time,int seq);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SetCubeFace">Online Help</a>
-*/
-void SetCubeFace(Texture* tex,int face);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SetCubeMode">Online Help</a>
-*/
-void SetCubeMode(Texture* tex,int mode);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ShowEntity">Online Help</a>
-*/
-void ShowEntity(Entity* ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SpriteViewMode">Online Help</a>
-*/
-void SpriteViewMode(Sprite* sprite,int mode);
-
-/*
-*/
-void StencilAlpha(Stencil* stencil, float a);
-
-/*
-*/
-void StencilClsColor(Stencil* stencil, float r,float g,float b);
-
-/*
-*/
-void StencilClsMode(Stencil* stencil,int cls_depth,int cls_zbuffer);
-
-/*
-*/
-void StencilMesh(Stencil* stencil, Mesh* mesh, int mode=1);
-
-/*
-*/
-void StencilMode(Stencil* stencil, int m, int o=1);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TerrainHeight">Online Help</a>
-*/
-float TerrainHeight (Terrain* terr, int x, int z);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TerrainX">Online Help</a>
-*/
-float TerrainX (Terrain* terr, float x, float y, float z);
-
-/*
-
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TerrainY">Online Help</a>
-*/
-float TerrainY (Terrain* terr, float x, float y, float z);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TerrainZ">Online Help</a>
-*/
-float TerrainZ (Terrain* terr, float x, float y, float z);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureBlend">Online Help</a>
-*/
-void TextureBlend(Texture* tex,int blend);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureCoords">Online Help</a>
-*/
-void TextureCoords(Texture* tex,int coords);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureHeight">Online Help</a>
-*/
-int TextureHeight(Texture* tex);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureFilter">Online Help</a>
-*/
-void TextureFilter(char* match_text,int flags);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureName">Online Help</a>
-*/
-const char* TextureName(Texture* tex);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureWidth">Online Help</a>
-*/
-int TextureWidth(Texture* tex);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormedX">Online Help</a>
-*/
-float TFormedX();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormedY">Online Help</a>
-*/
-float TFormedY();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormedZ">Online Help</a>
-*/
-float TFormedZ();
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormNormal">Online Help</a>
-*/
-void TFormNormal(float x,float y,float z,Entity* src_ent,Entity* dest_ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormPoint">Online Help</a>
-*/
-void TFormPoint(float x,float y,float z,Entity* src_ent,Entity* dest_ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormVector">Online Help</a>
-*/
-void TFormVector(float x,float y,float z,Entity* src_ent,Entity* dest_ent);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TranslateEntity">Online Help</a>
-*/
-void TranslateEntity(Entity* ent,float x,float y,float z,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TriangleVertex">Online Help</a>
-*/
-int TriangleVertex(Surface* surf,int tri_no,int corner);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TurnEntity">Online Help</a>
-*/
-void TurnEntity(Entity* ent,float x,float y,float z,bool glob);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=UpdateNormals">Online Help</a>
-*/
-void UpdateNormals(Mesh* mesh);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=UpdateNormals">Online Help</a>
-*/
-void UpdateTexCoords(Surface* surf);
-
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=UpdateWorld">Online Help</a>
-*/
-void UpdateWorld(float anim_speed);
-
-/*
-*/
-void UseStencil(Stencil* stencil);
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VectorPitch">Online Help</a>
-*/
-float VectorPitch(float vx,float vy,float vz);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VectorYaw">Online Help</a>
-*/
-float VectorYaw(float vx,float vy,float vz);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexAlpha">Online Help</a>
-*/
-float VertexAlpha(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexBlue">Online Help</a>
-*/
-float VertexBlue(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexColor">Online Help</a>
-*/
-void VertexColor(Surface* surf,int vid,float r,float g,float b,float a);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexCoords">Online Help</a>
-*/
-void VertexCoords(Surface* surf,int vid,float x,float y,float z);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexGreen">Online Help</a>
-*/
-float VertexGreen(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexNormal">Online Help</a>
-*/
-void VertexNormal(Surface* surf,int vid,float nx,float ny,float nz);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexNX">Online Help</a>
-*/
-float VertexNX(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexNY">Online Help</a>
-*/
-float VertexNY(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexNZ">Online Help</a>
-*/
-float VertexNZ(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexRed">Online Help</a>
-*/
-float VertexRed(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexTexCoords">Online Help</a>
-*/
-void VertexTexCoords(Surface* surf,int vid,float u,float v,float w,int coord_set);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexU">Online Help</a>
-*/
-float VertexU(Surface* surf,int vid,int coord_set);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexV">Online Help</a>
-*/
-float VertexV(Surface* surf,int vid,int coord_set);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexW">Online Help</a>
-*/
-float VertexW(Surface* surf,int vid,int coord_set);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexX">Online Help</a>
-*/
-float VertexX(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexY">Online Help</a>
-*/
-float VertexY(Surface* surf,int vid);
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexZ">Online Help</a>
-*/
-float VertexZ(Surface* surf,int vid);
-
-/*
-*/
-void VoxelSpriteMaterial(VoxelSprite* voxelspr, Material* mat);
-
-
-/*
-bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Wireframe">Online Help</a>
-*/
-void Wireframe(int enable);
-
-
-float EntityScaleX(Entity* ent,bool glob);
-
-float EntityScaleY(Entity* ent,bool glob);
-
-float EntityScaleZ(Entity* ent,bool glob);
-
-Shader* LoadShader(char* ShaderName, char* VshaderFileName, char* FshaderFileName);
-
-Shader* CreateShader(char* ShaderName, char* VshaderString, char* FshaderString);
-
-void ShadeSurface(Surface* surf, Shader* material);
-
-void ShadeMesh(Mesh* mesh, Shader* material);
-
-void ShadeEntity(Entity* ent, Shader* material);
-
-void ShaderTexture(Shader* material, Texture* tex, char* name, int index);
-
-void SetFloat(Shader* material, char* name, float v1);
-
-void SetFloat2(Shader* material, char* name, float v1, float v2);
-
-void SetFloat3(Shader* material, char* name, float v1, float v2, float v3);
-
-void SetFloat4(Shader* material, char* name, float v1, float v2, float v3, float v4);
-
-void UseFloat(Shader* material, char* name, float* v1);
-
-void UseFloat2(Shader* material, char* name, float* v1, float* v2);
-
-void UseFloat3(Shader* material, char* name, float* v1, float* v2, float* v3);
-
-void UseFloat4(Shader* material, char* name, float* v1, float* v2, float* v3, float* v4);
-
-void SetInteger(Shader* material, char* name, int v1);
-
-void SetInteger2(Shader* material, char* name, int v1, int v2):
-
-void SetInteger3(Shader* material, char* name, int v1, int v2, int v3);
-
-void SetInteger4(Shader* material, char* name, int v1, int v2, int v3, int v4);
-
-void UseInteger(Shader* material, char* name, int* v1);
-
-void UseInteger2(Shader* material, char* name, int* v1, int* v2);
-
-void UseInteger3(Shader* material, char* name, int* v1, int* v2, int* v3);
-
-void UseInteger4(Shader* material, char* name, int* v1, int* v2, int* v3, int* v4);
-
-void UseSurface(Shader* material, char* name, Surface* surf, int vbo);
-
-void UseMatrix(Shader* material, char* name, int mode);
-
-Material* LoadMaterial(char* filename,int flags, int frame_width,int frame_height,int first_frame,int frame_count);
-
-void ShaderMaterial(Shader* material, Material* tex, char* name, int index);
-
-
-
-
-
-
-OcTree* CreateOcTree(float w, float h, float d, Entity* parent_ent=0);
-
-void AddToOctree(OcTree* octree, Mesh* mesh, int level, float X, float Y, float Z, float Near=0.0, float Far=1000.0);
-
-
-} // extern "C"
-
-#endif
+#ifndef __functions_h__
+#define __functions_h__
+
+// functions
+extern "C" {
+
+void BufferToTex(Texture* tex,unsigned char* buffer, int frame);
+void BackBufferToTex(Texture* tex,int frame);
+void TexToBuffer(Texture* tex,unsigned char* buffer, int frame);
+
+
+/*
+bbdoc: Minib3d Only
+about:
+This command is the equivalent of Blitz3D's MeshCullBox command.
+
+It is used to set the radius of a mesh's 'cull sphere' - if the 'cull sphere' is not inside the viewing area, the mesh will not
+be rendered.
+
+A mesh's cull radius is set automatically, therefore in most cases you will not have to use this command.
+
+One time you may have to use it is for animated meshes where the default cull radius may not take into account all animation
+positions, resulting in the mesh being wrongly culled at extreme positions.
+*/
+void MeshCullRadius(Entity* ent, float radius);
+// Blitz3D functions, A-Z
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AddAnimSeq">Online Help</a>
+*/
+int AddAnimSeq(Entity* ent,int length);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AddMesh">Online Help</a>
+*/
+void AddMesh(Mesh* mesh1,Mesh* mesh2);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AddTriangle">Online Help</a>
+*/
+int AddTriangle(Surface* surf,int v0,int v1,int v2);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AddVertex">Online Help</a>
+*/
+int AddVertex(Surface* surf,float x, float y,float z,float u, float v,float w);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AmbientLight">Online Help</a>
+*/
+void AmbientLight(float r,float g,float b);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AntiAlias">Online Help</a>
+*/
+void AntiAlias(int samples);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Animate">Online Help</a>
+*/
+void Animate(Entity* ent,int mode,float speed,int seq,int trans);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Animating">Online Help</a>
+*/
+int Animating(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AnimLength">Online Help</a>
+*/
+int AnimLength(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AnimSeq">Online Help</a>
+*/
+int AnimSeq(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=AnimTime">Online Help</a>
+*/
+float AnimTime(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushAlpha">Online Help</a>
+*/
+void BrushAlpha(Brush* brush, float a);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushBlend">Online Help</a>
+*/
+void BrushBlend(Brush* brush,int blend);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushColor">Online Help</a>
+*/
+void BrushColor(Brush* brush,float r,float g,float b);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushFX">Online Help</a>
+*/
+void BrushFX(Brush* brush,int fx);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushShininess">Online Help</a>
+*/
+void BrushShininess(Brush* brush,float s);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=BrushTexture">Online Help</a>
+*/
+void BrushTexture(Brush* brush,Texture* tex,int frame,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraClsColor">Online Help</a>
+*/
+void CameraClsColor(Camera* cam, float r,float g,float b);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraClsMode">Online Help</a>
+*/
+void CameraClsMode(Camera* cam,int cls_depth,int cls_zbuffer);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraFogColor">Online Help</a>
+*/
+void CameraFogColor(Camera* cam,float r,float g,float b);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraFogMode">Online Help</a>
+*/
+void CameraFogMode(Camera* cam,int mode);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraFogRange">Online Help</a>
+*/
+void CameraFogRange(Camera* cam,float nnear,float nfar);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraPick">Online Help</a>
+*/
+Entity* CameraPick(Camera* cam,float x,float y);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraProject">Online Help</a>
+*/
+void CameraProject(Camera* cam,float x,float y,float z);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraProjMode">Online Help</a>
+*/
+void  CameraProjMode(Camera* cam,int mode);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraRange">Online Help</a>
+*/
+void  CameraRange(Camera* cam,float nnear,float nfar);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraViewport">Online Help</a>
+*/
+void  CameraViewport(Camera* cam,int x,int y,int width,int height);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CameraZoom">Online Help</a>
+*/
+void  CameraZoom(Camera* cam,float zoom);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ClearCollisions">Online Help</a>
+int ClearCollisions(){
+	Global::ClearCollisions();
+}
+*/
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ClearSurface">Online Help</a>
+*/
+void ClearSurface(Surface* surf,bool clear_verts,bool clear_tris);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ClearTextureFilters">Online Help</a>
+*/
+void ClearTextureFilters();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ClearWorld">Online Help</a>
+*/
+void ClearWorld(bool entities,bool brushes,bool textures);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionEntity">Online Help</a>
+*/
+Entity* CollisionEntity(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Collisions">Online Help</a>
+*/
+void Collisions(int src_no,int dest_no,int method_no,int response_no);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionNX">Online Help</a>
+*/
+float CollisionNX(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionNY">Online Help</a>
+*/
+float CollisionNY(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionNZ">Online Help</a>
+*/
+float CollisionNZ(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionSurface">Online Help</a>
+*/
+Surface* CollisionSurface(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionTime">Online Help</a>
+*/
+float CollisionTime(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionTriangle">Online Help</a>
+*/
+int CollisionTriangle(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionX">Online Help</a>
+*/
+float CollisionX(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionY">Online Help</a>
+*/
+float CollisionY(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CollisionZ">Online Help</a>
+*/
+float CollisionZ(Entity* ent,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountChildren">Online Help</a>
+*/
+int CountChildren(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountCollisions">Online Help</a>
+*/
+int CountCollisions(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CopyEntity">Online Help</a>
+*/
+Entity* CopyEntity(Entity* ent,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CopyMesh">Online Help</a>
+*/
+Mesh* CopyMesh(Mesh* mesh,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountSurfaces">Online Help</a>
+*/
+int CountSurfaces(Mesh* mesh);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountTriangles">Online Help</a>
+*/
+int CountTriangles(Surface* surf);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CountVertices">Online Help</a>
+*/
+int CountVertices(Surface* surf);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateBrush">Online Help</a>
+*/
+Brush* CreateBrush(float r,float g,float b);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateCamera">Online Help</a>
+*/
+Camera* CreateCamera(Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateCone">Online Help</a>
+*/
+Mesh* CreateCone(int segments,bool solid,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateCylinder">Online Help</a>
+*/
+Mesh* CreateCylinder(int segments,bool solid,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateCube">Online Help</a>
+*/
+Mesh* CreateCube(Entity* parent);
+
+Terrain* CreateGeosphere(int size, Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateMesh">Online Help</a>
+*/
+Mesh* CreateMesh(Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateLight">Online Help</a>
+*/
+Light* CreateLight(int light_type,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreatePivot">Online Help</a>
+*/
+Pivot* CreatePivot(Entity* parent);
+
+Mesh* CreatePlane(int divisions,Entity* parent);
+
+Mesh* CreateQuad(Entity* parent);
+
+ShadowObject* CreateShadow(Mesh* parent, char Static);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateSphere">Online Help</a>
+*/
+Mesh* CreateSphere(int segments,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateSprite">Online Help</a>
+*/
+Sprite* CreateSprite(Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateSurface">Online Help</a>
+*/
+Surface* CreateSurface(Mesh* mesh,Brush* brush);
+
+/*
+*/
+Stencil* CreateStencil();
+
+/*
+*/
+Terrain* CreateTerrain(int size, Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=CreateTexture">Online Help</a>
+*/
+Texture* CreateTexture(int width,int height,int flags,int frames);
+
+/*
+*/
+VoxelSprite* CreateVoxelSprite(int slices, Entity* parent);
+
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=DeltaPitch">Online Help</a>
+*/
+float DeltaPitch(Entity* ent1,Entity* ent2);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=DeltaYaw">Online Help</a>
+*/
+float DeltaYaw(Entity* ent1,Entity* ent2);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityAlpha">Online Help</a>
+*/
+void EntityAlpha(Entity* ent,float alpha);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityAutoFade">Online Help</a>
+*/
+void EntityAutoFade(Entity* ent,float near,float far);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityBlend">Online Help</a>
+*/
+void EntityBlend(Entity* ent, int blend);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityBox">Online Help</a>
+*/
+void EntityBox(Entity* ent,float x,float y,float z,float w,float h,float d);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityClass">Online Help</a>
+*/
+const char* EntityClass(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityCollided">Online Help</a>
+*/
+Entity* EntityCollided(Entity* ent,int type_no);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityColor">Online Help</a>
+*/
+void EntityColor(Entity* ent,float red,float green,float blue);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityDistance">Online Help</a>
+*/
+float EntityDistance(Entity* ent1,Entity* ent2);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityFX">Online Help</a>
+*/
+void EntityFX(Entity* ent,int fx);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityInView">Online Help</a>
+*/
+int EntityInView(Entity* ent,Camera* cam);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityName">Online Help</a>
+*/
+const char* EntityName(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityOrder">Online Help</a>
+*/
+void EntityOrder(Entity* ent,int order);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityParent">Online Help</a>
+
+
+
+
+*/
+void EntityParent(Entity* ent,Entity* parent_ent,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityPick">Online Help</a>
+*/
+Entity* EntityPick(Entity* ent,float range);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityPickMode">Online Help</a>
+*/
+void EntityPickMode(Entity* ent,int pick_mode,bool obscurer);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityPitch">Online Help</a>
+*/
+float EntityPitch(Entity* ent,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityRadius">Online Help</a>
+*/
+void EntityRadius(Entity* ent,float radius_x,float radius_y);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityRoll">Online Help</a>
+*/
+float EntityRoll(Entity* ent,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityShininess">Online Help</a>
+*/
+void EntityShininess(Entity* ent,float shine);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityTexture">Online Help</a>
+*/
+void EntityTexture(Entity* ent,Texture* tex,int frame,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityType">Online Help</a>
+*/
+void EntityType(Entity* ent,int type_no,bool recursive);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityVisible">Online Help</a>
+*/
+int EntityVisible(Entity* src_ent,Entity* dest_ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityX">Online Help</a>
+*/
+float EntityX(Entity* ent,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityY">Online Help</a>
+*/
+float EntityY(Entity* ent,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityYaw">Online Help</a>
+*/
+float EntityYaw(Entity* ent,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=EntityZ">Online Help</a>
+*/
+float EntityZ(Entity* ent,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ExtractAnimSeq">Online Help</a>
+*/
+int ExtractAnimSeq(Entity* ent,int first_frame,int last_frame,int seq);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FindChild">Online Help</a>
+*/
+Entity* FindChild(Entity* ent,char* child_name);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FindSurface">Online Help</a>
+*/
+Surface* FindSurface(Mesh* mesh,Brush* brush);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FitMesh">Online Help</a><p>
+*/
+void FitMesh(Mesh* mesh,float x,float y,float z,float width,float height,float depth,bool uniform);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FlipMesh">Online Help</a>
+*/
+void FlipMesh(Mesh* mesh);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FreeBrush">Online Help</a>
+*/
+void  FreeBrush(Brush* brush);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FreeEntity">Online Help</a>
+*/
+void FreeEntity(Entity* ent);
+
+void FreeShadow(ShadowObject* shad);
+
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=FreeTexture">Online Help</a>
+*/
+void FreeTexture(Texture* tex);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetBrushTexture">Online Help</a>
+*/
+Texture* GetBrushTexture(Brush* brush,int index);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetChild">Online Help</a>
+*/
+Entity* GetChild(Entity* ent,int child_no);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetEntityBrush">Online Help</a>
+*/
+Brush* GetEntityBrush(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetEntityType">Online Help</a>
+*/
+int GetEntityType(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ResetEntity">Online Help</a>
+*/
+float GetMatElement(Entity* ent,int row,int col);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetParent">Online Help</a>
+*/
+Entity* GetParentEntity(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetSurface">Online Help</a>
+*/
+Surface* GetSurface(Mesh* mesh,int surf_no);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=GetSurfaceBrush">Online Help</a>
+*/
+Brush* GetSurfaceBrush(Surface* surf);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Graphics3D">Online Help</a>
+*/
+void Graphics3D(int width,int height,int depth,int mode,int rate);
+
+/*
+*/
+void GraphicsResize(int width,int height);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=HandleSprite">Online Help</a>
+*/
+void HandleSprite(Sprite* sprite,float h_x,float h_y);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=HideEntity">Online Help</a>
+*/
+void HideEntity(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LightColor">Online Help</a>
+*/
+void LightColor(Light* light,float red,float green,float blue);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LightConeAngles">Online Help</a>
+*/
+void LightConeAngles(Light* light,float inner_ang,float outer_ang);
+
+/*
+
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LightRange">Online Help</a>
+*/
+void LightRange(Light* light,float range);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LinePick">Online Help</a>
+*/
+Entity* LinePick(float x,float y,float z,float dx,float dy,float dz,float radius);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadAnimMesh">Online Help</a>
+*/
+Mesh* LoadAnimMesh(char* file,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadAnimTexture">Online Help</a>
+*/
+Texture* LoadAnimTexture(char* file,int flags,int frame_width,int frame_height,int first_frame,int frame_count);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadBrush">Online Help</a>
+*/
+Brush* LoadBrush(char *file,int flags,float u_scale,float v_scale);
+
+Terrain* LoadGeosphere(char* file,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadMesh">Online Help</a>
+*/
+Mesh* LoadMesh(char* file,Entity* parent);
+
+
+Terrain* LoadTerrain(char* file,Entity* parent);
+
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadTexture">Online Help</a>
+*/
+Texture* LoadTexture(char* file,int flags);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=LoadSprite">Online Help</a>
+*/
+Sprite* LoadSprite(char* tex_file,int tex_flag,Entity* parent);
+
+/*
+*/
+Mesh* MeshCSG(Mesh* m1, Mesh* m2, int method = 1);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MeshDepth">Online Help</a>
+*/
+float MeshDepth(Mesh* mesh);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MeshesIntersect">Online Help</a>
+*/
+int MeshesIntersect(Mesh* mesh1,Mesh* mesh2);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MeshHeight">Online Help</a>
+*/
+float MeshHeight(Mesh* mesh);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MeshWidth">Online Help</a>
+*/
+float MeshWidth(Mesh* mesh);
+
+void ModifyGeosphere(Geosphere* geo, int x, int z, float new_height);
+
+void ModifyTerrain(Terrain* terr, int x, int z, float new_height);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=MoveEntity">Online Help</a>
+*/
+void MoveEntity(Entity* ent,float x,float y,float z);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=NameEntity">Online Help</a>
+*/
+void NameEntity(Entity* ent,char* name);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PaintEntity">Online Help</a>
+*/
+void PaintEntity(Entity* ent,Brush* brush);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PaintMesh">Online Help</a>
+*/
+void PaintMesh(Mesh* mesh,Brush* brush);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PaintSurface">Online Help</a>
+*/
+void PaintSurface(Surface* surf,Brush* brush);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedEntity">Online Help</a>
+*/
+Entity* PickedEntity();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedNX">Online Help</a>
+*/
+float PickedNX();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedNY">Online Help</a>
+*/
+float PickedNY();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedNZ">Online Help</a>
+*/
+float PickedNZ();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedSurface">Online Help</a>
+*/
+Surface* PickedSurface();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedTime">Online Help</a>
+*/
+float PickedTime();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedTriangle">Online Help</a>
+*/
+int PickedTriangle();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedX">Online Help</a>
+*/
+float PickedX();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedY">Online Help</a>
+*/
+float PickedY();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PickedZ">Online Help</a>
+*/
+float PickedZ();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PointEntity">Online Help</a>
+*/
+void PointEntity(Entity* ent,Entity* target_ent,float roll);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PositionEntity">Online Help</a>
+*/
+void PositionEntity(Entity* ent,float x,float y,float z,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PositionMesh">Online Help</a>
+*/
+void PositionMesh(Mesh* mesh,float px,float py,float pz);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=PositionTexture">Online Help</a>
+*/
+void PositionTexture(Texture* tex,float u_pos,float v_pos);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ProjectedX">Online Help</a>
+*/
+float ProjectedX();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ProjectedY">Online Help</a>
+*/
+float ProjectedY();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ProjectedZ">Online Help</a>
+*/
+float ProjectedZ();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RenderWorld">Online Help</a>
+*/
+void RenderWorld();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RepeatMesh">Online Help</a>
+*/
+Mesh* RepeatMesh(Mesh* mesh,Entity* parent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ResetEntity">Online Help</a>
+*/
+void ResetEntity(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RotateEntity">Online Help</a>
+*/
+void RotateEntity(Entity* ent,float x,float y,float z,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RotateMesh">Online Help</a>
+*/
+void RotateMesh(Mesh* mesh,float pitch,float yaw,float roll);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RotateSprite">Online Help</a>
+*/
+void RotateSprite(Sprite* sprite,float ang);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=RotateTexture">Online Help</a>
+*/
+void RotateTexture(Texture* tex,float ang);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ScaleEntity">Online Help</a>
+*/
+void ScaleEntity(Entity* ent,float x,float y,float z,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ScaleMesh">Online Help</a>
+*/
+void ScaleMesh(Mesh* mesh,float sx,float sy,float sz);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ScaleSprite">Online Help</a>
+*/
+void ScaleSprite(Sprite* sprite,float s_x,float s_y);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ScaleTexture">Online Help</a>
+*/
+void ScaleTexture(Texture* tex,float u_scale,float v_scale);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SetAnimTime">Online Help</a>
+*/
+void SetAnimTime(Entity* ent,float time,int seq);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SetCubeFace">Online Help</a>
+*/
+void SetCubeFace(Texture* tex,int face);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SetCubeMode">Online Help</a>
+*/
+void SetCubeMode(Texture* tex,int mode);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=ShowEntity">Online Help</a>
+*/
+void ShowEntity(Entity* ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=SpriteViewMode">Online Help</a>
+*/
+void SpriteViewMode(Sprite* sprite,int mode);
+
+/*
+*/
+void StencilAlpha(Stencil* stencil, float a);
+
+/*
+*/
+void StencilClsColor(Stencil* stencil, float r,float g,float b);
+
+/*
+*/
+void StencilClsMode(Stencil* stencil,int cls_depth,int cls_zbuffer);
+
+/*
+*/
+void StencilMesh(Stencil* stencil, Mesh* mesh, int mode=1);
+
+/*
+*/
+void StencilMode(Stencil* stencil, int m, int o=1);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TerrainHeight">Online Help</a>
+*/
+float TerrainHeight (Terrain* terr, int x, int z);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TerrainX">Online Help</a>
+*/
+float TerrainX (Terrain* terr, float x, float y, float z);
+
+/*
+
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TerrainY">Online Help</a>
+*/
+float TerrainY (Terrain* terr, float x, float y, float z);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TerrainZ">Online Help</a>
+*/
+float TerrainZ (Terrain* terr, float x, float y, float z);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureBlend">Online Help</a>
+*/
+void TextureBlend(Texture* tex,int blend);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureCoords">Online Help</a>
+*/
+void TextureCoords(Texture* tex,int coords);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureHeight">Online Help</a>
+*/
+int TextureHeight(Texture* tex);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureFilter">Online Help</a>
+*/
+void TextureFilter(char* match_text,int flags);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureName">Online Help</a>
+*/
+const char* TextureName(Texture* tex);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TextureWidth">Online Help</a>
+*/
+int TextureWidth(Texture* tex);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormedX">Online Help</a>
+*/
+float TFormedX();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormedY">Online Help</a>
+*/
+float TFormedY();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormedZ">Online Help</a>
+*/
+float TFormedZ();
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormNormal">Online Help</a>
+*/
+void TFormNormal(float x,float y,float z,Entity* src_ent,Entity* dest_ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormPoint">Online Help</a>
+*/
+void TFormPoint(float x,float y,float z,Entity* src_ent,Entity* dest_ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TFormVector">Online Help</a>
+*/
+void TFormVector(float x,float y,float z,Entity* src_ent,Entity* dest_ent);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TranslateEntity">Online Help</a>
+*/
+void TranslateEntity(Entity* ent,float x,float y,float z,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TriangleVertex">Online Help</a>
+*/
+int TriangleVertex(Surface* surf,int tri_no,int corner);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=TurnEntity">Online Help</a>
+*/
+void TurnEntity(Entity* ent,float x,float y,float z,bool glob);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=UpdateNormals">Online Help</a>
+*/
+void UpdateNormals(Mesh* mesh);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=UpdateNormals">Online Help</a>
+*/
+void UpdateTexCoords(Surface* surf);
+
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=UpdateWorld">Online Help</a>
+*/
+void UpdateWorld(float anim_speed);
+
+/*
+*/
+void UseStencil(Stencil* stencil);
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VectorPitch">Online Help</a>
+*/
+float VectorPitch(float vx,float vy,float vz);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VectorYaw">Online Help</a>
+*/
+float VectorYaw(float vx,float vy,float vz);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexAlpha">Online Help</a>
+*/
+float VertexAlpha(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexBlue">Online Help</a>
+*/
+float VertexBlue(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexColor">Online Help</a>
+*/
+void VertexColor(Surface* surf,int vid,float r,float g,float b,float a);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexCoords">Online Help</a>
+*/
+void VertexCoords(Surface* surf,int vid,float x,float y,float z);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexGreen">Online Help</a>
+*/
+float VertexGreen(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexNormal">Online Help</a>
+*/
+void VertexNormal(Surface* surf,int vid,float nx,float ny,float nz);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexNX">Online Help</a>
+*/
+float VertexNX(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexNY">Online Help</a>
+*/
+float VertexNY(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexNZ">Online Help</a>
+*/
+float VertexNZ(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexRed">Online Help</a>
+*/
+float VertexRed(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexTexCoords">Online Help</a>
+*/
+void VertexTexCoords(Surface* surf,int vid,float u,float v,float w,int coord_set);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexU">Online Help</a>
+*/
+float VertexU(Surface* surf,int vid,int coord_set);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexV">Online Help</a>
+*/
+float VertexV(Surface* surf,int vid,int coord_set);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexW">Online Help</a>
+*/
+float VertexW(Surface* surf,int vid,int coord_set);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexX">Online Help</a>
+*/
+float VertexX(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexY">Online Help</a>
+*/
+float VertexY(Surface* surf,int vid);
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=VertexZ">Online Help</a>
+*/
+float VertexZ(Surface* surf,int vid);
+
+/*
+*/
+void VoxelSpriteMaterial(VoxelSprite* voxelspr, Material* mat);
+
+
+/*
+bbdoc: <a href="http://www.blitzbasic.com/b3ddocs/command.php?name=Wireframe">Online Help</a>
+*/
+void Wireframe(int enable);
+
+
+float EntityScaleX(Entity* ent,bool glob);
+
+float EntityScaleY(Entity* ent,bool glob);
+
+float EntityScaleZ(Entity* ent,bool glob);
+
+Shader* LoadShader(char* ShaderName, char* VshaderFileName, char* FshaderFileName);
+
+Shader* CreateShader(char* ShaderName, char* VshaderString, char* FshaderString);
+
+void ShadeSurface(Surface* surf, Shader* material);
+
+void ShadeMesh(Mesh* mesh, Shader* material);
+
+void ShadeEntity(Entity* ent, Shader* material);
+
+void ShaderTexture(Shader* material, Texture* tex, char* name, int index);
+
+void SetFloat(Shader* material, char* name, float v1);
+
+void SetFloat2(Shader* material, char* name, float v1, float v2);
+
+void SetFloat3(Shader* material, char* name, float v1, float v2, float v3);
+
+void SetFloat4(Shader* material, char* name, float v1, float v2, float v3, float v4);
+
+void UseFloat(Shader* material, char* name, float* v1);
+
+void UseFloat2(Shader* material, char* name, float* v1, float* v2);
+
+void UseFloat3(Shader* material, char* name, float* v1, float* v2, float* v3);
+
+void UseFloat4(Shader* material, char* name, float* v1, float* v2, float* v3, float* v4);
+
+void SetInteger(Shader* material, char* name, int v1);
+
+void SetInteger2(Shader* material, char* name, int v1, int v2):
+
+void SetInteger3(Shader* material, char* name, int v1, int v2, int v3);
+
+void SetInteger4(Shader* material, char* name, int v1, int v2, int v3, int v4);
+
+void UseInteger(Shader* material, char* name, int* v1);
+
+void UseInteger2(Shader* material, char* name, int* v1, int* v2);
+
+void UseInteger3(Shader* material, char* name, int* v1, int* v2, int* v3);
+
+void UseInteger4(Shader* material, char* name, int* v1, int* v2, int* v3, int* v4);
+
+void UseSurface(Shader* material, char* name, Surface* surf, int vbo);
+
+void UseMatrix(Shader* material, char* name, int mode);
+
+Material* LoadMaterial(char* filename,int flags, int frame_width,int frame_height,int first_frame,int frame_count);
+
+void ShaderMaterial(Shader* material, Material* tex, char* name, int index);
+
+
+
+
+
+
+OcTree* CreateOcTree(float w, float h, float d, Entity* parent_ent=0);
+
+void AddToOctree(OcTree* octree, Mesh* mesh, int level, float X, float Y, float Z, float Near=0.0, float Far=1000.0);
+
+
+} // extern "C"
+
+#endif

+ 1364 - 1253
openb3dlib.mod/openb3d/src/geosphere.cpp

@@ -1,1253 +1,1364 @@
-/*
- *  geosphere.cpp
- *  openb3d
- *
- *
- */
-
-#include "glew.h"
-
-/*
-#ifdef linux
-#define GL_GLEXT_PROTOTYPES
-#include <GL/gl.h>
-#include <GL/glext.h>
-#endif
-#ifdef WIN32
-#include "GLee.h"
-#endif
-#ifdef __APPLE__
-#include "GLee.h"
-#endif
-*/
-
-
-#include "global.h"
-#include "entity.h"
-#include "camera.h"
-#include "brush.h"
-#include "geosphere.h"
-#include "pick.h"
-
-
-#include "stb_image.h"
-#include "string_helper.h"
-#include "file.h"
-#include "tree.h"
-
-
-static Line Ray;
-static float radius;
-
-
-Terrain* Geosphere::CopyEntity(Entity* parent_ent){
-
-	// new terr
-	Geosphere* geo=new Geosphere;
-
-	// copy contents of child list before adding parent
-	list<Entity*>::iterator it;
-	for(it=child_list.begin();it!=child_list.end();it++){
-		Entity* ent=*it;
-		ent->CopyEntity(geo);
-	}
-
-	// lists
-
-	// add parent, add to list
-	geo->AddParent(*parent_ent);
-	entity_list.push_back(geo);
-
-	// add to collision entity list
-	if(collision_type!=0){
-		CollisionPair::ent_lists[collision_type].push_back(geo);
-	}
-
-	// add to pick entity list
-	if(pick_mode){
-		Pick::ent_list.push_back(geo);
-	}
-
-	// update matrix
-	if(geo->parent){
-		geo->mat.Overwrite(geo->parent->mat);
-	}else{
-		geo->mat.LoadIdentity();
-	}
-
-	// copy entity info
-
-	geo->mat.Multiply(mat);
-
-	geo->px=px;
-	geo->py=py;
-	geo->pz=pz;
-	geo->sx=sx;
-	geo->sy=sy;
-	geo->sz=sz;
-	geo->rx=rx;
-	geo->ry=ry;
-	geo->rz=rz;
-	geo->qw=qw;
-	geo->qx=qx;
-	geo->qy=qy;
-	geo->qz=qz;
-
-	geo->name=name;
-	geo->class_name=class_name;
-	geo->order=order;
-	geo->hide=false;
-
-	geo->cull_radius=cull_radius;
-	geo->radius_x=radius_x;
-	geo->radius_y=radius_y;
-	geo->box_x=box_x;
-	geo->box_y=box_y;
-	geo->box_z=box_z;
-	geo->box_w=box_w;
-	geo->box_h=box_h;
-	geo->box_d=box_d;
-	geo->pick_mode=pick_mode;
-	geo->obscurer=obscurer;
-
-	//copy terrain info
-	geo->brush=brush;
-
-	geo->ShaderMat=ShaderMat;
-	//geo->EqToToast=0;
-
-
-	geo->size=size;
-	geo->vsize=vsize;
-	geo->hsize=hsize;
-	for (int i = 0; i<= ROAM_LMAX+1; i++){
-		geo->level2dzsize[i] = level2dzsize[i];
-	}
-	int tsize=size;
-	geo->height=new float[(tsize+1)*(tsize+1)];
-	for (int i = 0; i<= (tsize+1)*(tsize+1); i++){
-		geo->height[i]=height[i];
-	}
-	geo->NormalsMap=new float[(tsize+1)*(tsize+1)*5];
-	for (int i = 0; i<= (tsize+1)*(tsize+1)*5; i++){
-		geo->NormalsMap[i]=NormalsMap[i];
-	}
-
-	mesh_info=C_NewMeshInfo();
-	geo->c_col_tree=C_CreateColTree(mesh_info);
-	C_DeleteMeshInfo(mesh_info);
-
-	terrain_list.push_back(geo);
-
-
-	return geo;
-
-}
-
-Geosphere* Geosphere::CreateGeosphere(int tsize, Entity* parent_ent){
-
-	Geosphere* geo=new Geosphere;
-
-	for (int i = 0; i<= ROAM_LMAX; i++){
-		geo->level2dzsize[i] = 0;
-	}
-        int lmax=(int)(log(tsize)/log(2)-3.0);
-	if (lmax>=ROAM_LMAX) lmax=ROAM_LMAX;
-
-
-	const float LOD[20]={1700000,800000,40000,10000,5000,1000,200,10,1,0.1,0.005,
-	0.001,0.0005,0.0002,0.0001,0.00005,0.00002,0.00001,0.000005,0.000002};
-
-	for (int i = 0; i<= lmax; i++){
-		geo->level2dzsize[i] = tsize*LOD[i];/*1000000000.0*(float)pow((float)tsize/8192 / sqrt((float)(1 << i)),2);	// <-------------terrain detail here*/
-	}
-
-	geo->ShaderMat=0;
-	//geo->EqToToast=0;
-
-	//terr->brush=new brush;
-	mesh_info=C_NewMeshInfo();
-	geo->c_col_tree=C_CreateColTree(mesh_info);
-	C_DeleteMeshInfo(mesh_info);
-	geo->AddParent(*parent_ent);
-	terrain_list.push_back(geo);
-	if (tsize!=0){
-		geo->size=tsize;
-		geo->hsize=tsize/2;
-
-		geo->vsize=.05;
-		geo->height=new float[(tsize+1)*(tsize+1)];
-		geo->NormalsMap=new float[(tsize+1)*(tsize+1)*5];
-
-	}
-
-	return geo;
-
-}
-
-void Geosphere::UpdateTerrain(){
-
-	int fog=false;
-	if (glIsEnabled(GL_FOG)==GL_TRUE) fog=true; // if fog enabled, we'll enable it again at end of each surf loop in case of fx flag disabling it
-
-	glDisable(GL_ALPHA_TEST);
-
-	if (order!=0){
-		glDisable(GL_DEPTH_TEST);
-		glDepthMask(GL_FALSE);
-	}else{
-		glEnable(GL_DEPTH_TEST);
-		glDepthMask(GL_TRUE);
-	}
-
-	switch(brush.blend){
-		case 0:
-			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // alpha
-			break;
-		case 1:
-			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // alpha
-			break;
-		case 2:
-			glBlendFunc(GL_DST_COLOR,GL_ZERO); // multiply
-			break;
-		case 3:
-			glBlendFunc(GL_SRC_ALPHA,GL_ONE); // additive and alpha
-			break;
-		}
-
-	float ambient_red,ambient_green,ambient_blue;
-
-	// fx flag 1 - full bright ***todo*** disable all lights?
-	if (brush.fx & 1){
-		ambient_red  =1.0;
-		ambient_green=1.0;
-		ambient_blue =1.0;
-	}else{
-		ambient_red  =Global::ambient_red;
-		ambient_green=Global::ambient_green;
-		ambient_blue =Global::ambient_blue;
-	}
-
-	// fx flag 2 - vertex colours
-	if(brush.fx&2){
-			glEnable(GL_COLOR_MATERIAL);
-	}else{
-			glDisable(GL_COLOR_MATERIAL);
-	}
-
-	// fx flag 4 - flatshaded
-	if(brush.fx&4){
-		glShadeModel(GL_FLAT);
-	}else{
-		glShadeModel(GL_SMOOTH);
-	}
-
-	// fx flag 8 - disable fog
-	if(brush.fx&8){
-			glDisable(GL_FOG);
-	}
-
-	// fx flag 16 - disable backface culling
-	if(brush.fx&16){
-		glDisable(GL_CULL_FACE);
-	}else{
-		glEnable(GL_CULL_FACE);
-	}
-
-	// light + material color
-
-	float ambient[]={ambient_red,ambient_green,ambient_blue};
-	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient);
-
-	float mat_ambient[]={brush.red,brush.green,brush.blue,brush.alpha};
-	float mat_diffuse[]={brush.red,brush.green,brush.blue,brush.alpha};
-	float mat_specular[]={brush.shine,brush.shine,brush.shine,brush.shine};
-	float mat_shininess[]={100.0}; // upto 128
-
-	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,mat_ambient);
-	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse);
-	glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
-	glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,mat_shininess);
-
-	// textures
-
-	int tex_count=0;
-
-	if(ShaderMat!=NULL){
-		ShaderMat->TurnOn(0, mat);
-	}
-
-	tex_count=brush.no_texs;
-
-	int DisableCubeSphereMapping=0;
-	for(int ix=0;ix<tex_count;ix++){
-
-		if(brush.tex[ix]){
-
-			// Main brush texture takes precedent over surface brush texture
-			unsigned int texture=0;
-			int tex_flags=0,tex_blend=0,tex_coords=0;
-			float tex_u_scale=1.0,tex_v_scale=1.0,tex_u_pos=0.0,tex_v_pos=0.0,tex_ang=0.0;
-			int tex_cube_mode=0;
-
-
-			texture=brush.cache_frame[ix];
-			tex_flags=brush.tex[ix]->flags;
-			tex_blend=brush.tex[ix]->blend;
-			tex_coords=brush.tex[ix]->coords;
-			tex_u_scale=brush.tex[ix]->u_scale;
-			tex_v_scale=brush.tex[ix]->v_scale;
-			tex_u_pos=brush.tex[ix]->u_pos;
-			tex_v_pos=brush.tex[ix]->v_pos;
-			tex_ang=brush.tex[ix]->angle;
-			tex_cube_mode=brush.tex[ix]->cube_mode;
-			//frame=brush.tex_frame;
-
-			glActiveTexture(GL_TEXTURE0+ix);
-			glClientActiveTexture(GL_TEXTURE0+ix);
-
-			glEnable(GL_TEXTURE_2D);
-			glBindTexture(GL_TEXTURE_2D,texture); // call before glTexParameteri
-
-			// masked texture flag
-			if(tex_flags&4){
-				glEnable(GL_ALPHA_TEST);
-			}else{
-				glDisable(GL_ALPHA_TEST);
-			}
-
-			// mipmapping texture flag
-			if(tex_flags&8){
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
-			}else{
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-			}
-
-			// clamp u flag
-			if(tex_flags&16){
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
-			}else{
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
-			}
-
-			// clamp v flag
-			if(tex_flags&32){
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
-			}else{
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
-			}
-
-				// ***!ES***
-
-			// spherical environment map texture flag
-			if(tex_flags&64){
-				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
-				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
-				glEnable(GL_TEXTURE_GEN_S);
-				glEnable(GL_TEXTURE_GEN_T);
-				DisableCubeSphereMapping=1;
-			}/*else{
-				glDisable(GL_TEXTURE_GEN_S);
-				glDisable(GL_TEXTURE_GEN_T);
-			}*/
-
-				// cubic environment map texture flag
-				if(tex_flags&128){
-
-					glEnable(GL_TEXTURE_CUBE_MAP);
-					glBindTexture(GL_TEXTURE_CUBE_MAP,texture); // call before glTexParameteri
-
-					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
-					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
-					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
-					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
-					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
-
-					glEnable(GL_TEXTURE_GEN_S);
-					glEnable(GL_TEXTURE_GEN_T);
-					glEnable(GL_TEXTURE_GEN_R);
-					//glEnable(GL_TEXTURE_GEN_Q)
-
-					if(tex_cube_mode==1){
-						glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
-						glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
-						glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
-					}
-
-					if(tex_cube_mode==2){
-						glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
-						glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
-						glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
-					}
-					DisableCubeSphereMapping=1;
-
-				}else  if (DisableCubeSphereMapping!=0){
-
-					glDisable(GL_TEXTURE_CUBE_MAP);
-
-					// only disable tex gen s and t if sphere mapping isn't using them
-					if((tex_flags & 64)==0){
-						glDisable(GL_TEXTURE_GEN_S);
-						glDisable(GL_TEXTURE_GEN_T);
-					}
-
-					glDisable(GL_TEXTURE_GEN_R);
-					//glDisable(GL_TEXTURE_GEN_Q)
-
-				}
-
-
-			switch(tex_blend){
-				case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
-				break;
-				case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
-				break;
-				case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-				//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
-				break;
-				case 3: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_ADD);
-				break;
-				case 4:
-					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
-					glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGB_EXT);
-					break;
-				case 5:
-					glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
-					glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
-					glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE,2.0);
-					break;
-				default: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-			}
-
-
-			// reset texture matrix
-			glMatrixMode(GL_TEXTURE);
-			glLoadIdentity();
-
-			if(tex_u_pos!=0.0 || tex_v_pos!=0.0){
-				glTranslatef(tex_u_pos,tex_v_pos,0.0);
-			}
-			if(tex_ang!=0.0){
-				glRotatef(tex_ang,0.0,0.0,1.0);
-			}
-			if(tex_u_scale!=1.0 || tex_v_scale!=1.0){
-				glScalef(tex_u_scale,tex_v_scale,1.0);
-			}
-
-			// ***!ES***
-			// if spheremap flag=true then flip tex
-			if(tex_flags&64){
-				glScalef(1.0,-1.0,-1.0);
-			}
-
-			// if cubemap flag=true then manipulate texture matrix so that cubemap is displayed properly
-			if(tex_flags&128){
-
-				glScalef(1.0,-1.0,-1.0);
-
-				// get current modelview matrix (set in last camera update)
-				float mod_mat[16];
-				glGetFloatv(GL_MODELVIEW_MATRIX,&mod_mat[0]);
-
-				// get rotational inverse of current modelview matrix
-				Matrix new_mat;
-				new_mat.LoadIdentity();
-
-				new_mat.grid[0][0] = mod_mat[0];
-				new_mat.grid[1][0] = mod_mat[1];
-				new_mat.grid[2][0] = mod_mat[2];
-
-				new_mat.grid[0][1] = mod_mat[4];
-				new_mat.grid[1][1] = mod_mat[5];
-				new_mat.grid[2][1] = mod_mat[6];
-
-				new_mat.grid[0][2] = mod_mat[8];
-				new_mat.grid[1][2] = mod_mat[9];
-				new_mat.grid[2][2] = mod_mat[10];
-
-				glMultMatrixf(&new_mat.grid[0][0]);
-
-			}
-
-
-		}
-
-	}
-
-	// draw tris
-	glMatrixMode(GL_MODELVIEW);
-
-	glPushMatrix();
-	glMultMatrixf(&mat.grid[0][0]);
-	RecreateGeoROAM();
-	glPopMatrix();
-
-	// disable all texture layers
-	for(int ix=0;ix<tex_count;ix++){
-
-		glActiveTexture(GL_TEXTURE0+ix);
-		glClientActiveTexture(GL_TEXTURE0+ix);
-
-		// reset texture matrix
-		glMatrixMode(GL_TEXTURE);
-		glLoadIdentity();
-
-		glDisable(GL_TEXTURE_2D);
-
-		// ***!ES***
-		if (DisableCubeSphereMapping!=0){
-			glDisable(GL_TEXTURE_CUBE_MAP);
-			glDisable(GL_TEXTURE_GEN_S);
-			glDisable(GL_TEXTURE_GEN_T);
-			glDisable(GL_TEXTURE_GEN_R);
-			DisableCubeSphereMapping=0;
-		}
-
-	}
-
-	if (fog==true){
-		glEnable(GL_FOG);
-	}
-
-	if(ShaderMat!=NULL){
-		ShaderMat->TurnOff();
-	}
-
-}
-
-void Geosphere::RecreateGeoROAM(){
-
-	/*xcf = eyepoint->EntityX();
-	ycf = eyepoint->EntityY();
-	zcf = -eyepoint->EntityZ();*/
-
-	TFormPoint(eyepoint->EntityX(true), eyepoint->EntityY(true), eyepoint->EntityZ(true), 0, this);
-	xcf = tformed_x;
-	ycf = tformed_y;
-	zcf = -tformed_z;
-
-	//int i;
-
-	float h1= (height[(int)hsize*(int)size+ (int)hsize]*vsize+1)*size;
-	float h2= (height[(int) size*(int)size+ (int)hsize]*vsize+1)*size;
-	float h3= (height[(int)hsize*(int)size+ (int) size]*vsize+1)*size;
-	float h4=-(height[(int)    0*(int)size+ (int)hsize]*vsize+1)*size;
-	float h5=-(height[(int)hsize*(int)size]*vsize+1)*size;
-	float h6=-(height[0]*vsize+1)*size;
-
-
-	float v[9][5]={
-	{ 0,  h1,  0, hsize, hsize},
-
-	{ h2,  0,  0, size, hsize},
-	{ 0,  0,  h3, hsize, size},
-	{ h4,  0,  0, 0, hsize},
-	{ 0,  0,  h5, hsize, 0},
-
-	{ 0,  h6,  0, size, size},
-	{ 0,  h6,  0, 0, size},
-	{ 0,  h6,  0, 0, 0},
-	{ 0,  h6,  0, size, 0}};
-
-
-
-	// diamond radius - apply entity scale
-	float rx=EntityScaleX(true);
-	float ry=EntityScaleY(true);
-	float rz=EntityScaleZ(true);
-	if(rx>=ry && rx>=rz){
-		dradius=abs(rx);
-	}else if(ry>=rx && ry>=rz){
-		dradius=abs(ry);
-	}else{
-		dradius=abs(rz);
-	}
-
-
-	tmat = MQ_GetMatrix(true);
-
-
-	triangleindex = 0;
-
-	glBegin(GL_TRIANGLES);
-
-	geosub( 0, v[0], v[1], v[2]);
-	geosub( 0, v[0], v[2], v[3]);
-	geosub( 0, v[0], v[3], v[4]);
-	geosub( 0, v[0], v[4], v[1]);
-
-	geosub( 0, v[2], v[1], v[5]);
-	geosub( 0, v[3], v[2], v[6]);
-	geosub( 0, v[4], v[3], v[7]);
-	geosub( 0, v[1], v[4], v[8]);
-
-
-
-	glEnd();
-
-	delete tmat;
-
-
-}
-
-void Geosphere::geosub(int l, float v2[], float v1[], float v0[]){
-
-	float vc[3][5];	/* New (split) vertices */
-	float ds;	/* maximum midpoint displacement */
-	float dx,dy,dz;	/* difference vector */
-	float rd;	/* squared sphere bound radius */
-	float rc;	/* squared distance from vc To camera position */
-
-	if (l < ROAM_LMAX) {
-		ds = level2dzsize[l];
-
-		/* compute radius of diamond bounding sphere (squared) */
-		float x,y,z;
-		x = (v0[0] + v1[0] + v2[0]) / 3;
-		y = (v0[1] + v1[1] + v2[1]) / 3;
-		z = (v0[2] + v1[2] + v2[2]) / 3;
-		rd = 0.0;
-		dx = v0[0] - x;
-		dy = v0[1] - y;
-		dz = v0[2] - z;
-		rc = dx * dx + dy * dy + dz * dz;
-		if (rc > rd) {rd = rc;}
-		dx = v1[0] - x;
-		dy = v1[1] - y;
-		dz = v1[2] - z;
-		rc = dx * dx + dy * dy + dz * dz;
-		if (rc > rd) {rd = rc;}
-		dx = v2[0] - x;
-		dy = v2[1] - y;
-		dz = v2[2] - z;
-		rc = dx * dx + dy * dy + dz * dz;
-		if (rc > rd) {rd = rc;}
-		rd = sqrt(rd)*dradius;
-
-
-		float vcx=x;
-		float vcy=y;
-		float vcz=-z;
-		tmat->TransformVec(vcx, vcy, vcz, 1);
-
-		for (int i = 0 ;i<= 5; i++){
-			float d = eyepoint->frustum[i][0] * vcx + eyepoint->frustum[i][1] * vcy - eyepoint->frustum[i][2] * vcz + eyepoint->frustum[i][3];
-			if (d <= -rd) return;//{ds=ds/10; break;}
-			//m = m << 1;
-		}
-
-		/* compute distance from split point To camera (squared) */
-		dx = x - xcf;
-		dy = y - ycf;
-		dz = z - zcf;
-		rc = dx*dx+dy*dy+dz*dz;
-
-		/* If not error large on screen, recursively split */
-		if (ds > rc) {/*<---------terrain detail here*/
-
-			l++;
-			float nx, ny, nz, d, h;
-
-			nx=(v0[0]+v1[0])/2;
-			ny=(v0[1]+v1[1])/2;
-			nz=(v0[2]+v1[2])/2;
-
-			dx = nx - xcf;
-			dy = ny - ycf;
-			dz = nz - zcf;
-			rc = dx*dx+dy*dy+dz*dz+size*size/l/l*11.973;
-
-
-			vc[0][3]=(v0[3]+v1[3])/2; vc[0][4]=(v0[4]+v1[4])/2;
-			h=height[(int)vc[0][3]*(int)size+ (int)vc[0][4]]*vsize+1;
-			if (ds > rc) {
-				d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
-			}else{
-				d=1;
-			}
-			vc[0][0]=nx/d; vc[0][1]=ny/d; vc[0][2]=nz/d; 
-
-
-			nx=(v1[0]+v2[0])/2;
-			ny=(v1[1]+v2[1])/2;
-			nz=(v1[2]+v2[2])/2;
-
-			dx = nx - xcf;
-			dy = ny - ycf;
-			dz = nz - zcf;
-			rc = dx*dx+dy*dy+dz*dz+size*size/l/l*11.973;
-
-			vc[1][3]=(v1[3]+v2[3])/2; vc[1][4]=(v1[4]+v2[4])/2;
-			h=height[(int)vc[1][3]*(int)size+ (int)vc[1][4]]*vsize+1;
-			if (ds > rc) {
-				d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
-			}else{
-				d=1;
-			}
-			vc[1][0]=nx/d; vc[1][1]=ny/d; vc[1][2]=nz/d; 
-
-
-			nx=(v2[0]+v0[0])/2;
-			ny=(v2[1]+v0[1])/2;
-			nz=(v2[2]+v0[2])/2;
-
-			dx = nx - xcf;
-			dy = ny - ycf;
-			dz = nz - zcf;
-			rc = dx*dx+dy*dy+dz*dz+size*size/l/l*11.973;
-
-			vc[2][3]=(v2[3]+v0[3])/2; vc[2][4]=(v2[4]+v0[4])/2;
-			h=height[(int)vc[2][3]*(int)size+ (int)vc[2][4]]*vsize+1;
-			if (ds > rc) {
-				d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
-			}else{
-				d=1;
-			}
-			vc[2][0]=nx/d; vc[2][1]=ny/d; vc[2][2]=nz/d; 
-
-			geosub(l, v0, vc[2], vc[0]);
-			geosub(l, v1, vc[0], vc[1]);
-			geosub(l, v2, vc[1], vc[2]);
-			geosub(l, vc[2], vc[1], vc[0]);
-
-			return;
-		}
-
-	 }
-
-	float *n0, *n1, *n2;
-
-	n0=&NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])];
-	n1=&NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])];
-	n2=&NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])];
-
-	//uv[0]=0.5f * ( 1.0f + ArcTan0); uv[1]= acos( v0[1] ) * ( 1 / M_PI ); uv[2]=0;
-	glMultiTexCoord2fv(GL_TEXTURE0, &n0[3]);
-	glMultiTexCoord2fv(GL_TEXTURE1, &n0[3]);
-	glNormal3fv(&n0[0]);
-	glVertex3fv(&v0[0]);
-
-	//uv[0]=0.5f * ( 1.0f + ArcTan1); uv[1]= acos( v1[1] ) * ( 1 / M_PI ); uv[2]=0;
-	glMultiTexCoord2fv(GL_TEXTURE0, &n1[3]);
-	glMultiTexCoord2fv(GL_TEXTURE1, &n1[3]);
-	glNormal3fv(&n1[0]);
-	glVertex3fv(&v1[0]);
-
-	//uv[0]=0.5f * ( 1.0f + ArcTan2); uv[1]= acos( v2[1] ) * ( 1 / M_PI ); uv[2]=0;
-	glMultiTexCoord2fv(GL_TEXTURE0, &n2[3]);
-	glMultiTexCoord2fv(GL_TEXTURE1, &n2[3]);
-	glNormal3fv(&n2[0]);
-	glVertex3fv(&v2[0]);
-}
-
-
-void Geosphere::TOASTsub(int l, float v2[], float v1[], float v0[]){
-
-	float vc[3][5];	/* New (split) vertices */
-
-	if (l > 0) {
-		l--;
-		float nx, ny, nz, d;
-
-		nx=(v0[0]+v1[0])/2;
-		ny=(v0[1]+v1[1])/2;
-		nz=(v0[2]+v1[2])/2;
-
-		vc[0][3]=(v0[3]+v1[3])/2; vc[0][4]=(v0[4]+v1[4])/2;
-		d=sqrt(nx*nx+ny*ny+nz*nz);
-		vc[0][0]=nx/d; vc[0][1]=ny/d; vc[0][2]=nz/d; 
-
-
-		nx=(v1[0]+v2[0])/2;
-		ny=(v1[1]+v2[1])/2;
-		nz=(v1[2]+v2[2])/2;
-
-		vc[1][3]=(v1[3]+v2[3])/2; vc[1][4]=(v1[4]+v2[4])/2;
-		d=sqrt(nx*nx+ny*ny+nz*nz);
-		vc[1][0]=nx/d; vc[1][1]=ny/d; vc[1][2]=nz/d; 
-
-
-		nx=(v2[0]+v0[0])/2;
-		ny=(v2[1]+v0[1])/2;
-		nz=(v2[2]+v0[2])/2;
-
-		vc[2][3]=(v2[3]+v0[3])/2; vc[2][4]=(v2[4]+v0[4])/2;
-		d=sqrt(nx*nx+ny*ny+nz*nz);
-		vc[2][0]=nx/d; vc[2][1]=ny/d; vc[2][2]=nz/d; 
-
-		TOASTsub(l, v0, vc[2], vc[0]);
-		TOASTsub(l, v1, vc[0], vc[1]);
-		TOASTsub(l, v2, vc[1], vc[2]);
-		TOASTsub(l, vc[2], vc[1], vc[0]);
-
-		return;
-	}
-
-	float ax,ay,az,bx,by,bz;
-	float nx,ny,nz,ns;
-	float h0,h1,h2;
-
-	h0=height[(int)v0[3]*(int)size+ (int)v0[4]]*vsize+1;
-	h1=height[(int)v1[3]*(int)size+ (int)v1[4]]*vsize+1;
-	h2=height[(int)v2[3]*(int)size+ (int)v2[4]]*vsize+1;
-
-	ax = h1*v1[0]-h0*v0[0];
-	ay = h1*v1[1]-h0*v0[1];
-	az = h1*v1[2]-h0*v0[2];
-	bx = h2*v2[0]-h1*v1[0];
-	by = h2*v2[1]-h1*v1[1];
-	bz = h2*v2[2]-h1*v1[2];
-	nx = ( ay * bz ) - ( az * by );
-	ny = ( az * bx ) - ( ax * bz );
-	nz = ( ax * by ) - ( ay * bx );
-	ns = sqrt( nx * nx + ny*ny + nz*nz );
-	if (ns != 0) ns = 1;
-	nx /= ns;
-	ny /= ns;
-	nz /= ns;
-	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])]=nx;
-	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])+1]=ny;
-	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])+2]=nz;
-
-	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])]=nx;
-	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])+1]=ny;
-	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])+2]=nz;
-
-	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])]=nx;
-	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])+1]=ny;
-	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])+2]=nz;
-
-
-	float u,v;
-	u=0.5f * (-1.0 +atan2( v0[2] , v0[0] ) * (-1 / M_PI ));
-	v=acos( v0[1] ) * ( 1 / M_PI );
-	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])+3]=u*size;
-	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])+4]=v*size;
-
-	u=0.5f * (-1.0 +atan2( v1[2] , v1[0] ) * (-1 / M_PI ));
-	v=acos( v1[1] ) * ( 1 / M_PI );
-	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])+3]=u*size;
-	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])+4]=v*size;
-
-	u=0.5f * (-1.0 +atan2( v2[2] , v2[0] ) * (-1 / M_PI ));
-	v=acos( v2[1] ) * ( 1 / M_PI );
-	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])+3]=u*size;
-	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])+4]=v*size;
-
-}
-
-
-
-void Geosphere::ModifyGeosphere (int x, int y, float new_height){
-	/*int width=size*2;		//Most accurate approach: it wastes a lot of memory
-	if (EqToToast==0){	//First time: must create a look-up map to convert equirectangular coords to TOAST coords
-		EqToToast=new int[(int)(size+1)*width];
-		for (int y=0;y<size;y++){
-			for (int x=0;x<size;x++){
-				int x1=-NormalsMap[5*(x*(int)size+ y)+3]*2;
-				int y1=NormalsMap[5*(x*(int)size+ y)+4];
-
-				//geo->height[x*(int)geo->size+y]=((float)*(buffer+x1+y1*width))/255.0;
-				if (x1+y1*width<0) {
-					x1=0; y1=0;
-				}
-				EqToToast[x1+y1*width]=x*(int)size+y;
-			}
-		}
-	}
-
-	height[EqToToast[x+y*width]]=new_height;*/
-
-
-	//Less accurate approach: some lines might be distorted, but for little changes on a map should be good enough
-
-	float r=sqrt((x % (int)hsize)*(x % (int)hsize)+(hsize-(x % (int)hsize))*(hsize-(x % (int)hsize)))/hsize;
-
-
-	if (x<hsize){
-		if (y<=hsize){
-
-			r=(r*(hsize-y)+1*y)/hsize;
-			y=y/r;
-
-			x=x* y/hsize;
-			y=y-x;
-		}else{
-			r=(r*(y-hsize)+1*(2*hsize-y))/hsize;
-			y=2*hsize-(2*hsize-y)/r;
-
-			x=y-(x*(y-2*hsize)/hsize)-hsize;
-			y=y-x;
-		}
-	}else if (x<hsize*2){
-		x=hsize*2-x;
-		if (y<=hsize){
-
-			r=(r*(hsize-y)+1*y)/hsize;
-			y=y/r;
-
-			x=x* y/hsize;
-			y=x-y;
-		}else{
-
-			r=(r*(y-hsize)+1*(2*hsize-y))/hsize;
-			y=2*hsize-(2*hsize-y)/r;
-
-
-			x=y-(x*(y-2*hsize)/hsize)-hsize;
-			y=x-y;
-		}
-	}else if (x<hsize*3){
-		x=x-hsize*2;
-		if (y<=hsize){
-
-			r=(r*(hsize-y)+1*y)/hsize;
-			y=y/r;
-
-			x=-x* y/hsize;
-			y=-y-x;
-		}else{
-			r=(r*(y-hsize)+1*(2*hsize-y))/hsize;
-			y=2*hsize-(2*hsize-y)/r;
-
-			x=(x*(y-2*hsize)/hsize)+hsize-y;
-			y=-y-x;
-		}
-	}else{
-		x=hsize*4-x;
-		if (y<=hsize) {
-
-			r=(r*(hsize-y)+1*y)/hsize;
-			y=y/r;
-
-			x=-x* y/hsize;
-			y=x+y;
-		}else{
-			r=(r*(y-hsize)+1*(2*hsize-y))/hsize;
-			y=2*hsize-(2*hsize-y)/r;
-
-			x=(x*(y-2*hsize)/hsize)+hsize-y;
-			y=x+y;
-		}
-	
-	}
-	x+=hsize;
-	y+=hsize;
-	height[x+y*(int)size]=new_height;
-}
-
-void Geosphere::EquirectangularToTOAST (){
-	/*for (int x=0; x<size*2; x++){
-		for (int y=0; y<size; y++){
-			int x1=x, y1=y;
-			EquirectangularToTOAST (x1, y1);
-
-			NormalsMap[5*(x1*(int)size+ y1)+3]=x/2;
-			NormalsMap[5*(x1*(int)size+ y1)+4]=y;
-		}
-	}*/
-	float v[9][5]={
-	{ 0,  1,  0, hsize, hsize},
-	{ 1,  0,  0, size, hsize},
-	{ 0,  0,  1, hsize, size},
-	{-1,  0,  0, 0, hsize},
-	{ 0,  0, -1, hsize, 0},
-
-	{ 0, -1,  0, size, size},
-	{ 0, -1,  0, 0, size},
-	{ 0, -1,  0, 0, 0},
-	{ 0, -1,  0, size, 0}};
-
-	int l=(int)(log(hsize)/log(2));
-
-	TOASTsub( l, v[0], v[1], v[2]);
-	TOASTsub( l, v[0], v[2], v[3]);
-	TOASTsub( l, v[0], v[3], v[4]);
-	TOASTsub( l, v[0], v[4], v[1]);
-
-	TOASTsub( l, v[2], v[1], v[5]);
-	TOASTsub( l, v[3], v[2], v[6]);
-	TOASTsub( l, v[4], v[3], v[7]);
-	TOASTsub( l, v[1], v[4], v[8]);
-
-}
-
-Geosphere* Geosphere::LoadGeosphere(string filename,Entity* parent_ent){
-	//filename=Strip(filename); // get rid of path info
-
-	if(File::ResourceFilePath(filename)==""){
-		cout << "Error: Cannot Find Terrain: " << filename << endl;
-		return NULL;
-	}
-
-	string filename_left=Left(filename,Len(filename)-4);
-	string filename_right=Right(filename,3);
-
-	//const char* c_filename_left=filename_left.c_str();
-	//const char* c_filename_right=filename_right.c_str();
-
-	Geosphere* geo;
-
-	unsigned char* pixels;
-
-	int width,height;
-
-	pixels=stbi_load(filename.c_str(),&width,&height,0,1);   //Memory leak fixed by D.J.Peters
-
-	// all OK ?
-	if (pixels!=NULL) {
-		// work with a copy of the pixel pointer
-		unsigned char* buffer=pixels;
-		geo=Geosphere::CreateGeosphere(width, parent_ent);
-
-		geo->size=height;
-		geo->hsize=height/2;
-		geo->EquirectangularToTOAST();
-
-		for (int y=0;y<geo->size;y++){
-			for (int x=0;x<geo->size;x++){
-				int x1=geo->NormalsMap[5*(x*(int)geo->size+ y)+3]*2;
-				int y1=geo->NormalsMap[5*(x*(int)geo->size+ y)+4];
-
-				if (x1+y1*width<0) {
-					x1=0; y1=0;
-				}
-
-				geo->height[x*(int)geo->size+y]=((float)*(buffer+x1+y1*width))/255.0;
-			}
-		}
-		stbi_image_free(pixels);
-		pixels=NULL;
-	} else {
-		// create a dummy terrain only as a dirty fallback
-		height =128;
-		geo=Geosphere::CreateGeosphere(256, parent_ent);
-		geo->size=height;
-		geo->hsize=height/2;
-		//geo->height=new float[(width+1)*(width+1)];
-		for (int x=0;x<=geo->size-1;x++){
-			for (int y=0;y<=geo->size-1;y++){
-				geo->height[x*(int)geo->size+y]=0.0f;
-			}
-		}
-	}
-
-
-	//geo->UpdateNormals();
-
-	return geo;
-}
-
-void Geosphere::TreeCheck(CollisionInfo* ci){
-	Ray=ci->coll_line;
-	radius=ci->radius;
-
-	TFormPoint(Ray.o.x, Ray.o.y, Ray.o.z, 0, this);
-	xcf = tformed_x;
-	ycf = tformed_y;
-	zcf = -tformed_z;
-
-
-	//int i;
-	float h1= (height[(int)hsize*(int)size+ (int)hsize]*vsize+1)*size;
-	float h2= (height[(int) size*(int)size+ (int)hsize]*vsize+1)*size;
-	float h3= (height[(int)hsize*(int)size+ (int) size]*vsize+1)*size;
-	float h4=-(height[(int)    0*(int)size+ (int)hsize]*vsize+1)*size;
-	float h5=-(height[(int)hsize*(int)size]*vsize+1)*size;
-	float h6=-(height[0]*vsize+1)*size;
-
-
-	float v[9][5]={
-	{ 0,  h1,  0, hsize, hsize},
-
-	{ h2,  0,  0, size, hsize},
-	{ 0,  0,  h3, hsize, size},
-	{ h4,  0,  0, 0, hsize},
-	{ 0,  0,  h5, hsize, 0},
-
-	{ 0,  h6,  0, size, size},
-	{ 0,  h6,  0, 0, size},
-	{ 0,  h6,  0, 0, 0},
-	{ 0,  h6,  0, size, 0}};
-
-
-	// diamond radius - apply entity scale
-	float rx=EntityScaleX(true);
-	float ry=EntityScaleY(true);
-	float rz=EntityScaleZ(true);
-	if(rx>=ry && rx>=rz){
-		dradius=abs(rx);
-	}else if(ry>=rx && ry>=rz){
-		dradius=abs(ry);
-	}else{
-		dradius=abs(rz);
-	}
-
-
-	tmat = MQ_GetMatrix(true);
-
-
-
-	if(c_col_tree!=NULL){
-		C_DeleteColTree(c_col_tree);
-		c_col_tree=NULL;
-	}
-
-	mesh_info=C_NewMeshInfo();
-	triangleindex = 0;
-
-
-	/* recurse on the two base triangles */
-	c_col_tree_geosub( 0, v[0], v[1], v[2]);
-	c_col_tree_geosub( 0, v[0], v[2], v[3]);
-	c_col_tree_geosub( 0, v[0], v[3], v[4]);
-	c_col_tree_geosub( 0, v[0], v[4], v[1]);
-
-	c_col_tree_geosub( 0, v[2], v[1], v[5]);
-	c_col_tree_geosub( 0, v[3], v[2], v[6]);
-	c_col_tree_geosub( 0, v[4], v[3], v[7]);
-	c_col_tree_geosub( 0, v[1], v[4], v[8]);
-
-	c_col_tree=C_CreateColTree(mesh_info);
-	C_DeleteMeshInfo(mesh_info);
-	delete tmat;
-
-
-
-}
-
-void Geosphere::c_col_tree_geosub(int l, float v2[], float v1[], float v0[]){
-
-	float vc[3][5];	/* New (split) vertices */
-	float ds;	/* maximum midpoint displacement */
-	float dx,dy,dz;	/* difference vector */
-	float rd;	/* squared sphere bound radius */
-	float rc;	/* squared distance from vc To camera position */
-
-	if (l < ROAM_LMAX) {
-		ds = level2dzsize[l];
-
-		/* compute radius of diamond bounding sphere (squared) */
-		float x,y,z;
-		x = (v0[0] + v1[0] + v2[0]) / 3;
-		y = (v0[1] + v1[1] + v2[1]) / 3;
-		z = (v0[2] + v1[2] + v2[2]) / 3;
-		rd = 0.0;
-		dx = v0[0] - x;
-		dy = v0[1] - y;
-		dz = v0[2] - z;
-		rc = dx * dx + dy * dy + dz * dz;
-		if (rc > rd) {rd = rc;}
-		dx = v1[0] - x;
-		dy = v1[1] - y;
-		dz = v1[2] - z;
-		rc = dx * dx + dy * dy + dz * dz;
-		if (rc > rd) {rd = rc;}
-		dx = v2[0] - x;
-		dy = v2[1] - y;
-		dz = v2[2] - z;
-		rc = dx * dx + dy * dy + dz * dz;
-		if (rc > rd) {rd = rc;}
-		rd = sqrt(rd)*dradius;
-
-
-		float vcx=x;
-		float vcy=y;
-		float vcz=-z;
-		tmat->TransformVec(vcx, vcy, vcz, 1);
-
-		/*Is triangle on the collision line?*/
-
-		Vector Sphere;
-		Sphere.x=vcx;
-		Sphere.y=vcy;
-		Sphere.z=vcz;
-		Line dst( Sphere-Ray.o,Ray.d );
-
-		float a=dst.d.dot(dst.d);
-		if( !a ) return;
-		float b=dst.o.dot(dst.d)*2;
-		float c=dst.o.dot(dst.o)-rd*rd;
-		float d=b*b-4*a*c;
-
-		if (d<0) return;
-
-
-		/* compute distance from split point To camera (squared) */
-		dx = x - xcf;
-		dy = y - ycf;
-		dz = z - zcf;
-		rc = dx*dx+dy*dy+dz*dz;
-
-		/* If not error large on screen, recursively split */
-		if (ds > rc) {/*<---------terrain detail here*/
-			l++;
-			float nx, ny, nz, d, h;
-
-			nx=(v0[0]+v1[0])/2;
-			ny=(v0[1]+v1[1])/2;
-			nz=(v0[2]+v1[2])/2;
-
-			vc[0][3]=(v0[3]+v1[3])/2; vc[0][4]=(v0[4]+v1[4])/2;
-			h=height[(int)vc[0][3]*(int)size+ (int)vc[0][4]]*vsize+1;
-			d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
-
-			vc[0][0]=nx/d; vc[0][1]=ny/d; vc[0][2]=nz/d; 
-
-
-			nx=(v1[0]+v2[0])/2;
-			ny=(v1[1]+v2[1])/2;
-			nz=(v1[2]+v2[2])/2;
-
-			vc[1][3]=(v1[3]+v2[3])/2; vc[1][4]=(v1[4]+v2[4])/2;
-			h=height[(int)vc[1][3]*(int)size+ (int)vc[1][4]]*vsize+1;
-			d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
-
-			vc[1][0]=nx/d; vc[1][1]=ny/d; vc[1][2]=nz/d; 
-
-
-			nx=(v2[0]+v0[0])/2;
-			ny=(v2[1]+v0[1])/2;
-			nz=(v2[2]+v0[2])/2;
-			vc[2][3]=(v2[3]+v0[3])/2; vc[2][4]=(v2[4]+v0[4])/2;
-			h=height[(int)vc[2][3]*(int)size+ (int)vc[2][4]]*vsize+1;
-			d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
-
-			vc[2][0]=nx/d; vc[2][1]=ny/d; vc[2][2]=nz/d; 
-
-			c_col_tree_geosub(l, v0, vc[2], vc[0]);
-			c_col_tree_geosub(l, v1, vc[0], vc[1]);
-			c_col_tree_geosub(l, v2, vc[1], vc[2]);
-			c_col_tree_geosub(l, vc[2], vc[1], vc[0]);
-
-			return;
-		}
-
-	 }
-
-	//add to collisiontree
-	C_AddVertex(mesh_info,v0[0],v0[1],-v0[2],0);
-	C_AddVertex(mesh_info,v1[0],v1[1],-v1[2],0);
-	C_AddVertex(mesh_info,v2[0],v2[1],-v2[2],0);
-	C_AddTriangle(mesh_info, triangleindex, triangleindex*3+2, triangleindex*3+1, triangleindex*3+0, 0);
-	triangleindex++;
-}
-
-void Geosphere::FreeEntity(){
-
-	delete[] height;
-	delete[] NormalsMap;		
-	//delete[] EqToToast;		
-
-	delete c_col_tree;
-
-	Entity::FreeEntity();
-
-	delete this;
-
-	return;
-
-}
-
+/*
+ *  geosphere.cpp
+ *  openb3d
+ *
+ *
+ */
+
+#include "glew.h"
+
+/*
+#ifdef linux
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+#endif
+#ifdef WIN32
+#include "GLee.h"
+#endif
+#ifdef __APPLE__
+#include "GLee.h"
+#endif
+*/
+
+
+#include "global.h"
+#include "entity.h"
+#include "camera.h"
+#include "brush.h"
+#include "geosphere.h"
+#include "pick.h"
+
+
+#include "stb_image.h"
+#include "string_helper.h"
+#include "file.h"
+#include "tree.h"
+
+
+static Line Ray;
+static float radius;
+
+static vector<float> vertices;
+
+
+Terrain* Geosphere::CopyEntity(Entity* parent_ent){
+
+	// new terr
+	Geosphere* geo=new Geosphere;
+
+	// copy contents of child list before adding parent
+	list<Entity*>::iterator it;
+	for(it=child_list.begin();it!=child_list.end();it++){
+		Entity* ent=*it;
+		ent->CopyEntity(geo);
+	}
+
+	// lists
+
+	// add parent, add to list
+	geo->AddParent(*parent_ent);
+	entity_list.push_back(geo);
+
+	// add to collision entity list
+	if(collision_type!=0){
+		CollisionPair::ent_lists[collision_type].push_back(geo);
+	}
+
+	// add to pick entity list
+	if(pick_mode){
+		Pick::ent_list.push_back(geo);
+	}
+
+	// update matrix
+	if(geo->parent){
+		geo->mat.Overwrite(geo->parent->mat);
+	}else{
+		geo->mat.LoadIdentity();
+	}
+
+	// copy entity info
+
+	geo->mat.Multiply(mat);
+
+	geo->px=px;
+	geo->py=py;
+	geo->pz=pz;
+	geo->sx=sx;
+	geo->sy=sy;
+	geo->sz=sz;
+	geo->rx=rx;
+	geo->ry=ry;
+	geo->rz=rz;
+	geo->qw=qw;
+	geo->qx=qx;
+	geo->qy=qy;
+	geo->qz=qz;
+
+	geo->name=name;
+	geo->class_name=class_name;
+	geo->order=order;
+	geo->hide=false;
+
+	geo->cull_radius=cull_radius;
+	geo->radius_x=radius_x;
+	geo->radius_y=radius_y;
+	geo->box_x=box_x;
+	geo->box_y=box_y;
+	geo->box_z=box_z;
+	geo->box_w=box_w;
+	geo->box_h=box_h;
+	geo->box_d=box_d;
+	geo->pick_mode=pick_mode;
+	geo->obscurer=obscurer;
+
+	//copy terrain info
+	geo->brush=brush;
+
+	geo->ShaderMat=ShaderMat;
+	//geo->EqToToast=0;
+
+
+	geo->size=size;
+	geo->vsize=vsize;
+	geo->hsize=hsize;
+	for (int i = 0; i<= ROAM_LMAX+1; i++){
+		geo->level2dzsize[i] = level2dzsize[i];
+	}
+	int tsize=size;
+	geo->height=new float[(tsize+1)*(tsize+1)];
+	for (int i = 0; i<= (tsize+1)*(tsize+1); i++){
+		geo->height[i]=height[i];
+	}
+	geo->NormalsMap=new float[(tsize+1)*(tsize+1)*5];
+	for (int i = 0; i<= (tsize+1)*(tsize+1)*5; i++){
+		geo->NormalsMap[i]=NormalsMap[i];
+	}
+
+	mesh_info=C_NewMeshInfo();
+	geo->c_col_tree=C_CreateColTree(mesh_info);
+	C_DeleteMeshInfo(mesh_info);
+
+	terrain_list.push_back(geo);
+
+
+	return geo;
+
+}
+
+Geosphere* Geosphere::CreateGeosphere(int tsize, Entity* parent_ent){
+
+	Geosphere* geo=new Geosphere;
+
+	for (int i = 0; i<= ROAM_LMAX; i++){
+		geo->level2dzsize[i] = 0;
+	}
+        int lmax=(int)(log(tsize)/log(2)-3.0);
+	if (lmax>=ROAM_LMAX) lmax=ROAM_LMAX;
+
+
+	const float LOD[20]={1700000,800000,40000,10000,5000,1000,200,10,1,0.1,0.005,
+	0.001,0.0005,0.0002,0.0001,0.00005,0.00002,0.00001,0.000005,0.000002};
+
+	for (int i = 0; i<= lmax; i++){
+		geo->level2dzsize[i] = tsize*LOD[i];/*1000000000.0*(float)pow((float)tsize/8192 / sqrt((float)(1 << i)),2);	// <-------------terrain detail here*/
+	}
+
+	geo->ShaderMat=0;
+	//geo->EqToToast=0;
+
+	//terr->brush=new brush;
+	mesh_info=C_NewMeshInfo();
+	geo->c_col_tree=C_CreateColTree(mesh_info);
+	C_DeleteMeshInfo(mesh_info);
+	geo->AddParent(*parent_ent);
+	terrain_list.push_back(geo);
+	if (tsize!=0){
+		geo->size=tsize;
+		geo->hsize=tsize/2;
+
+		geo->vsize=.05;
+		geo->height=new float[(tsize+1)*(tsize+1)];
+		geo->NormalsMap=new float[(tsize+1)*(tsize+1)*5];
+
+	}
+
+	return geo;
+
+}
+
+void Geosphere::UpdateTerrain(){
+
+	glBindBuffer(GL_ARRAY_BUFFER,0);
+
+	RecreateGeoROAM();
+
+	glDisable(GL_ALPHA_TEST);
+
+	if (order!=0){
+		glDisable(GL_DEPTH_TEST);
+		glDepthMask(GL_FALSE);
+	}else{
+		glEnable(GL_DEPTH_TEST);
+		glDepthMask(GL_TRUE);
+	}
+
+	switch(brush.blend){
+		case 0:
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // alpha
+			break;
+		case 1:
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // alpha
+			break;
+		case 2:
+			glBlendFunc(GL_DST_COLOR,GL_ZERO); // multiply
+			break;
+		case 3:
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE); // additive and alpha
+			break;
+		}
+
+	float ambient_red,ambient_green,ambient_blue;
+
+	// fx flag 1 - full bright ***todo*** disable all lights?
+	if (brush.fx & 1){
+		if(Global::fx1!=true){
+			Global::fx1=true;
+			glDisableClientState(GL_NORMAL_ARRAY);
+		}
+		ambient_red  =1.0;
+		ambient_green=1.0;
+		ambient_blue =1.0;
+	}else{
+		if(Global::fx1!=false){
+			Global::fx1=false;
+			glEnableClientState(GL_NORMAL_ARRAY);
+		}
+		ambient_red  =Global::ambient_red;
+		ambient_green=Global::ambient_green;
+		ambient_blue =Global::ambient_blue;
+	}
+
+	// fx flag 2 - vertex colours
+	/*if(brush.fx&2){
+
+			glEnable(GL_COLOR_MATERIAL);
+	}else{
+			glDisable(GL_COLOR_MATERIAL);
+	}*/
+	if(Global::fx2!=false){
+		Global::fx2=false;
+		glDisableClientState(GL_COLOR_ARRAY);
+		glDisable(GL_COLOR_MATERIAL);
+	}
+
+
+	// fx flag 4 - flatshaded
+	if(brush.fx&4){
+		glShadeModel(GL_FLAT);
+	}else{
+		glShadeModel(GL_SMOOTH);
+	}
+
+	// fx flag 8 - disable fog
+	if(brush.fx&8){
+		if(Global::fog_enabled==true){ // only disable if fog enabled in camera update
+			glDisable(GL_FOG);
+		}
+	}
+
+	// fx flag 16 - disable backface culling
+	if(brush.fx&16){
+		glDisable(GL_CULL_FACE);
+	}else{
+		glEnable(GL_CULL_FACE);
+	}
+
+	// light + material color
+
+	float ambient[]={ambient_red,ambient_green,ambient_blue};
+	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient);
+
+	float mat_ambient[]={brush.red,brush.green,brush.blue,brush.alpha};
+	float mat_diffuse[]={brush.red,brush.green,brush.blue,brush.alpha};
+	float mat_specular[]={brush.shine,brush.shine,brush.shine,brush.shine};
+	float mat_shininess[]={100.0}; // upto 128
+
+	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,mat_ambient);
+	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse);
+	glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
+	glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,mat_shininess);
+
+	// textures
+
+	int tex_count=0;
+
+	if(ShaderMat!=NULL){
+		ShaderMat->TurnOn(0, mat);
+	}
+
+	tex_count=brush.no_texs;
+
+	int DisableCubeSphereMapping=0;
+	for(int ix=0;ix<tex_count;ix++){
+
+		if(brush.tex[ix]){
+
+			// Main brush texture takes precedent over surface brush texture
+			unsigned int texture=0;
+			int tex_flags=0,tex_blend=0,tex_coords=0;
+			float tex_u_scale=1.0,tex_v_scale=1.0,tex_u_pos=0.0,tex_v_pos=0.0,tex_ang=0.0;
+			int tex_cube_mode=0;
+
+
+			texture=brush.cache_frame[ix];
+			tex_flags=brush.tex[ix]->flags;
+			tex_blend=brush.tex[ix]->blend;
+			tex_coords=brush.tex[ix]->coords;
+			tex_u_scale=brush.tex[ix]->u_scale;
+			tex_v_scale=brush.tex[ix]->v_scale;
+			tex_u_pos=brush.tex[ix]->u_pos;
+			tex_v_pos=brush.tex[ix]->v_pos;
+			tex_ang=brush.tex[ix]->angle;
+			tex_cube_mode=brush.tex[ix]->cube_mode;
+			//frame=brush.tex_frame;
+
+			glActiveTexture(GL_TEXTURE0+ix);
+			glClientActiveTexture(GL_TEXTURE0+ix);
+
+			glEnable(GL_TEXTURE_2D);
+			glBindTexture(GL_TEXTURE_2D,texture); // call before glTexParameteri
+
+			// masked texture flag
+			if(tex_flags&4){
+				glEnable(GL_ALPHA_TEST);
+			}else{
+				glDisable(GL_ALPHA_TEST);
+			}
+
+			// mipmapping texture flag
+			if(tex_flags&8){
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
+			}else{
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+			}
+
+			// clamp u flag
+			if(tex_flags&16){
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+			}else{
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
+			}
+
+			// clamp v flag
+			if(tex_flags&32){
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+			}else{
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
+			}
+
+				// ***!ES***
+
+			// spherical environment map texture flag
+			if(tex_flags&64){
+				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
+				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
+				glEnable(GL_TEXTURE_GEN_S);
+				glEnable(GL_TEXTURE_GEN_T);
+				DisableCubeSphereMapping=1;
+			}/*else{
+				glDisable(GL_TEXTURE_GEN_S);
+				glDisable(GL_TEXTURE_GEN_T);
+			}*/
+
+				// cubic environment map texture flag
+				if(tex_flags&128){
+
+					glEnable(GL_TEXTURE_CUBE_MAP);
+					glBindTexture(GL_TEXTURE_CUBE_MAP,texture); // call before glTexParameteri
+
+					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
+					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+					glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+
+					glEnable(GL_TEXTURE_GEN_S);
+					glEnable(GL_TEXTURE_GEN_T);
+					glEnable(GL_TEXTURE_GEN_R);
+					//glEnable(GL_TEXTURE_GEN_Q)
+
+					if(tex_cube_mode==1){
+						glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+						glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+						glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+					}
+
+					if(tex_cube_mode==2){
+						glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+						glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+						glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+					}
+					DisableCubeSphereMapping=1;
+
+				}else  if (DisableCubeSphereMapping!=0){
+
+					glDisable(GL_TEXTURE_CUBE_MAP);
+
+					// only disable tex gen s and t if sphere mapping isn't using them
+					if((tex_flags & 64)==0){
+						glDisable(GL_TEXTURE_GEN_S);
+						glDisable(GL_TEXTURE_GEN_T);
+					}
+
+					glDisable(GL_TEXTURE_GEN_R);
+					//glDisable(GL_TEXTURE_GEN_Q)
+
+				}
+
+
+			switch(tex_blend){
+				case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
+				break;
+				case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
+				break;
+				case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+				//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
+				break;
+				case 3: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_ADD);
+				break;
+				case 4:
+					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
+					glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGB_EXT);
+					break;
+				case 5:
+					glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
+					glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
+					glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE,2.0);
+					break;
+				default: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+			}
+
+			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+			glTexCoordPointer(2,GL_FLOAT,32,&vertices[6]);
+
+
+			// reset texture matrix
+			glMatrixMode(GL_TEXTURE);
+			glLoadIdentity();
+
+			if(tex_u_pos!=0.0 || tex_v_pos!=0.0){
+				glTranslatef(tex_u_pos,tex_v_pos,0.0);
+			}
+			if(tex_ang!=0.0){
+				glRotatef(tex_ang,0.0,0.0,1.0);
+			}
+			if(tex_u_scale!=1.0 || tex_v_scale!=1.0){
+				glScalef(tex_u_scale,tex_v_scale,1.0);
+			}
+
+			// ***!ES***
+			// if spheremap flag=true then flip tex
+			if(tex_flags&64){
+				glScalef(1.0,-1.0,-1.0);
+			}
+
+			// if cubemap flag=true then manipulate texture matrix so that cubemap is displayed properly
+			if(tex_flags&128){
+
+				glScalef(1.0,-1.0,-1.0);
+
+				// get current modelview matrix (set in last camera update)
+				float mod_mat[16];
+				glGetFloatv(GL_MODELVIEW_MATRIX,&mod_mat[0]);
+
+				// get rotational inverse of current modelview matrix
+				Matrix new_mat;
+				new_mat.LoadIdentity();
+
+				new_mat.grid[0][0] = mod_mat[0];
+				new_mat.grid[1][0] = mod_mat[1];
+				new_mat.grid[2][0] = mod_mat[2];
+
+				new_mat.grid[0][1] = mod_mat[4];
+				new_mat.grid[1][1] = mod_mat[5];
+				new_mat.grid[2][1] = mod_mat[6];
+
+				new_mat.grid[0][2] = mod_mat[8];
+				new_mat.grid[1][2] = mod_mat[9];
+				new_mat.grid[2][2] = mod_mat[10];
+
+				glMultMatrixf(&new_mat.grid[0][0]);
+
+			}
+
+
+		}
+
+	}
+
+	// draw tris
+	glMatrixMode(GL_MODELVIEW);
+
+	glPushMatrix();
+	glMultMatrixf(&mat.grid[0][0]);
+	glVertexPointer(3,GL_FLOAT,32,&vertices[0]);
+	glNormalPointer(GL_FLOAT,32,&vertices[3]);
+
+	glDrawArrays(GL_TRIANGLES, 0, triangleindex*3);
+	glPopMatrix();
+
+	// disable all texture layers
+	for(int ix=0;ix<tex_count;ix++){
+
+		glActiveTexture(GL_TEXTURE0+ix);
+		glClientActiveTexture(GL_TEXTURE0+ix);
+
+		// reset texture matrix
+		glMatrixMode(GL_TEXTURE);
+		glLoadIdentity();
+
+		glDisable(GL_TEXTURE_2D);
+
+		// ***!ES***
+		if (DisableCubeSphereMapping!=0){
+			glDisable(GL_TEXTURE_CUBE_MAP);
+			glDisable(GL_TEXTURE_GEN_S);
+			glDisable(GL_TEXTURE_GEN_T);
+			glDisable(GL_TEXTURE_GEN_R);
+			DisableCubeSphereMapping=0;
+		}
+
+	}
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+
+	if (brush.fx&8 && Global::fog_enabled==true){
+		glEnable(GL_FOG);
+	}
+
+	if(ShaderMat!=NULL){
+		ShaderMat->TurnOff();
+	}
+
+
+}
+
+void Geosphere::RecreateGeoROAM(){
+
+	/*xcf = eyepoint->EntityX();
+	ycf = eyepoint->EntityY();
+	zcf = -eyepoint->EntityZ();*/
+
+	TFormPoint(eyepoint->EntityX(true), eyepoint->EntityY(true), eyepoint->EntityZ(true), 0, this);
+	xcf = tformed_x;
+	ycf = tformed_y;
+	zcf = -tformed_z;
+
+	//int i;
+
+	float h1= (height[(int)hsize*(int)size+ (int)hsize]*vsize+1)*size;
+	float h2= (height[(int) size*(int)size+ (int)hsize]*vsize+1)*size;
+	float h3= (height[(int)hsize*(int)size+ (int) size]*vsize+1)*size;
+	float h4=-(height[(int)    0*(int)size+ (int)hsize]*vsize+1)*size;
+	float h5=-(height[(int)hsize*(int)size]*vsize+1)*size;
+	float h6=-(height[0]*vsize+1)*size;
+
+
+	float v[9][5]={
+	{ 0,  h1,  0, hsize, hsize},
+
+	{ h2,  0,  0, size, hsize},
+	{ 0,  0,  h3, hsize, size},
+	{ h4,  0,  0, 0, hsize},
+	{ 0,  0,  h5, hsize, 0},
+
+	{ 0,  h6,  0, size, size},
+	{ 0,  h6,  0, 0, size},
+	{ 0,  h6,  0, 0, 0},
+	{ 0,  h6,  0, size, 0}};
+
+
+
+	// diamond radius - apply entity scale
+	float rx=EntityScaleX(true);
+	float ry=EntityScaleY(true);
+	float rz=EntityScaleZ(true);
+	if(rx>=ry && rx>=rz){
+		dradius=abs(rx);
+	}else if(ry>=rx && ry>=rz){
+		dradius=abs(ry);
+	}else{
+		dradius=abs(rz);
+	}
+
+
+	tmat = MQ_GetMatrix(true);
+
+
+	triangleindex = 0;
+
+	vertices.clear();
+
+	geosub( 0, v[0], v[1], v[2]);
+	geosub( 0, v[0], v[2], v[3]);
+	geosub( 0, v[0], v[3], v[4]);
+	geosub( 0, v[0], v[4], v[1]);
+
+	geosub( 0, v[2], v[1], v[5]);
+	geosub( 0, v[3], v[2], v[6]);
+	geosub( 0, v[4], v[3], v[7]);
+	geosub( 0, v[1], v[4], v[8]);
+
+
+	delete tmat;
+
+
+}
+
+void Geosphere::geosub(int l, float v2[], float v1[], float v0[]){
+
+	float vc[3][5];			/* New (split) vertices */
+	float ds;			/* maximum midpoint displacement */
+	float dx,dy,dz;			/* difference vector */
+	float rd;			/* squared sphere bound radius */
+	float nx[3],ny[3], nz[3];
+	float rc, rc0, rc1, rc2;	/* squared distance from vc To camera position */
+
+	if (l < ROAM_LMAX) {
+		ds = level2dzsize[l];
+
+		/* compute radius of diamond bounding sphere (squared) */
+		float x,y,z;
+		x = (v0[0] + v1[0] + v2[0]) / 3;
+		y = (v0[1] + v1[1] + v2[1]) / 3;
+		z = (v0[2] + v1[2] + v2[2]) / 3;
+		rd = 0.0;
+		dx = v0[0] - x;
+		dy = v0[1] - y;
+		dz = v0[2] - z;
+		rc = dx * dx + dy * dy + dz * dz;
+		if (rc > rd) {rd = rc;}
+		dx = v1[0] - x;
+		dy = v1[1] - y;
+		dz = v1[2] - z;
+		rc = dx * dx + dy * dy + dz * dz;
+		if (rc > rd) {rd = rc;}
+		dx = v2[0] - x;
+		dy = v2[1] - y;
+		dz = v2[2] - z;
+		rc = dx * dx + dy * dy + dz * dz;
+		if (rc > rd) {rd = rc;}
+		rd = sqrt(rd)*dradius;
+
+
+		float vcx=x;
+		float vcy=y;
+		float vcz=-z;
+		tmat->TransformVec(vcx, vcy, vcz, 1);
+
+		for (int i = 0 ;i<= 5; i++){
+			float d = eyepoint->frustum[i][0] * vcx + eyepoint->frustum[i][1] * vcy - eyepoint->frustum[i][2] * vcz + eyepoint->frustum[i][3];
+			if (d <= -rd) return;//{ds=ds/10; break;}
+			//m = m << 1;
+		}
+
+		/* compute distance from split point To camera (squared) */
+		/*dx = x - xcf;
+		dy = y - ycf;
+		dz = z - zcf;
+		rc = dx*dx+dy*dy+dz*dz;*/
+		nx[0]=(v0[0]+v1[0])/2;
+		ny[0]=(v0[1]+v1[1])/2;
+		nz[0]=(v0[2]+v1[2])/2;
+
+		dx = nx[0] - xcf;
+		dy = ny[0] - ycf;
+		dz = nz[0] - zcf;
+		rc0 = dx*dx+dy*dy+dz*dz;
+		rc=rc0;
+
+		nx[1]=(v1[0]+v2[0])/2;
+		ny[1]=(v1[1]+v2[1])/2;
+		nz[1]=(v1[2]+v2[2])/2;
+
+		dx = nx[1] - xcf;
+		dy = ny[1] - ycf;
+		dz = nz[1] - zcf;
+		rc1 = dx*dx+dy*dy+dz*dz;
+		if (rc>rc1) {rc=rc1;}
+
+		nx[2]=(v2[0]+v0[0])/2;
+		ny[2]=(v2[1]+v0[1])/2;
+		nz[2]=(v2[2]+v0[2])/2;
+
+		dx = nx[2] - xcf;
+		dy = ny[2] - ycf;
+		dz = nz[2] - zcf;
+		rc2 = dx*dx+dy*dy+dz*dz;
+		if (rc>rc2) {rc=rc2;}
+
+
+
+		/* If not error large on screen, recursively split */
+		if (ds > rc) {/*<---------terrain detail here*/
+
+			float d,h;
+			/*float nx, ny, nz, d, h, ts;
+
+			ts=size/(1<<l)*4.8;//size*size/l/l*11.973;
+			ts*=ts;*/
+
+			l++;
+
+			/*nx=(v0[0]+v1[0])/2;
+			ny=(v0[1]+v1[1])/2;
+			nz=(v0[2]+v1[2])/2;
+
+			dx = nx - xcf;
+			dy = ny - ycf;
+			dz = nz - zcf;
+			rc = dx*dx+dy*dy+dz*dz+ts;*/
+
+
+			vc[0][3]=(v0[3]+v1[3])/2; vc[0][4]=(v0[4]+v1[4])/2;
+			h=height[(int)vc[0][3]*(int)size+ (int)vc[0][4]]*vsize+1;
+			if (ds > rc0) {
+				d=sqrt(nx[0]*nx[0]+ny[0]*ny[0]+nz[0]*nz[0])/(size)/h;
+			}else{
+				d=1;
+			}
+			vc[0][0]=nx[0]/d; vc[0][1]=ny[0]/d; vc[0][2]=nz[0]/d; 
+
+
+			/*nx=(v1[0]+v2[0])/2;
+			ny=(v1[1]+v2[1])/2;
+			nz=(v1[2]+v2[2])/2;
+
+			dx = nx - xcf;
+			dy = ny - ycf;
+			dz = nz - zcf;
+			rc = dx*dx+dy*dy+dz*dz+ts;*/
+
+			vc[1][3]=(v1[3]+v2[3])/2; vc[1][4]=(v1[4]+v2[4])/2;
+			h=height[(int)vc[1][3]*(int)size+ (int)vc[1][4]]*vsize+1;
+			if (ds > rc1) {
+				d=sqrt(nx[1]*nx[1]+ny[1]*ny[1]+nz[1]*nz[1])/(size)/h;
+			}else{
+				d=1;
+			}
+			vc[1][0]=nx[1]/d; vc[1][1]=ny[1]/d; vc[1][2]=nz[1]/d; 
+
+
+			/*nx=(v2[0]+v0[0])/2;
+			ny=(v2[1]+v0[1])/2;
+			nz=(v2[2]+v0[2])/2;
+
+			dx = nx - xcf;
+			dy = ny - ycf;
+			dz = nz - zcf;
+			rc = dx*dx+dy*dy+dz*dz+ts;*/
+
+			vc[2][3]=(v2[3]+v0[3])/2; vc[2][4]=(v2[4]+v0[4])/2;
+			h=height[(int)vc[2][3]*(int)size+ (int)vc[2][4]]*vsize+1;
+			if (ds > rc2) {
+				d=sqrt(nx[2]*nx[2]+ny[2]*ny[2]+nz[2]*nz[2])/(size)/h;
+			}else{
+				d=1;
+			}
+			vc[2][0]=nx[2]/d; vc[2][1]=ny[2]/d; vc[2][2]=nz[2]/d; 
+
+			geosub(l, v0, vc[2], vc[0]);
+			geosub(l, v1, vc[0], vc[1]);
+			geosub(l, v2, vc[1], vc[2]);
+			geosub(l, vc[2], vc[1], vc[0]);
+
+			return;
+		}
+
+	 }
+
+	float *n0, *n1, *n2;
+
+	n0=&NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])];
+	n1=&NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])];
+	n2=&NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])];
+
+	vertices.push_back(v0[0]); vertices.push_back(v0[1]); vertices.push_back(v0[2]);
+	vertices.push_back(n0[0]); vertices.push_back(n0[1]); vertices.push_back(n0[2]);
+	vertices.push_back(n0[3]);
+	vertices.push_back(n0[4]);
+
+
+	vertices.push_back(v1[0]); vertices.push_back(v1[1]); vertices.push_back(v1[2]);
+	vertices.push_back(n1[0]); vertices.push_back(n1[1]); vertices.push_back(n1[2]);
+	vertices.push_back(n1[3]);
+	vertices.push_back(n1[4]);
+
+
+	vertices.push_back(v2[0]); vertices.push_back(v2[1]); vertices.push_back(v2[2]);
+	vertices.push_back(n2[0]); vertices.push_back(n2[1]); vertices.push_back(n2[2]);
+	vertices.push_back(n2[3]);
+	vertices.push_back(n2[4]);
+
+	triangleindex++;
+
+
+}
+
+
+void Geosphere::TOASTsub(int l, float v2[], float v1[], float v0[]){
+
+	float vc[3][5];	/* New (split) vertices */
+
+	if (l > 0) {
+		l--;
+		float nx, ny, nz, d;
+
+		nx=(v0[0]+v1[0])/2;
+		ny=(v0[1]+v1[1])/2;
+		nz=(v0[2]+v1[2])/2;
+
+		vc[0][3]=(v0[3]+v1[3])/2; vc[0][4]=(v0[4]+v1[4])/2;
+		d=sqrt(nx*nx+ny*ny+nz*nz);
+		vc[0][0]=nx/d; vc[0][1]=ny/d; vc[0][2]=nz/d; 
+
+
+		nx=(v1[0]+v2[0])/2;
+		ny=(v1[1]+v2[1])/2;
+		nz=(v1[2]+v2[2])/2;
+
+		vc[1][3]=(v1[3]+v2[3])/2; vc[1][4]=(v1[4]+v2[4])/2;
+		d=sqrt(nx*nx+ny*ny+nz*nz);
+		vc[1][0]=nx/d; vc[1][1]=ny/d; vc[1][2]=nz/d; 
+
+
+		nx=(v2[0]+v0[0])/2;
+		ny=(v2[1]+v0[1])/2;
+		nz=(v2[2]+v0[2])/2;
+
+		vc[2][3]=(v2[3]+v0[3])/2; vc[2][4]=(v2[4]+v0[4])/2;
+		d=sqrt(nx*nx+ny*ny+nz*nz);
+		vc[2][0]=nx/d; vc[2][1]=ny/d; vc[2][2]=nz/d; 
+
+		TOASTsub(l, v0, vc[2], vc[0]);
+		TOASTsub(l, v1, vc[0], vc[1]);
+		TOASTsub(l, v2, vc[1], vc[2]);
+		TOASTsub(l, vc[2], vc[1], vc[0]);
+
+		return;
+	}
+
+	/*float ax,ay,az,bx,by,bz;
+	float nx,ny,nz,ns;
+	float h0,h1,h2;
+
+	h0=height[(int)v0[3]*(int)size+ (int)v0[4]]*vsize+1;
+	h1=height[(int)v1[3]*(int)size+ (int)v1[4]]*vsize+1;
+	h2=height[(int)v2[3]*(int)size+ (int)v2[4]]*vsize+1;
+
+	ax = h1*v1[0]-h0*v0[0];
+	ay = h1*v1[1]-h0*v0[1];
+	az = h1*v1[2]-h0*v0[2];
+	bx = h2*v2[0]-h1*v1[0];
+	by = h2*v2[1]-h1*v1[1];
+	bz = h2*v2[2]-h1*v1[2];
+	nx = ( ay * bz ) - ( az * by );
+	ny = ( az * bx ) - ( ax * bz );
+	nz = ( ax * by ) - ( ay * bx );
+	ns = sqrt( nx * nx + ny*ny + nz*nz );
+	if (ns != 0) ns = 1;
+	nx /= ns;
+	ny /= ns;
+	nz /= ns;
+	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])]=nx;
+	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])+1]=ny;
+	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])+2]=nz;
+
+	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])]=nx;
+	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])+1]=ny;
+	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])+2]=nz;
+
+	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])]=nx;
+	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])+1]=ny;
+	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])+2]=nz;*/
+
+
+	float u,v;
+	u=0.5f * (-1.0 +atan2( v0[2] , v0[0] ) * (-1 / M_PI ));
+	v=acos( v0[1] ) * ( 1 / M_PI );
+	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])+3]=u*size;
+	NormalsMap[5*(int)((int)v0[3]*(int)size+ v0[4])+4]=v*size;
+
+	u=0.5f * (-1.0 +atan2( v1[2] , v1[0] ) * (-1 / M_PI ));
+	v=acos( v1[1] ) * ( 1 / M_PI );
+	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])+3]=u*size;
+	NormalsMap[5*(int)((int)v1[3]*(int)size+ v1[4])+4]=v*size;
+
+	u=0.5f * (-1.0 +atan2( v2[2] , v2[0] ) * (-1 / M_PI ));
+	v=acos( v2[1] ) * ( 1 / M_PI );
+	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])+3]=u*size;
+	NormalsMap[5*(int)((int)v2[3]*(int)size+ v2[4])+4]=v*size;
+
+}
+
+
+
+void Geosphere::ModifyGeosphere (int x, int y, float new_height){
+	/*int width=size*2;		//Most accurate approach: it wastes a lot of memory
+	if (EqToToast==0){	//First time: must create a look-up map to convert equirectangular coords to TOAST coords
+		EqToToast=new int[(int)(size+1)*width];
+		for (int y=0;y<size;y++){
+			for (int x=0;x<size;x++){
+				int x1=-NormalsMap[5*(x*(int)size+ y)+3]*2;
+				int y1=NormalsMap[5*(x*(int)size+ y)+4];
+
+				//geo->height[x*(int)geo->size+y]=((float)*(buffer+x1+y1*width))/255.0;
+				if (x1+y1*width<0) {
+					x1=0; y1=0;
+				}
+				EqToToast[x1+y1*width]=x*(int)size+y;
+			}
+		}
+	}
+
+	height[EqToToast[x+y*width]]=new_height;*/
+
+
+	//Less accurate approach: some lines might be distorted, but for little changes on a map should be good enough
+
+	float r=sqrt((x % (int)hsize)*(x % (int)hsize)+(hsize-(x % (int)hsize))*(hsize-(x % (int)hsize)))/hsize;
+
+
+	if (x<hsize){
+		if (y<=hsize){
+
+			r=(r*(hsize-y)+1*y)/hsize;
+			y=y/r;
+
+			x=x* y/hsize;
+			y=y-x;
+		}else{
+			r=(r*(y-hsize)+1*(2*hsize-y))/hsize;
+			y=2*hsize-(2*hsize-y)/r;
+
+			x=y-(x*(y-2*hsize)/hsize)-hsize;
+			y=y-x;
+		}
+	}else if (x<hsize*2){
+		x=hsize*2-x;
+		if (y<=hsize){
+
+			r=(r*(hsize-y)+1*y)/hsize;
+			y=y/r;
+
+			x=x* y/hsize;
+			y=x-y;
+		}else{
+
+			r=(r*(y-hsize)+1*(2*hsize-y))/hsize;
+			y=2*hsize-(2*hsize-y)/r;
+
+
+			x=y-(x*(y-2*hsize)/hsize)-hsize;
+			y=x-y;
+		}
+	}else if (x<hsize*3){
+		x=x-hsize*2;
+		if (y<=hsize){
+
+			r=(r*(hsize-y)+1*y)/hsize;
+			y=y/r;
+
+			x=-x* y/hsize;
+			y=-y-x;
+		}else{
+			r=(r*(y-hsize)+1*(2*hsize-y))/hsize;
+			y=2*hsize-(2*hsize-y)/r;
+
+			x=(x*(y-2*hsize)/hsize)+hsize-y;
+			y=-y-x;
+		}
+	}else{
+		x=hsize*4-x;
+		if (y<=hsize) {
+
+			r=(r*(hsize-y)+1*y)/hsize;
+			y=y/r;
+
+			x=-x* y/hsize;
+			y=x+y;
+		}else{
+			r=(r*(y-hsize)+1*(2*hsize-y))/hsize;
+			y=2*hsize-(2*hsize-y)/r;
+
+			x=(x*(y-2*hsize)/hsize)+hsize-y;
+			y=x+y;
+		}
+	
+	}
+	x+=hsize;
+	y+=hsize;
+	height[x+y*(int)size]=new_height;
+}
+
+void Geosphere::EquirectangularToTOAST (){
+	/*for (int x=0; x<size*2; x++){
+		for (int y=0; y<size; y++){
+			int x1=x, y1=y;
+			EquirectangularToTOAST (x1, y1);
+
+			NormalsMap[5*(x1*(int)size+ y1)+3]=x/2;
+			NormalsMap[5*(x1*(int)size+ y1)+4]=y;
+		}
+	}*/
+	float v[9][5]={
+	{ 0,  1,  0, hsize, hsize},
+	{ 1,  0,  0, size, hsize},
+	{ 0,  0,  1, hsize, size},
+	{-1,  0,  0, 0, hsize},
+	{ 0,  0, -1, hsize, 0},
+
+	{ 0, -1,  0, size, size},
+	{ 0, -1,  0, 0, size},
+	{ 0, -1,  0, 0, 0},
+	{ 0, -1,  0, size, 0}};
+
+	int l=(int)(log(hsize)/log(2));
+
+	TOASTsub( l, v[0], v[1], v[2]);
+	TOASTsub( l, v[0], v[2], v[3]);
+	TOASTsub( l, v[0], v[3], v[4]);
+	TOASTsub( l, v[0], v[4], v[1]);
+
+	TOASTsub( l, v[2], v[1], v[5]);
+	TOASTsub( l, v[3], v[2], v[6]);
+	TOASTsub( l, v[4], v[3], v[7]);
+	TOASTsub( l, v[1], v[4], v[8]);
+
+}
+
+void Geosphere::UpdateNormals (int preserve){
+		for (int y=0;y<size;y++){
+			for (int x=0;x<size;x++){
+				float theta=-M_PI*(NormalsMap[5*(x*(int)size+ y)+3]-hsize)/size*2;
+				float phi=M_PI*(NormalsMap[5*(x*(int)size+ y)+4])/size;
+				if (preserve==0){
+					NormalsMap[5*(x*(int)size+ y)]=sin(phi) * cos(theta);
+					NormalsMap[5*(x*(int)size+ y)+1]=cos(phi);
+					NormalsMap[5*(x*(int)size+ y)+2]=sin(phi) * sin(theta);
+				}else{
+					float a,b,c, d,e,f;
+					a=sin(phi) * cos(theta);
+					b=cos(phi);
+					c=sin(phi) * sin(theta);
+
+					d=NormalsMap[5*(x*(int)size+ y)];
+					e=NormalsMap[5*(x*(int)size+ y)+1];
+					f=NormalsMap[5*(x*(int)size+ y)+2];
+
+					NormalsMap[5*(x*(int)size+ y)]=a*e+c*d;
+					NormalsMap[5*(x*(int)size+ y)+1]=b*e+f;
+					NormalsMap[5*(x*(int)size+ y)+2]=c*e-a*d;
+
+				}
+			}
+		}
+}
+
+Geosphere* Geosphere::LoadGeosphere(string filename,Entity* parent_ent){
+	//filename=Strip(filename); // get rid of path info
+
+	if(File::ResourceFilePath(filename)==""){
+		cout << "Error: Cannot Find Terrain: " << filename << endl;
+		return NULL;
+	}
+
+	string filename_left=Left(filename,Len(filename)-4);
+	string filename_right=Right(filename,3);
+
+	//const char* c_filename_left=filename_left.c_str();
+	//const char* c_filename_right=filename_right.c_str();
+
+	Geosphere* geo;
+
+	unsigned char* pixels;
+
+	int width,height;
+
+	pixels=stbi_load(filename.c_str(),&width,&height,0,1);   //Memory leak fixed by D.J.Peters
+
+	short* tmpNormals=0;		//An equirectangular normal maps
+
+	// all OK ?
+	if (pixels!=NULL) {
+		// work with a copy of the pixel pointer
+		unsigned char* buffer=pixels;
+
+		tmpNormals=new short[(width+1)*(height+1)*2];	// Build an equirectangular normals map, that will be used to build
+								// the final normals map in TOAST projection.
+		for (int x=1;x<=width;x++){
+			for (int y=1;y<=height-2;y++){
+				tmpNormals[2*(y*(int)width+x)]=((short)*(buffer+(x-1)+y*width)) - ((short)*(buffer+(x+1)+y*width));
+				tmpNormals[2*(y*(int)width+x)+1]=((short)*(buffer+x+(y-1)*width)) - ((short)*(buffer+x+(y+1)*width));
+			}
+		}
+
+
+		geo=Geosphere::CreateGeosphere(width, parent_ent);
+
+		geo->size=height;
+		geo->hsize=height/2;
+		geo->EquirectangularToTOAST();
+
+		for (int y=0;y<geo->size;y++){
+			for (int x=0;x<geo->size;x++){
+				int x1=geo->NormalsMap[5*(x*(int)geo->size+ y)+3]*2;
+				int y1=geo->NormalsMap[5*(x*(int)geo->size+ y)+4];
+
+				if (x1+y1*width<0) {
+					x1=0; y1=0;
+				}
+
+				geo->height[x*(int)geo->size+y]=((float)*(buffer+x1+y1*width))/255.0;
+				geo->NormalsMap[5*(x*(int)geo->size+ y)]=(float)tmpNormals[2*(y1*(int)width+x1)];
+				geo->NormalsMap[5*(x*(int)geo->size+ y)+1]=256;
+				geo->NormalsMap[5*(x*(int)geo->size+ y)+2]=(float)tmpNormals[2*(y1*(int)width+x1)+1];
+			}
+		}
+		stbi_image_free(pixels);
+		pixels=NULL;
+	} else {
+		// create a dummy terrain only as a dirty fallback
+		height =128;
+		geo=Geosphere::CreateGeosphere(256, parent_ent);
+		geo->size=height;
+		geo->hsize=height/2;
+		//geo->height=new float[(width+1)*(width+1)];
+		for (int x=0;x<=geo->size-1;x++){
+			for (int y=0;y<=geo->size-1;y++){
+				geo->height[x*(int)geo->size+y]=0.0f;
+			}
+		}
+	}
+
+
+	geo->UpdateNormals(true);
+	delete tmpNormals;
+
+	return geo;
+}
+
+void Geosphere::TreeCheck(CollisionInfo* ci){
+	Ray=ci->coll_line;
+	radius=ci->radius;
+
+	TFormPoint(Ray.o.x, Ray.o.y, Ray.o.z, 0, this);
+	xcf = tformed_x;
+	ycf = tformed_y;
+	zcf = -tformed_z;
+
+
+	//int i;
+	float h1= (height[(int)hsize*(int)size+ (int)hsize]*vsize+1)*size;
+	float h2= (height[(int) size*(int)size+ (int)hsize]*vsize+1)*size;
+	float h3= (height[(int)hsize*(int)size+ (int) size]*vsize+1)*size;
+	float h4=-(height[(int)    0*(int)size+ (int)hsize]*vsize+1)*size;
+	float h5=-(height[(int)hsize*(int)size]*vsize+1)*size;
+	float h6=-(height[0]*vsize+1)*size;
+
+
+	float v[9][5]={
+	{ 0,  h1,  0, hsize, hsize},
+
+	{ h2,  0,  0, size, hsize},
+	{ 0,  0,  h3, hsize, size},
+	{ h4,  0,  0, 0, hsize},
+	{ 0,  0,  h5, hsize, 0},
+
+	{ 0,  h6,  0, size, size},
+	{ 0,  h6,  0, 0, size},
+	{ 0,  h6,  0, 0, 0},
+	{ 0,  h6,  0, size, 0}};
+
+
+	// diamond radius - apply entity scale
+	float rx=EntityScaleX(true);
+	float ry=EntityScaleY(true);
+	float rz=EntityScaleZ(true);
+	if(rx>=ry && rx>=rz){
+		dradius=abs(rx);
+	}else if(ry>=rx && ry>=rz){
+		dradius=abs(ry);
+	}else{
+		dradius=abs(rz);
+	}
+
+
+	tmat = MQ_GetMatrix(true);
+
+
+
+	if(c_col_tree!=NULL){
+		C_DeleteColTree(c_col_tree);
+		c_col_tree=NULL;
+	}
+
+	mesh_info=C_NewMeshInfo();
+	triangleindex = 0;
+
+
+	/* recurse on the two base triangles */
+	c_col_tree_geosub( 0, v[0], v[1], v[2]);
+	c_col_tree_geosub( 0, v[0], v[2], v[3]);
+	c_col_tree_geosub( 0, v[0], v[3], v[4]);
+	c_col_tree_geosub( 0, v[0], v[4], v[1]);
+
+	c_col_tree_geosub( 0, v[2], v[1], v[5]);
+	c_col_tree_geosub( 0, v[3], v[2], v[6]);
+	c_col_tree_geosub( 0, v[4], v[3], v[7]);
+	c_col_tree_geosub( 0, v[1], v[4], v[8]);
+
+	c_col_tree=C_CreateColTree(mesh_info);
+	C_DeleteMeshInfo(mesh_info);
+	delete tmat;
+
+
+
+}
+
+void Geosphere::c_col_tree_geosub(int l, float v2[], float v1[], float v0[]){
+
+	float vc[3][5];	/* New (split) vertices */
+	float ds;	/* maximum midpoint displacement */
+	float dx,dy,dz;	/* difference vector */
+	float rd;	/* squared sphere bound radius */
+	float rc;	/* squared distance from vc To camera position */
+
+	if (l < ROAM_LMAX) {
+		ds = level2dzsize[l];
+
+		/* compute radius of diamond bounding sphere (squared) */
+		float x,y,z;
+		x = (v0[0] + v1[0] + v2[0]) / 3;
+		y = (v0[1] + v1[1] + v2[1]) / 3;
+		z = (v0[2] + v1[2] + v2[2]) / 3;
+		rd = 0.0;
+		dx = v0[0] - x;
+		dy = v0[1] - y;
+		dz = v0[2] - z;
+		rc = dx * dx + dy * dy + dz * dz;
+		if (rc > rd) {rd = rc;}
+		dx = v1[0] - x;
+		dy = v1[1] - y;
+		dz = v1[2] - z;
+		rc = dx * dx + dy * dy + dz * dz;
+		if (rc > rd) {rd = rc;}
+		dx = v2[0] - x;
+		dy = v2[1] - y;
+		dz = v2[2] - z;
+		rc = dx * dx + dy * dy + dz * dz;
+		if (rc > rd) {rd = rc;}
+		rd = sqrt(rd)*dradius;
+
+
+		float vcx=x;
+		float vcy=y;
+		float vcz=-z;
+		tmat->TransformVec(vcx, vcy, vcz, 1);
+
+		/*Is triangle on the collision line?*/
+
+		Vector Sphere;
+		Sphere.x=vcx;
+		Sphere.y=vcy;
+		Sphere.z=vcz;
+		Line dst( Sphere-Ray.o,Ray.d );
+
+		float a=dst.d.dot(dst.d);
+		if( !a ) return;
+		float b=dst.o.dot(dst.d)*2;
+		float c=dst.o.dot(dst.o)-rd*rd;
+		float d=b*b-4*a*c;
+
+		if (d<0) return;
+
+
+		/* compute distance from split point To camera (squared) */
+		dx = x - xcf;
+		dy = y - ycf;
+		dz = z - zcf;
+		rc = dx*dx+dy*dy+dz*dz;
+
+		/* If not error large on screen, recursively split */
+		if (ds > rc) {/*<---------terrain detail here*/
+			l++;
+			float nx, ny, nz, d, h;
+
+			nx=(v0[0]+v1[0])/2;
+			ny=(v0[1]+v1[1])/2;
+			nz=(v0[2]+v1[2])/2;
+
+			vc[0][3]=(v0[3]+v1[3])/2; vc[0][4]=(v0[4]+v1[4])/2;
+			h=height[(int)vc[0][3]*(int)size+ (int)vc[0][4]]*vsize+1;
+			d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
+
+			vc[0][0]=nx/d; vc[0][1]=ny/d; vc[0][2]=nz/d; 
+
+
+			nx=(v1[0]+v2[0])/2;
+			ny=(v1[1]+v2[1])/2;
+			nz=(v1[2]+v2[2])/2;
+
+			vc[1][3]=(v1[3]+v2[3])/2; vc[1][4]=(v1[4]+v2[4])/2;
+			h=height[(int)vc[1][3]*(int)size+ (int)vc[1][4]]*vsize+1;
+			d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
+
+			vc[1][0]=nx/d; vc[1][1]=ny/d; vc[1][2]=nz/d; 
+
+
+			nx=(v2[0]+v0[0])/2;
+			ny=(v2[1]+v0[1])/2;
+			nz=(v2[2]+v0[2])/2;
+			vc[2][3]=(v2[3]+v0[3])/2; vc[2][4]=(v2[4]+v0[4])/2;
+			h=height[(int)vc[2][3]*(int)size+ (int)vc[2][4]]*vsize+1;
+			d=sqrt(nx*nx+ny*ny+nz*nz)/(size)/h;
+
+			vc[2][0]=nx/d; vc[2][1]=ny/d; vc[2][2]=nz/d; 
+
+			c_col_tree_geosub(l, v0, vc[2], vc[0]);
+			c_col_tree_geosub(l, v1, vc[0], vc[1]);
+			c_col_tree_geosub(l, v2, vc[1], vc[2]);
+			c_col_tree_geosub(l, vc[2], vc[1], vc[0]);
+
+			return;
+		}
+
+	 }
+
+	//add to collisiontree
+	C_AddVertex(mesh_info,v0[0],v0[1],-v0[2],0);
+	C_AddVertex(mesh_info,v1[0],v1[1],-v1[2],0);
+	C_AddVertex(mesh_info,v2[0],v2[1],-v2[2],0);
+	C_AddTriangle(mesh_info, triangleindex, triangleindex*3+2, triangleindex*3+1, triangleindex*3+0, 0);
+	triangleindex++;
+}
+
+void Geosphere::FreeEntity(){
+
+	delete[] height;
+	delete[] NormalsMap;		
+	//delete[] EqToToast;		
+
+	delete c_col_tree;
+
+	Entity::FreeEntity();
+
+	delete this;
+
+	return;
+
+}
+

+ 1 - 1
openb3dlib.mod/openb3d/src/geosphere.h

@@ -39,7 +39,7 @@ public:
 	//void TreeCheck(CollisionInfo* ci);
 	void UpdateTerrain();
 	void RecreateGeoROAM();
-	void UpdateNormals();
+	void UpdateNormals(int preserve=0);
 
 	void ModifyGeosphere (int x, int y, float new_height);
 	void TreeCheck(CollisionInfo* ci);

+ 16 - 0
openb3dlib.mod/openb3d/src/global.cpp

@@ -35,6 +35,16 @@ int Global::width=640,Global::height=480;
 
 int Global::Shadows_enabled=false;
 
+int Global::alpha_enable=-1;
+
+int Global::blend_mode=-1;
+
+int Global::fx1=-1;
+
+int Global::fx2=-1;
+
+
+
 Pivot* Global::root_ent=new Pivot();
 
 Camera* Global::camera_in_use;
@@ -206,6 +216,10 @@ void Global::UpdateEntityAnim(Mesh& mesh){
 			if(anim_start==true) mesh.anim_time=first;
 
 		}else{
+			if(mesh.anim_mode==4){	//Manual mode
+				Animation::AnimateMesh3(&mesh);
+				return;
+			}
 
 			Animation::AnimateMesh(&mesh,mesh.anim_time,first,last);
 
@@ -217,6 +231,7 @@ void Global::UpdateEntityAnim(Mesh& mesh){
 				if(mesh.anim_time>last){
 					mesh.anim_time=first+(mesh.anim_time-last);
 				}
+				return;
 
 			}
 
@@ -237,6 +252,7 @@ void Global::UpdateEntityAnim(Mesh& mesh){
 						mesh.anim_dir=1;
 					}
 				}
+				return;
 
 			}
 

+ 7 - 0
openb3dlib.mod/openb3d/src/global.h

@@ -45,6 +45,13 @@ public:
 	static void UpdateWorld(float anim_speed=1.0);
 	static void RenderWorld();
 	static void UpdateEntityAnim(Mesh& mesh);
+
+	static int alpha_enable;
+	static int blend_mode;
+	static int fx1;
+	static int fx2;
+
+
 	
 };
 

+ 1719 - 1719
openb3dlib.mod/openb3d/src/material.cpp

@@ -1,1719 +1,1719 @@
-#include <iostream>
-#include <string>
-;
-
-#include "glew.h"
-/*
-#ifdef linux
-#define GL_GLEXT_PROTOTYPES
-#include <GL/gl.h>
-#include <GL/glext.h>
-#include <GL/glu.h>
-#endif
-#ifdef WIN32
-#include "GLee.h"
-#include <GL\glu.h>
-#endif
-#ifdef __APPLE__
-#include "GLee.h"
-#include <OpenGL/glu.h>
-#endif
-*/
-#include "surface.h"
-#include "camera.h"
-#include "shadermat.h"
-#include "file.h"
-#include "global.h"
-#include "stb_image.h"
-
-
-list<ShaderObject*> ShaderObject::ShaderObjectList;
-list<ProgramObject*> ProgramObject::ProgramObjectList;
-int Shader::ShaderIDCount;
-
-
-/*ShaderObject* ShaderObject::CreateVertShader(string shaderFileName);
-ShaderObject* ShaderObject::CreateFragShader(string shaderFileName);
-ShaderObject* ShaderObject::CreateVertShaderFromString(string shadercode);
-ShaderObject* ShaderObject::CreateFragShaderFromString(string shadercode);
-*/
-
-
-ShaderObject* ShaderObject::CreateVertShader(string shaderFileName){
-	// Load the shader and dump it into a Byte Array
-	File* file=File::ReadFile(shaderFileName); // opens as ASCII!
-	if(file==0) {
-		return 0;
-	}
-
-/*	unsigned long pos=file.tellg();
-	file.seekg(0,ios::end);
-	unsigned long FileLength = file.tellg();
-	file.seekg(ios::beg);
-*/	
-	fseek(file->pFile, 0L, SEEK_END);
-	unsigned long FileLength = ftell(file->pFile);
-	fseek(file->pFile, 0L, SEEK_SET);
-
-	//int ShaderObject;
-	ShaderObject* myShader = new ShaderObject;
-	
-	myShader->ShaderObj = glCreateShader(GL_VERTEX_SHADER);
-	myShader->ShaderType = 1; // 1 = Vert, 2 = Frag/Pixel
-
-	char* shaderSrc;
-
-	shaderSrc = new char[FileLength+1];
-	if (shaderSrc == 0) return 0;   // can't reserve memory
-   
-	// FileLength isn't always strlen cause some characters are stripped in ascii read...
-	// it is important to 0-terminate the real length later, len is just max possible value... 
-	shaderSrc[FileLength] = 0; 
-
-	unsigned int i=0;
-	while (!file->Eof())
-	{
-		shaderSrc[i] = file->ReadByte();       // get character from file.
-		i++;
-	}
-    
-	shaderSrc[i] = 0;  // 0-terminate it at the correct position
-    
-	file->CloseFile();
-
-
-	
-	int shaderLen[1];
-	shaderLen[0] = i;
-
-	//Local shaderPtr:Byte Ptr[1]
-	//shaderPtr[0] = Varptr(shaderSrc[0])
-
-	// Send shader to ShaderObject, then compile it
-	glShaderSource(myShader->ShaderObj,1, (const GLchar**)&shaderSrc, 0);
-	glCompileShader(myShader->ShaderObj);
-
-	// Did the shader compile successfuly?
-	int compiled;
-	glGetShaderiv(myShader->ShaderObj,GL_COMPILE_STATUS, &compiled);
-
-	if (!compiled){
-		delete myShader;
-		return 0;
-		}
-
-
-	//myShader.Attached = New TList
-	myShader->shaderName = shaderFileName;
-	ShaderObject::ShaderObjectList.push_back(myShader);
-	
-	return myShader;
-}
-
-
-
-
-/*
-'-----------------------------------------------------------
-'CreateFragShader:tShaderObject(shaderFileName:String)
-'
-'Creates a Fragment Shader Object from a File
-'
-'Returns: A tShaderObject if successful, or Null if it fails
-'-----------------------------------------------------------
-*/
-
-
-ShaderObject* ShaderObject::CreateFragShader(string shaderFileName){
-	// Load the shader and dump it into a Byte Array
-	File* file=File::ReadFile(shaderFileName); // opens as ASCII!
-
-	if(file==0) {
-		return 0;
-	}
-
-/*	unsigned long pos=file.tellg();
-	file.seekg(0,ios::end);
-	unsigned long FileLength = file.tellg();
-	file.seekg(ios::beg);
-*/	
-	fseek(file->pFile, 0L, SEEK_END);
-	unsigned long FileLength = ftell(file->pFile);
-	fseek(file->pFile, 0L, SEEK_SET);
-
-	//int ShaderObject;
-	ShaderObject* myShader = new ShaderObject;
-	
-	myShader->ShaderObj = glCreateShader(GL_FRAGMENT_SHADER);
-	myShader->ShaderType = 2; // 1 = Vert, 2 = Frag/Pixel
-
-	char* shaderSrc;
-
-	shaderSrc = new char[FileLength+1];
-	if (shaderSrc == 0) return 0;   // can't reserve memory
-   
-	// FileLength isn't always strlen cause some characters are stripped in ascii read...
-	// it is important to 0-terminate the real length later, len is just max possible value... 
-	shaderSrc[FileLength] = 0; 
-
-	unsigned int i=0;
-	while (!file->Eof())
-	{
-		shaderSrc[i] = file->ReadByte();       // get character from file.
-		i++;
-	}
-    
-	shaderSrc[i] = 0;  // 0-terminate it at the correct position
-    
-	file->CloseFile();
-
-
-	
-	int shaderLen[1];
-	shaderLen[0] = i;
-
-	//Local shaderPtr:Byte Ptr[1]
-	//shaderPtr[0] = Varptr(shaderSrc[0])
-
-	// Send shader to ShaderObject, then compile it
-	glShaderSource(myShader->ShaderObj,1, (const GLchar**)&shaderSrc, 0);
-	glCompileShader(myShader->ShaderObj);
-
-	// Did the shader compile successfuly?
-	int compiled;
-	glGetShaderiv(myShader->ShaderObj,GL_COMPILE_STATUS, &compiled);
-
-	if (!compiled){
-		delete myShader;
-		return 0;
-		}
-
-
-	//myShader.Attached = New TList
-	myShader->shaderName = shaderFileName;
-	ShaderObject::ShaderObjectList.push_back(myShader);
-	return myShader;
-}
-/*
-
-'-----------------------------------------------------------
-'CreateVertShader:tShaderObject(shaderFileName:String)
-'
-'Creates a Vertex Shader Object from a File
-'
-'Returns: A tShaderObject if successful, or Null if it fails
-'-----------------------------------------------------------
-*/
-ShaderObject* ShaderObject::CreateVertShaderFromString(string shadercode){
-	// Load the shader and dump it into a Byte Array
-	if (shadercode == ""){
-		return 0;
-	}
-	
-	//Local tempShaderName:String = "Code"+Rand(10000)
-	unsigned int FileLength = shadercode.size();
-	//int ShaderObject;
-	ShaderObject* myShader = new ShaderObject;
-	
-	myShader->ShaderObj = glCreateShader(GL_VERTEX_SHADER);
-	myShader->ShaderType = 1; // 1 = Vert, 2 = Frag/Pixel
-
-	//Create a Byte Array to which the Shader Source will be copied to
-	//The extra Array Byte (FileLength+1) is so we can Null terminate the array
-	char* shaderSrc;
-
-	shaderSrc = new char[FileLength+1];
-	if (shaderSrc == 0) return 0;   // can't reserve memory
-   
-	// FileLength isn't always strlen cause some characters are stripped in ascii read...
-	// it is important to 0-terminate the real length later, len is just max possible value... 
-	shaderSrc[FileLength] = 0; 
-
-	unsigned int i=0;
-	while (i<FileLength)
-	{
-		shaderSrc[i] = shadercode[i];       // get character from file.
-		i++;
-	}
-    
-	shaderSrc[i] = 0;  // 0-terminate it at the correct position
-
-
-	// Send shader to ShaderObject, then compile it
-	glShaderSource(myShader->ShaderObj,1, (const GLchar**)&shaderSrc, 0);
-	glCompileShader(myShader->ShaderObj);
-
-	// Did the shader compile successfuly?
-	int compiled;
-	glGetShaderiv(myShader->ShaderObj,GL_COMPILE_STATUS, &compiled);
-
-	if (!compiled){
-		delete myShader;
-		return 0;
-		}
-
-
-	//myShader.Attached = New TList
-	//myShader->shaderName = shaderFileName;
-	ShaderObject::ShaderObjectList.push_back(myShader);
-	
-	return myShader;
-}
-
-/*
-'-----------------------------------------------------------
-'CreateFragShader:tShaderObject(shaderFileName:String)
-'
-'Creates a Fragment Shader Object from a File
-'
-'Returns: A tShaderObject if successful, or Null if it fails
-'-----------------------------------------------------------*/
-
-ShaderObject* ShaderObject::CreateFragShaderFromString(string shadercode){
-	// Load the shader and dump it into a Byte Array
-	if (shadercode == ""){
-		return 0;
-	}
-	
-	//Local tempShaderName:String = "Code"+Rand(10000)
-	unsigned int FileLength = shadercode.size();
-	//int ShaderObject;
-	ShaderObject* myShader = new ShaderObject;
-	
-	myShader->ShaderObj = glCreateShader(GL_FRAGMENT_SHADER);
-	myShader->ShaderType = 2; // 1 = Vert, 2 = Frag/Pixel
-
-	//Create a Byte Array to which the Shader Source will be copied to
-	//The extra Array Byte (FileLength+1) is so we can Null terminate the array
-	char* shaderSrc;
-
-	shaderSrc = new char[FileLength+1];
-	if (shaderSrc == 0) return 0;   // can't reserve memory
-   
-	// FileLength isn't always strlen cause some characters are stripped in ascii read...
-	// it is important to 0-terminate the real length later, len is just max possible value... 
-	shaderSrc[FileLength] = 0; 
-
-	unsigned int i=0;
-	while (i<FileLength)
-	{
-		shaderSrc[i] = shadercode[i];       // get character from file.
-		i++;
-	}
-    
-	shaderSrc[i] = 0;  // 0-terminate it at the correct position
-
-
-	// Send shader to ShaderObject, then compile it
-	glShaderSource(myShader->ShaderObj,1, (const GLchar**)&shaderSrc, 0);
-	glCompileShader(myShader->ShaderObj);
-
-	// Did the shader compile successfuly?
-	int compiled;
-	glGetShaderiv(myShader->ShaderObj,GL_COMPILE_STATUS, &compiled);
-
-	if (!compiled){
-		delete myShader;
-		return 0;
-		}
-
-
-	//myShader.Attached = New TList
-	//myShader->shaderName = shaderFileName;
-	ShaderObject::ShaderObjectList.push_back(myShader);
-	
-	return myShader;
-}
-
-
-void ShaderObject::DeleteVertShader(ShaderObject* vShader){
-	if (vShader==0) return;
-
-	ShaderObject::ShaderObjectList.remove(vShader);
-	
-	// Detach this ShaderObject from all ProgramObjects it was attached to
-	list<ProgramObject*>::iterator it;
-
-	for(it=ProgramObject::ProgramObjectList.begin();it!=ProgramObject::ProgramObjectList.end();it++){
-		ProgramObject* p=*it;
-
-		p->DetachVertShader(vShader);
-	}
-	
-	// Delete the shader
-	glDeleteShader(vShader->ShaderObj);
-	delete vShader;
-}
-
-void ShaderObject::DeleteFragShader(ShaderObject* fShader){
-	if (fShader==0) return;
-
-	ShaderObject::ShaderObjectList.remove(fShader);
-	
-	// Detach this ShaderObject from all ProgramObjects it was attached to
-	list<ProgramObject*>::iterator it;
-
-	for(it=ProgramObject::ProgramObjectList.begin();it!=ProgramObject::ProgramObjectList.end();it++){
-		ProgramObject* p=*it;
-
-		p->DetachFragShader(fShader);
-	}
-	
-	// Delete the shader
-	glDeleteShader(fShader->ShaderObj);
-	delete fShader;
-}	
-/*Function DeleteFragShader(fShader:tShaderObject Var)
-	If Not fShader Return
-	
-	RemoveLink(ListFindLink(ShaderObjectList,fShader))
-		
-	' Detach this ShaderObject from all ProgramObjects it was attached to
-	For Local p:tProgramObject = EachIn ProgramObjectList
-		If ListContains(p.fList, fShader)
-			p.DetachFragShader(fShader)
-		End If
-	Next
-	
-	' Delete the shader
-	glDeleteObjectARB(fShader.ShaderObject)
-	?Debug
-		Print "Deleted ShaderObject '"+fShader.shaderName+"'"
-		Print
-	?
-	fShader = Null
-End Function
-*/
-
-
-
-
-//ShaderMat
-
-Sampler* Sampler::Create(string Name, int Slot, Texture* Tex){
-	Sampler* S = new Sampler;
-	S->Name = Name;
-	S->Slot = Slot;
-	S->texture = Tex;
-	return S;
-}
-
-
-	
-Shader* Shader::CreateShaderMaterial(string Name){
-	Shader* s= new Shader;
-	s->texCount=0;
-	if (Name == ""){
-		Name = "NoName";
-	}
-	if (1==1){//HardwareInfo->ShaderSupport{
-		stringstream sstm;
-		sstm << Name << s->ID;
-		s->ID = ShaderIDCount;
-		s->arb_program = ProgramObject::Create(sstm.str());
-		s->name = Name;
-	}else{
-		return 0;
-	}
-	ShaderIDCount++;
-
-	for (int i=0; i<=254; i++){
-		s->Shader_Tex[i] = 0;
-	}
-
-	return s;
-}
-	
-/*void Shader::UpdateData(Surface* surf) {
-	for (unsigned int i=0;i<Parameters.size();i++){
-		switch(Parameters[i].type){
-		case 0:
-			if (arb_program !=0){arb_program->SetParameter1F(Parameters[i].name,*(Parameters[i].fp[0]));}
-			break;
-		case 7:
-			if (arb_program !=0){arb_program->SetParameter3F(Parameters[i].name, 
-			Parameters[i].ent->EntityX(), 
-			Parameters[i].ent->EntityY(),
-			Parameters[i].ent->EntityZ());}
-			break;
-		case 13:
-			if (arb_program !=0){arb_program->SetParameterArray(Parameters[i].name,Parameters[i].surf,Parameters[i].vbo);}
-			break;
-		case 14:
-			if (arb_program !=0){
-				GLfloat modelViewMatrix[16];
-				glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix);
-				arb_program->SetMatrix4F(Parameters[i].name, modelViewMatrix);
-			}
-			break;
-
-		case 15:
-			if (arb_program !=0){
-				GLfloat modelViewMatrix[16];
-				glGetFloatv(GL_PROJECTION_MATRIX, modelViewMatrix);
-				arb_program->SetMatrix4F(Parameters[i].name, modelViewMatrix);
-			}
-			break;
-
-
-		//default:
-		}
-	}
-}
-	*/
-// internal 
-void Shader::TurnOn(Surface* surf, Matrix& mat){
-	ProgramAttriBegin();
-	// Update Data
-
-	for (unsigned int i=0;i<Parameters.size();i++){
-		switch(Parameters[i].type){
-		case 0:
-			if (arb_program !=0){arb_program->SetParameter1F(Parameters[i].name,*(Parameters[i].fp[0]));}
-			break;
-		case 1:
-			if (arb_program !=0){arb_program->SetParameter2F(Parameters[i].name,*(Parameters[i].fp[0]),*(Parameters[i].fp[1]));}
-			break;
-		case 2:
-			if (arb_program !=0){arb_program->SetParameter3F(Parameters[i].name,*(Parameters[i].fp[0]),*(Parameters[i].fp[1]),
-			*(Parameters[i].fp[2]));}
-			break;
-		case 3:
-			if (arb_program !=0){arb_program->SetParameter4F(Parameters[i].name,*(Parameters[i].fp[0]),*(Parameters[i].fp[1]),
-			*(Parameters[i].fp[2]),*(Parameters[i].fp[3]));}
-			break;
-		case 4:
-			if (arb_program !=0){arb_program->SetParameter1I(Parameters[i].name,*(Parameters[i].ip[0]));}
-			break;
-		case 5:
-			if (arb_program !=0){arb_program->SetParameter2I(Parameters[i].name,*(Parameters[i].ip[0]),*(Parameters[i].ip[1]));}
-			break;
-		case 6:
-			if (arb_program !=0){arb_program->SetParameter3I(Parameters[i].name,*(Parameters[i].ip[0]),*(Parameters[i].ip[1]),
-			*(Parameters[i].ip[2]));}
-			break;
-		case 7:
-			if (arb_program !=0){arb_program->SetParameter4I(Parameters[i].name,*(Parameters[i].ip[0]),*(Parameters[i].ip[1]),
-			*(Parameters[i].ip[2]),*(Parameters[i].ip[3]));}
-			break;
-		case 8:
-			if (arb_program !=0){arb_program->SetParameter3F(Parameters[i].name, 
-			Parameters[i].ent->EntityX(), 
-			Parameters[i].ent->EntityY(),
-			Parameters[i].ent->EntityZ());}
-			break;
-		case 13:
-			if (arb_program !=0){arb_program->SetParameterArray(Parameters[i].name,Parameters[i].surf,Parameters[i].vbo);}
-			break;
-		case 14:
-			if (arb_program !=0){
-				Matrix new_mat=Global::camera_in_use->mat.Inverse();
-				new_mat.Multiply(mat);
-				arb_program->SetMatrix4F(Parameters[i].name, &new_mat.grid[0][0]);
-			}
-			break;
-
-		case 15:
-			if (arb_program !=0){
-				arb_program->SetMatrix4F(Parameters[i].name, &Global::camera_in_use->proj_mat[0]);
-			}
-			break;
-
-
-		//default:
-		}
-	}
-
-	if (UpdateSampler != 0){
-		for (int i=0; i<=254; i++){
-			if (Shader_Tex[i] == 0) break;
-			if (arb_program !=0){arb_program->SetParameter1I(Shader_Tex[i]->Name,Shader_Tex[i]->Slot);}
-		}
-		UpdateSampler = 0;
-	}
-	
-	if (surf!=0) {
-		int DisableCubeSphereMapping=0;
-		for (int ix=0;ix<=254;ix++){
-			if (Shader_Tex[ix] == 0) break;
-			// Main brush texture takes precedent over surface brush texture
-			unsigned int texture=0;
-			int tex_flags=0,tex_blend=0,tex_coords=0;
-			float tex_u_scale=1.0,tex_v_scale=1.0,tex_u_pos=0.0,tex_v_pos=0.0,tex_ang=0.0;
-			int tex_cube_mode=0;//,frame=0;
-			texture=Shader_Tex[ix]->texture->texture;
-			tex_flags=Shader_Tex[ix]->texture->flags;
-			tex_blend=Shader_Tex[ix]->texture->blend;
-			tex_coords=Shader_Tex[ix]->texture->coords;
-			tex_u_scale=Shader_Tex[ix]->texture->u_scale;
-			tex_v_scale=Shader_Tex[ix]->texture->v_scale;
-			tex_u_pos=Shader_Tex[ix]->texture->u_pos;
-			tex_v_pos=Shader_Tex[ix]->texture->v_pos;
-			tex_ang=Shader_Tex[ix]->texture->angle;
-			tex_cube_mode=Shader_Tex[ix]->texture->cube_mode;
-											
-			glActiveTexture(GL_TEXTURE0+ix);
-			glClientActiveTexture(GL_TEXTURE0+ix);
-
-			if (Shader_Tex[ix]->is3D==0){
-				glEnable(GL_TEXTURE_2D);
-				glBindTexture(GL_TEXTURE_2D,texture); // call before glTexParameteri
-				// mipmapping texture flag
-				if(tex_flags&8){
-					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
-				}else{
-					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-				}
-			}else{
-				glEnable(GL_TEXTURE_3D);
-				glBindTexture(GL_TEXTURE_3D,texture); // call before glTexParameteri
-				// mipmapping texture flag
-				if(tex_flags&8){
-					glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-					glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
-				}else{
-					glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-					glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-				}
-			}
-
-			// masked texture flag
-			if(tex_flags&4){
-				glEnable(GL_ALPHA_TEST);
-			}else{
-				glDisable(GL_ALPHA_TEST);
-			}
-		
-		
-			// clamp u flag
-			if(tex_flags&16){
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
-			}else{						
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
-			}
-			
-			// clamp v flag
-			if(tex_flags&32){
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
-			}else{
-				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
-			}
-	
-			// ***!ES***
-			///*
-			// spherical environment map texture flag
-			if(tex_flags&64){
-				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
-				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
-				glEnable(GL_TEXTURE_GEN_S);
-				glEnable(GL_TEXTURE_GEN_T);
-				DisableCubeSphereMapping=1;
-			}/*else{
-				glDisable(GL_TEXTURE_GEN_S);
-				glDisable(GL_TEXTURE_GEN_T);
-			}*/
-					
-			// cubic environment map texture flag
-			if(tex_flags&128){
-
-				glEnable(GL_TEXTURE_CUBE_MAP);
-				glBindTexture(GL_TEXTURE_CUBE_MAP,texture); // call before glTexParameteri
-				
-				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
-				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
-				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
-				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
-				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
-				
-				glEnable(GL_TEXTURE_GEN_S);
-				glEnable(GL_TEXTURE_GEN_T);
-				glEnable(GL_TEXTURE_GEN_R);
-				//glEnable(GL_TEXTURE_GEN_Q)
-				if(tex_cube_mode==1){
-					glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
-					glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
-					glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
-				}
-				
-				if(tex_cube_mode==2){
-					glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
-					glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
-					glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
-				}
-				DisableCubeSphereMapping=1;
-			}
-			else if (DisableCubeSphereMapping!=0){
-
-				glDisable(GL_TEXTURE_CUBE_MAP);
-				
-				// only disable tex gen s and t if sphere mapping isn't using them
-				if((tex_flags&64)==0){
-					glDisable(GL_TEXTURE_GEN_S);
-					glDisable(GL_TEXTURE_GEN_T);
-				}
-				
-				glDisable(GL_TEXTURE_GEN_R);
-				//glDisable(GL_TEXTURE_GEN_Q)
-
-			}
-			
-			switch(tex_blend){
-				case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
-				break;
-				case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
-				break;
-				case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-				//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
-				break;
-				case 3: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_ADD);
-				break;
-				case 4:
-					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); 
-					glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGB_EXT); 
-					break;
-				case 5:
-					glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
-					glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
-					glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE,2.0);
-					break;
-				default: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-			}
-
-			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
-			if (Shader_Tex[ix]->is3D==0){
-
-				if(surf->vbo_enabled==true && surf->no_tris>=Global::vbo_min_tris){
-			
-					if(tex_coords==0){
-						glBindBuffer(GL_ARRAY_BUFFER,surf->vbo_id[1]);
-						glTexCoordPointer(2,GL_FLOAT,0,NULL);
-					}else{
-						glBindBuffer(GL_ARRAY_BUFFER,surf->vbo_id[2]);
-						glTexCoordPointer(2,GL_FLOAT,0,NULL);
-					}
-				
-				}else{
-			
-					if(tex_coords==0){
-						//glBindBufferARB(GL_ARRAY_BUFFER_ARB,0) already reset above
-						glTexCoordPointer(2,GL_FLOAT,0,&surf->vert_tex_coords0[0]);
-					}else{
-						//glBindBufferARB(GL_ARRAY_BUFFER_ARB,0)
-						glTexCoordPointer(2,GL_FLOAT,0,&surf->vert_tex_coords1[0]);
-					}
-
-				}
-
-			}else{
-				if(surf->vbo_enabled==true && surf->no_tris>=Global::vbo_min_tris){
-			
-					glBindBuffer(GL_ARRAY_BUFFER,surf->vbo_id[2]);
-					glTexCoordPointer(3,GL_FLOAT,0,NULL);
-				
-				}else{
-			
-					//glBindBufferARB(GL_ARRAY_BUFFER_ARB,0)
-					glTexCoordPointer(3,GL_FLOAT,0,&surf->vert_tex_coords1[0]);
-
-				}
-			}
-
-							
-			// reset texture matrix
-			glMatrixMode(GL_TEXTURE);
-			glLoadIdentity();
-					
-			if(tex_u_pos!=0.0 || tex_v_pos!=0.0){
-				glTranslatef(tex_u_pos,tex_v_pos,0.0);
-			}
-			if(tex_ang!=0.0){
-				glRotatef(tex_ang,0.0,0.0,1.0);
-			}
-			if(tex_u_scale!=1.0 || tex_v_scale!=1.0){
-				glScalef(tex_u_scale,tex_v_scale,1.0);
-			}
-
-			///* ***!ES***
-			// if spheremap flag=true then flip tex
-			if(tex_flags&64){
-				glScalef(1.0,-1.0,-1.0);
-			}
-			
-			// if cubemap flag=true then manipulate texture matrix so that cubemap is displayed properly 
-			if(tex_flags&128){
-
-				glScalef(1.0,-1.0,-1.0);
-				
-				// get current modelview matrix (set in last camera update)
-				float mod_mat[16];
-				glGetFloatv(GL_MODELVIEW_MATRIX,&mod_mat[0]);
-				// get rotational inverse of current modelview matrix
-				Matrix new_mat;
-				new_mat.LoadIdentity();
-					
-				new_mat.grid[0][0] = mod_mat[0];
-				new_mat.grid[1][0] = mod_mat[1];
-				new_mat.grid[2][0] = mod_mat[2];
-
-				new_mat.grid[0][1] = mod_mat[4];
-				new_mat.grid[1][1] = mod_mat[5];
-				new_mat.grid[2][1] = mod_mat[6];
-
-				new_mat.grid[0][2] = mod_mat[8];
-				new_mat.grid[1][2] = mod_mat[9];
-				new_mat.grid[2][2] = mod_mat[10];
-					
-				glMultMatrixf(&new_mat.grid[0][0]);
-
-			}
-			//*/
-						
-		}
-	}
-
-}
-	
-void Shader::TurnOff(){
-	ProgramAttriEnd();
-	for (int ix=0; ix<=254; ix++){
-		if (Shader_Tex[ix] == 0) break;
-
-		glActiveTexture(GL_TEXTURE0+ix);
-		glClientActiveTexture(GL_TEXTURE0+ix);
-				
-		// reset texture matrix
-		glMatrixMode(GL_TEXTURE);
-		glLoadIdentity();
-				
-		if (Shader_Tex[ix]->is3D==0){
-			glDisable(GL_TEXTURE_2D);
-		}else{
-			glDisable(GL_TEXTURE_3D);
-		}
-				
-		glDisable(GL_TEXTURE_CUBE_MAP);
-		glDisable(GL_TEXTURE_GEN_S);
-		glDisable(GL_TEXTURE_GEN_T);
-		glDisable(GL_TEXTURE_GEN_R);
-			
-	}
-	for (unsigned int i=0;i<Parameters.size();i++){
-		switch(Parameters[i].type){
-		case 13:
-			if (arb_program !=0){	
-				int loc= glGetAttribLocation(arb_program->Program, Parameters[i].name.c_str());
-				glDisableVertexAttribArray(loc);
-			}
-		}
-	}
-
-
-}
-		
-
-/*	Method AddShader(_vert:String = Null , _frag:String = Null)
-'		If arb_program = Null Then Return
-'		Local Vert:TShaderObject
-'		Local Frag:TShaderObject
-'		
-'		If _Vert <> Null Then 
-'			Vert = TGlobal.RenderInterface.CreateVertexShaderObj(arb_program.languageType,_vert,arb_program)
-'			arb_program.attachVertShader(Vert)
-'		EndIf
-'		
-'		If _frag <> Null Then 
-'			frag = TGlobal.RenderInterface.CreatePixelShaderObj(arb_program.languageType,_frag,arb_program)
-'			arb_program.attachFragShader(frag)
-'		EndIf
-'	End Method*/
-	
-void Shader::AddShader(string _vert, string _frag){
-	if (arb_program == 0) return;
-	ShaderObject* Vert;
-	ShaderObject* Frag;
-	
-	if (_vert != ""){
-		Vert = ShaderObject::CreateVertShader(_vert);
-		arb_program->AttachVertShader(Vert);
-	}
-		
-	if (_frag != ""){
-		Frag = ShaderObject::CreateFragShader(_frag);
-		arb_program->AttachFragShader(Frag);
-	}
-}
-	
-void Shader::AddShaderFromString(string _vert, string _frag){
-	if (arb_program == 0) return;
-	ShaderObject* Vert;
-	ShaderObject* Frag;
-		
-	if (_vert != ""){
-		Vert = ShaderObject::CreateVertShaderFromString(_vert);
-		arb_program->AttachVertShader(Vert);
-	}
-		
-	if (_frag != ""){
-		Frag = ShaderObject::CreateFragShaderFromString(_frag);
-		arb_program->AttachFragShader(Frag);
-	}
-}
-
-
-
-	/*Method ListShaders()
-		If arb_program = Null Then Return
-		'arb_program.ListAttachedShaders()
-	End Method */
-
-void Shader::AddSampler2D(string Name, int Slot, Texture* Tex){
-	Shader_Tex[Slot] = Sampler::Create(Name,Slot,Tex);
-	UpdateSampler = 1;
-	Shader_Tex[Slot]->is3D=0;
-	texCount++;
-}
-	
-void Shader::AddSampler3D(string Name, int Slot, Texture* Tex){
-	Shader_Tex[Slot] = Sampler::Create(Name,Slot,Tex);
-	UpdateSampler = 1;
-	Shader_Tex[Slot]->is3D=1;
-	texCount++;
-}
-
-
-void Shader::ProgramAttriBegin(){
-	if (arb_program !=0){arb_program->Activate();}
-}	
-
-void Shader::ProgramAttriEnd(){
-	if (arb_program !=0){arb_program->DeActivate();}
-}	
-
-void Shader::SetFloat(string name, float v1){
-	ProgramAttriBegin();
-	if (arb_program !=0){arb_program->SetParameter1F(name, v1);}
-	ProgramAttriEnd();
-}
-
-void Shader::SetFloat2(string name, float v1, float v2){
-	ProgramAttriBegin();
-	if (arb_program !=0){arb_program->SetParameter2F(name, v1, v2);}
-	ProgramAttriEnd();
-}
-
-void Shader::SetFloat3(string name, float v1, float v2, float v3){
-	ProgramAttriBegin();
-	if (arb_program !=0){arb_program->SetParameter3F(name, v1, v2, v3);}
-	ProgramAttriEnd();
-}
-
-void Shader::SetFloat4(string name, float v1, float v2, float v3, float v4){
-	ProgramAttriBegin();
-	if (arb_program !=0){arb_program->SetParameter4F(name, v1, v2, v3, v4);}
-	ProgramAttriEnd();
-}
-
-void Shader::UseFloat(string name, float* v1){
-	ShaderData data;
-	data.name=name;
-	data.type=0;
-	data.fp[0]=v1;
-	Parameters.push_back(data);
-}
-
-void Shader::UseFloat2(string name, float* v1, float* v2){
-	ShaderData data;
-	data.name=name;
-	data.type=1;
-	data.fp[0]=v1;
-	data.fp[1]=v2;
-	Parameters.push_back(data);
-}
-
-void Shader::UseFloat3(string name, float* v1, float* v2, float* v3){
-	ShaderData data;
-	data.name=name;
-	data.type=2;
-	data.fp[0]=v1;
-	data.fp[1]=v2;
-	data.fp[2]=v3;
-	Parameters.push_back(data);
-}
-
-void Shader::UseFloat4(string name, float* v1, float* v2, float* v3, float* v4){
-	ShaderData data;
-	data.name=name;
-	data.type=3;
-	data.fp[0]=v1;
-	data.fp[1]=v2;
-	data.fp[2]=v3;
-	data.fp[3]=v4;
-	Parameters.push_back(data);
-}
-
-void Shader::SetInteger(string name, int v1){
-	ProgramAttriBegin();
-	if (arb_program !=0){arb_program->SetParameter1I(name, v1);}
-	ProgramAttriEnd();
-}
-
-void Shader::SetInteger2(string name, int v1, int v2){
-	ProgramAttriBegin();
-	if (arb_program !=0){arb_program->SetParameter2I(name, v1, v2);}
-	ProgramAttriEnd();
-}
-
-void Shader::SetInteger3(string name, int v1, int v2, int v3){
-	ProgramAttriBegin();
-	if (arb_program !=0){arb_program->SetParameter3I(name, v1, v2, v3);}
-	ProgramAttriEnd();
-}
-
-void Shader::SetInteger4(string name, int v1, int v2, int v3, int v4){
-	ProgramAttriBegin();
-	if (arb_program !=0){arb_program->SetParameter4I(name, v1, v2, v3, v4);}
-	ProgramAttriEnd();
-}
-
-void Shader::UseInteger(string name, int* v1){
-	ShaderData data;
-	data.name=name;
-	data.type=4;
-	data.ip[0]=v1;
-	Parameters.push_back(data);
-}
-
-void Shader::UseInteger2(string name, int* v1, int* v2){
-	ShaderData data;
-	data.name=name;
-	data.type=5;
-	data.ip[0]=v1;
-	data.ip[1]=v2;
-	Parameters.push_back(data);
-}
-
-void Shader::UseInteger3(string name, int* v1, int* v2, int* v3){
-	ShaderData data;
-	data.name=name;
-	data.type=6;
-	data.ip[0]=v1;
-	data.ip[1]=v2;
-	data.ip[2]=v3;
-	Parameters.push_back(data);
-}
-
-void Shader::UseInteger4(string name, int* v1, int* v2, int* v3, int* v4){
-	ShaderData data;
-	data.name=name;
-	data.type=7;
-	data.ip[0]=v1;
-	data.ip[1]=v2;
-	data.ip[2]=v3;
-	data.ip[3]=v4;
-	Parameters.push_back(data);
-}
-
-
-
-void Shader::UseSurface(string name, Surface* surf, int vbo){
-	ShaderData data;
-	data.name=name;
-	data.type=13;
-	data.surf=surf;
-	data.vbo=vbo;
-	Parameters.push_back(data);
-}
-
-void Shader::UseMatrix(string name, int mode){
-	ShaderData data;
-	data.name=name;
-	if (mode==1) {
-		data.type=14;
-	}else{
-		data.type=15;
-	}
-	Parameters.push_back(data);
-}
-/*void Shader::SetParameter1S(string name, float v1){
-	if (arb_program !=0){arb_program->SetParameter1S(name, v1);}
-}
-
-void Shader::SetParameter2S(string name, float v1, float v2){
-	if (arb_program !=0){arb_program->SetParameter2S(name, v1, v2);}
-}
-
-void Shader::SetParameter3S(string name, float v1, float v2, float v3){
-	if (arb_program !=0){arb_program->SetParameter3S(name, v1, v2, v3);}
-}
-
-void Shader::SetParameter4S(string name, float v1, float v2, float v3, float v4){
-	if (arb_program !=0){arb_program->SetParameter4S(name, v1, v2, v3, v4);}
-}
-
-void Shader::SetParameter1I(string name, int v1){
-	if (arb_program !=0){arb_program->SetParameter1I(name, v1);}
-}
-
-void Shader::SetParameter2I(string name, int v1, int v2){
-	if (arb_program !=0){arb_program->SetParameter2I(name, v1, v2);}
-}
-
-void Shader::SetParameter3I(string name, int v1, int v2, int v3){
-	if (arb_program !=0){arb_program->SetParameter3I(name, v1, v2, v3);}
-}
-
-void Shader::SetParameter4I(string name, int v1, int v2, int v3, int v4){
-	if (arb_program !=0){arb_program->SetParameter4I(name, v1, v2, v3, v4);}
-}
- 
-void Shader::SetVector1I(string name, int* v1){
-	if (arb_program !=0){arb_program->SetVector1I(name, v1);}
-}
-
-void Shader::SetVector2I(string name, int* v1){
-	if (arb_program !=0){arb_program->SetVector2I(name, v1);}
-}
-
-void Shader::SetVector3I(string name, int* v1){
-	if (arb_program !=0){arb_program->SetVector3I(name, v1);}
-}
-
-void Shader::SetVector4I(string name, int* v1){
-	if (arb_program !=0){arb_program->SetVector4I(name, v1);}
-}
-
-void Shader::SetParameter1F(string name, float v1){
-	//if (arb_program !=0){arb_program->SetParameter1F(name, v1);}
-	ShaderData data;
-	data.name=name;
-	data.type=0;
-	data.valuef[0]=v1;
-	Parameters.push_back(data);
-}
-
-void Shader::SetParameter2F(string name, float v1, float v2){
-	if (arb_program !=0){arb_program->SetParameter2F(name, v1, v2);}
-}
-
-void Shader::SetParameter3F(string name, float v1, float v2, float v3){
-	if (arb_program !=0){arb_program->SetParameter3F(name, v1, v2, v3);}
-}
-
-void Shader::SetParameter4F(string name, float v1, float v2, float v3, float v4){
-	if (arb_program !=0){arb_program->SetParameter4F(name, v1, v2, v3, v4);}
-}
-
-void Shader::SetVector1F(string name, float* v1){
-	if (arb_program !=0){arb_program->SetVector1F(name, v1);}
-}
-
-void Shader::SetVector2F(string name, float* v1){
-	if (arb_program !=0){arb_program->SetVector2F(name, v1);}
-}
-
-void Shader::SetVector3F(string name, float* v1){
-	if (arb_program !=0){arb_program->SetVector3F(name, v1);}
-}
-
-void Shader::SetVector4F(string name, float* v1){
-	if (arb_program !=0){arb_program->SetVector4F(name, v1);}
-}
-
-void Shader::SetMatrix2F(string name, float* m){
-	//if (arb_program !=0){arb_program->SetMatrix2F(name, m);}
-	ShaderData data;
-	data.name=name;
-	data.type=11;
-	data.pf=m;
-	Parameters.push_back(data);
-
-}
-
-void Shader::SetMatrix3F(string name, float* m){
-	if (arb_program !=0){arb_program->SetMatrix3F(name, m);}
-}
-
-void Shader::SetMatrix4F(string name, float* m){
-	if (arb_program !=0){arb_program->SetMatrix4F(name, m);}
-}
-
-void Shader::SetParameter1D(string name, double v1){
-	if (arb_program !=0){arb_program->SetParameter1D(name, v1);}
-}
-
-void Shader::SetParameter2D(string name, double v1, double v2){
-	if (arb_program !=0){arb_program->SetParameter2D(name, v1, v2);}
-}
-
-void Shader::SetParameter3D(string name, double v1, double v2, double v3){
-	if (arb_program !=0){arb_program->SetParameter3D(name, v1, v2, v3);}
-}
-
-void Shader::SetParameter4D(string name, double v1, double v2, double v3, double v4){
-	if (arb_program !=0){arb_program->SetParameter4D(name, v1, v2, v3, v4);}
-}*/
-
-//ShaderObject
-
-ProgramObject* ProgramObject::Create(string name){
-	ProgramObject* p = new ProgramObject;
-		
-	//Create a new GL ProgramObject
-	p->Program = glCreateProgram();
-	if (p->Program == 0){
-		p = 0;
-		return 0;
-	}
-		
-	/*--------------------------------
-	'The amount of Vert & Frag Shaders
-	'attached to this Program Object
-	'---------------------------------*/
-	p->vertShaderCount = 0;
-	p->fragShaderCount = 0;
-	
-	/*--------------------------------------
-	'These lists contain any Vert or Frag
-	'Shader Objects Attached to this Program
-	'-------------------------------------
-	p->vList:TList = CreateList();
-	p->fList:TList = CreateList();*/
-	
-	//This Program Objects Name
-	p->progName = name;
-		
-	/*-----------------------------
-	'Add this Program Object to the
-	'Global list of ProgramObjects
-	'------------------------------*/
-	ProgramObjectList.push_back(p);
-	return p;
-}
-
-void ProgramObject::Activate(){
-	glUseProgram(Program);
-}
-
-void ProgramObject::DeActivate(){
-	glUseProgram(0);
-}
-
-void ProgramObject::RefreshTypeMap(){
-	TypeMap.clear();
-		
-	int maxlen;
-	int count;
-		 
-	glGetProgramiv( Program,GL_ACTIVE_UNIFORM_MAX_LENGTH ,&maxlen);
-	glGetProgramiv( Program,GL_ACTIVE_UNIFORMS ,&count);
-	char* name=new char[maxlen+1];
-	for (int i=0;i<=count; i++){
-		int glsize;
-		GLenum gltype;
-		glGetActiveUniform (Program,i,maxlen,0,&glsize,&gltype,name);
-		TypeMap[name]=1;//"Uniform"
-	}
-	delete [] name;
-
-	glGetProgramiv( Program,GL_ACTIVE_ATTRIBUTE_MAX_LENGTH ,&maxlen);
-	glGetProgramiv( Program,GL_ACTIVE_ATTRIBUTES ,&count);
-	name=new char[maxlen+1];
-	for (int i=0;i<=count; i++){
-		int glsize;
-		GLenum gltype;
-		glGetActiveAttrib(Program,i,maxlen,0,&glsize,&gltype,name);
-		TypeMap[name]=2;//"Attribute"
-	}
-	delete [] name;
-		
-		
-}
-
-// Get the Uniform Variable Location from a ProgramObject
-int ProgramObject::GetUniLoc(string name){
-	return glGetUniformLocation(Program, name.c_str());
-}
-
-// Get the Attribute Variable Location from a ProgramObject
-int ProgramObject::GetAttribLoc(string name){
-	return glGetAttribLocation(Program, name.c_str());
-}
-
-void ProgramObject::SetParameter1S(string name, float v1){
-	int loc= glGetAttribLocation(Program, name.c_str());
-	glVertexAttrib1s(loc, v1);
-}
-	
-void ProgramObject::SetParameter2S(string name, float v1, float v2) {
-	int loc= glGetAttribLocation(Program, name.c_str());
-	glVertexAttrib2s(loc, v1,v2);
-}
-	 
-void ProgramObject::SetParameter3S(string name, float v1, float v2, float v3){
-	int loc= glGetAttribLocation(Program, name.c_str());
-	glVertexAttrib3s(loc, v1,v2,v3);
-}
-	  
-void ProgramObject::SetParameter4S(string name, float v1, float v2, float v3, float v4){
-	int loc= glGetAttribLocation(Program, name.c_str());
-	glVertexAttrib4s(loc, v1,v2,v3,v4);
-}
-	
-//------------------------------------------------------------
-// Int Parameter
-	
-void ProgramObject::SetParameter1I(string name, int v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform1i(loc,v1);
-}
-
-void ProgramObject::SetParameter2I(string name, int v1, int v2){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform2i(loc,v1,v2);
-}
-
-void ProgramObject::SetParameter3I(string name, int v1, int v2, int v3){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform3i(loc,v1,v2,v3);
-}
-
-void ProgramObject::SetParameter4I(string name, int v1, int v2, int v3, int v4){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform4i(loc,v1,v2,v3,v4);
-}
-	
-//----------------------------------------------------------------------------------
-// Int Vectors
-
-void ProgramObject::SetVector1I(string name, int* v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform1iv(loc,1,v1);
-}
-				
-void ProgramObject::SetVector2I(string name, int* v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform2iv(loc,1,v1);
-}
-										
-void ProgramObject::SetVector3I(string name, int* v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform3iv(loc,1,v1);
-}
-										
-void ProgramObject::SetVector4I(string name, int* v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform4iv(loc,1,v1);
-}
-				
-//-------------------------------------------------------------------------------------
-// Double Parameter ( automatically Attributes, because Uniform doubles does not exist)
-	
-void ProgramObject::SetParameter1D(string name, double v1){
-	int loc= glGetAttribLocation(Program, name.c_str());
-	glVertexAttrib1d(loc, v1);
-}
-	 
-void ProgramObject::SetParameter2D(string name, double v1, double v2){
-	int loc= glGetAttribLocation(Program, name.c_str());
-	glVertexAttrib2d(loc, v1, v2);
-}
-	 
-void ProgramObject::SetParameter3D(string name, double v1, double v2, double v3){
-	int loc= glGetAttribLocation(Program, name.c_str());
-	glVertexAttrib3d(loc, v1, v2, v3);
-}
-	 
-void ProgramObject::SetParameter4D(string name, double v1, double v2, double v3, double v4){
-	int loc= glGetAttribLocation(Program, name.c_str());
-	glVertexAttrib4d(loc, v1, v2, v3, v4);
-}
-
-
-//-------------------------------------------------------------------------------------
-// Array Parameter
-
-void ProgramObject::SetParameterArray(string name, Surface* surf, int vbo){
-	int loc= glGetAttribLocation(Program, name.c_str());
-	if(surf->vbo_enabled!=0){
-		surf->reset_vbo=vbo;
-
-		Surface& surf2=*surf;
-		glBindBuffer(GL_ARRAY_BUFFER,0);
-		switch (vbo){
-		case 1:
-			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[0]);
-			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
-			break;
-		case 2:
-			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[1]);
-			glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
-
-		case 3:
-			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[2]);
-			glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
-			break;
-		case 4:
-			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[3]);
-			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
-			break;
-		case 5:
-			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[4]);
-			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 16, 0);
-			break;
-
-		case 6:
-			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[4]);
-			glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, 0);
-			break;
-		}
-
-	}else{
-		Surface& surf2=*surf;
-		glBindBuffer(GL_ARRAY_BUFFER,0);
-		switch (vbo){
-		case 1:
-			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, &surf2.vert_coords[0]);
-			break;
-		case 2:
-			glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, &surf2.vert_tex_coords0[0]);
-			break;
-		case 3:
-			glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, &surf2.vert_tex_coords1[0]);
-			break;
-		case 4:
-			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, &surf2.vert_norm[0]);
-			break;
-		case 5:
-			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 16, &surf2.vert_col[0]);
-			break;
-
-		case 6:
-			glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, &surf2.vert_col[0]);
-			break;
-		}
-	}
-
-	glEnableVertexAttribArray(loc);
-}
-
-//-------------------------------------------------------------------------------------
-// Float Parameter
-
-void ProgramObject::SetParameter1F(string name, float v){
-	if (TypeMap.find(name) == TypeMap.end() ){
-		return;
-	}
-	int ParameterType=TypeMap.find(name)->second;
-	
-	if (ParameterType == 1){		//"Uniform" 
-		int loc= glGetUniformLocation(Program, name.c_str());
-		glUniform1f(loc, v);
-			
-	} else if (ParameterType == 2){		//"Attribute"
- 
-		int loc= glGetAttribLocation(Program, name.c_str());
-		glVertexAttrib1f(loc, v);
-
-	}
-		
-}
-
-void ProgramObject::SetParameter2F(string name, float v1, float v2){
-	if (TypeMap.find(name) == TypeMap.end() ){
-		return;
-	}
-	int ParameterType=TypeMap.find(name)->second;
-	
-	if (ParameterType == 1){		//"Uniform" 
-		int loc= glGetUniformLocation(Program, name.c_str());
-		glUniform2f(loc, v1, v2);
-			
-	} else if (ParameterType == 2){		//"Attribute"
- 
-		int loc= glGetAttribLocation(Program, name.c_str());
-		glVertexAttrib2f(loc, v1, v2);
-
-	}
-
-}
-
-void ProgramObject::SetParameter3F(string name, float v1, float v2, float v3){
-		
-	if (TypeMap.find(name) == TypeMap.end() ){
-		return;
-	}
-	int ParameterType=TypeMap.find(name)->second;
-		
-	if (ParameterType == 1){		//"Uniform" 
-		int loc= glGetUniformLocation(Program, name.c_str());
-		glUniform3f(loc, v1,v2,v3);
-			
-	} else if (ParameterType == 2){		//"Attribute"
- 
-		int loc= glGetAttribLocation(Program, name.c_str());
-		glVertexAttrib3f(loc, v1, v2, v3);
-
-	}
-}
-
-void ProgramObject::SetParameter4F(string name, float v1, float v2, float v3, float v4){
-	if (TypeMap.find(name) == TypeMap.end() ){
-		return;
-	}
-	int ParameterType=TypeMap.find(name)->second;
-		
-	if (ParameterType == 1){		//"Uniform" 
-		int loc= glGetUniformLocation(Program, name.c_str());
-		glUniform4f(loc, v1,v2,v3,v4);
-			
-	} else if (ParameterType == 2){		//"Attribute"
- 
-		int loc= glGetAttribLocation(Program, name.c_str());
-		glVertexAttrib4f(loc, v1, v2, v3,v4);
-
-	}
-}
-
-//---------------------------------------------------------------------------------------------------
-// Float Vectors
-
-
-void ProgramObject::SetVector1F(string name, float* v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform1fv(loc,1,v1);
-}
-
-void ProgramObject::SetVector2F(string name, float* v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform2fv(loc,1,v1);
-}
-
-void ProgramObject::SetVector3F(string name, float* v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform3fv(loc,1,v1);
-}
-
-void ProgramObject::SetVector4F(string name, float* v1){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniform4fv(loc,1,v1);
-}
-
-
-//--------------------------------------------------------------------------------------------------
-// Matrices
-
-void ProgramObject::SetMatrix2F(string name, float* m){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniformMatrix2fv(loc, 1 , 0, m );
-} 
-
-void ProgramObject::SetMatrix3F(string name, float* m){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniformMatrix3fv(loc, 1 , 0, m );	
-}
-
-void ProgramObject::SetMatrix4F(string name, float* m){
-	int loc= glGetUniformLocation(Program, name.c_str());
-	glUniformMatrix4fv(loc, 1 , 0, m );
-}
-
-
-//----------------------------------------------------------
-//Attach & Link a Vertex Shader Object to this ProgramObject
-//----------------------------------------------------------
-int ProgramObject::AttachVertShader(ShaderObject* myShader){
-	/*-------------------------
-	'Attach & Link a VertShader
-	'------------------------*/
-	glAttachShader(Program, myShader->ShaderObj);
-	glLinkProgram(Program);
-
-
-	/*-------------------------------
-	'Check if it Linked successfully
-	'------------------------------*/
-	int linked;
-	glValidateProgram(Program);
-	glGetProgramiv(Program,GL_LINK_STATUS, &linked);
-	
-	if (linked==0){
-		return 0;
-	}
-
-	//Add this VertShaderObject to this ProgramObjects list
-	vList.push_back(myShader);
-
-	//Add this ProgramObject to this Shaders 'attached to' list
-	myShader->Attached.push_back(this);
-	RefreshTypeMap();
-	return 1;
-}
-
-//------------------------------------------------------------
-//Attach & Link a Fragment Shader Object to this ProgramObject
-//------------------------------------------------------------
-int ProgramObject::AttachFragShader(ShaderObject* myShader){
-	/*-------------------------
-	'Attach & Link a FragShader
-	'------------------------*/
-	glAttachShader(Program, myShader->ShaderObj);
-	glLinkProgram(Program);
-
-
-	/*-------------------------------
-	'Check if it Linked successfully
-	'------------------------------*/
-	int linked;
-	glValidateProgram(Program);
-	glGetProgramiv(Program,GL_LINK_STATUS, &linked);
-
-	if (linked==0){
-		return 0;
-	}
-
-	//Add this FragShaderObject to this ProgramObjects list
-	fList.push_back(myShader);
-	
-	//Add this ProgramObject to this Shaders 'attached to' list
-	myShader->Attached.push_back(this);
-	RefreshTypeMap();
-	return 1;
-}
-
-//-------------------------------------------------------
-//Detach a VertShader:tShaderObject from a tProgramObject
-//-------------------------------------------------------
-void ProgramObject::DetachVertShader(ShaderObject* vShader){
-	list<ShaderObject*>::iterator it;
-
-	for(it=vList.begin();it!=vList.end();it++){
-		if (vShader==*it){
-			glDetachShader(Program, vShader->ShaderObj);
-			vList.remove(vShader);
-			vShader->Attached.remove(this);
-			break;
-		}
-	}
-}
-
-//-------------------------------------------------------
-//Detach a FragShader:tShaderObject from a tProgramObject
-//-------------------------------------------------------
-void ProgramObject::DetachFragShader(ShaderObject* fShader){
-	list<ShaderObject*>::iterator it;
-
-	for(it=fList.begin();it!=vList.end();it++){
-		if (fShader==*it){
-			glDetachShader(Program, fShader->ShaderObj);
-			fList.remove(fShader);
-			fShader->Attached.remove(this);
-			break;
-		}
-	}
-}
-
-
-/*------------------------------------------------------
-/Dump a list of Shaders attached to this tProgramObject
-/------------------------------------------------------
-Method ListAttachedShaders()
-	Print "Vertex Shader(s) attached to ProgramObject '"+Self.progName+"'"
-	Print "----------------------------------------------------------------------"
-	If vList.Count() = 0
-		Print "No Vertex Shaders attached"
-	Else
-		For Local v:tShaderObject = EachIn vList
-			Print v.shaderName
-		Next
-	End If
-		
-	Print
-	Print "Fragment Shader(s) attached to ProgramObject '"+Self.progName+"'"
-	Print "-----------------------------------------------------------------------"
-	If fList.Count() = 0
-		Print "No Fragment Shaders attached"
-	Else
-		For Local f:tShaderObject = EachIn fList
-			Print f.shaderName
-		Next
-	End If
-	Print
-End Method*/
-
-void CopyPixels (unsigned char *src, unsigned int srcWidth, unsigned int srcHeight, unsigned int srcX, unsigned int srcY, unsigned char *dst, unsigned int dstWidth, unsigned int dstHeight, unsigned int bytesPerPixel);
-
-
-Material* Material::LoadMaterial(string filename,int flags, int frame_width,int frame_height,int first_frame,int frame_count){
-
-	//filename=Strip(filename); // get rid of path info
-
-	if(File::ResourceFilePath(filename)==""){
-		cout << "Error: Cannot Find Texture: " << filename << endl;
-		return NULL;
-	}
-
-	Material* tex=new Material();
-	tex->file=filename;
-
-	// set tex.flags before TexInList
-	tex->flags=flags;
-	tex->FilterFlags();
-
-	/*// check to see if texture with same properties exists already, if so return existing texture
-	Texture* old_tex=tex->TexInList();
-	if(old_tex){
-		return old_tex;
-	}else{
-		tex_list.push_back(tex);
-	}*/
-
-	//const char* c_filename_left=filename_left.c_str();
-	//const char* c_filename_right=filename_right.c_str();
-
-
-	unsigned char* buffer;
-
-	buffer=stbi_load(filename.c_str(),&tex->width,&tex->height,0,4);
-
-	unsigned int name;
-
-	glGenTextures (1,&name);
-	glBindTexture (GL_TEXTURE_3D,name);
-
-	tex->no_frames=frame_count;
-	//tex->frames=new unsigned int[frame_count];
-
-	unsigned char* dstbuffer=new unsigned char[frame_width*frame_height*4*frame_count];
-
-	glGenTextures (1,&name);
-	glBindTexture (GL_TEXTURE_3D,name);
-
-
-	//tex.gltex=tex.gltex[..tex.no_frames]
-
-	int frames_in_row=tex->width/frame_width;
-
-	for (int i=0;i<frame_count;i++){
-		CopyPixels (buffer,tex->width, tex->height,frame_width*(i%frames_in_row), frame_height*(i/frames_in_row),
-		dstbuffer+i*(frame_width * frame_height * 4), frame_width, frame_height, 4);
-
-
-	}
-
-	glTexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP, GL_TRUE);
-	glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,frame_width, frame_height, frame_count, 0, GL_RGBA, GL_UNSIGNED_BYTE, dstbuffer);
-
-	tex->texture=name;
-	tex->width=frame_width;
-	tex->height=frame_height;
-	delete dstbuffer;
-	stbi_image_free(buffer);
-
-
-	return tex;
-
-}
-
+#include <iostream>
+#include <string>
+;
+
+#include "glew.h"
+/*
+#ifdef linux
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glu.h>
+#endif
+#ifdef WIN32
+#include "GLee.h"
+#include <GL\glu.h>
+#endif
+#ifdef __APPLE__
+#include "GLee.h"
+#include <OpenGL/glu.h>
+#endif
+*/
+#include "surface.h"
+#include "camera.h"
+#include "shadermat.h"
+#include "file.h"
+#include "global.h"
+#include "stb_image.h"
+
+
+list<ShaderObject*> ShaderObject::ShaderObjectList;
+list<ProgramObject*> ProgramObject::ProgramObjectList;
+int Shader::ShaderIDCount;
+
+
+/*ShaderObject* ShaderObject::CreateVertShader(string shaderFileName);
+ShaderObject* ShaderObject::CreateFragShader(string shaderFileName);
+ShaderObject* ShaderObject::CreateVertShaderFromString(string shadercode);
+ShaderObject* ShaderObject::CreateFragShaderFromString(string shadercode);
+*/
+
+
+ShaderObject* ShaderObject::CreateVertShader(string shaderFileName){
+	// Load the shader and dump it into a Byte Array
+	File* file=File::ReadFile(shaderFileName); // opens as ASCII!
+	if(file==0) {
+		return 0;
+	}
+
+/*	unsigned long pos=file.tellg();
+	file.seekg(0,ios::end);
+	unsigned long FileLength = file.tellg();
+	file.seekg(ios::beg);
+*/	
+	fseek(file->pFile, 0L, SEEK_END);
+	unsigned long FileLength = ftell(file->pFile);
+	fseek(file->pFile, 0L, SEEK_SET);
+
+	//int ShaderObject;
+	ShaderObject* myShader = new ShaderObject;
+	
+	myShader->ShaderObj = glCreateShader(GL_VERTEX_SHADER);
+	myShader->ShaderType = 1; // 1 = Vert, 2 = Frag/Pixel
+
+	char* shaderSrc;
+
+	shaderSrc = new char[FileLength+1];
+	if (shaderSrc == 0) return 0;   // can't reserve memory
+   
+	// FileLength isn't always strlen cause some characters are stripped in ascii read...
+	// it is important to 0-terminate the real length later, len is just max possible value... 
+	shaderSrc[FileLength] = 0; 
+
+	unsigned int i=0;
+	while (!file->Eof())
+	{
+		shaderSrc[i] = file->ReadByte();       // get character from file.
+		i++;
+	}
+    
+	shaderSrc[i] = 0;  // 0-terminate it at the correct position
+    
+	file->CloseFile();
+
+
+	
+	int shaderLen[1];
+	shaderLen[0] = i;
+
+	//Local shaderPtr:Byte Ptr[1]
+	//shaderPtr[0] = Varptr(shaderSrc[0])
+
+	// Send shader to ShaderObject, then compile it
+	glShaderSource(myShader->ShaderObj,1, (const GLchar**)&shaderSrc, 0);
+	glCompileShader(myShader->ShaderObj);
+
+	// Did the shader compile successfuly?
+	int compiled;
+	glGetShaderiv(myShader->ShaderObj,GL_COMPILE_STATUS, &compiled);
+
+	if (!compiled){
+		delete myShader;
+		return 0;
+		}
+
+
+	//myShader.Attached = New TList
+	myShader->shaderName = shaderFileName;
+	ShaderObject::ShaderObjectList.push_back(myShader);
+	
+	return myShader;
+}
+
+
+
+
+/*
+'-----------------------------------------------------------
+'CreateFragShader:tShaderObject(shaderFileName:String)
+'
+'Creates a Fragment Shader Object from a File
+'
+'Returns: A tShaderObject if successful, or Null if it fails
+'-----------------------------------------------------------
+*/
+
+
+ShaderObject* ShaderObject::CreateFragShader(string shaderFileName){
+	// Load the shader and dump it into a Byte Array
+	File* file=File::ReadFile(shaderFileName); // opens as ASCII!
+
+	if(file==0) {
+		return 0;
+	}
+
+/*	unsigned long pos=file.tellg();
+	file.seekg(0,ios::end);
+	unsigned long FileLength = file.tellg();
+	file.seekg(ios::beg);
+*/	
+	fseek(file->pFile, 0L, SEEK_END);
+	unsigned long FileLength = ftell(file->pFile);
+	fseek(file->pFile, 0L, SEEK_SET);
+
+	//int ShaderObject;
+	ShaderObject* myShader = new ShaderObject;
+	
+	myShader->ShaderObj = glCreateShader(GL_FRAGMENT_SHADER);
+	myShader->ShaderType = 2; // 1 = Vert, 2 = Frag/Pixel
+
+	char* shaderSrc;
+
+	shaderSrc = new char[FileLength+1];
+	if (shaderSrc == 0) return 0;   // can't reserve memory
+   
+	// FileLength isn't always strlen cause some characters are stripped in ascii read...
+	// it is important to 0-terminate the real length later, len is just max possible value... 
+	shaderSrc[FileLength] = 0; 
+
+	unsigned int i=0;
+	while (!file->Eof())
+	{
+		shaderSrc[i] = file->ReadByte();       // get character from file.
+		i++;
+	}
+    
+	shaderSrc[i] = 0;  // 0-terminate it at the correct position
+    
+	file->CloseFile();
+
+
+	
+	int shaderLen[1];
+	shaderLen[0] = i;
+
+	//Local shaderPtr:Byte Ptr[1]
+	//shaderPtr[0] = Varptr(shaderSrc[0])
+
+	// Send shader to ShaderObject, then compile it
+	glShaderSource(myShader->ShaderObj,1, (const GLchar**)&shaderSrc, 0);
+	glCompileShader(myShader->ShaderObj);
+
+	// Did the shader compile successfuly?
+	int compiled;
+	glGetShaderiv(myShader->ShaderObj,GL_COMPILE_STATUS, &compiled);
+
+	if (!compiled){
+		delete myShader;
+		return 0;
+		}
+
+
+	//myShader.Attached = New TList
+	myShader->shaderName = shaderFileName;
+	ShaderObject::ShaderObjectList.push_back(myShader);
+	return myShader;
+}
+/*
+
+'-----------------------------------------------------------
+'CreateVertShader:tShaderObject(shaderFileName:String)
+'
+'Creates a Vertex Shader Object from a File
+'
+'Returns: A tShaderObject if successful, or Null if it fails
+'-----------------------------------------------------------
+*/
+ShaderObject* ShaderObject::CreateVertShaderFromString(string shadercode){
+	// Load the shader and dump it into a Byte Array
+	if (shadercode == ""){
+		return 0;
+	}
+	
+	//Local tempShaderName:String = "Code"+Rand(10000)
+	unsigned int FileLength = shadercode.size();
+	//int ShaderObject;
+	ShaderObject* myShader = new ShaderObject;
+	
+	myShader->ShaderObj = glCreateShader(GL_VERTEX_SHADER);
+	myShader->ShaderType = 1; // 1 = Vert, 2 = Frag/Pixel
+
+	//Create a Byte Array to which the Shader Source will be copied to
+	//The extra Array Byte (FileLength+1) is so we can Null terminate the array
+	char* shaderSrc;
+
+	shaderSrc = new char[FileLength+1];
+	if (shaderSrc == 0) return 0;   // can't reserve memory
+   
+	// FileLength isn't always strlen cause some characters are stripped in ascii read...
+	// it is important to 0-terminate the real length later, len is just max possible value... 
+	shaderSrc[FileLength] = 0; 
+
+	unsigned int i=0;
+	while (i<FileLength)
+	{
+		shaderSrc[i] = shadercode[i];       // get character from file.
+		i++;
+	}
+    
+	shaderSrc[i] = 0;  // 0-terminate it at the correct position
+
+
+	// Send shader to ShaderObject, then compile it
+	glShaderSource(myShader->ShaderObj,1, (const GLchar**)&shaderSrc, 0);
+	glCompileShader(myShader->ShaderObj);
+
+	// Did the shader compile successfuly?
+	int compiled;
+	glGetShaderiv(myShader->ShaderObj,GL_COMPILE_STATUS, &compiled);
+
+	if (!compiled){
+		delete myShader;
+		return 0;
+		}
+
+
+	//myShader.Attached = New TList
+	//myShader->shaderName = shaderFileName;
+	ShaderObject::ShaderObjectList.push_back(myShader);
+	
+	return myShader;
+}
+
+/*
+'-----------------------------------------------------------
+'CreateFragShader:tShaderObject(shaderFileName:String)
+'
+'Creates a Fragment Shader Object from a File
+'
+'Returns: A tShaderObject if successful, or Null if it fails
+'-----------------------------------------------------------*/
+
+ShaderObject* ShaderObject::CreateFragShaderFromString(string shadercode){
+	// Load the shader and dump it into a Byte Array
+	if (shadercode == ""){
+		return 0;
+	}
+	
+	//Local tempShaderName:String = "Code"+Rand(10000)
+	unsigned int FileLength = shadercode.size();
+	//int ShaderObject;
+	ShaderObject* myShader = new ShaderObject;
+	
+	myShader->ShaderObj = glCreateShader(GL_FRAGMENT_SHADER);
+	myShader->ShaderType = 2; // 1 = Vert, 2 = Frag/Pixel
+
+	//Create a Byte Array to which the Shader Source will be copied to
+	//The extra Array Byte (FileLength+1) is so we can Null terminate the array
+	char* shaderSrc;
+
+	shaderSrc = new char[FileLength+1];
+	if (shaderSrc == 0) return 0;   // can't reserve memory
+   
+	// FileLength isn't always strlen cause some characters are stripped in ascii read...
+	// it is important to 0-terminate the real length later, len is just max possible value... 
+	shaderSrc[FileLength] = 0; 
+
+	unsigned int i=0;
+	while (i<FileLength)
+	{
+		shaderSrc[i] = shadercode[i];       // get character from file.
+		i++;
+	}
+    
+	shaderSrc[i] = 0;  // 0-terminate it at the correct position
+
+
+	// Send shader to ShaderObject, then compile it
+	glShaderSource(myShader->ShaderObj,1, (const GLchar**)&shaderSrc, 0);
+	glCompileShader(myShader->ShaderObj);
+
+	// Did the shader compile successfuly?
+	int compiled;
+	glGetShaderiv(myShader->ShaderObj,GL_COMPILE_STATUS, &compiled);
+
+	if (!compiled){
+		delete myShader;
+		return 0;
+		}
+
+
+	//myShader.Attached = New TList
+	//myShader->shaderName = shaderFileName;
+	ShaderObject::ShaderObjectList.push_back(myShader);
+	
+	return myShader;
+}
+
+
+void ShaderObject::DeleteVertShader(ShaderObject* vShader){
+	if (vShader==0) return;
+
+	ShaderObject::ShaderObjectList.remove(vShader);
+	
+	// Detach this ShaderObject from all ProgramObjects it was attached to
+	list<ProgramObject*>::iterator it;
+
+	for(it=ProgramObject::ProgramObjectList.begin();it!=ProgramObject::ProgramObjectList.end();it++){
+		ProgramObject* p=*it;
+
+		p->DetachVertShader(vShader);
+	}
+	
+	// Delete the shader
+	glDeleteShader(vShader->ShaderObj);
+	delete vShader;
+}
+
+void ShaderObject::DeleteFragShader(ShaderObject* fShader){
+	if (fShader==0) return;
+
+	ShaderObject::ShaderObjectList.remove(fShader);
+	
+	// Detach this ShaderObject from all ProgramObjects it was attached to
+	list<ProgramObject*>::iterator it;
+
+	for(it=ProgramObject::ProgramObjectList.begin();it!=ProgramObject::ProgramObjectList.end();it++){
+		ProgramObject* p=*it;
+
+		p->DetachFragShader(fShader);
+	}
+	
+	// Delete the shader
+	glDeleteShader(fShader->ShaderObj);
+	delete fShader;
+}	
+/*Function DeleteFragShader(fShader:tShaderObject Var)
+	If Not fShader Return
+	
+	RemoveLink(ListFindLink(ShaderObjectList,fShader))
+		
+	' Detach this ShaderObject from all ProgramObjects it was attached to
+	For Local p:tProgramObject = EachIn ProgramObjectList
+		If ListContains(p.fList, fShader)
+			p.DetachFragShader(fShader)
+		End If
+	Next
+	
+	' Delete the shader
+	glDeleteObjectARB(fShader.ShaderObject)
+	?Debug
+		Print "Deleted ShaderObject '"+fShader.shaderName+"'"
+		Print
+	?
+	fShader = Null
+End Function
+*/
+
+
+
+
+//ShaderMat
+
+Sampler* Sampler::Create(string Name, int Slot, Texture* Tex){
+	Sampler* S = new Sampler;
+	S->Name = Name;
+	S->Slot = Slot;
+	S->texture = Tex;
+	return S;
+}
+
+
+	
+Shader* Shader::CreateShaderMaterial(string Name){
+	Shader* s= new Shader;
+	s->texCount=0;
+	if (Name == ""){
+		Name = "NoName";
+	}
+	if (1==1){//HardwareInfo->ShaderSupport{
+		stringstream sstm;
+		sstm << Name << s->ID;
+		s->ID = ShaderIDCount;
+		s->arb_program = ProgramObject::Create(sstm.str());
+		s->name = Name;
+	}else{
+		return 0;
+	}
+	ShaderIDCount++;
+
+	for (int i=0; i<=254; i++){
+		s->Shader_Tex[i] = 0;
+	}
+
+	return s;
+}
+	
+/*void Shader::UpdateData(Surface* surf) {
+	for (unsigned int i=0;i<Parameters.size();i++){
+		switch(Parameters[i].type){
+		case 0:
+			if (arb_program !=0){arb_program->SetParameter1F(Parameters[i].name,*(Parameters[i].fp[0]));}
+			break;
+		case 7:
+			if (arb_program !=0){arb_program->SetParameter3F(Parameters[i].name, 
+			Parameters[i].ent->EntityX(), 
+			Parameters[i].ent->EntityY(),
+			Parameters[i].ent->EntityZ());}
+			break;
+		case 13:
+			if (arb_program !=0){arb_program->SetParameterArray(Parameters[i].name,Parameters[i].surf,Parameters[i].vbo);}
+			break;
+		case 14:
+			if (arb_program !=0){
+				GLfloat modelViewMatrix[16];
+				glGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix);
+				arb_program->SetMatrix4F(Parameters[i].name, modelViewMatrix);
+			}
+			break;
+
+		case 15:
+			if (arb_program !=0){
+				GLfloat modelViewMatrix[16];
+				glGetFloatv(GL_PROJECTION_MATRIX, modelViewMatrix);
+				arb_program->SetMatrix4F(Parameters[i].name, modelViewMatrix);
+			}
+			break;
+
+
+		//default:
+		}
+	}
+}
+	*/
+// internal 
+void Shader::TurnOn(Surface* surf, Matrix& mat){
+	ProgramAttriBegin();
+	// Update Data
+
+	for (unsigned int i=0;i<Parameters.size();i++){
+		switch(Parameters[i].type){
+		case 0:
+			if (arb_program !=0){arb_program->SetParameter1F(Parameters[i].name,*(Parameters[i].fp[0]));}
+			break;
+		case 1:
+			if (arb_program !=0){arb_program->SetParameter2F(Parameters[i].name,*(Parameters[i].fp[0]),*(Parameters[i].fp[1]));}
+			break;
+		case 2:
+			if (arb_program !=0){arb_program->SetParameter3F(Parameters[i].name,*(Parameters[i].fp[0]),*(Parameters[i].fp[1]),
+			*(Parameters[i].fp[2]));}
+			break;
+		case 3:
+			if (arb_program !=0){arb_program->SetParameter4F(Parameters[i].name,*(Parameters[i].fp[0]),*(Parameters[i].fp[1]),
+			*(Parameters[i].fp[2]),*(Parameters[i].fp[3]));}
+			break;
+		case 4:
+			if (arb_program !=0){arb_program->SetParameter1I(Parameters[i].name,*(Parameters[i].ip[0]));}
+			break;
+		case 5:
+			if (arb_program !=0){arb_program->SetParameter2I(Parameters[i].name,*(Parameters[i].ip[0]),*(Parameters[i].ip[1]));}
+			break;
+		case 6:
+			if (arb_program !=0){arb_program->SetParameter3I(Parameters[i].name,*(Parameters[i].ip[0]),*(Parameters[i].ip[1]),
+			*(Parameters[i].ip[2]));}
+			break;
+		case 7:
+			if (arb_program !=0){arb_program->SetParameter4I(Parameters[i].name,*(Parameters[i].ip[0]),*(Parameters[i].ip[1]),
+			*(Parameters[i].ip[2]),*(Parameters[i].ip[3]));}
+			break;
+		case 8:
+			if (arb_program !=0){arb_program->SetParameter3F(Parameters[i].name, 
+			Parameters[i].ent->EntityX(), 
+			Parameters[i].ent->EntityY(),
+			Parameters[i].ent->EntityZ());}
+			break;
+		case 13:
+			if (arb_program !=0){arb_program->SetParameterArray(Parameters[i].name,Parameters[i].surf,Parameters[i].vbo);}
+			break;
+		case 14:
+			if (arb_program !=0){
+				Matrix new_mat=Global::camera_in_use->mat.Inverse();
+				new_mat.Multiply(mat);
+				arb_program->SetMatrix4F(Parameters[i].name, &new_mat.grid[0][0]);
+			}
+			break;
+
+		case 15:
+			if (arb_program !=0){
+				arb_program->SetMatrix4F(Parameters[i].name, &Global::camera_in_use->proj_mat[0]);
+			}
+			break;
+
+
+		//default:
+		}
+	}
+
+	if (UpdateSampler != 0){
+		for (int i=0; i<=254; i++){
+			if (Shader_Tex[i] == 0) break;
+			if (arb_program !=0){arb_program->SetParameter1I(Shader_Tex[i]->Name,Shader_Tex[i]->Slot);}
+		}
+		UpdateSampler = 0;
+	}
+	
+	if (surf!=0) {
+		int DisableCubeSphereMapping=0;
+		for (int ix=0;ix<=254;ix++){
+			if (Shader_Tex[ix] == 0) break;
+			// Main brush texture takes precedent over surface brush texture
+			unsigned int texture=0;
+			int tex_flags=0,tex_blend=0,tex_coords=0;
+			float tex_u_scale=1.0,tex_v_scale=1.0,tex_u_pos=0.0,tex_v_pos=0.0,tex_ang=0.0;
+			int tex_cube_mode=0;//,frame=0;
+			texture=Shader_Tex[ix]->texture->texture;
+			tex_flags=Shader_Tex[ix]->texture->flags;
+			tex_blend=Shader_Tex[ix]->texture->blend;
+			tex_coords=Shader_Tex[ix]->texture->coords;
+			tex_u_scale=Shader_Tex[ix]->texture->u_scale;
+			tex_v_scale=Shader_Tex[ix]->texture->v_scale;
+			tex_u_pos=Shader_Tex[ix]->texture->u_pos;
+			tex_v_pos=Shader_Tex[ix]->texture->v_pos;
+			tex_ang=Shader_Tex[ix]->texture->angle;
+			tex_cube_mode=Shader_Tex[ix]->texture->cube_mode;
+											
+			glActiveTexture(GL_TEXTURE0+ix);
+			glClientActiveTexture(GL_TEXTURE0+ix);
+
+			if (Shader_Tex[ix]->is3D==0){
+				glEnable(GL_TEXTURE_2D);
+				glBindTexture(GL_TEXTURE_2D,texture); // call before glTexParameteri
+				// mipmapping texture flag
+				if(tex_flags&8){
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
+				}else{
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+				}
+			}else{
+				glEnable(GL_TEXTURE_3D);
+				glBindTexture(GL_TEXTURE_3D,texture); // call before glTexParameteri
+				// mipmapping texture flag
+				if(tex_flags&8){
+					glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+					glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
+				}else{
+					glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+					glTexParameteri(GL_TEXTURE_3D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+				}
+			}
+
+			// masked texture flag
+			if(tex_flags&4){
+				glEnable(GL_ALPHA_TEST);
+			}else{
+				glDisable(GL_ALPHA_TEST);
+			}
+		
+		
+			// clamp u flag
+			if(tex_flags&16){
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+			}else{						
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
+			}
+			
+			// clamp v flag
+			if(tex_flags&32){
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+			}else{
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
+			}
+	
+			// ***!ES***
+			///*
+			// spherical environment map texture flag
+			if(tex_flags&64){
+				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
+				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
+				glEnable(GL_TEXTURE_GEN_S);
+				glEnable(GL_TEXTURE_GEN_T);
+				DisableCubeSphereMapping=1;
+			}/*else{
+				glDisable(GL_TEXTURE_GEN_S);
+				glDisable(GL_TEXTURE_GEN_T);
+			}*/
+					
+			// cubic environment map texture flag
+			if(tex_flags&128){
+
+				glEnable(GL_TEXTURE_CUBE_MAP);
+				glBindTexture(GL_TEXTURE_CUBE_MAP,texture); // call before glTexParameteri
+				
+				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
+				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+				glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+				
+				glEnable(GL_TEXTURE_GEN_S);
+				glEnable(GL_TEXTURE_GEN_T);
+				glEnable(GL_TEXTURE_GEN_R);
+				//glEnable(GL_TEXTURE_GEN_Q)
+				if(tex_cube_mode==1){
+					glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+					glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+					glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+				}
+				
+				if(tex_cube_mode==2){
+					glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+					glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+					glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+				}
+				DisableCubeSphereMapping=1;
+			}
+			else if (DisableCubeSphereMapping!=0){
+
+				glDisable(GL_TEXTURE_CUBE_MAP);
+				
+				// only disable tex gen s and t if sphere mapping isn't using them
+				if((tex_flags&64)==0){
+					glDisable(GL_TEXTURE_GEN_S);
+					glDisable(GL_TEXTURE_GEN_T);
+				}
+				
+				glDisable(GL_TEXTURE_GEN_R);
+				//glDisable(GL_TEXTURE_GEN_Q)
+
+			}
+			
+			switch(tex_blend){
+				case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
+				break;
+				case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
+				break;
+				case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+				//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
+				break;
+				case 3: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_ADD);
+				break;
+				case 4:
+					glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); 
+					glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGB_EXT); 
+					break;
+				case 5:
+					glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
+					glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
+					glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE,2.0);
+					break;
+				default: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+			}
+
+			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+			if (Shader_Tex[ix]->is3D==0){
+
+				if(surf->vbo_enabled==true && surf->no_tris>=Global::vbo_min_tris){
+			
+					if(tex_coords==0){
+						glBindBuffer(GL_ARRAY_BUFFER,surf->vbo_id[1]);
+						glTexCoordPointer(2,GL_FLOAT,0,NULL);
+					}else{
+						glBindBuffer(GL_ARRAY_BUFFER,surf->vbo_id[2]);
+						glTexCoordPointer(2,GL_FLOAT,0,NULL);
+					}
+				
+				}else{
+			
+					if(tex_coords==0){
+						//glBindBufferARB(GL_ARRAY_BUFFER_ARB,0) already reset above
+						glTexCoordPointer(2,GL_FLOAT,0,&surf->vert_tex_coords0[0]);
+					}else{
+						//glBindBufferARB(GL_ARRAY_BUFFER_ARB,0)
+						glTexCoordPointer(2,GL_FLOAT,0,&surf->vert_tex_coords1[0]);
+					}
+
+				}
+
+			}else{
+				if(surf->vbo_enabled==true && surf->no_tris>=Global::vbo_min_tris){
+			
+					glBindBuffer(GL_ARRAY_BUFFER,surf->vbo_id[2]);
+					glTexCoordPointer(3,GL_FLOAT,0,NULL);
+				
+				}else{
+			
+					//glBindBufferARB(GL_ARRAY_BUFFER_ARB,0)
+					glTexCoordPointer(3,GL_FLOAT,0,&surf->vert_tex_coords1[0]);
+
+				}
+			}
+
+							
+			// reset texture matrix
+			glMatrixMode(GL_TEXTURE);
+			glLoadIdentity();
+					
+			if(tex_u_pos!=0.0 || tex_v_pos!=0.0){
+				glTranslatef(tex_u_pos,tex_v_pos,0.0);
+			}
+			if(tex_ang!=0.0){
+				glRotatef(tex_ang,0.0,0.0,1.0);
+			}
+			if(tex_u_scale!=1.0 || tex_v_scale!=1.0){
+				glScalef(tex_u_scale,tex_v_scale,1.0);
+			}
+
+			///* ***!ES***
+			// if spheremap flag=true then flip tex
+			if(tex_flags&64){
+				glScalef(1.0,-1.0,-1.0);
+			}
+			
+			// if cubemap flag=true then manipulate texture matrix so that cubemap is displayed properly 
+			if(tex_flags&128){
+
+				glScalef(1.0,-1.0,-1.0);
+				
+				// get current modelview matrix (set in last camera update)
+				float mod_mat[16];
+				glGetFloatv(GL_MODELVIEW_MATRIX,&mod_mat[0]);
+				// get rotational inverse of current modelview matrix
+				Matrix new_mat;
+				new_mat.LoadIdentity();
+					
+				new_mat.grid[0][0] = mod_mat[0];
+				new_mat.grid[1][0] = mod_mat[1];
+				new_mat.grid[2][0] = mod_mat[2];
+
+				new_mat.grid[0][1] = mod_mat[4];
+				new_mat.grid[1][1] = mod_mat[5];
+				new_mat.grid[2][1] = mod_mat[6];
+
+				new_mat.grid[0][2] = mod_mat[8];
+				new_mat.grid[1][2] = mod_mat[9];
+				new_mat.grid[2][2] = mod_mat[10];
+					
+				glMultMatrixf(&new_mat.grid[0][0]);
+
+			}
+			//*/
+						
+		}
+	}
+
+}
+	
+void Shader::TurnOff(){
+	ProgramAttriEnd();
+	for (int ix=0; ix<=254; ix++){
+		if (Shader_Tex[ix] == 0) break;
+
+		glActiveTexture(GL_TEXTURE0+ix);
+		glClientActiveTexture(GL_TEXTURE0+ix);
+				
+		// reset texture matrix
+		glMatrixMode(GL_TEXTURE);
+		glLoadIdentity();
+				
+		if (Shader_Tex[ix]->is3D==0){
+			glDisable(GL_TEXTURE_2D);
+		}else{
+			glDisable(GL_TEXTURE_3D);
+		}
+				
+		glDisable(GL_TEXTURE_CUBE_MAP);
+		glDisable(GL_TEXTURE_GEN_S);
+		glDisable(GL_TEXTURE_GEN_T);
+		glDisable(GL_TEXTURE_GEN_R);
+			
+	}
+	for (unsigned int i=0;i<Parameters.size();i++){
+		switch(Parameters[i].type){
+		case 13:
+			if (arb_program !=0){	
+				int loc= glGetAttribLocation(arb_program->Program, Parameters[i].name.c_str());
+				glDisableVertexAttribArray(loc);
+			}
+		}
+	}
+
+
+}
+		
+
+/*	Method AddShader(_vert:String = Null , _frag:String = Null)
+'		If arb_program = Null Then Return
+'		Local Vert:TShaderObject
+'		Local Frag:TShaderObject
+'		
+'		If _Vert <> Null Then 
+'			Vert = TGlobal.RenderInterface.CreateVertexShaderObj(arb_program.languageType,_vert,arb_program)
+'			arb_program.attachVertShader(Vert)
+'		EndIf
+'		
+'		If _frag <> Null Then 
+'			frag = TGlobal.RenderInterface.CreatePixelShaderObj(arb_program.languageType,_frag,arb_program)
+'			arb_program.attachFragShader(frag)
+'		EndIf
+'	End Method*/
+	
+void Shader::AddShader(string _vert, string _frag){
+	if (arb_program == 0) return;
+	ShaderObject* Vert;
+	ShaderObject* Frag;
+	
+	if (_vert != ""){
+		Vert = ShaderObject::CreateVertShader(_vert);
+		arb_program->AttachVertShader(Vert);
+	}
+		
+	if (_frag != ""){
+		Frag = ShaderObject::CreateFragShader(_frag);
+		arb_program->AttachFragShader(Frag);
+	}
+}
+	
+void Shader::AddShaderFromString(string _vert, string _frag){
+	if (arb_program == 0) return;
+	ShaderObject* Vert;
+	ShaderObject* Frag;
+		
+	if (_vert != ""){
+		Vert = ShaderObject::CreateVertShaderFromString(_vert);
+		arb_program->AttachVertShader(Vert);
+	}
+		
+	if (_frag != ""){
+		Frag = ShaderObject::CreateFragShaderFromString(_frag);
+		arb_program->AttachFragShader(Frag);
+	}
+}
+
+
+
+	/*Method ListShaders()
+		If arb_program = Null Then Return
+		'arb_program.ListAttachedShaders()
+	End Method */
+
+void Shader::AddSampler2D(string Name, int Slot, Texture* Tex){
+	Shader_Tex[Slot] = Sampler::Create(Name,Slot,Tex);
+	UpdateSampler = 1;
+	Shader_Tex[Slot]->is3D=0;
+	texCount++;
+}
+	
+void Shader::AddSampler3D(string Name, int Slot, Texture* Tex){
+	Shader_Tex[Slot] = Sampler::Create(Name,Slot,Tex);
+	UpdateSampler = 1;
+	Shader_Tex[Slot]->is3D=1;
+	texCount++;
+}
+
+
+void Shader::ProgramAttriBegin(){
+	if (arb_program !=0){arb_program->Activate();}
+}	
+
+void Shader::ProgramAttriEnd(){
+	if (arb_program !=0){arb_program->DeActivate();}
+}	
+
+void Shader::SetFloat(string name, float v1){
+	ProgramAttriBegin();
+	if (arb_program !=0){arb_program->SetParameter1F(name, v1);}
+	ProgramAttriEnd();
+}
+
+void Shader::SetFloat2(string name, float v1, float v2){
+	ProgramAttriBegin();
+	if (arb_program !=0){arb_program->SetParameter2F(name, v1, v2);}
+	ProgramAttriEnd();
+}
+
+void Shader::SetFloat3(string name, float v1, float v2, float v3){
+	ProgramAttriBegin();
+	if (arb_program !=0){arb_program->SetParameter3F(name, v1, v2, v3);}
+	ProgramAttriEnd();
+}
+
+void Shader::SetFloat4(string name, float v1, float v2, float v3, float v4){
+	ProgramAttriBegin();
+	if (arb_program !=0){arb_program->SetParameter4F(name, v1, v2, v3, v4);}
+	ProgramAttriEnd();
+}
+
+void Shader::UseFloat(string name, float* v1){
+	ShaderData data;
+	data.name=name;
+	data.type=0;
+	data.fp[0]=v1;
+	Parameters.push_back(data);
+}
+
+void Shader::UseFloat2(string name, float* v1, float* v2){
+	ShaderData data;
+	data.name=name;
+	data.type=1;
+	data.fp[0]=v1;
+	data.fp[1]=v2;
+	Parameters.push_back(data);
+}
+
+void Shader::UseFloat3(string name, float* v1, float* v2, float* v3){
+	ShaderData data;
+	data.name=name;
+	data.type=2;
+	data.fp[0]=v1;
+	data.fp[1]=v2;
+	data.fp[2]=v3;
+	Parameters.push_back(data);
+}
+
+void Shader::UseFloat4(string name, float* v1, float* v2, float* v3, float* v4){
+	ShaderData data;
+	data.name=name;
+	data.type=3;
+	data.fp[0]=v1;
+	data.fp[1]=v2;
+	data.fp[2]=v3;
+	data.fp[3]=v4;
+	Parameters.push_back(data);
+}
+
+void Shader::SetInteger(string name, int v1){
+	ProgramAttriBegin();
+	if (arb_program !=0){arb_program->SetParameter1I(name, v1);}
+	ProgramAttriEnd();
+}
+
+void Shader::SetInteger2(string name, int v1, int v2){
+	ProgramAttriBegin();
+	if (arb_program !=0){arb_program->SetParameter2I(name, v1, v2);}
+	ProgramAttriEnd();
+}
+
+void Shader::SetInteger3(string name, int v1, int v2, int v3){
+	ProgramAttriBegin();
+	if (arb_program !=0){arb_program->SetParameter3I(name, v1, v2, v3);}
+	ProgramAttriEnd();
+}
+
+void Shader::SetInteger4(string name, int v1, int v2, int v3, int v4){
+	ProgramAttriBegin();
+	if (arb_program !=0){arb_program->SetParameter4I(name, v1, v2, v3, v4);}
+	ProgramAttriEnd();
+}
+
+void Shader::UseInteger(string name, int* v1){
+	ShaderData data;
+	data.name=name;
+	data.type=4;
+	data.ip[0]=v1;
+	Parameters.push_back(data);
+}
+
+void Shader::UseInteger2(string name, int* v1, int* v2){
+	ShaderData data;
+	data.name=name;
+	data.type=5;
+	data.ip[0]=v1;
+	data.ip[1]=v2;
+	Parameters.push_back(data);
+}
+
+void Shader::UseInteger3(string name, int* v1, int* v2, int* v3){
+	ShaderData data;
+	data.name=name;
+	data.type=6;
+	data.ip[0]=v1;
+	data.ip[1]=v2;
+	data.ip[2]=v3;
+	Parameters.push_back(data);
+}
+
+void Shader::UseInteger4(string name, int* v1, int* v2, int* v3, int* v4){
+	ShaderData data;
+	data.name=name;
+	data.type=7;
+	data.ip[0]=v1;
+	data.ip[1]=v2;
+	data.ip[2]=v3;
+	data.ip[3]=v4;
+	Parameters.push_back(data);
+}
+
+
+
+void Shader::UseSurface(string name, Surface* surf, int vbo){
+	ShaderData data;
+	data.name=name;
+	data.type=13;
+	data.surf=surf;
+	data.vbo=vbo;
+	Parameters.push_back(data);
+}
+
+void Shader::UseMatrix(string name, int mode){
+	ShaderData data;
+	data.name=name;
+	if (mode==1) {
+		data.type=14;
+	}else{
+		data.type=15;
+	}
+	Parameters.push_back(data);
+}
+/*void Shader::SetParameter1S(string name, float v1){
+	if (arb_program !=0){arb_program->SetParameter1S(name, v1);}
+}
+
+void Shader::SetParameter2S(string name, float v1, float v2){
+	if (arb_program !=0){arb_program->SetParameter2S(name, v1, v2);}
+}
+
+void Shader::SetParameter3S(string name, float v1, float v2, float v3){
+	if (arb_program !=0){arb_program->SetParameter3S(name, v1, v2, v3);}
+}
+
+void Shader::SetParameter4S(string name, float v1, float v2, float v3, float v4){
+	if (arb_program !=0){arb_program->SetParameter4S(name, v1, v2, v3, v4);}
+}
+
+void Shader::SetParameter1I(string name, int v1){
+	if (arb_program !=0){arb_program->SetParameter1I(name, v1);}
+}
+
+void Shader::SetParameter2I(string name, int v1, int v2){
+	if (arb_program !=0){arb_program->SetParameter2I(name, v1, v2);}
+}
+
+void Shader::SetParameter3I(string name, int v1, int v2, int v3){
+	if (arb_program !=0){arb_program->SetParameter3I(name, v1, v2, v3);}
+}
+
+void Shader::SetParameter4I(string name, int v1, int v2, int v3, int v4){
+	if (arb_program !=0){arb_program->SetParameter4I(name, v1, v2, v3, v4);}
+}
+ 
+void Shader::SetVector1I(string name, int* v1){
+	if (arb_program !=0){arb_program->SetVector1I(name, v1);}
+}
+
+void Shader::SetVector2I(string name, int* v1){
+	if (arb_program !=0){arb_program->SetVector2I(name, v1);}
+}
+
+void Shader::SetVector3I(string name, int* v1){
+	if (arb_program !=0){arb_program->SetVector3I(name, v1);}
+}
+
+void Shader::SetVector4I(string name, int* v1){
+	if (arb_program !=0){arb_program->SetVector4I(name, v1);}
+}
+
+void Shader::SetParameter1F(string name, float v1){
+	//if (arb_program !=0){arb_program->SetParameter1F(name, v1);}
+	ShaderData data;
+	data.name=name;
+	data.type=0;
+	data.valuef[0]=v1;
+	Parameters.push_back(data);
+}
+
+void Shader::SetParameter2F(string name, float v1, float v2){
+	if (arb_program !=0){arb_program->SetParameter2F(name, v1, v2);}
+}
+
+void Shader::SetParameter3F(string name, float v1, float v2, float v3){
+	if (arb_program !=0){arb_program->SetParameter3F(name, v1, v2, v3);}
+}
+
+void Shader::SetParameter4F(string name, float v1, float v2, float v3, float v4){
+	if (arb_program !=0){arb_program->SetParameter4F(name, v1, v2, v3, v4);}
+}
+
+void Shader::SetVector1F(string name, float* v1){
+	if (arb_program !=0){arb_program->SetVector1F(name, v1);}
+}
+
+void Shader::SetVector2F(string name, float* v1){
+	if (arb_program !=0){arb_program->SetVector2F(name, v1);}
+}
+
+void Shader::SetVector3F(string name, float* v1){
+	if (arb_program !=0){arb_program->SetVector3F(name, v1);}
+}
+
+void Shader::SetVector4F(string name, float* v1){
+	if (arb_program !=0){arb_program->SetVector4F(name, v1);}
+}
+
+void Shader::SetMatrix2F(string name, float* m){
+	//if (arb_program !=0){arb_program->SetMatrix2F(name, m);}
+	ShaderData data;
+	data.name=name;
+	data.type=11;
+	data.pf=m;
+	Parameters.push_back(data);
+
+}
+
+void Shader::SetMatrix3F(string name, float* m){
+	if (arb_program !=0){arb_program->SetMatrix3F(name, m);}
+}
+
+void Shader::SetMatrix4F(string name, float* m){
+	if (arb_program !=0){arb_program->SetMatrix4F(name, m);}
+}
+
+void Shader::SetParameter1D(string name, double v1){
+	if (arb_program !=0){arb_program->SetParameter1D(name, v1);}
+}
+
+void Shader::SetParameter2D(string name, double v1, double v2){
+	if (arb_program !=0){arb_program->SetParameter2D(name, v1, v2);}
+}
+
+void Shader::SetParameter3D(string name, double v1, double v2, double v3){
+	if (arb_program !=0){arb_program->SetParameter3D(name, v1, v2, v3);}
+}
+
+void Shader::SetParameter4D(string name, double v1, double v2, double v3, double v4){
+	if (arb_program !=0){arb_program->SetParameter4D(name, v1, v2, v3, v4);}
+}*/
+
+//ShaderObject
+
+ProgramObject* ProgramObject::Create(string name){
+	ProgramObject* p = new ProgramObject;
+		
+	//Create a new GL ProgramObject
+	p->Program = glCreateProgram();
+	if (p->Program == 0){
+		p = 0;
+		return 0;
+	}
+		
+	/*--------------------------------
+	'The amount of Vert & Frag Shaders
+	'attached to this Program Object
+	'---------------------------------*/
+	p->vertShaderCount = 0;
+	p->fragShaderCount = 0;
+	
+	/*--------------------------------------
+	'These lists contain any Vert or Frag
+	'Shader Objects Attached to this Program
+	'-------------------------------------
+	p->vList:TList = CreateList();
+	p->fList:TList = CreateList();*/
+	
+	//This Program Objects Name
+	p->progName = name;
+		
+	/*-----------------------------
+	'Add this Program Object to the
+	'Global list of ProgramObjects
+	'------------------------------*/
+	ProgramObjectList.push_back(p);
+	return p;
+}
+
+void ProgramObject::Activate(){
+	glUseProgram(Program);
+}
+
+void ProgramObject::DeActivate(){
+	glUseProgram(0);
+}
+
+void ProgramObject::RefreshTypeMap(){
+	TypeMap.clear();
+		
+	int maxlen;
+	int count;
+		 
+	glGetProgramiv( Program,GL_ACTIVE_UNIFORM_MAX_LENGTH ,&maxlen);
+	glGetProgramiv( Program,GL_ACTIVE_UNIFORMS ,&count);
+	char* name=new char[maxlen+1];
+	for (int i=0;i<=count; i++){
+		int glsize;
+		GLenum gltype;
+		glGetActiveUniform (Program,i,maxlen,0,&glsize,&gltype,name);
+		TypeMap[name]=1;//"Uniform"
+	}
+	delete [] name;
+
+	glGetProgramiv( Program,GL_ACTIVE_ATTRIBUTE_MAX_LENGTH ,&maxlen);
+	glGetProgramiv( Program,GL_ACTIVE_ATTRIBUTES ,&count);
+	name=new char[maxlen+1];
+	for (int i=0;i<=count; i++){
+		int glsize;
+		GLenum gltype;
+		glGetActiveAttrib(Program,i,maxlen,0,&glsize,&gltype,name);
+		TypeMap[name]=2;//"Attribute"
+	}
+	delete [] name;
+		
+		
+}
+
+// Get the Uniform Variable Location from a ProgramObject
+int ProgramObject::GetUniLoc(string name){
+	return glGetUniformLocation(Program, name.c_str());
+}
+
+// Get the Attribute Variable Location from a ProgramObject
+int ProgramObject::GetAttribLoc(string name){
+	return glGetAttribLocation(Program, name.c_str());
+}
+
+void ProgramObject::SetParameter1S(string name, float v1){
+	int loc= glGetAttribLocation(Program, name.c_str());
+	glVertexAttrib1s(loc, v1);
+}
+	
+void ProgramObject::SetParameter2S(string name, float v1, float v2) {
+	int loc= glGetAttribLocation(Program, name.c_str());
+	glVertexAttrib2s(loc, v1,v2);
+}
+	 
+void ProgramObject::SetParameter3S(string name, float v1, float v2, float v3){
+	int loc= glGetAttribLocation(Program, name.c_str());
+	glVertexAttrib3s(loc, v1,v2,v3);
+}
+	  
+void ProgramObject::SetParameter4S(string name, float v1, float v2, float v3, float v4){
+	int loc= glGetAttribLocation(Program, name.c_str());
+	glVertexAttrib4s(loc, v1,v2,v3,v4);
+}
+	
+//------------------------------------------------------------
+// Int Parameter
+	
+void ProgramObject::SetParameter1I(string name, int v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform1i(loc,v1);
+}
+
+void ProgramObject::SetParameter2I(string name, int v1, int v2){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform2i(loc,v1,v2);
+}
+
+void ProgramObject::SetParameter3I(string name, int v1, int v2, int v3){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform3i(loc,v1,v2,v3);
+}
+
+void ProgramObject::SetParameter4I(string name, int v1, int v2, int v3, int v4){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform4i(loc,v1,v2,v3,v4);
+}
+	
+//----------------------------------------------------------------------------------
+// Int Vectors
+
+void ProgramObject::SetVector1I(string name, int* v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform1iv(loc,1,v1);
+}
+				
+void ProgramObject::SetVector2I(string name, int* v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform2iv(loc,1,v1);
+}
+										
+void ProgramObject::SetVector3I(string name, int* v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform3iv(loc,1,v1);
+}
+										
+void ProgramObject::SetVector4I(string name, int* v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform4iv(loc,1,v1);
+}
+				
+//-------------------------------------------------------------------------------------
+// Double Parameter ( automatically Attributes, because Uniform doubles does not exist)
+	
+void ProgramObject::SetParameter1D(string name, double v1){
+	int loc= glGetAttribLocation(Program, name.c_str());
+	glVertexAttrib1d(loc, v1);
+}
+	 
+void ProgramObject::SetParameter2D(string name, double v1, double v2){
+	int loc= glGetAttribLocation(Program, name.c_str());
+	glVertexAttrib2d(loc, v1, v2);
+}
+	 
+void ProgramObject::SetParameter3D(string name, double v1, double v2, double v3){
+	int loc= glGetAttribLocation(Program, name.c_str());
+	glVertexAttrib3d(loc, v1, v2, v3);
+}
+	 
+void ProgramObject::SetParameter4D(string name, double v1, double v2, double v3, double v4){
+	int loc= glGetAttribLocation(Program, name.c_str());
+	glVertexAttrib4d(loc, v1, v2, v3, v4);
+}
+
+
+//-------------------------------------------------------------------------------------
+// Array Parameter
+
+void ProgramObject::SetParameterArray(string name, Surface* surf, int vbo){
+	int loc= glGetAttribLocation(Program, name.c_str());
+	if(surf->vbo_enabled!=0){
+		surf->reset_vbo=vbo;
+
+		Surface& surf2=*surf;
+		glBindBuffer(GL_ARRAY_BUFFER,0);
+		switch (vbo){
+		case 1:
+			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[0]);
+			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+			break;
+		case 2:
+			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[1]);
+			glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+		case 3:
+			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[2]);
+			glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+			break;
+		case 4:
+			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[3]);
+			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
+			break;
+		case 5:
+			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[4]);
+			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 16, 0);
+			break;
+
+		case 6:
+			glBindBuffer(GL_ARRAY_BUFFER,surf2.vbo_id[4]);
+			glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, 0);
+			break;
+		}
+
+	}else{
+		Surface& surf2=*surf;
+		glBindBuffer(GL_ARRAY_BUFFER,0);
+		switch (vbo){
+		case 1:
+			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, &surf2.vert_coords[0]);
+			break;
+		case 2:
+			glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, &surf2.vert_tex_coords0[0]);
+			break;
+		case 3:
+			glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, &surf2.vert_tex_coords1[0]);
+			break;
+		case 4:
+			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0, &surf2.vert_norm[0]);
+			break;
+		case 5:
+			glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 16, &surf2.vert_col[0]);
+			break;
+
+		case 6:
+			glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, &surf2.vert_col[0]);
+			break;
+		}
+	}
+
+	glEnableVertexAttribArray(loc);
+}
+
+//-------------------------------------------------------------------------------------
+// Float Parameter
+
+void ProgramObject::SetParameter1F(string name, float v){
+	if (TypeMap.find(name) == TypeMap.end() ){
+		return;
+	}
+	int ParameterType=TypeMap.find(name)->second;
+	
+	if (ParameterType == 1){		//"Uniform" 
+		int loc= glGetUniformLocation(Program, name.c_str());
+		glUniform1f(loc, v);
+			
+	} else if (ParameterType == 2){		//"Attribute"
+ 
+		int loc= glGetAttribLocation(Program, name.c_str());
+		glVertexAttrib1f(loc, v);
+
+	}
+		
+}
+
+void ProgramObject::SetParameter2F(string name, float v1, float v2){
+	if (TypeMap.find(name) == TypeMap.end() ){
+		return;
+	}
+	int ParameterType=TypeMap.find(name)->second;
+	
+	if (ParameterType == 1){		//"Uniform" 
+		int loc= glGetUniformLocation(Program, name.c_str());
+		glUniform2f(loc, v1, v2);
+			
+	} else if (ParameterType == 2){		//"Attribute"
+ 
+		int loc= glGetAttribLocation(Program, name.c_str());
+		glVertexAttrib2f(loc, v1, v2);
+
+	}
+
+}
+
+void ProgramObject::SetParameter3F(string name, float v1, float v2, float v3){
+		
+	if (TypeMap.find(name) == TypeMap.end() ){
+		return;
+	}
+	int ParameterType=TypeMap.find(name)->second;
+		
+	if (ParameterType == 1){		//"Uniform" 
+		int loc= glGetUniformLocation(Program, name.c_str());
+		glUniform3f(loc, v1,v2,v3);
+			
+	} else if (ParameterType == 2){		//"Attribute"
+ 
+		int loc= glGetAttribLocation(Program, name.c_str());
+		glVertexAttrib3f(loc, v1, v2, v3);
+
+	}
+}
+
+void ProgramObject::SetParameter4F(string name, float v1, float v2, float v3, float v4){
+	if (TypeMap.find(name) == TypeMap.end() ){
+		return;
+	}
+	int ParameterType=TypeMap.find(name)->second;
+		
+	if (ParameterType == 1){		//"Uniform" 
+		int loc= glGetUniformLocation(Program, name.c_str());
+		glUniform4f(loc, v1,v2,v3,v4);
+			
+	} else if (ParameterType == 2){		//"Attribute"
+ 
+		int loc= glGetAttribLocation(Program, name.c_str());
+		glVertexAttrib4f(loc, v1, v2, v3,v4);
+
+	}
+}
+
+//---------------------------------------------------------------------------------------------------
+// Float Vectors
+
+
+void ProgramObject::SetVector1F(string name, float* v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform1fv(loc,1,v1);
+}
+
+void ProgramObject::SetVector2F(string name, float* v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform2fv(loc,1,v1);
+}
+
+void ProgramObject::SetVector3F(string name, float* v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform3fv(loc,1,v1);
+}
+
+void ProgramObject::SetVector4F(string name, float* v1){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniform4fv(loc,1,v1);
+}
+
+
+//--------------------------------------------------------------------------------------------------
+// Matrices
+
+void ProgramObject::SetMatrix2F(string name, float* m){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniformMatrix2fv(loc, 1 , 0, m );
+} 
+
+void ProgramObject::SetMatrix3F(string name, float* m){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniformMatrix3fv(loc, 1 , 0, m );	
+}
+
+void ProgramObject::SetMatrix4F(string name, float* m){
+	int loc= glGetUniformLocation(Program, name.c_str());
+	glUniformMatrix4fv(loc, 1 , 0, m );
+}
+
+
+//----------------------------------------------------------
+//Attach & Link a Vertex Shader Object to this ProgramObject
+//----------------------------------------------------------
+int ProgramObject::AttachVertShader(ShaderObject* myShader){
+	/*-------------------------
+	'Attach & Link a VertShader
+	'------------------------*/
+	glAttachShader(Program, myShader->ShaderObj);
+	glLinkProgram(Program);
+
+
+	/*-------------------------------
+	'Check if it Linked successfully
+	'------------------------------*/
+	int linked;
+	glValidateProgram(Program);
+	glGetProgramiv(Program,GL_LINK_STATUS, &linked);
+	
+	if (linked==0){
+		return 0;
+	}
+
+	//Add this VertShaderObject to this ProgramObjects list
+	vList.push_back(myShader);
+
+	//Add this ProgramObject to this Shaders 'attached to' list
+	myShader->Attached.push_back(this);
+	RefreshTypeMap();
+	return 1;
+}
+
+//------------------------------------------------------------
+//Attach & Link a Fragment Shader Object to this ProgramObject
+//------------------------------------------------------------
+int ProgramObject::AttachFragShader(ShaderObject* myShader){
+	/*-------------------------
+	'Attach & Link a FragShader
+	'------------------------*/
+	glAttachShader(Program, myShader->ShaderObj);
+	glLinkProgram(Program);
+
+
+	/*-------------------------------
+	'Check if it Linked successfully
+	'------------------------------*/
+	int linked;
+	glValidateProgram(Program);
+	glGetProgramiv(Program,GL_LINK_STATUS, &linked);
+
+	if (linked==0){
+		return 0;
+	}
+
+	//Add this FragShaderObject to this ProgramObjects list
+	fList.push_back(myShader);
+	
+	//Add this ProgramObject to this Shaders 'attached to' list
+	myShader->Attached.push_back(this);
+	RefreshTypeMap();
+	return 1;
+}
+
+//-------------------------------------------------------
+//Detach a VertShader:tShaderObject from a tProgramObject
+//-------------------------------------------------------
+void ProgramObject::DetachVertShader(ShaderObject* vShader){
+	list<ShaderObject*>::iterator it;
+
+	for(it=vList.begin();it!=vList.end();it++){
+		if (vShader==*it){
+			glDetachShader(Program, vShader->ShaderObj);
+			vList.remove(vShader);
+			vShader->Attached.remove(this);
+			break;
+		}
+	}
+}
+
+//-------------------------------------------------------
+//Detach a FragShader:tShaderObject from a tProgramObject
+//-------------------------------------------------------
+void ProgramObject::DetachFragShader(ShaderObject* fShader){
+	list<ShaderObject*>::iterator it;
+
+	for(it=fList.begin();it!=vList.end();it++){
+		if (fShader==*it){
+			glDetachShader(Program, fShader->ShaderObj);
+			fList.remove(fShader);
+			fShader->Attached.remove(this);
+			break;
+		}
+	}
+}
+
+
+/*------------------------------------------------------
+/Dump a list of Shaders attached to this tProgramObject
+/------------------------------------------------------
+Method ListAttachedShaders()
+	Print "Vertex Shader(s) attached to ProgramObject '"+Self.progName+"'"
+	Print "----------------------------------------------------------------------"
+	If vList.Count() = 0
+		Print "No Vertex Shaders attached"
+	Else
+		For Local v:tShaderObject = EachIn vList
+			Print v.shaderName
+		Next
+	End If
+		
+	Print
+	Print "Fragment Shader(s) attached to ProgramObject '"+Self.progName+"'"
+	Print "-----------------------------------------------------------------------"
+	If fList.Count() = 0
+		Print "No Fragment Shaders attached"
+	Else
+		For Local f:tShaderObject = EachIn fList
+			Print f.shaderName
+		Next
+	End If
+	Print
+End Method*/
+
+void CopyPixels (unsigned char *src, unsigned int srcWidth, unsigned int srcHeight, unsigned int srcX, unsigned int srcY, unsigned char *dst, unsigned int dstWidth, unsigned int dstHeight, unsigned int bytesPerPixel);
+
+
+Material* Material::LoadMaterial(string filename,int flags, int frame_width,int frame_height,int first_frame,int frame_count){
+
+	//filename=Strip(filename); // get rid of path info
+
+	if(File::ResourceFilePath(filename)==""){
+		cout << "Error: Cannot Find Texture: " << filename << endl;
+		return NULL;
+	}
+
+	Material* tex=new Material();
+	tex->file=filename;
+
+	// set tex.flags before TexInList
+	tex->flags=flags;
+	tex->FilterFlags();
+
+	/*// check to see if texture with same properties exists already, if so return existing texture
+	Texture* old_tex=tex->TexInList();
+	if(old_tex){
+		return old_tex;
+	}else{
+		tex_list.push_back(tex);
+	}*/
+
+	//const char* c_filename_left=filename_left.c_str();
+	//const char* c_filename_right=filename_right.c_str();
+
+
+	unsigned char* buffer;
+
+	buffer=stbi_load(filename.c_str(),&tex->width,&tex->height,0,4);
+
+	unsigned int name;
+
+	glGenTextures (1,&name);
+	glBindTexture (GL_TEXTURE_3D,name);
+
+	tex->no_frames=frame_count;
+	//tex->frames=new unsigned int[frame_count];
+
+	unsigned char* dstbuffer=new unsigned char[frame_width*frame_height*4*frame_count];
+
+	glGenTextures (1,&name);
+	glBindTexture (GL_TEXTURE_3D,name);
+
+
+	//tex.gltex=tex.gltex[..tex.no_frames]
+
+	int frames_in_row=tex->width/frame_width;
+
+	for (int i=0;i<frame_count;i++){
+		CopyPixels (buffer,tex->width, tex->height,frame_width*(i%frames_in_row), frame_height*(i/frames_in_row),
+		dstbuffer+i*(frame_width * frame_height * 4), frame_width, frame_height, 4);
+
+
+	}
+
+	glTexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP, GL_TRUE);
+	glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,frame_width, frame_height, frame_count, 0, GL_RGBA, GL_UNSIGNED_BYTE, dstbuffer);
+
+	tex->texture=name;
+	tex->width=frame_width;
+	tex->height=frame_height;
+	delete dstbuffer;
+	stbi_image_free(buffer);
+
+
+	return tex;
+
+}
+

+ 294 - 0
openb3dlib.mod/openb3d/src/md2.cpp

@@ -0,0 +1,294 @@
+#include "model.h"
+#include "entity.h"
+#include "bone.h"
+#include "mesh.h"
+#include "texture.h"
+#include "file.h"
+#include <list>
+
+namespace loadMD2{
+
+const float md2_anorms[][3]={
+{ -0.525731f,  0.000000f,  0.850651f }, 
+{ -0.442863f,  0.238856f,  0.864188f }, 
+{ -0.295242f,  0.000000f,  0.955423f }, 
+{ -0.309017f,  0.500000f,  0.809017f }, 
+{ -0.162460f,  0.262866f,  0.951056f }, 
+{  0.000000f,  0.000000f,  1.000000f }, 
+{  0.000000f,  0.850651f,  0.525731f }, 
+{ -0.147621f,  0.716567f,  0.681718f }, 
+{  0.147621f,  0.716567f,  0.681718f }, 
+{  0.000000f,  0.525731f,  0.850651f }, 
+{  0.309017f,  0.500000f,  0.809017f }, 
+{  0.525731f,  0.000000f,  0.850651f }, 
+{  0.295242f,  0.000000f,  0.955423f }, 
+{  0.442863f,  0.238856f,  0.864188f }, 
+{  0.162460f,  0.262866f,  0.951056f }, 
+{ -0.681718f,  0.147621f,  0.716567f }, 
+{ -0.809017f,  0.309017f,  0.500000f }, 
+{ -0.587785f,  0.425325f,  0.688191f }, 
+{ -0.850651f,  0.525731f,  0.000000f }, 
+{ -0.864188f,  0.442863f,  0.238856f }, 
+{ -0.716567f,  0.681718f,  0.147621f }, 
+{ -0.688191f,  0.587785f,  0.425325f }, 
+{ -0.500000f,  0.809017f,  0.309017f }, 
+{ -0.238856f,  0.864188f,  0.442863f }, 
+{ -0.425325f,  0.688191f,  0.587785f }, 
+{ -0.716567f,  0.681718f, -0.147621f }, 
+{ -0.500000f,  0.809017f, -0.309017f }, 
+{ -0.525731f,  0.850651f,  0.000000f }, 
+{  0.000000f,  0.850651f, -0.525731f }, 
+{ -0.238856f,  0.864188f, -0.442863f }, 
+{  0.000000f,  0.955423f, -0.295242f }, 
+{ -0.262866f,  0.951056f, -0.162460f }, 
+{  0.000000f,  1.000000f,  0.000000f }, 
+{  0.000000f,  0.955423f,  0.295242f }, 
+{ -0.262866f,  0.951056f,  0.162460f }, 
+{  0.238856f,  0.864188f,  0.442863f }, 
+{  0.262866f,  0.951056f,  0.162460f }, 
+{  0.500000f,  0.809017f,  0.309017f }, 
+{  0.238856f,  0.864188f, -0.442863f }, 
+{  0.262866f,  0.951056f, -0.162460f }, 
+{  0.500000f,  0.809017f, -0.309017f }, 
+{  0.850651f,  0.525731f,  0.000000f }, 
+{  0.716567f,  0.681718f,  0.147621f }, 
+{  0.716567f,  0.681718f, -0.147621f }, 
+{  0.525731f,  0.850651f,  0.000000f }, 
+{  0.425325f,  0.688191f,  0.587785f }, 
+{  0.864188f,  0.442863f,  0.238856f }, 
+{  0.688191f,  0.587785f,  0.425325f }, 
+{  0.809017f,  0.309017f,  0.500000f }, 
+{  0.681718f,  0.147621f,  0.716567f }, 
+{  0.587785f,  0.425325f,  0.688191f }, 
+{  0.955423f,  0.295242f,  0.000000f }, 
+{  1.000000f,  0.000000f,  0.000000f }, 
+{  0.951056f,  0.162460f,  0.262866f }, 
+{  0.850651f, -0.525731f,  0.000000f }, 
+{  0.955423f, -0.295242f,  0.000000f }, 
+{  0.864188f, -0.442863f,  0.238856f }, 
+{  0.951056f, -0.162460f,  0.262866f }, 
+{  0.809017f, -0.309017f,  0.500000f }, 
+{  0.681718f, -0.147621f,  0.716567f }, 
+{  0.850651f,  0.000000f,  0.525731f }, 
+{  0.864188f,  0.442863f, -0.238856f }, 
+{  0.809017f,  0.309017f, -0.500000f }, 
+{  0.951056f,  0.162460f, -0.262866f }, 
+{  0.525731f,  0.000000f, -0.850651f }, 
+{  0.681718f,  0.147621f, -0.716567f }, 
+{  0.681718f, -0.147621f, -0.716567f }, 
+{  0.850651f,  0.000000f, -0.525731f }, 
+{  0.809017f, -0.309017f, -0.500000f }, 
+{  0.864188f, -0.442863f, -0.238856f }, 
+{  0.951056f, -0.162460f, -0.262866f }, 
+{  0.147621f,  0.716567f, -0.681718f }, 
+{  0.309017f,  0.500000f, -0.809017f }, 
+{  0.425325f,  0.688191f, -0.587785f }, 
+{  0.442863f,  0.238856f, -0.864188f }, 
+{  0.587785f,  0.425325f, -0.688191f }, 
+{  0.688191f,  0.587785f, -0.425325f }, 
+{ -0.147621f,  0.716567f, -0.681718f }, 
+{ -0.309017f,  0.500000f, -0.809017f }, 
+{  0.000000f,  0.525731f, -0.850651f }, 
+{ -0.525731f,  0.000000f, -0.850651f }, 
+{ -0.442863f,  0.238856f, -0.864188f }, 
+{ -0.295242f,  0.000000f, -0.955423f }, 
+{ -0.162460f,  0.262866f, -0.951056f }, 
+{  0.000000f,  0.000000f, -1.000000f }, 
+{  0.295242f,  0.000000f, -0.955423f }, 
+{  0.162460f,  0.262866f, -0.951056f }, 
+{ -0.442863f, -0.238856f, -0.864188f }, 
+{ -0.309017f, -0.500000f, -0.809017f }, 
+{ -0.162460f, -0.262866f, -0.951056f }, 
+{  0.000000f, -0.850651f, -0.525731f }, 
+{ -0.147621f, -0.716567f, -0.681718f }, 
+{  0.147621f, -0.716567f, -0.681718f }, 
+{  0.000000f, -0.525731f, -0.850651f }, 
+{  0.309017f, -0.500000f, -0.809017f }, 
+{  0.442863f, -0.238856f, -0.864188f }, 
+{  0.162460f, -0.262866f, -0.951056f }, 
+{  0.238856f, -0.864188f, -0.442863f }, 
+{  0.500000f, -0.809017f, -0.309017f }, 
+{  0.425325f, -0.688191f, -0.587785f }, 
+{  0.716567f, -0.681718f, -0.147621f }, 
+{  0.688191f, -0.587785f, -0.425325f }, 
+{  0.587785f, -0.425325f, -0.688191f }, 
+{  0.000000f, -0.955423f, -0.295242f }, 
+{  0.000000f, -1.000000f,  0.000000f }, 
+{  0.262866f, -0.951056f, -0.162460f }, 
+{  0.000000f, -0.850651f,  0.525731f }, 
+{  0.000000f, -0.955423f,  0.295242f }, 
+{  0.238856f, -0.864188f,  0.442863f }, 
+{  0.262866f, -0.951056f,  0.162460f }, 
+{  0.500000f, -0.809017f,  0.309017f }, 
+{  0.716567f, -0.681718f,  0.147621f }, 
+{  0.525731f, -0.850651f,  0.000000f }, 
+{ -0.238856f, -0.864188f, -0.442863f }, 
+{ -0.500000f, -0.809017f, -0.309017f }, 
+{ -0.262866f, -0.951056f, -0.162460f }, 
+{ -0.850651f, -0.525731f,  0.000000f }, 
+{ -0.716567f, -0.681718f, -0.147621f }, 
+{ -0.716567f, -0.681718f,  0.147621f }, 
+{ -0.525731f, -0.850651f,  0.000000f }, 
+{ -0.500000f, -0.809017f,  0.309017f }, 
+{ -0.238856f, -0.864188f,  0.442863f }, 
+{ -0.262866f, -0.951056f,  0.162460f }, 
+{ -0.864188f, -0.442863f,  0.238856f }, 
+{ -0.809017f, -0.309017f,  0.500000f }, 
+{ -0.688191f, -0.587785f,  0.425325f }, 
+{ -0.681718f, -0.147621f,  0.716567f }, 
+{ -0.442863f, -0.238856f,  0.864188f }, 
+{ -0.587785f, -0.425325f,  0.688191f }, 
+{ -0.309017f, -0.500000f,  0.809017f }, 
+{ -0.147621f, -0.716567f,  0.681718f }, 
+{ -0.425325f, -0.688191f,  0.587785f }, 
+{ -0.162460f, -0.262866f,  0.951056f }, 
+{  0.442863f, -0.238856f,  0.864188f }, 
+{  0.162460f, -0.262866f,  0.951056f }, 
+{  0.309017f, -0.500000f,  0.809017f }, 
+{  0.147621f, -0.716567f,  0.681718f }, 
+{  0.000000f, -0.525731f,  0.850651f }, 
+{  0.425325f, -0.688191f,  0.587785f }, 
+{  0.587785f, -0.425325f,  0.688191f }, 
+{  0.688191f, -0.587785f,  0.425325f }, 
+{ -0.955423f,  0.295242f,  0.000000f }, 
+{ -0.951056f,  0.162460f,  0.262866f }, 
+{ -1.000000f,  0.000000f,  0.000000f }, 
+{ -0.850651f,  0.000000f,  0.525731f }, 
+{ -0.955423f, -0.295242f,  0.000000f }, 
+{ -0.951056f, -0.162460f,  0.262866f }, 
+{ -0.864188f,  0.442863f, -0.238856f }, 
+{ -0.951056f,  0.162460f, -0.262866f }, 
+{ -0.809017f,  0.309017f, -0.500000f }, 
+{ -0.864188f, -0.442863f, -0.238856f }, 
+{ -0.951056f, -0.162460f, -0.262866f }, 
+{ -0.809017f, -0.309017f, -0.500000f }, 
+{ -0.681718f,  0.147621f, -0.716567f }, 
+{ -0.681718f, -0.147621f, -0.716567f }, 
+{ -0.850651f,  0.000000f, -0.525731f }, 
+{ -0.688191f,  0.587785f, -0.425325f }, 
+{ -0.587785f,  0.425325f, -0.688191f }, 
+{ -0.425325f,  0.688191f, -0.587785f }, 
+{ -0.425325f, -0.688191f, -0.587785f }, 
+{ -0.587785f, -0.425325f, -0.688191f }, 
+{ -0.688191f, -0.587785f, -0.425325f }
+};
+
+
+Mesh* LoadMD2(string filename,Entity* parent_ent){
+	File* Stream;
+	Stream = File::ReadFile(filename);
+	if (Stream == 0) return 0;
+
+	if (Stream->ReadInt()!=844121161) return 0;
+	if (Stream->ReadInt()!=8) return 0;
+
+	Mesh* mesh=Mesh::CreateMesh(parent_ent);
+	Surface* surf = mesh->CreateSurface();
+
+	int skinwidth=Stream->ReadInt(); int skinheight=Stream->ReadInt();
+	int framesize=Stream->ReadInt();
+	int num_skins=Stream->ReadInt();
+	int num_vertices=Stream->ReadInt();
+	int num_st=Stream->ReadInt();
+	int num_tris=Stream->ReadInt();
+	int num_glcmds=Stream->ReadInt();
+	int num_frames=Stream->ReadInt();
+	int offset_skins=Stream->ReadInt();
+	int offset_st=Stream->ReadInt();
+	int offset_tris=Stream->ReadInt();
+	int offset_frames=Stream->ReadInt();
+	int offset_glcmds=Stream->ReadInt();
+	int offset_end=Stream->ReadInt();
+	//string skin[num_skins];
+	float* st=new float[num_st*2];
+	surf->vert_tex_coords0.reserve(num_vertices*2);
+	surf->no_verts=num_vertices;
+
+	Surface* anim_surf=new Surface();
+
+	mesh->anim_surf_list.push_back(anim_surf);
+	anim_surf->no_verts=surf->no_verts;
+
+	anim_surf->vert_coords.resize(num_vertices*3,0);
+
+	/*unsigned short tri[num_tris*6];
+	Stream->SeekFile(stream, offset_skins);
+	For Local i=0 To num_skins-1
+	skin[i]=ReadString(stream,64)
+	Next*/
+	Stream->SeekFile(offset_st);
+	for(int i=0;i<num_st;i++){
+		st[(i*2)+0]=(float)Stream->ReadShort()/(float)skinwidth;
+		st[(i*2)+1]=(float)Stream->ReadShort()/(float)skinheight;
+	}
+
+	Stream->SeekFile(offset_tris);
+	for(int i=0;i<num_tris;i++){
+		int v0=Stream->ReadShort();
+		int v1=Stream->ReadShort();
+		int v2=Stream->ReadShort();
+		int tc0=Stream->ReadShort();
+		int tc1=Stream->ReadShort();
+		int tc2=Stream->ReadShort();
+
+		surf->AddTriangle(v2,v1,v0);
+		surf->VertexTexCoords(v0,st[(tc0*2)+0],st[(tc0*2)+1]);
+		surf->VertexTexCoords(v1,st[(tc1*2)+0],st[(tc1*2)+1]);
+		surf->VertexTexCoords(v2,st[(tc2*2)+0],st[(tc2*2)+1]);
+	}
+
+
+	Stream->SeekFile(offset_frames);
+	//mesh._animator=New TVertexAnimator	
+	for(int i=0;i<num_frames;i++){
+
+		float sx=Stream->ReadFloat();
+		float sy=Stream->ReadFloat();
+		float sz=Stream->ReadFloat();
+
+		float tx=Stream->ReadFloat();
+		float ty=Stream->ReadFloat();
+		float tz=Stream->ReadFloat();
+
+		for(int i2=1;i2<=16;i2++){Stream->ReadByte();}
+
+		for(int v=0;v<num_vertices;v++){
+			float x=(float)((unsigned char)Stream->ReadByte())*sx+tx;
+			float y=(float)((unsigned char)Stream->ReadByte())*sy+ty;
+			float z=(float)((unsigned char)Stream->ReadByte())*sz+tz;
+
+			int ni=Stream->ReadByte();
+			surf->vert_coords.push_back(x);
+			surf->vert_coords.push_back(y);
+			surf->vert_coords.push_back(-z);
+
+			surf->vert_norm.push_back(md2_anorms[ni][2]);
+			surf->vert_norm.push_back(md2_anorms[ni][1]);
+			surf->vert_norm.push_back(-md2_anorms[ni][0]);
+
+			surf->vert_col.push_back(1.0);
+			surf->vert_col.push_back(1.0);
+			surf->vert_col.push_back(1.0);
+			surf->vert_col.push_back(1.0);
+
+			surf->vert_tex_coords1.push_back(0.0);
+			surf->vert_tex_coords1.push_back(0.0);
+
+
+		}
+		anim_surf->vert_weight4.push_back(i);
+	}
+	if (num_frames>1) mesh->anim=2;
+	mesh->anim_seqs_first[0]=0;
+	mesh->anim_seqs_last[0]=num_frames-1;
+	mesh->no_surfs=-1;
+
+
+	delete st;
+	return mesh;
+
+}
+
+
+
+}

+ 3 - 0
openb3dlib.mod/openb3d/src/md2.h

@@ -0,0 +1,3 @@
+namespace loadMD2{
+  Mesh* LoadMD2(string URL, Entity* parent_ent);
+}

+ 61 - 28
openb3dlib.mod/openb3d/src/mesh.cpp

@@ -31,11 +31,13 @@
 #include "model.h"
 #include "pick.h"
 #include "geom.h"
+#include "animation.h"
 #include "maths_helper.h"
 #include "string_helper.h"
 #include "csg.h"
 #include "3ds.h"
 #include "x.h"
+#include "md2.h"
 
 #include <iostream>
 #include <vector>
@@ -337,6 +339,7 @@ Mesh* Mesh::LoadMesh(string filename,Entity* parent_ent){
 Mesh* Mesh::LoadAnimMesh(string filename,Entity* parent_ent){
 
 	if(Right(filename,4)==".3ds") return load3ds::Load3ds(filename, parent_ent);//filename=Replace(filename,".3ds",".b3d");
+	if(Right(filename,4)==".md2") return loadMD2::LoadMD2(filename, parent_ent);//filename=Replace(filename,".3ds",".b3d");
 
 	return LoadAnimB3D(filename,parent_ent);
 
@@ -989,8 +992,43 @@ Mesh* Mesh::RepeatMesh(Entity* parent_ent){
 	}*/
 
 	mesh->surf_list=surf_list;
-	mesh->anim_surf_list=anim_surf_list;
 	// copy anim surf list
+	if (anim!=64 && anim!=0){
+		for (int i=anim_seqs_first[0];i<=anim_seqs_last[0];i++){
+			Animation::AnimateMesh(this,i, anim_seqs_first[0], anim_seqs_last[0]);
+			list<Surface*>::iterator it2;
+			for(it2=anim_surf_list.begin();it2!=anim_surf_list.end();it2++){
+
+				Surface* surf=*it2;
+
+				Surface* new_surf=new Surface;
+				mesh->anim_surf_list.push_back(new_surf);
+
+				new_surf->no_verts=surf->no_verts;
+
+				// copy array
+				new_surf->vert_coords=surf->vert_coords;
+
+				new_surf->vert_array_size=surf->vert_array_size;
+				new_surf->tri_array_size=surf->tri_array_size;
+				new_surf->vmin=surf->vmin;
+				new_surf->vmax=surf->vmax;
+
+				new_surf->vbo_enabled=surf->vbo_enabled;
+				new_surf->reset_vbo=-1; // (-1 = all)
+
+			}
+
+		}
+		anim_surf_list=mesh->anim_surf_list;
+
+		anim=64;
+		mesh->anim=64;
+	} else {
+		mesh->anim_surf_list=anim_surf_list;
+		mesh->anim=anim;
+	}
+
 	/*for(it2=anim_surf_list.begin();it2!=anim_surf_list.end();it2++){
 
 		Surface* surf=*it2;
@@ -1012,7 +1050,6 @@ Mesh* Mesh::RepeatMesh(Entity* parent_ent){
 
 }
 
-
 void Mesh::AddMesh(Mesh* mesh2){
 
 	//int cs2=mesh2->CountSurfaces();
@@ -2054,11 +2091,11 @@ void Mesh::Render(){
 
 	list<Surface*>::iterator surf_it;
 
-	int any_surf=false;
+	//int any_surf=false;
 
 	for(surf_it=surf_list.begin();surf_it!=surf_list.end();surf_it++){
 
-		any_surf=true;
+		//any_surf=true;
 
 		Surface& surf=**surf_it;
 		Surface& anim_surf=**anim_surf_it;
@@ -2086,7 +2123,7 @@ void Mesh::Render(){
 
 		}
 
-		if(anim==true){
+		if(anim){
 
 			// get anim_surf
 
@@ -2137,17 +2174,16 @@ void Mesh::Render(){
 
 		//}
 
-		static int alpha_enable=-1;
 		if(surf.alpha_enable==true){
-			if(alpha_enable!=true){
-				alpha_enable=true;
+			if(Global::alpha_enable!=true){
+				Global::alpha_enable=true;
 				glEnable(GL_BLEND);
 			}
 			glDepthMask(GL_FALSE); // must be set to false every time, as it's always equal to true before it's called
 			depth_mask_disabled=true; // set this to true to we know when to enable depth mask at bottom of function
 		}else{
-			if(alpha_enable!=false){
-				alpha_enable=false;
+			if(Global::alpha_enable!=false){
+				Global::alpha_enable=false;
 				glDisable(GL_BLEND);
 				//glDepthMask(GL_TRUE); already set to true
 			}
@@ -2155,9 +2191,8 @@ void Mesh::Render(){
 
 		// blend modes
 
-		static int blend_mode=-1;
-		if(blend!=blend_mode){
-			blend_mode=blend;
+		if(blend!=Global::blend_mode){
+			Global::blend_mode=blend;
 
 			switch(blend){
 				case 0:
@@ -2179,18 +2214,17 @@ void Mesh::Render(){
 		// fx modes
 
 		// fx flag 1 - full bright ***todo*** disable all lights?
-		static int fx1=-1;
 		if(fx&1){
-			if(fx1!=true){
-				fx1=true;
+			if(Global::fx1!=true){
+				Global::fx1=true;
 				glDisableClientState(GL_NORMAL_ARRAY);
 			}
 			ambient_red  =1.0;
 			ambient_green=1.0;
 			ambient_blue =1.0;
 		}else{
-			if(fx1!=false){
-				fx1=false;
+			if(Global::fx1!=false){
+				Global::fx1=false;
 				glEnableClientState(GL_NORMAL_ARRAY);
 			}
 			ambient_red  =Global::ambient_red;
@@ -2199,16 +2233,15 @@ void Mesh::Render(){
 		}
 
 		// fx flag 2 - vertex colours
-		static int fx2=-1;
 		if(fx&2){
-			if(fx2!=true){
-				fx2=true;
+			if(Global::fx2!=true){
+				Global::fx2=true;
 				glEnableClientState(GL_COLOR_ARRAY);
 				glEnable(GL_COLOR_MATERIAL);
 			}
 		}else{
-			if(fx2!=false){
-				fx2=false;
+			if(Global::fx2!=false){
+				Global::fx2=false;
 				glDisableClientState(GL_COLOR_ARRAY);
 				glDisable(GL_COLOR_MATERIAL);
 			}
@@ -2453,7 +2486,7 @@ void Mesh::Render(){
 					switch(tex_blend){
 						case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
 						break;
-						case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
+						case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
 						break;
 						case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 						//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
@@ -2633,7 +2666,7 @@ void Mesh::Render(){
 		fog_disabled=false; // set to false again for when we repeat loop
 	}
 
-	if(any_surf==false) cout << "No surf: " << EntityName() << endl;
+	//if(any_surf==false) cout << "No surf: " << EntityName() << endl;
 
 }
 
@@ -2645,11 +2678,11 @@ void Mesh::UpdateShadow(){
 
 	list<Surface*>::iterator surf_it;
 
-	int any_surf=false;
+	//int any_surf=false;
 
 	for(surf_it=surf_list.begin();surf_it!=surf_list.end();surf_it++){
 
-		any_surf=true;
+		//any_surf=true;
 
 		Surface& surf=**surf_it;
 		Surface& anim_surf=**anim_surf_it;
@@ -2669,7 +2702,7 @@ void Mesh::UpdateShadow(){
 
 		}
 
-		if(anim==true){
+		if(anim){
 
 			// get anim_surf
 

+ 1496 - 0
openb3dlib.mod/openb3d/src/metaball.cpp

@@ -0,0 +1,1496 @@
+#include "glew.h"
+/*
+#ifdef linux
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+#endif
+#ifdef WIN32
+#include <gl\GLee.h>
+#endif
+*/
+#include "metaball.h"
+#include "global.h"
+#include "camera.h"
+#include "pick.h"
+
+static float Xcf, Ycf, Zcf;
+
+static list<Blob*> render_blobs;
+
+static int level;
+
+
+const int edgeTable[256]={
+0x0  , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
+0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
+0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
+0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
+0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
+0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
+0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
+0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
+0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
+0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
+0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
+0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
+0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
+0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
+0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
+0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
+0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
+0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
+0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
+0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
+0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
+0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
+0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
+0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
+0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
+0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
+0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
+0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
+0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
+0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
+0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
+0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0   };
+
+//gives which vertices to join to form triangles for the surface
+const int triTable[256][16] =
+{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
+{3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
+{3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
+{3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
+{9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
+{9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
+{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
+{8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
+{9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
+{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
+{3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
+{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
+{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
+{4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
+{9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
+{5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
+{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
+{9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
+{0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
+{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
+{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
+{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
+{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
+{5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
+{9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
+{0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
+{1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
+{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
+{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
+{2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
+{7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
+{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
+{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
+{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
+{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
+{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
+{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
+{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
+{1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
+{9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
+{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
+{2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
+{0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
+{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
+{6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
+{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
+{6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
+{5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
+{1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
+{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
+{6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
+{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
+{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
+{3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
+{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
+{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
+{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
+{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
+{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
+{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
+{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
+{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
+{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
+{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
+{1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
+{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
+{0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
+{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
+{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
+{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
+{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
+{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
+{3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
+{6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
+{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
+{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
+{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
+{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
+{7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
+{7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
+{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
+{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
+{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
+{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
+{0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
+{7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
+{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
+{2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
+{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
+{7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
+{2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
+{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
+{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
+{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
+{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
+{7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
+{6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
+{8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
+{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
+{6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
+{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
+{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
+{8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
+{0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
+{1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
+{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
+{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
+{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
+{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
+{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
+{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
+{9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
+{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
+{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
+{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
+{7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
+{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
+{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
+{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
+{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
+{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
+{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
+{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
+{6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
+{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
+{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
+{6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
+{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
+{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
+{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
+{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
+{9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
+{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
+{1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
+{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
+{0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
+{5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
+{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
+{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
+{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
+{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
+{2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
+{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
+{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
+{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
+{1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
+{9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
+{9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
+{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
+{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
+{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
+{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
+{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
+{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
+{9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
+{5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
+{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
+{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
+{8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
+{0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
+{9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
+{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
+{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
+{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
+{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
+{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
+{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
+{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
+{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
+{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
+{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
+{1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
+{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
+{4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
+{0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
+{3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
+{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
+{0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
+{9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
+{1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}};
+
+
+
+
+float MetaballsField (float x, float y, float z){
+	list<Blob*>::iterator it;
+	float field=0;
+	for(it=render_blobs.begin();it!=render_blobs.end();it++){
+		Blob* blob=*it;
+		float xd = blob->mat.grid[3][0]-x;
+		float yd = blob->mat.grid[3][1]-y;
+		float zd = blob->mat.grid[3][2]+z;
+		float r2=xd*xd + yd*yd + zd*zd;
+		field+=blob->charge/r2;
+		/*if (r2<=1)
+			field+=(1-r2)*(1-r2);*/
+
+	}
+
+	return field;
+}
+
+
+Fluid* Fluid::CreateFluid(){
+	Fluid* fluid=new Fluid();
+	fluid->class_name="Fluid";
+
+	Global::root_ent->child_list.push_back(fluid);
+	fluid->parent=0;
+
+	entity_list.push_back(fluid);
+
+	fluid->UpdateMat(true);
+
+	fluid->min_x=-999999999;
+	fluid->max_x=999999999;
+	fluid->min_y=-999999999;
+	fluid->max_y=999999999;
+	fluid->min_z=-999999999;
+	fluid->max_z=999999999;
+	fluid->no_surfs=1;
+
+	Surface* surf=new Surface();
+	fluid->surf_list.push_back(surf);
+
+	fluid->ScalarField=&MetaballsField;
+
+	fluid->threshold=.5;
+
+	fluid->ResetBuffers();
+
+
+	return fluid;
+
+}
+
+void Fluid::FreeEntity(){
+	Surface* surf=*surf_list.begin();
+	delete surf;
+	surf_list.clear();
+
+
+	for (int i=0;i<20;i++){
+		for (int i1=0;i1<62;i1++){
+			delete[] xzbuffer[i][i1];
+			delete[] xybuffer[i][i1];
+			delete[] yzbuffer[i][i1];
+		}
+		delete[] xzbuffer[i];
+		delete[] xybuffer[i];
+		delete[] yzbuffer[i];
+
+	}
+
+	delete[] xzbuffer;
+	delete[] xybuffer;
+	delete[] yzbuffer;
+
+	delete[] buffercenter;
+
+	Entity::FreeEntity();
+
+	delete this;
+
+	return;
+
+
+}
+
+
+void Fluid::MarchingCube(float x, float y, float z, float x1, float y1, float z1, float F[8]){
+
+	float EdgeX[12], EdgeY[12], EdgeZ[12];
+
+	Surface* surf=*surf_list.begin();
+
+	unsigned char cubeIndex=0;
+	
+	if(F[6] < threshold)
+		cubeIndex |= 1;
+	if(F[7] < threshold)
+		cubeIndex |= 2;
+	if(F[3] < threshold)
+		cubeIndex |= 4;
+	if(F[2] < threshold)
+		cubeIndex |= 8;
+	if(F[4] < threshold)
+		cubeIndex |= 16;
+	if(F[5] < threshold)
+		cubeIndex |= 32;
+	if(F[1] < threshold)
+		cubeIndex |= 64;
+	if(F[0] < threshold)
+		cubeIndex |= 128;
+
+	//look this value up in the edge table to see which edges to interpolate along
+	int usedEdges=edgeTable[cubeIndex];
+
+	//if the cube is entirely within/outside surface, no faces			
+	if(usedEdges==0 || usedEdges==255)
+		return;
+
+	if(usedEdges & 1){
+		float Ratio = ( threshold - F[6] )/( F[7] - F[6] );
+
+		EdgeX[0] = x  + Ratio*(x1 - x );
+		EdgeY[0] = y1 + Ratio*(y1 - y1);
+		EdgeZ[0] = z1 + Ratio*(z1 - z1);
+
+
+	}
+	if(usedEdges & 2){
+		float Ratio = ( threshold - F[7] )/( F[3] - F[7] );
+
+		EdgeX[1] = x1 + Ratio*(x1 - x1);
+		EdgeY[1] = y1 + Ratio*(y1 - y1);
+		EdgeZ[1] = z1 + Ratio*(z  - z1);
+
+	}
+	if(usedEdges & 4){
+		float Ratio = ( threshold - F[3] )/( F[2] - F[3] );
+
+		EdgeX[2] = x1 + Ratio*(x  - x1);
+		EdgeY[2] = y1 + Ratio*(y1 - y1);
+		EdgeZ[2] = z  + Ratio*(z  - z );
+
+	}
+	if(usedEdges & 8){
+		float Ratio = ( threshold - F[2] )/( F[6] - F[2] );
+
+		EdgeX[3] = x  + Ratio*(x  - x );
+		EdgeY[3] = y1 + Ratio*(y1 - y1);
+		EdgeZ[3] = z  + Ratio*(z1 - z );
+
+	}
+
+
+	if(usedEdges & 16){
+		float Ratio = ( threshold - F[4] )/( F[5] - F[4] );
+
+		EdgeX[4] = x  + Ratio*(x1 - x );
+		EdgeY[4] = y  + Ratio*(y  - y );
+		EdgeZ[4] = z1 + Ratio*(z1 - z1);
+
+	}
+	if(usedEdges & 32){
+		float Ratio = ( threshold - F[5] )/( F[1] - F[5] );
+
+		EdgeX[5] = x1 + Ratio*(x1 - x1);
+		EdgeY[5] = y  + Ratio*(y  - y );
+		EdgeZ[5] = z1 + Ratio*(z  - z1);
+
+	}
+	if(usedEdges & 64){
+		float Ratio = ( threshold - F[1] )/( F[0] - F[1] );
+
+		EdgeX[6] = x1 + Ratio*(x  - x1);
+		EdgeY[6] = y  + Ratio*(y  - y );
+		EdgeZ[6] = z  + Ratio*(z  - z );
+
+	}
+	if(usedEdges & 128){
+		float Ratio = ( threshold - F[0] )/( F[4] - F[0] );
+
+		EdgeX[7] = x  + Ratio*(x  - x );
+		EdgeY[7] = y  + Ratio*(y  - y );
+		EdgeZ[7] = z  + Ratio*(z1 - z );
+	}
+
+
+	if(usedEdges & 256){
+		float Ratio = ( threshold - F[4] )/( F[6] - F[4] );
+
+		EdgeX[8] = x  + Ratio*(x  - x );
+		EdgeY[8] = y  + Ratio*(y1 - y );
+		EdgeZ[8] = z1 + Ratio*(z1 - z1);
+	}
+	if(usedEdges & 512){
+		float Ratio = ( threshold - F[5] )/( F[7] - F[5] );
+
+		EdgeX[9] = x1 + Ratio*(x1 - x1);
+		EdgeY[9] = y  + Ratio*(y1 - y );
+		EdgeZ[9] = z1 + Ratio*(z1 - z1);
+	}
+	if(usedEdges & 1024){
+		float Ratio = ( threshold - F[1] )/( F[3] - F[1] );
+
+		EdgeX[10] = x1 + Ratio*(x1 - x1);
+		EdgeY[10] = y  + Ratio*(y1 - y );
+		EdgeZ[10] = z  + Ratio*(z  - z );
+	}
+	if(usedEdges & 2048){
+		float Ratio = ( threshold - F[0] )/( F[2] - F[0] );
+
+		EdgeX[11] = x  + Ratio*(x  - x );
+		EdgeY[11] = y  + Ratio*(y1 - y );
+		EdgeZ[11] = z  + Ratio*(z  - z );
+	}
+
+	for(int k=0; triTable[cubeIndex][k]!=-1; k+=3){
+
+
+
+		surf->vert_coords.push_back( EdgeX[triTable[cubeIndex][k+0]]);
+		surf->vert_coords.push_back( EdgeY[triTable[cubeIndex][k+0]]);
+		surf->vert_coords.push_back(-EdgeZ[triTable[cubeIndex][k+0]]);
+
+		surf->vert_coords.push_back( EdgeX[triTable[cubeIndex][k+1]]);
+		surf->vert_coords.push_back( EdgeY[triTable[cubeIndex][k+1]]);
+		surf->vert_coords.push_back(-EdgeZ[triTable[cubeIndex][k+1]]);
+
+		surf->vert_coords.push_back( EdgeX[triTable[cubeIndex][k+2]]);
+		surf->vert_coords.push_back( EdgeY[triTable[cubeIndex][k+2]]);
+		surf->vert_coords.push_back(-EdgeZ[triTable[cubeIndex][k+2]]);
+
+		if(brush.fx&4){
+			float ax,ay,az,bx,by,bz;
+			float nx,ny,nz;
+			ax = EdgeX[triTable[cubeIndex][k+1]]-EdgeX[triTable[cubeIndex][k+0]];
+			ay = EdgeY[triTable[cubeIndex][k+1]]-EdgeY[triTable[cubeIndex][k+0]];
+			az = EdgeZ[triTable[cubeIndex][k+1]]-EdgeZ[triTable[cubeIndex][k+0]];
+			bx = EdgeX[triTable[cubeIndex][k+2]]-EdgeX[triTable[cubeIndex][k+1]];
+			by = EdgeY[triTable[cubeIndex][k+2]]-EdgeY[triTable[cubeIndex][k+1]];
+			bz = EdgeZ[triTable[cubeIndex][k+2]]-EdgeZ[triTable[cubeIndex][k+1]];
+			nx = ( ay * bz ) - ( az * by );
+			ny = ( az * bx ) - ( ax * bz );
+			nz = ( ax * by ) - ( ay * bx );
+
+
+			surf->vert_norm.push_back(nx); surf->vert_norm.push_back(ny);surf->vert_norm.push_back(nz);
+			surf->vert_norm.push_back(nx); surf->vert_norm.push_back(ny);surf->vert_norm.push_back(nz);
+			surf->vert_norm.push_back(nx); surf->vert_norm.push_back(ny);surf->vert_norm.push_back(nz);
+		}else{
+
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+0]]+1,EdgeY[triTable[cubeIndex][k+0]],EdgeZ[triTable[cubeIndex][k+0]])-ScalarField(EdgeX[triTable[cubeIndex][k+0]]-1,EdgeY[triTable[cubeIndex][k+0]],EdgeZ[triTable[cubeIndex][k+0]]));
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+0]],EdgeY[triTable[cubeIndex][k+0]]+1,EdgeZ[triTable[cubeIndex][k+0]])-ScalarField(EdgeX[triTable[cubeIndex][k+0]],EdgeY[triTable[cubeIndex][k+0]]-1,EdgeZ[triTable[cubeIndex][k+0]]));
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+0]],EdgeY[triTable[cubeIndex][k+0]],EdgeZ[triTable[cubeIndex][k+0]]+1)-ScalarField(EdgeX[triTable[cubeIndex][k+0]],EdgeY[triTable[cubeIndex][k+0]],EdgeZ[triTable[cubeIndex][k+0]]-1));
+
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+1]]+1,EdgeY[triTable[cubeIndex][k+1]],EdgeZ[triTable[cubeIndex][k+1]])-ScalarField(EdgeX[triTable[cubeIndex][k+1]]-1,EdgeY[triTable[cubeIndex][k+1]],EdgeZ[triTable[cubeIndex][k+1]]));
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+1]],EdgeY[triTable[cubeIndex][k+1]]+1,EdgeZ[triTable[cubeIndex][k+1]])-ScalarField(EdgeX[triTable[cubeIndex][k+1]],EdgeY[triTable[cubeIndex][k+1]]-1,EdgeZ[triTable[cubeIndex][k+1]]));
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+1]],EdgeY[triTable[cubeIndex][k+1]],EdgeZ[triTable[cubeIndex][k+1]]+1)-ScalarField(EdgeX[triTable[cubeIndex][k+1]],EdgeY[triTable[cubeIndex][k+1]],EdgeZ[triTable[cubeIndex][k+1]]-1));
+
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+2]]+1,EdgeY[triTable[cubeIndex][k+2]],EdgeZ[triTable[cubeIndex][k+2]])-ScalarField(EdgeX[triTable[cubeIndex][k+2]]-1,EdgeY[triTable[cubeIndex][k+2]],EdgeZ[triTable[cubeIndex][k+2]]));
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+2]],EdgeY[triTable[cubeIndex][k+2]]+1,EdgeZ[triTable[cubeIndex][k+2]])-ScalarField(EdgeX[triTable[cubeIndex][k+2]],EdgeY[triTable[cubeIndex][k+2]]-1,EdgeZ[triTable[cubeIndex][k+2]]));
+			surf->vert_norm.push_back(ScalarField(EdgeX[triTable[cubeIndex][k+2]],EdgeY[triTable[cubeIndex][k+2]],EdgeZ[triTable[cubeIndex][k+2]]+1)-ScalarField(EdgeX[triTable[cubeIndex][k+2]],EdgeY[triTable[cubeIndex][k+2]],EdgeZ[triTable[cubeIndex][k+2]]-1));
+		}
+
+
+
+
+
+/*surf->vert_col.push_back(1.0);
+surf->vert_col.push_back(1.0);
+surf->vert_col.push_back(1.0);
+surf->vert_col.push_back(1.0);
+surf->vert_col.push_back(1.0);
+surf->vert_col.push_back(1.0);
+surf->vert_col.push_back(1.0);
+surf->vert_col.push_back(1.0);
+surf->vert_col.push_back(1.0);*/
+
+		surf->no_verts+=3;
+
+	}
+
+
+
+/*int v1,v2,v3;
+v3=surf->AddVertex(x,y1,-z);
+v2=surf->AddVertex(x1,y,-z);
+v1=surf->AddVertex(x,y,-z);
+v4=surf->AddVertex(x,y,-z1);
+v5=surf->AddVertex(x1,y,-z);
+v6=surf->AddVertex(x,y1,-z);*/
+
+//surf->AddTriangle(v1,v2,v3);
+
+
+}
+
+
+float Fluid::MiddlePoint (float A, float B, float C, float D){
+
+/*
+	if (A<threshold){
+		if (C>=threshold){
+			if (B<threshold){
+				if (D>=threshold){
+					float m=(A + B) / 2;
+					return (threshold-m) / ((threshold-A) / (C - A) + (threshold-B) / (D - B))+m;
+
+				} else
+				{
+				}
+			} 
+			
+		} else if (B>=threshold){
+			if (C<threshold){
+				if (D>=threshold){
+					float m=(A + C) / 2;
+					return (threshold-m) / ((threshold-A) / (B - A) + (threshold-C) / (D - C))+m;
+
+
+				}
+			}
+		}
+
+	} else {
+		if (C<threshold){
+			if (B>=threshold){
+				if (D<threshold){
+					float m=(C + D) / 2;
+					return (threshold-m) / ((threshold-C) / (A - C) + (threshold-D) / (B - D))+m;
+
+
+				}
+			}
+		} else if (B<threshold){
+			if (C>=threshold){
+				if (D<threshold){
+					float m=(B + D) / 2;
+					return (threshold-m) / ((threshold-B) / (A - B) + (threshold-D) / (C - D))+m;
+
+				}
+			}
+		}
+	}*/
+
+	unsigned char sideIndex=0;
+	
+	if(A < threshold)
+		sideIndex |= 1;
+	if(B < threshold)
+		sideIndex |= 2;
+	if(C < threshold)
+		sideIndex |= 4;
+	if(D < threshold)
+		sideIndex |= 8;
+
+	switch (sideIndex){
+		case 9:
+		case 14:
+		case 1:{
+			float c1=(threshold-A) / (C - A);
+			float c2=(threshold-A) / (B - A);
+			return (threshold-A) / (2*(c1*c2) / (c1+c2))+A;
+			}
+		case 2:
+		case 13:
+		case 6:{
+			float c1=(threshold-B) / (A - B);
+			float c2=(threshold-B) / (D - B);
+			return (threshold-B) / (2*(c1*c2) / (c1+c2))+B;
+			}
+		case 12:
+		case 3:{
+			float m=(threshold-A) / (C - A) + (threshold-B) / (D - B);
+			if (m<1)
+				{
+					float m2=(A+B)/2;
+					return (threshold-m2)/m +m2;
+				}else{
+					float m2=(C+D)/2;
+					return (threshold-m2)/(2-m) +m2;
+				}
+			}
+		case 11:
+		case 4:{
+			float c1=(threshold-C) / (A - C);
+			float c2=(threshold-C) / (D - C);
+			return (threshold-C) / (2*(c1*c2) / (c1+c2))+C;
+			}
+		case 10:
+		case 5:{
+			float m=(threshold-A) / (B - A) + (threshold-C) / (D - C);
+			if (m<1)
+				{
+					float m2=(A+C)/2;
+					return (threshold-m2)/m +m2;
+				}else{
+					float m2=(B+D)/2;
+					return (threshold-m2)/(2-m) +m2;
+				}
+			}
+		case 7:
+		case 8:{
+			float c1=(threshold-D) / (C - D);
+			float c2=(threshold-D) / (B - D);
+			return (threshold-D) / (2*(c1*c2) / (c1+c2))+D;
+			}
+/*		case 10:{
+			float m=(B + D) / 2;
+			return (threshold-m) / ((threshold-B) / (A - B) + (threshold-D) / (C - D))+m;
+			}
+		case 12:{
+			float m=(C + D) / 2;
+			return (threshold-m) / ((threshold-C) / (A - C) + (threshold-D) / (B - D))+m;
+			}
+*/
+		default:
+			return (A+B+C+D)/4;
+	}
+	
+}
+
+
+void Fluid::BuildCubeGrid(float x, float y, float z, float l, float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8){
+
+	for (int i = 0 ;i<= 5; i++){
+		float d = Global::camera_in_use->frustum[i][0] * x +
+		 Global::camera_in_use->frustum[i][1] * y -
+		 Global::camera_in_use->frustum[i][2] * z +
+		 Global::camera_in_use->frustum[i][3];
+		if (d <= -l*sqrt(6)) return;//{ds=ds/10; break;}
+	}
+
+	float dx,dy,dz;	
+	float rc;	
+
+	/* compute distance from node To camera (approximated for speed, don't need to be exact) */
+	dx = abs(x - Xcf); dy = abs(y - Ycf); dz = abs(z - Zcf);
+	rc = dx+dy+dz;
+
+	if (rc*.1<=3*l){
+
+		int ix=(x - Xcf)/l+.5+buffercenter[level];
+		int iy=(y - Ycf)/l+.5+buffercenter[level];
+		int iz=(z - Zcf)/l+.5+buffercenter[level];
+
+		float F[27];
+		F[0] =f1;							//ScalarField(x-l, y-l, z-l);
+		F[1] =xzbuffer[level][ix+1][iz+1];				//ScalarField(x  , y-l, z-l);
+		F[2] =f2;							//ScalarField(x+l, y-l, z-l);
+		F[3] =xybuffer[level][ix+1][iy+1];				//ScalarField(x-l, y,   z-l);
+		F[4] =xybuffer[level][ix][iy];					//ScalarField(x  , y,   z-l);
+		F[5] =xybuffer[level][ix+1][iy];				//ScalarField(x+l, y,   z-l);
+		F[6] =f3;							//ScalarField(x-l, y+l, z-l);
+		F[7] =xybuffer[level][ix][iy+1];				//ScalarField(x  , y+l, z-l);
+		F[8] =f4;							//ScalarField(x+l, y+l, z-l);
+
+		F[9] =yzbuffer[level][iy+1][iz+1];				//ScalarField(x-l, y-l, z);
+		F[10]=xzbuffer[level][ix][iz];					//ScalarField(x,   y-l, z);
+		F[11]=xzbuffer[level][ix+1][iz];				//ScalarField(x+l, y-l, z);
+		F[12]=yzbuffer[level][iy][iz];					//ScalarField(x-l, y,   z);
+		F[13]=ScalarField(x,   y,   z);
+		F[14]=ScalarField(x+l, y,   z);
+		F[15]=yzbuffer[level][iy+1][iz];				//ScalarField(x-l, y+l, z);
+		F[16]=ScalarField(x,   y+l, z);
+		F[17]=ScalarField(x+l, y+l, z);
+
+		F[18]=f5;							//ScalarField(x-l, y-l, z+l);
+		F[19]=xzbuffer[level][ix][iz+1];				//ScalarField(x  , y-l, z+l);
+		F[20]=f6;							//ScalarField(x+l, y-l, z+l);
+		F[21]=yzbuffer[level][iy][iz+1];				//ScalarField(x-l, y,   z+l);
+		F[22]=ScalarField(x  , y,   z+l);
+		F[23]=ScalarField(x+l, y,   z+l);
+		F[24]=f7;							//ScalarField(x-l, y+l, z+l);
+		F[25]=ScalarField(x  , y+l, z+l);
+		F[26]=f8;							//ScalarField(x+l, y+l, z+l);
+
+		//fix cracks
+
+		dx = abs(x - Xcf); dy = abs(y - Ycf); dz = abs(z - 2 * l - Zcf);	//Back
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[1] = (f1+f2)/2;
+			F[3] = (f1+f3)/2;
+			F[4] = MiddlePoint(f1,f2,f3,f4);
+			F[5] = (f2+f4)/2;
+			F[7] = (f3+f4)/2;
+		}
+
+		dx = abs(x - Xcf); dy = abs(y - Ycf); dz = abs(z + 2 * l - Zcf);	//Front
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[19] = (f5+f6)/2;
+			F[21] = (f5+f7)/2;
+			F[22] = MiddlePoint(f5,f6,f7,f8);
+			F[23] = (f6+f8)/2;
+			F[25] = (f7+f8)/2;
+		}
+
+		dx = abs(x - 2 * l - Xcf); dy = abs(y - Ycf); dz = abs(z - Zcf);	//Left
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[3] = (f1+f3)/2;
+			F[9] = (f1+f5)/2;
+			F[12] = MiddlePoint(f1,f3,f5,f7);
+			F[15] = (f3+f7)/2;
+			F[21] = (f5+f7)/2;
+		}
+
+		dx = abs(x + 2 * l - Xcf); dy = abs(y - Ycf); dz = abs(z - Zcf);	//Right
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[5] = (f2+f4)/2;
+			F[11] = (f2+f6)/2;
+			F[14] = MiddlePoint(f2,f4,f6,f8);
+			F[17] = (f4+f8)/2;
+			F[23] = (f6+f8)/2;
+		}
+
+		dx = abs(x - Xcf); dy = abs(y - 2 * l - Ycf); dz = abs(z - Zcf);	//Up
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[1] = (f1+f2)/2;
+			F[9] = (f1+f5)/2;
+			F[10] = MiddlePoint(f1,f2,f5,f6);
+			F[11] = (f2+f6)/2;
+			F[19] = (f5+f6)/2;
+		}
+
+		dx = abs(x - Xcf); dy = abs(y + 2 * l - Ycf); dz = abs(z - Zcf);	//Down
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[7] = (f3+f4)/2;
+			F[15] = (f3+f7)/2;
+			F[16] = MiddlePoint(f3,f4,f7,f8);
+			F[17] = (f4+f8)/2;
+			F[25] = (f7+f8)/2;
+		}
+
+		//Edges
+		dx = abs(x - Xcf); dy = abs(y - 2 * l - Ycf); dz = abs(z - 2 * l - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[1] = (f1+f2)/2;
+		}
+
+		dx = abs(x - Xcf); dy = abs(y + 2 * l - Ycf); dz = abs(z - 2 * l - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[7] = (f3+f4)/2;
+		}
+
+		dx = abs(x - Xcf); dy = abs(y - 2 * l - Ycf); dz = abs(z + 2 * l - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[19] = (f5+f6)/2;
+		}
+
+		dx = abs(x - Xcf); dy = abs(y + 2 * l - Ycf); dz = abs(z + 2 * l - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[25] = (f7+f8)/2;
+		}
+
+
+		dx = abs(x - 2 * l - Xcf); dy = abs(y - 2 * l - Ycf); dz = abs(z - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[9] = (f1+f5)/2;
+		}
+
+		dx = abs(x + 2 * l - Xcf); dy = abs(y - 2 * l - Ycf); dz = abs(z - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[11] = (f2+f6)/2;
+		}
+
+		dx = abs(x - 2 * l - Xcf); dy = abs(y + 2 * l - Ycf); dz = abs(z - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[15] = (f3+f7)/2;
+		}
+
+		dx = abs(x + 2 * l - Xcf); dy = abs(y + 2 * l - Ycf); dz = abs(z - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[17] = (f4+f8)/2;
+		}
+
+		dx = abs(x - 2 * l - Xcf); dy = abs(y - Ycf); dz = abs(z - 2 * l - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[3] = (f1+f3)/2;
+		}
+
+		dx = abs(x + 2 * l - Xcf); dy = abs(y - Ycf); dz = abs(z - 2 * l - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[5] = (f2+f4)/2;
+		}
+
+		dx = abs(x - 2 * l - Xcf); dy = abs(y - Ycf); dz = abs(z + 2 * l - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[21] = (f5+f7)/2;
+		}
+
+		dx = abs(x + 2 * l - Xcf); dy = abs(y - Ycf); dz = abs(z + 2 * l - Zcf);
+		rc = dx+dy+dz;
+		if (rc*.1>3*l){
+			F[23] = (f6+f8)/2;
+		}
+
+		//Stores data that will be reused, so we don't have to compute them again
+
+		xzbuffer[level][ix][iz]=F[16];
+		xzbuffer[level][ix+1][iz]=F[17];
+		xzbuffer[level][ix][iz+1]=F[25];
+		xzbuffer[level][ix+1][iz+1]=F[7];
+
+		xybuffer[level][ix][iy]=F[22];
+		xybuffer[level][ix+1][iy]=F[23];
+		xybuffer[level][ix][iy+1]=F[25];
+		xybuffer[level][ix+1][iy+1]=F[21];
+
+		yzbuffer[level][iy][iz]=F[14];
+		yzbuffer[level][iy+1][iz]=F[17];
+		yzbuffer[level][iy][iz+1]=F[23];
+		yzbuffer[level][iy+1][iz+1]=F[11];
+
+
+		l=l/2;
+		level+=1;
+
+		BuildCubeGrid (x-l, y-l, z-l,l,  F[0], F[1], F[3], F[4], F[9], F[10], F[12], F[13]);
+		BuildCubeGrid (x+l, y-l, z-l,l,  F[1], F[2], F[4], F[5], F[10], F[11], F[13], F[14]);
+		BuildCubeGrid (x-l, y+l, z-l,l,  F[3], F[4], F[6], F[7], F[12], F[13], F[15], F[16]);
+		BuildCubeGrid (x+l, y+l, z-l,l,  F[4], F[5], F[7], F[8], F[13], F[14], F[16], F[17]);
+		BuildCubeGrid (x-l, y-l, z+l,l,  F[9], F[10], F[12], F[13], F[18], F[19], F[21], F[22]);
+		BuildCubeGrid (x+l, y-l, z+l,l,  F[10], F[11], F[13], F[14], F[19], F[20], F[22], F[23]);
+		BuildCubeGrid (x-l, y+l, z+l,l,  F[12], F[13], F[15], F[16], F[21], F[22], F[24], F[25]);
+		BuildCubeGrid (x+l, y+l, z+l,l,  F[13], F[14], F[16], F[17], F[22], F[23], F[25], F[26]);
+
+		level-=1;
+	} else {
+		float F[8];
+		F[0] =f1;
+		F[1] =f2;
+		F[2] =f3;
+		F[3] =f4;
+		F[4] =f5;
+		F[5] =f6;
+		F[6] =f7;
+		F[7] =f8;
+
+
+		MarchingCube (x-l, y-l, z-l,x+l,y+l,z+l, F);
+	}
+
+}
+
+void Fluid::ResetBuffers(){
+
+	xzbuffer=new float**[20];
+	xybuffer=new float**[20];
+	yzbuffer=new float**[20];
+	buffercenter=new int[20];
+
+	for (int i=0;i<20;i++){
+		buffercenter[i]=31;
+		xzbuffer[i]=new float*[62];
+		xybuffer[i]=new float*[62];
+		yzbuffer[i]=new float*[62];
+		for (int i1=0;i1<62;i1++){
+			xzbuffer[i][i1]=new float[62];
+			xybuffer[i][i1]=new float[62];
+			yzbuffer[i][i1]=new float[62];
+		}
+
+	}
+
+}
+
+void Fluid::Render(){
+	Xcf=Global::camera_in_use->EntityX();
+	Ycf=Global::camera_in_use->EntityY();
+	Zcf=Global::camera_in_use->EntityZ();
+
+	Surface* surf=*surf_list.begin();
+	surf->no_verts=0;
+
+	surf->vert_coords.clear();
+	surf->vert_norm.clear();
+	surf->vert_col.clear();
+	surf->no_tris=0;
+
+	if (fastmode){
+		// Only metaballs that are in the view frustum are used to compute the scalar field
+		render_blobs.clear();
+		list<Blob*>::iterator it;
+
+		for(it=metaball_list.begin();it!=metaball_list.end();it++){
+			Blob* blob=*it;
+			if (Global::camera_in_use->EntityInFrustum(blob)){
+				render_blobs.push_back(blob);
+			}
+		}
+	}else{
+		render_blobs=metaball_list;
+	}
+
+	level=0;
+
+
+
+	surf->tris.clear();
+
+
+	glBindBuffer(GL_ARRAY_BUFFER,0);
+
+	BuildCubeGrid (Xcf, Ycf, Zcf, Global::camera_in_use->range_far,0,0,0,0,0,0,0,0);
+
+
+	glDisable(GL_ALPHA_TEST);
+
+	if (order!=0){
+		glDisable(GL_DEPTH_TEST);
+		glDepthMask(GL_FALSE);
+	}else{
+		glEnable(GL_DEPTH_TEST);
+		glDepthMask(GL_TRUE);
+	}
+
+	switch(brush.blend){
+		case 0:
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // alpha
+			break;
+		case 1:
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // alpha
+			break;
+		case 2:
+			glBlendFunc(GL_DST_COLOR,GL_ZERO); // multiply
+			break;
+		case 3:
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE); // additive and alpha
+			break;
+		}
+
+	float ambient_red,ambient_green,ambient_blue;
+
+	// fx flag 1 - full bright ***todo*** disable all lights?
+	if (brush.fx & 1){
+		if(Global::fx1!=true){
+			Global::fx1=true;
+			glDisableClientState(GL_NORMAL_ARRAY);
+		}
+		ambient_red  =1.0;
+		ambient_green=1.0;
+		ambient_blue =1.0;
+	}else{
+		if(Global::fx1!=false){
+			Global::fx1=false;
+			glEnableClientState(GL_NORMAL_ARRAY);
+		}
+		ambient_red  =Global::ambient_red;
+		ambient_green=Global::ambient_green;
+		ambient_blue =Global::ambient_blue;
+	}
+
+	// fx flag 2 - vertex colours
+	if(Global::fx2!=false){
+		Global::fx2=false;
+		glDisableClientState(GL_COLOR_ARRAY);
+		glDisable(GL_COLOR_MATERIAL);
+	}
+
+
+	// fx flag 4 - flatshaded
+	if(!brush.fx&4){
+		glShadeModel(GL_SMOOTH);
+	}
+
+	// fx flag 8 - disable fog
+	if(brush.fx&8){
+		if(Global::fog_enabled==true){ // only disable if fog enabled in camera update
+			glDisable(GL_FOG);
+		}
+	}
+
+	// fx flag 16 - disable backface culling
+	if(brush.fx&16){
+		glDisable(GL_CULL_FACE);
+	}else{
+		glEnable(GL_CULL_FACE);
+	}
+
+	// light + material color
+
+	float ambient[]={ambient_red,ambient_green,ambient_blue};
+	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient);
+
+	float mat_ambient[]={brush.red,brush.green,brush.blue,brush.alpha};
+	float mat_diffuse[]={brush.red,brush.green,brush.blue,brush.alpha};
+	float mat_specular[]={brush.shine,brush.shine,brush.shine,brush.shine};
+	float mat_shininess[]={100.0}; // upto 128
+
+	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,mat_ambient);
+	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat_diffuse);
+	glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
+	glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,mat_shininess);
+
+
+	int DisableCubeSphereMapping=0;
+	int tex_count=0;
+
+	if(surf->ShaderMat!=NULL){
+		surf->ShaderMat->TurnOn(surf, mat);
+	}else{
+
+		tex_count=brush.no_texs;
+		for(int ix=0;ix<tex_count;ix++){
+
+			if(brush.tex[ix]){
+
+				// Main brush texture takes precedent over surface brush texture
+				unsigned int texture=0;
+				int tex_flags=0,tex_blend=0;
+				float tex_u_scale=1.0,tex_v_scale=1.0,tex_u_pos=0.0,tex_v_pos=0.0,tex_ang=0.0;
+				int tex_cube_mode=0;
+
+
+				texture=brush.cache_frame[ix];
+				tex_flags=brush.tex[ix]->flags;
+				tex_blend=brush.tex[ix]->blend;
+				tex_u_scale=brush.tex[ix]->u_scale;
+				tex_v_scale=brush.tex[ix]->v_scale;
+				tex_u_pos=brush.tex[ix]->u_pos;
+				tex_v_pos=brush.tex[ix]->v_pos;
+				tex_ang=brush.tex[ix]->angle;
+				tex_cube_mode=brush.tex[ix]->cube_mode;
+				//frame=brush.tex_frame;
+
+				glActiveTexture(GL_TEXTURE0+ix);
+				glClientActiveTexture(GL_TEXTURE0+ix);
+
+				glEnable(GL_TEXTURE_2D);
+				glBindTexture(GL_TEXTURE_2D,texture); // call before glTexParameteri
+
+				// masked texture flag
+				if(tex_flags&4){
+					glEnable(GL_ALPHA_TEST);
+				}else{
+					glDisable(GL_ALPHA_TEST);
+				}
+
+				// mipmapping texture flag
+				if(tex_flags&8){
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
+				}else{
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+				}
+
+				// clamp u flag
+				if(tex_flags&16){
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+				}else{
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
+				}
+
+				// clamp v flag
+				if(tex_flags&32){
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+				}else{
+					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
+				}
+
+					// ***!ES***
+
+					if(tex_flags<64){
+						glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+						glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+						glEnable(GL_TEXTURE_GEN_S);
+						glEnable(GL_TEXTURE_GEN_T);
+					}
+
+					// spherical environment map texture flag
+					if(tex_flags&64){
+						glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
+						glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
+						glEnable(GL_TEXTURE_GEN_S);
+						glEnable(GL_TEXTURE_GEN_T);
+					}
+
+					// cubic environment map texture flag
+					if(tex_flags&128){
+
+						glEnable(GL_TEXTURE_CUBE_MAP);
+						glBindTexture(GL_TEXTURE_CUBE_MAP,texture); // call before glTexParameteri
+
+						glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+						glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+						glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
+						glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+						glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+
+						glEnable(GL_TEXTURE_GEN_S);
+						glEnable(GL_TEXTURE_GEN_T);
+						glEnable(GL_TEXTURE_GEN_R);
+						//glEnable(GL_TEXTURE_GEN_Q)
+
+						if(tex_cube_mode==1){
+							glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+							glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+							glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_REFLECTION_MAP);
+						}
+
+						if(tex_cube_mode==2){
+							glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+							glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+							glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);
+						}
+						DisableCubeSphereMapping=1;
+
+					}else  if (DisableCubeSphereMapping!=0){
+
+						glDisable(GL_TEXTURE_CUBE_MAP);
+
+						glDisable(GL_TEXTURE_GEN_R);
+
+					}
+
+
+				switch(tex_blend){
+					case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
+					break;
+					case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
+					break;
+					case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+					//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
+					break;
+					case 3: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_ADD);
+					break;
+					case 4:
+						glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
+						glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGB_EXT);
+						break;
+					case 5:
+						glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
+						glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
+						glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE,2.0);
+						break;
+					default: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+				}
+
+				//No texture coords are used, since the surface is implicit
+
+				// reset texture matrix
+				glMatrixMode(GL_TEXTURE);
+				glLoadIdentity();
+
+				if(tex_u_pos!=0.0 || tex_v_pos!=0.0){
+					glTranslatef(tex_u_pos,tex_v_pos,0.0);
+				}
+				if(tex_ang!=0.0){
+					glRotatef(tex_ang,0.0,0.0,1.0);
+				}
+				if(tex_u_scale!=1.0 || tex_v_scale!=1.0){
+					glScalef(tex_u_scale,tex_v_scale,1.0);
+				}
+
+				// ***!ES***
+				// if spheremap flag=true then flip tex
+				if(tex_flags&64){
+					glScalef(1.0,-1.0,-1.0);
+				}
+
+				// if cubemap flag=true then manipulate texture matrix so that cubemap is displayed properly
+				if(tex_flags&128){
+
+					glScalef(1.0,-1.0,-1.0);
+
+					// get current modelview matrix (set in last camera update)
+					float mod_mat[16];
+					glGetFloatv(GL_MODELVIEW_MATRIX,&mod_mat[0]);
+
+					// get rotational inverse of current modelview matrix
+					Matrix new_mat;
+					new_mat.LoadIdentity();
+
+					new_mat.grid[0][0] = mod_mat[0];
+					new_mat.grid[1][0] = mod_mat[1];
+					new_mat.grid[2][0] = mod_mat[2];
+
+					new_mat.grid[0][1] = mod_mat[4];
+					new_mat.grid[1][1] = mod_mat[5];
+					new_mat.grid[2][1] = mod_mat[6];
+
+					new_mat.grid[0][2] = mod_mat[8];
+					new_mat.grid[1][2] = mod_mat[9];
+					new_mat.grid[2][2] = mod_mat[10];
+
+					glMultMatrixf(&new_mat.grid[0][0]);
+
+				}
+
+
+			}
+
+		}
+	}
+
+	// draw tris
+	glMatrixMode(GL_MODELVIEW);
+
+
+	glNormalPointer(GL_FLOAT,0,&surf->vert_norm[0]);
+	glColorPointer(4,GL_FLOAT,0,&surf->vert_col[0]);
+
+	glVertexPointer(3,GL_FLOAT,0,&surf->vert_coords[0]);
+	glDrawArrays(GL_TRIANGLES,0,surf->no_verts);
+
+	// disable all texture layers
+	for(int ix=0;ix<tex_count;ix++){
+
+		glActiveTexture(GL_TEXTURE0+ix);
+		glClientActiveTexture(GL_TEXTURE0+ix);
+
+		// reset texture matrix
+		glMatrixMode(GL_TEXTURE);
+		glLoadIdentity();
+
+		glDisable(GL_TEXTURE_2D);
+
+		// ***!ES***
+		if (DisableCubeSphereMapping!=0){
+			glDisable(GL_TEXTURE_CUBE_MAP);
+			glDisable(GL_TEXTURE_GEN_S);
+			glDisable(GL_TEXTURE_GEN_T);
+			glDisable(GL_TEXTURE_GEN_R);
+			DisableCubeSphereMapping=0;
+		}
+
+	}
+
+
+	if (brush.fx&8 && Global::fog_enabled==true){
+		glEnable(GL_FOG);
+	}
+	if(surf->ShaderMat!=NULL){
+		surf->ShaderMat->TurnOff();
+	}
+
+}
+
+
+void Blob::FreeEntity(){
+
+	fluid->metaball_list.remove(this);
+
+	Entity::FreeEntity();
+	
+	delete this;
+	
+	return;
+
+}
+
+
+Blob* Blob::CreateBlob(Fluid* fluid, float radius, Entity* parent_ent){
+	if(parent_ent==NULL) parent_ent=Global::root_ent;
+
+	Blob* blob=new Blob;
+	blob->class_name="Blob";
+		
+	blob->AddParent(*parent_ent);
+	entity_list.push_back(blob);
+
+	// update matrix
+	if(blob->parent!=NULL){
+		blob->mat.Overwrite(blob->parent->mat);
+		blob->UpdateMat();
+	}else{
+		blob->UpdateMat(true);
+	}
+
+	blob->charge=radius;
+	float crs=radius*radius;
+	blob->cull_radius=sqrt(crs+crs+crs);
+	blob->fluid=fluid;
+
+
+	fluid->metaball_list.push_back(blob);
+	
+	return blob;
+
+}
+
+Blob* Blob::CopyEntity(Entity* parent_ent){
+
+	if(parent_ent==NULL) parent_ent=Global::root_ent;
+
+	// new blob
+	Blob* blob=new Blob;
+
+	// copy contents of child list before adding parent
+	list<Entity*>::iterator it;
+	for(it=child_list.begin();it!=child_list.end();it++){
+		Entity* ent=*it;
+		ent->CopyEntity(blob);
+	}
+	
+	// lists
+	
+	// add parent, add to list
+	blob->AddParent(*parent_ent);
+	entity_list.push_back(blob);
+	
+	// add to collision entity list
+	if(collision_type!=0){
+		CollisionPair::ent_lists[collision_type].push_back(blob);
+	}
+	
+	// add to pick entity list
+	if(pick_mode){
+		Pick::ent_list.push_back(blob);
+	}
+	
+	// update matrix
+	if(blob->parent){
+		blob->mat.Overwrite(blob->parent->mat);
+	}else{
+		blob->mat.LoadIdentity();
+	}
+	
+	// copy entity info
+	
+	blob->mat.Multiply(mat);
+	
+	blob->px=px;
+	blob->py=py;
+	blob->pz=pz;
+	blob->sx=sx;
+	blob->sy=sy;
+	blob->sz=sz;
+	blob->rx=rx;
+	blob->ry=ry;
+	blob->rz=rz;
+	blob->qw=qw;
+	blob->qx=qx;
+	blob->qy=qy;
+	blob->qz=qz;
+
+	blob->name=name;
+	blob->class_name=class_name;
+	blob->order=order;
+	blob->hide=false;
+	
+	blob->cull_radius=cull_radius;
+	blob->radius_x=radius_x;
+	blob->radius_y=radius_y;
+	blob->box_x=box_x;
+	blob->box_y=box_y;
+	blob->box_z=box_z;
+	blob->box_w=box_w;
+	blob->box_h=box_h;
+	blob->box_d=box_d;
+	blob->pick_mode=pick_mode;
+	blob->obscurer=obscurer;
+
+	blob->charge=charge;
+	blob->fluid=fluid;
+
+	return blob;
+	
+}
+

+ 64 - 0
openb3dlib.mod/openb3d/src/metaball.h

@@ -0,0 +1,64 @@
+#ifndef METABALL_H
+#define METABALL_H
+
+#include "mesh.h"
+
+#include <iostream>
+using namespace std;
+
+class Blob;
+
+class Fluid : public Mesh{
+
+private:
+	int* buffercenter;
+	float ***xzbuffer;
+	float ***xybuffer;
+	float ***yzbuffer;
+
+	void ResetBuffers();
+
+	void MarchingCube(float x, float y, float z, float x1, float y1, float z1, float F[8]);
+
+	float MiddlePoint (float A, float B, float C, float D);
+
+	void BuildCubeGrid (float x, float y, float z, float l,
+		float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8);
+
+	float (*ScalarField)(float x, float y, float z);
+public:
+	list<Blob*> metaball_list;
+
+	int fastmode;
+
+	float threshold;
+
+	int* cells;
+
+	static Fluid* CreateFluid();
+
+	void FreeEntity(void);
+
+	void Render();
+
+};
+
+
+class Blob : public Entity{
+ 
+public:
+
+	float charge;
+	Fluid* fluid;
+	
+	Blob(){};
+	
+	Blob* CopyEntity(Entity* parent_ent=NULL);
+	void FreeEntity(void);
+	
+	static Blob* CreateBlob(Fluid* fluid, float radius, Entity* parent_ent=NULL);
+	void Update(){}
+ 
+ };
+
+#endif

+ 2 - 2
openb3dlib.mod/openb3d/src/model.cpp

@@ -332,7 +332,7 @@ Mesh* LoadAnimB3D(string f_name,Entity* parent_ent_ext){
 				// if not then the texture created above (supplied as param below) will be returned
 				new_tex=Texture::LoadTexture(te_file,te_flags);//,tex[tex_no]); ***todo***
 				*/
-				
+
 				te_file=Texture::NewFilePath(f_name,te_file);				
 				Texture* new_tex=Texture::LoadTexture(te_file,te_flags);
 
@@ -647,7 +647,7 @@ Mesh* LoadAnimB3D(string f_name,Entity* parent_ent_ext){
 
 			if(mesh!=NULL){
 
-				mesh->anim=true;
+				mesh->anim=1;
 
 				//mesh->frames=a_frames
 				mesh->anim_seqs_first[0]=0;

+ 13 - 11
openb3dlib.mod/openb3d/src/octree.cpp

@@ -39,16 +39,18 @@ void OcTreeChild::AddToOctree(Mesh* mesh1, int level, float X, float Y, float Z,
 	
 	if (level==0){
 		mesh=mesh1;
-		if (block!=0){
-			if (mesh->parent!=0) {
-				mesh->parent->child_list.remove(mesh);
+		if (mesh!=0){
+			if (block!=0){
+				if (mesh->parent!=0) {
+					mesh->parent->child_list.remove(mesh);
+				}else{
+					Global::root_ent->child_list.remove(mesh);
+				}
 			}else{
-				Global::root_ent->child_list.remove(mesh);
+				mesh->hide=true;
 			}
-		}else{
-			mesh->hide=true;
+			mesh->Alpha();
 		}
-		mesh->Alpha();
 		/*mesh->GetBounds();
 		if ((mesh->max_x>width	|| mesh->min_x<-width)	||
 		    (mesh->max_y>height	|| mesh->min_y<-height)	||
@@ -351,13 +353,13 @@ void OcTreeChild::RenderChild(){
 
 				mesh_temp->brush=mesh->brush;
 
-				mesh_temp->anim=0;
-				mesh_temp->anim_render=0;
 				if(mesh->anim_render){
+					mesh_temp->anim=mesh->anim;
+					mesh_temp->anim_render=mesh->anim_render;
 					mesh_temp->anim_surf_list=mesh->anim_surf_list;
-				}else{
-					mesh_temp->surf_list=mesh->surf_list;
 				}
+				mesh_temp->surf_list=mesh->surf_list;
+				
 
 
 				mesh_temp->mat=mat2;

+ 159 - 0
openb3dlib.mod/openb3d/src/particle.cpp

@@ -0,0 +1,159 @@
+#include "glew.h"
+/*
+#ifdef linux
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+#endif
+#ifdef WIN32
+#include <gl\GLee.h>
+#endif
+*/
+
+#include "camera.h"
+#include "particle.h"
+#include "surface.h"
+
+list<ParticleBatch*> ParticleBatch::particle_batch_list;
+
+void ParticleBatch::Render(){
+	int depth_mask_disabled=false;
+
+	Surface* surf=*surf_list.begin();
+
+	glDisable(GL_ALPHA_TEST); // ?
+
+	if(Global::fx1!=true){
+		Global::fx1=true;
+		glDisableClientState(GL_NORMAL_ARRAY);
+	}
+
+	if(Global::fx2!=true){
+		Global::fx2=true;
+		glEnableClientState(GL_COLOR_ARRAY);
+		glEnable(GL_COLOR_MATERIAL);
+	}
+
+	if(surf->alpha_enable==true){
+		if(Global::alpha_enable!=true){
+			Global::alpha_enable=true;
+			glEnable(GL_BLEND);
+		}
+		glDepthMask(GL_FALSE); // must be set to false every time, as it's always equal to true before it's called
+		depth_mask_disabled=true; // set this to true to we know when to enable depth mask at bottom of function
+	}else{
+		if(Global::alpha_enable!=false){
+			Global::alpha_enable=false;
+			glDisable(GL_BLEND);
+			//glDepthMask(GL_TRUE); already set to true
+		}
+	}
+
+	if(brush.blend!=Global::blend_mode){
+		Global::blend_mode=brush.blend;
+
+		switch(brush.blend){
+			case 0:
+				glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // alpha
+				break;
+			case 1:
+				glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // alpha
+				break;
+			case 2:
+				glBlendFunc(GL_DST_COLOR,GL_ZERO); // multiply
+				break;
+			case 3:
+				glBlendFunc(GL_SRC_ALPHA,GL_ONE); // additive and alpha
+				break;
+		}
+
+	}
+
+
+	glEnable( GL_POINT_SPRITE ); 
+
+	float quadratic[] = {0,0,1};
+	glPointParameterfv( GL_POINT_DISTANCE_ATTENUATION, quadratic );
+
+	glEnable( GL_POINT_SMOOTH );
+	glPointSize(brush.tex[0]->width * Global::camera_in_use->vheight*.5);
+	glActiveTexture(GL_TEXTURE0);
+	glEnable( GL_TEXTURE_2D );
+
+	if(brush.tex[0]->flags&4){
+		glEnable(GL_ALPHA_TEST);
+	}
+
+	switch(brush.tex[0]->blend){
+		case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
+		break;
+		case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
+		break;
+		case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+		//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
+		break;
+		case 3: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_ADD);
+		break;
+		case 4:
+			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
+			glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_DOT3_RGB_EXT);
+			break;
+		case 5:
+			glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
+			glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_MODULATE);
+			glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE,2.0);
+			break;
+		default: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+	}
+
+
+	glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
+	glBindTexture(GL_TEXTURE_2D, brush.tex[0]->texture);
+
+
+
+
+	glColorPointer(4,GL_FLOAT,0,&surf->vert_col[0]);
+
+	glVertexPointer(3,GL_FLOAT,0,&surf->vert_coords[0]);
+	glDrawArrays(GL_POINTS,0,surf->no_verts);
+
+	glDisable( GL_POINT_SPRITE ); 
+	glDisable( GL_POINT_SMOOTH );
+
+	// enable depth mask again if it was disabled when blend was enabled
+	if(depth_mask_disabled==true){
+		glDepthMask(GL_TRUE);
+		depth_mask_disabled=false; // set to false again for when we repeat loop
+	}
+
+
+
+	//Trails
+
+	for(int i=0;i<=surf->no_verts-1;i++){
+		surf->vert_col[i*4+3]*=.99;
+		surf->vert_coords[i*3]+=0;
+		surf->vert_coords[i*3+1]+=.1;
+		surf->vert_coords[i*3+2]+=0;
+
+	}
+
+
+int del_trail_points=surf->no_verts/1;//3000;
+
+	if (del_trail_points!=0){
+		surf->vert_tex_coords0.clear();
+		surf->vert_tex_coords1.clear();
+		if (surf->no_verts<=del_trail_points){
+			surf->vert_coords.clear();
+			surf->vert_col.clear();
+			surf->no_verts=0;
+		}else{
+			surf->vert_coords.erase(surf->vert_coords.begin(),surf->vert_coords.begin()+del_trail_points*3);
+			surf->vert_col.erase(surf->vert_col.begin(),surf->vert_col.begin()+del_trail_points*4);
+			surf->no_verts-=del_trail_points;
+		}
+	}
+
+}

+ 115 - 0
openb3dlib.mod/openb3d/src/particle.h

@@ -0,0 +1,115 @@
+#ifndef PARTICLE_H
+#define PARTICLE_H
+
+#include "mesh.h"
+#include "global.h"
+#include "surface.h"
+#include "texture.h"
+
+#include <iostream>
+using namespace std;
+
+/*class Particle : public Mesh{
+	public:
+
+	void Render();
+
+};*/
+
+
+
+class ParticleBatch: public Mesh{
+
+public:
+
+	static list<ParticleBatch*> particle_batch_list;
+
+	void Render();
+
+	
+	ParticleBatch(){
+		no_surfs=1;
+		no_bones=0;
+		
+		c_col_tree=NULL;
+		reset_col_tree=0;
+		
+		reset_bounds=true;
+		
+		min_x=-999999999;;min_y=-999999999;;min_z=-999999999;;max_x=999999999;;max_y=999999999;;max_z=999999999;;
+	};
+	
+	static Surface* GetParticleBatchSurface(Texture* tex,int blend,int order){
+	
+		ParticleBatch* particle_batch=NULL;
+	
+		// check if particle batch already exists for specified texture, if so return it
+		list<ParticleBatch*>::iterator it;
+		for(it=particle_batch_list.begin();it!=particle_batch_list.end();it++){
+			particle_batch=*it;
+			if(particle_batch->brush.tex[0]==tex && particle_batch->brush.blend==blend && particle_batch->order==order){
+				return *particle_batch->surf_list.begin();
+			}
+		}
+		
+		// if no particle batch surface exists, create new particle batch with new surface
+		particle_batch=new ParticleBatch;
+		Surface* surf=new Surface;
+		surf->vbo_enabled=false;
+		surf->ShaderMat=0;
+		particle_batch->surf_list.push_back(surf);
+		particle_batch->hide=false;
+		entity_list.push_back(particle_batch);
+		Global::root_ent->child_list.push_back(particle_batch);
+
+
+		particle_batch->brush.tex[0]=tex;
+		particle_batch->brush.blend=blend;
+		particle_batch->order=order;
+		particle_batch_list.push_back(particle_batch);
+		return surf;
+		
+	}
+
+/*	Mesh* GetParticleBatchMesh(){
+
+		mesh=new Particle();
+	
+		mesh->surf_list.push_back(surf);
+	
+		mesh->no_surfs=mesh->no_surfs+1;
+	
+		// new mesh surface - update reset flags
+		mesh->reset_bounds=true;
+		mesh->reset_col_tree=true;
+		
+		mesh->brush.tex[0]=texture;
+		mesh->brush.cache_frame[0]=texture->texture;
+
+		mesh->brush.no_texs=1;
+		mesh->brush.blend=blend;
+		mesh->brush.fx=35;
+		
+		mesh->order=order;
+
+		return mesh;
+	
+	}
+	
+	static void Clear(){
+
+		list<ParticleBatch*>::iterator it;
+		for(it=particle_batch_list.begin();it!=particle_batch_list.end();it++){
+			ParticleBatch* particle_batch=*it;
+			delete particle_batch->mesh;
+			delete particle_batch->surf;
+			delete particle_batch;
+		}
+		particle_batch_list.clear();
+	
+	}*/
+
+};
+
+
+#endif

+ 556 - 542
openb3dlib.mod/openb3d/src/shadow.cpp

@@ -1,542 +1,556 @@
-
-#include "glew.h"
-/*
-#ifdef linux
-#define GL_GLEXT_PROTOTYPES
-#include <GL/gl.h>
-#include <GL/glext.h>
-#endif
-#ifdef WIN32
-#include "GLee.h"
-#endif
-#ifdef __APPLE__
-#include "GLee.h"
-#endif
-*/
-
-#include "shadow.h"
-#include "light.h"
-#include "mesh.h"
-#include "global.h"
-
-float ShadowObject::ShadowRed   =0;
-float ShadowObject::ShadowGreen =0;
-float ShadowObject::ShadowBlue  =0;
-float ShadowObject::ShadowAlpha =.5;
-
-list<ShadowObject*> ShadowObject::shadow_list;
-
-float ShadowObject::light_x, ShadowObject::light_y, ShadowObject::light_z;
-char ShadowObject::top_caps=true;
-float ShadowObject::VolumeLength=1000;
-int ShadowObject::parallel;
-int ShadowObject::midStencilVal;
-//int ShadowObject::RenderedVolumes;
-//int ShadowObject::Frame;
-//int ShadowObject::Time;
-
-void ShadowObject::FreeShadow() {
-	shadow_list.remove(this);
-	ShadowMesh->FreeEntity();
-
-	vector<ShadowTriangle*>::iterator it;
-	for(it=Tri.begin();it!=Tri.end();it++){
-		delete *it;
-	}
-	if (shadow_list.size()==0) Global::Shadows_enabled=0;
-
-}
-
-void ShadowObject::SetShadowColor(int R, int G, int B, int A){
-	ShadowRed   = R/255.0;
-	ShadowGreen = G/255.0;
-	ShadowBlue  = B/255.0;
-	ShadowAlpha = A;
-}
-
-void ShadowObject::ShadowInit(){
-		int StencilBits;
-		glGetIntegerv(GL_STENCIL_BITS, &StencilBits);
-		midStencilVal = (StencilBits - 1)^2;
-		glClearStencil(midStencilVal);
-}
-
-ShadowObject* ShadowObject::Create(Mesh* Parent, char Static){
-		ShadowObject* S = new ShadowObject;
-		S->ShadowMesh=Mesh::CreateMesh();
-		Global::root_ent->child_list.remove(S->ShadowMesh);
-		S->ShadowMesh->EntityBlend(0);
-		S->ShadowMesh->EntityAlpha (0.2);
-		S->ShadowMesh->EntityColor  (255, 0, 0);
-		S->ShadowMesh->EntityFX (17);
-		S->ShadowVolume = S->ShadowMesh->CreateSurface();
-		S->Parent = Parent;
-		S->Static = Static;
-		shadow_list.push_back(S);
-		S->Init();
-		return S;
-}
-
-void ShadowObject::RemoveShadowfromMesh(Mesh* M) {
-	list<ShadowObject*>::iterator it;
-	for(it=shadow_list.begin();it!=shadow_list.end();it++){
-		ShadowObject* S=*it;
-		if (S->Parent == M){
-			shadow_list.remove(S);
-			return;
-		}
-	}
-}
-
-void ShadowObject::Update(Camera* Cam){
-	//RenderedVolumes = 0;
-	//Global::RenderWorld();
-		/*If TGlobal.Buffer <> Null
-				Cam.SaveViewport()
-				Cam.vx=0
-				Cam.vy=0
-				Cam.vwidth = TGlobal.Buffer.W
-				Cam.vheight = TGlobal.Buffer.H
-				TGlobal.Buffer.Setbuffer()
-		End If*/
-	vector<Light*>::iterator it;
-	for(it=Light::light_list.begin();it!=Light::light_list.end();++it){
-		Light* Light=*it;
-
-		light_x = Light->EntityX(true) * (1 + parallel * 1);
-		light_y = Light->EntityY(true) * (1 + parallel * 1);
-		light_z = Light->EntityZ(true) * (1 + parallel * 1);
-
-		Cam->CameraClsMode(false,false);
-		Cam->Update();
-
-		list<ShadowObject*>::iterator it2;
-		for(it2=shadow_list.begin();it2!=shadow_list.end();it2++){
-			ShadowObject* S=*it2;
-			if (S->Parent->hide==false && Light->EntityDistance(S->Parent)<1/Light->range){
-				VolumeLength=(Cam->range_far-S->Parent->EntityDistance(Cam))/(S->Parent->EntityDistance(Light)+abs(S->Parent->cull_radius));
-				S->ShadowMesh->reset_bounds = true;
-				S->ShadowMesh->GetBounds();
-				S->UpdateCaster();
-				S->Render = true;
-			}else{
-				S->Render = false;
-			}
-			//RenderedVolumes++;
-		}
-
-		Cam->CameraClsMode(false,false);
-
-		ShadowRenderWorldZFail();
-
-	}
-	Cam->CameraClsMode(true , true) ;
-	/*	If TGlobal.Buffer <> Null Then
-			TGLobal.Buffer.UnSetBuffer()
-			Cam.RestoreViewPort()
-		End If
-
-	Frame++;*/
-}
-
-void ShadowObject::RenderVolume(){
-	glEnable(GL_POLYGON_OFFSET_FILL);
-	glPolygonOffset(0.0, 4.0);
-	list<ShadowObject*>::iterator it;
-	for(it=shadow_list.begin();it!=shadow_list.end();it++){
-		ShadowObject* S=*it;
-		if (S->Render == true) {S->ShadowMesh->UpdateShadow();}
-	}
-	glDisable(GL_POLYGON_OFFSET_FILL);
-}
-
-void ShadowObject::UpdateAnim(){
-	Surface* surf;// = Parent->GetSurface(1);
-	Surface* anim_surf;
-
-	list<Surface*>::iterator surf_it;
-	surf_it=Parent->surf_list.begin();
-
-	list<Surface*>::iterator an_it;
-	an_it=Parent->anim_surf_list.begin();
-
-	vector<ShadowTriangle*>::iterator it;
-
-	int cnt;
-	int cnt_surf = Parent->CountSurfaces();
-	it=Tri.begin();
-  // for(it=Tri.begin();it!=Tri.end();it++){
-
-	for (int s = 1; s<= cnt_surf;s++){
-		surf = *surf_it;
-		anim_surf = *an_it;
-		cnt = surf->CountTriangles() - 1;
-
-		for (int v = 0;v<=cnt;v++){
-			ShadowTriangle* T=*it;
-			int vert0 = surf->TriangleVertex(T->tris, 0);
-			int vert1 = surf->TriangleVertex(T->tris, 1);
-			int vert2 = surf->TriangleVertex(T->tris, 2);
-			T->v1x = anim_surf->VertexX(vert0);
-			T->v1y = anim_surf->VertexY(vert0);
-			T->v1z = anim_surf->VertexZ(vert0);
-			T->v2x = anim_surf->VertexX(vert1);
-			T->v2y = anim_surf->VertexY(vert1);
-			T->v2z = anim_surf->VertexZ(vert1);
-			T->v3x = anim_surf->VertexX(vert2);
-			T->v3y = anim_surf->VertexY(vert2);
-			T->v3z = anim_surf->VertexZ(vert2);
-			it++;
-		}
-		surf_it++;
-		an_it++;
-	}
-}
-
-void ShadowObject::Init(){
-	int cnt = -1;
-	cnt_tris = - 1;
-	int cnt_surf = Parent->CountSurfaces();
-
-	for (int s = 1; s<= cnt_surf;s++){
-		Surface* surf = Parent->GetSurface(s);
-		cnt = surf->CountTriangles() - 1;
-
-		for (int v = 0;v<=cnt;v++){
-			cnt_tris = cnt_tris + 1;
-			/*if (cnt+1 > Tri.size){
-					tri = tri[..tri.length + 1]
-			}*/
-			ShadowTriangle* etet = new ShadowTriangle;
-			Tri.push_back(etet);
-			etet->tris = v;
-			int vert0 = surf->TriangleVertex(v, 0);
-			int vert1 = surf->TriangleVertex(v, 1);
-			int vert2 = surf->TriangleVertex(v, 2);
-			etet->v1x = surf->VertexX(vert0);
-			etet->v1y = surf->VertexY(vert0);
-			etet->v1z = surf->VertexZ(vert0);
-			etet->v2x = surf->VertexX(vert1);
-			etet->v2y = surf->VertexY(vert1);
-			etet->v2z = surf->VertexZ(vert1);
-			etet->v3x = surf->VertexX(vert2);
-			etet->v3y = surf->VertexY(vert2);
-			etet->v3z = surf->VertexZ(vert2);
-			etet->ta = -1;
-			etet->tb = -1;
-			etet->tc = -1;
-		}
-	}
-	//int cnt_tris = cnt_tris
-	float v1a_x, v1a_y, v1a_z, v1b_x, v1b_y, v1b_z, v1c_x, v1c_y, v1c_z;
-
-	bool v1a_v2a, v1a_v2b, v1a_v2c, v1b_v2a, v1b_v2b, v1b_v2c, v1c_v2a, v1c_v2b, v1c_v2c;
-
-	for (int a = 0;a<= cnt_tris;a++){
-		ShadowTriangle* at = Tri[a];
-		v1a_x  = at->v1x;
-		v1a_y  = at->v1y;
-		v1a_z  = at->v1z;
-		v1b_x  = at->v2x;
-		v1b_y  = at->v2y;
-		v1b_z  = at->v2z;
-		v1c_x  = at->v3x;
-		v1c_y  = at->v3y;
-		v1c_z  = at->v3z;
-		for (int b = a + 1;b<= cnt_tris; b++){
-			ShadowTriangle* bt = Tri[b];
-			v1a_v2a = (v1a_x == bt->v1x && v1a_y == bt->v1y && v1a_z == bt->v1z);
-			v1a_v2b = (v1a_x == bt->v2x && v1a_y == bt->v2y && v1a_z == bt->v2z);
-			v1a_v2c = (v1a_x == bt->v3x && v1a_y == bt->v3y && v1a_z == bt->v3z);
-			v1b_v2a = (v1b_x == bt->v1x && v1b_y == bt->v1y && v1b_z == bt->v1z);
-			v1b_v2b = (v1b_x == bt->v2x && v1b_y == bt->v2y && v1b_z == bt->v2z);
-			v1b_v2c = (v1b_x == bt->v3x && v1b_y == bt->v3y && v1b_z == bt->v3z);
-			v1c_v2a = (v1c_x == bt->v1x && v1c_y == bt->v1y && v1c_z == bt->v1z);
-			v1c_v2b = (v1c_x == bt->v2x && v1c_y == bt->v2y && v1c_z == bt->v2z);
-			v1c_v2c = (v1c_x == bt->v3x && v1c_y == bt->v3y && v1c_z == bt->v3z);
-
-			if (bt->ta==-1){
-				if (v1a_v2b!=0 && v1b_v2a!=0 && at->ta==-1){
-					at->ta = b;
-					bt->ta = a;}
-				else if (v1b_v2b!=0 && v1c_v2a!=0 && at->tb==-1){
-					at->tb = b;
-					bt->ta = a;}
-				else if (v1c_v2b!=0 && v1a_v2a!=0 && at->ta==-1){
-					at->tc = b;
-					bt->ta = a;}
-			}
-			if (bt->tb==-1){
-				if (v1a_v2c!=0 && v1b_v2b!=0 && at->ta==-1){
-					at->ta = b;
-					bt->tb = a;}
-				else if (v1b_v2c!=0 && v1c_v2b!=0 && at->tb==-1){
-					at->tb = b;
-					bt->tb = a;}
-				else if (v1c_v2c!=0 && v1a_v2b!=0 && at->tc==-1){
-					at->tc = b;
-					bt->tb = a;}
-			}
-			if (bt->tc==-1){
-				if (v1a_v2a!=0 && v1b_v2c!=0 && at->ta==-1){
-					at->ta = b;
-					bt->tc = a;}
-				else if (v1b_v2a!=0 && v1c_v2c!=0 && at->tb==-1){
-					at->tb = b;
-					bt->tc = a;}
-				else if (v1c_v2a!=0 && v1a_v2c!=0 && at->tc==-1){
-					at->tc = b;
-					bt->tc = a;
-				}
-			}
-		}
-
-	}
-	InitShadow();
-}
-
-void ShadowObject::InitShadow(){
-	if (Global::Shadows_enabled==0){
-	  Global::Shadows_enabled=true;
-	  ShadowInit();
-	}
-	for (int v = 0;v<=cnt_tris;v++){
-		ShadowTriangle* etet = Tri[v];
-		if (etet->ta > -1) etet->id_ta = Tri[etet->ta];
-		if (etet->tb > -1) etet->id_tb = Tri[etet->tb];
-		if (etet->tc > -1) etet->id_tc = Tri[etet->tc];
-	}
-}
-
-void ShadowObject::UpdateCaster(){
-	if (Static!=0 && VCreated!=0) return;
-	VCreated = true;
-	if (ShadowVolume!=0) {ShadowVolume->ClearSurface();}
-	if (Parent->anim!=0) {UpdateAnim();}
-
-	float e0x, e0y, e0z, e1x, e1y, e1z;
-
-	float normlight_x, normlight_y, normlight_z;
-
-	float r1x, r1y, r1z, r2x, r2y, r2z, r3x, r3y, r3z;
-
-	int vert1, vert2, vert3, vert4;
-
-	char check1=0;
-	char check2=0;
-	char check3=0;
-
-	Matrix* mat1 = Parent->MQ_GetMatrix(true);
-
-	vector<ShadowTriangle*>::iterator it;
-
-
-/*	for (int v = 0;v<=cnt_tris;v++){
-		ShadowTriangle* etet = Tri[v];
-
-		Entity::TFormPoint (etet->v1x, etet->v1y, etet->v1z, Parent, 0);
-		etet->tf_v1x= Entity::TFormedX();
-		etet->tf_v1y= Entity::TFormedY();
-		etet->tf_v1z= Entity::TFormedZ();
-		Entity::TFormPoint (etet->v2x, etet->v2y, etet->v2z, Parent, 0);
-		etet->tf_v2x= Entity::TFormedX();
-		etet->tf_v2y= Entity::TFormedY();
-		etet->tf_v2z= Entity::TFormedZ();
-		Entity::TFormPoint (etet->v3x, etet->v3y, etet->v3z, Parent, 0);
-		etet->tf_v3x= Entity::TFormedX();
-		etet->tf_v3y= Entity::TFormedY();
-		etet->tf_v3z= Entity::TFormedZ();
-		*/
-	for(it=Tri.begin();it!=Tri.end();it++){
-		ShadowTriangle* etet = *it;
-
-		etet->tf_v1x= etet->v1x;
-		etet->tf_v1y= etet->v1y;
-		etet->tf_v1z= etet->v1z;
-		mat1->TransformVec(etet->tf_v1x, etet->tf_v1y, etet->tf_v1z, 1);
-
-		etet->tf_v2x= etet->v2x;
-		etet->tf_v2y= etet->v2y;
-		etet->tf_v2z= etet->v2z;
-		mat1->TransformVec(etet->tf_v2x, etet->tf_v2y, etet->tf_v2z, 1);
-
-		etet->tf_v3x= etet->v3x;
-		etet->tf_v3y= etet->v3y;
-		etet->tf_v3z= etet->v3z;
-		mat1->TransformVec(etet->tf_v3x, etet->tf_v3y, etet->tf_v3z, 1);
-
-		e0x= etet->tf_v3x - etet->tf_v2x;
-		e0y= etet->tf_v3y - etet->tf_v2y;
-		e0z= etet->tf_v3z - etet->tf_v2z;
-		e1x= etet->tf_v2x - etet->tf_v1x;
-		e1y= etet->tf_v2y - etet->tf_v1y;
-		e1z= etet->tf_v2z - etet->tf_v1z;
-		normlight_x  = (etet->tf_v1x  - light_x ) * (e0y  * e1z  - e0z  * e1y );
-		normlight_y  = (etet->tf_v1y  - light_y ) * (e0z  * e1x  - e0x  * e1z );
-		normlight_z  = (etet->tf_v1z  - light_z ) * (e0x  * e1y  - e0y  * e1x );
-		etet->cull = (normlight_x  + normlight_y  + normlight_z  > 0);
-	}
-	delete mat1;
-
-//	for (int v = 0;v<=cnt_tris;v++){
-//		ShadowTriangle* etet = Tri[v];
-	for(it=Tri.begin();it!=Tri.end();it++){
-		ShadowTriangle* etet = *it;
-		r1x  = etet->tf_v1x  + (etet->tf_v1x  - light_x ) * VolumeLength;
-		r1y  = etet->tf_v1y  + (etet->tf_v1y  - light_y ) * VolumeLength;
-		r1z  = etet->tf_v1z  + (etet->tf_v1z  - light_z ) * VolumeLength;
-		r2x  = etet->tf_v2x  + (etet->tf_v2x  - light_x ) * VolumeLength;
-		r2y  = etet->tf_v2y  + (etet->tf_v2y  - light_y ) * VolumeLength;
-		r2z  = etet->tf_v2z  + (etet->tf_v2z  - light_z ) * VolumeLength;
-		r3x  = etet->tf_v3x  + (etet->tf_v3x  - light_x ) * VolumeLength;
-		r3y  = etet->tf_v3y  + (etet->tf_v3y  - light_y ) * VolumeLength;
-		r3z  = etet->tf_v3z  + (etet->tf_v3z  - light_z ) * VolumeLength;
-
-
-
-		if (etet->cull == 0) {
-			if (etet->ta > -1) {check1 = etet->id_ta->cull;} else {check1 = 1;}
-			if (etet->tb > -1) {check2 = etet->id_tb->cull;} else {check2 = 1;}
-			if (etet->tc > -1) {check3 = etet->id_tc->cull;} else {check3 = 1;}
-
-			if (check1!=0){
-				vert1 = ShadowVolume->AddVertex(etet->tf_v1x , etet->tf_v1y , etet->tf_v1z);
-				vert2 = ShadowVolume->AddVertex(etet->tf_v2x , etet->tf_v2y , etet->tf_v2z);
-				vert3 = ShadowVolume->AddVertex(r1x , r1y , r1z);
-				vert4 = ShadowVolume->AddVertex(r2x , r2y , r2z);
-				ShadowVolume->AddTriangle (vert1, vert3, vert4);
-				ShadowVolume->AddTriangle (vert1, vert4, vert2);
-			}
-			if (check2!=0){
-				vert1 = ShadowVolume->AddVertex(etet->tf_v2x , etet->tf_v2y , etet->tf_v2z);
-				vert2 = ShadowVolume->AddVertex(etet->tf_v3x , etet->tf_v3y , etet->tf_v3z);
-				vert3 = ShadowVolume->AddVertex(r2x , r2y , r2z);
-				vert4 = ShadowVolume->AddVertex(r3x , r3y , r3z);
-				ShadowVolume->AddTriangle (vert1, vert3, vert4);
-				ShadowVolume->AddTriangle (vert1, vert4, vert2);
-			}
-			if (check3!=0){
-				vert1 = ShadowVolume->AddVertex(etet->tf_v1x , etet->tf_v1y , etet->tf_v1z);
-				vert2 = ShadowVolume->AddVertex(etet->tf_v3x , etet->tf_v3y , etet->tf_v3z);
-				vert3 = ShadowVolume->AddVertex(r1x , r1y , r1z);
-				vert4 = ShadowVolume->AddVertex(r3x , r3y , r3z);
-				ShadowVolume->AddTriangle (vert1, vert4, vert3);
-				ShadowVolume->AddTriangle (vert1, vert2, vert4);
-			}
-			if (top_caps!=0){
-				vert1 = ShadowVolume->AddVertex(etet->tf_v1x , etet->tf_v1y , etet->tf_v1z);
-				vert2 = ShadowVolume->AddVertex(etet->tf_v2x , etet->tf_v2y , etet->tf_v2z);
-				vert3 = ShadowVolume->AddVertex(etet->tf_v3x , etet->tf_v3y , etet->tf_v3z);
-
-				ShadowVolume->AddTriangle (vert1, vert2, vert3);
-			}
-		/*} else */
-			if (parallel == 0){
-				vert1 = ShadowVolume->AddVertex(r1x , r1y , r1z);
-				vert2 = ShadowVolume->AddVertex(r2x , r2y , r2z);
-				vert3 = ShadowVolume->AddVertex(r3x , r3y , r3z);
-				ShadowVolume->AddTriangle (vert1, vert3, vert2);
-			}
-		}
-	}
-}
-
-void ShadowObject::ShadowRenderWorldZFail(){
-	glEnable(GL_STENCIL_TEST);
-	/*Pass 1 Ambient Pass
-	 First clear the stencil Buffer */
-	glClearStencil(midStencilVal);
-
-	glClear(GL_STENCIL_BUFFER_BIT);
-
-	glDepthMask(GL_FALSE);
-	glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
-	// we wanted the first ambient pass above in the Color Buffer but we don't want the volumes in
-	// there ..removing the above line is fun though :P
-	glEnable( GL_CULL_FACE );
-	glEnable( GL_STENCIL_TEST );
-
-	// Render the shadow volume And increment the stencil every where a front
-	// facing polygon is rendered.
-
-	// Incrementing the stencil Buffer when back face depth fails
-	glStencilFunc( GL_ALWAYS, midStencilVal, 0xffffffff); // ~0 is like 0xFFFFFFFF Or something :P
-	glStencilOp( GL_KEEP, GL_INCR_WRAP, GL_KEEP ); // incrementing on the depth fail
-	glCullFace( GL_BACK   ); // cull front facing polys For this pass
-
-	RenderVolume();
-
-	// Render the shadow volume And decrement the stencil every where a back
-	// facing polygon is rendered.
-	glStencilOp( GL_KEEP, GL_DECR_WRAP, GL_KEEP ); // decrementing on the depth fail
-	glCullFace( GL_FRONT   ); // And now culling back facing polys
-
-	RenderVolume();
-
-	// When done, set the states back To something more typical.
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	glEnable(GL_LIGHTING);
-	glDepthMask(GL_TRUE);
-
-	glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
-	glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
-
-	//
-	// Render the lit part...
-	//
-	glStencilFunc( GL_EQUAL, midStencilVal, 0xffffffff); // again with the ~0 :P
-	// When done, set the states back To something more typical.
-	glEnable(GL_DEPTH_TEST);
-	glCullFace( GL_BACK   ); // cull front facing polys For this pass
-
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	glEnable(GL_LIGHTING);
-	glDepthMask(GL_TRUE);
-
-	glCullFace(GL_BACK);
-	glStencilFunc(GL_NOTEQUAL, midStencilVal, 0xffffff);
-	glStencilOp(GL_KEEP , GL_KEEP , GL_KEEP);
-
-// NOTE: is it the projektion matrix ?
-	glPushMatrix();
-	  glLoadIdentity();
-	  glMatrixMode(GL_MODELVIEW);
-	  glPushMatrix();
-	    glLoadIdentity();
-	    glOrtho(0 , 1 , 1 , 0 , 0 , 1);
-
-	    //float no_mat[]={0.0,0.0};
-	    float mat_ambient[]={ShadowRed,ShadowGreen,ShadowBlue,.5};
-	    float mat_diffuse[]={0,0,0,0.5};
-	    float mat_specular[]={0,0,0,0.5};
-	    float mat_shininess[]={0.0}; // upto 128
-
-	    glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
-	    glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
-	    glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
-	    glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
-
-	    glEnable(GL_BLEND);
-	    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
-	    glDisable(GL_DEPTH_TEST);
-	    glColor4f(0.0, 0.0, 0.0, 1.0);
-
-	    glBegin(GL_QUADS);
-		    glVertex2i(0, 0);
-		    glVertex2i(0, 1);
-		    glVertex2i(1, 1);
-		    glVertex2i(1, 0);
-	    glEnd();
-
-	    glEnable(GL_DEPTH_TEST);
-	  glPopMatrix();
-	  // NOTE: is it the projektion matrix ?
-	  glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-
-	glCullFace( GL_BACK   ); // cull front facing polys For this pass
-	glDisable(GL_STENCIL_TEST);
-
-}
-
-
+
+#include "glew.h"
+/*
+#ifdef linux
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+#endif
+#ifdef WIN32
+#include "GLee.h"
+#endif
+#ifdef __APPLE__
+#include "GLee.h"
+#endif
+*/
+
+#include "shadow.h"
+#include "light.h"
+#include "mesh.h"
+#include "global.h"
+
+float ShadowObject::ShadowRed   =0;
+float ShadowObject::ShadowGreen =0;
+float ShadowObject::ShadowBlue  =0;
+float ShadowObject::ShadowAlpha =.5;
+
+list<ShadowObject*> ShadowObject::shadow_list;
+
+float ShadowObject::light_x, ShadowObject::light_y, ShadowObject::light_z;
+char ShadowObject::top_caps=true;
+float ShadowObject::VolumeLength=1000;
+int ShadowObject::parallel;
+int ShadowObject::midStencilVal;
+//int ShadowObject::RenderedVolumes;
+//int ShadowObject::Frame;
+//int ShadowObject::Time;
+
+void ShadowObject::FreeShadow() {
+	shadow_list.remove(this);
+	ShadowMesh->FreeEntity();
+
+	vector<ShadowTriangle*>::iterator it;
+	for(it=Tri.begin();it!=Tri.end();it++){
+		delete *it;
+	}
+	if (shadow_list.size()==0) Global::Shadows_enabled=0;
+
+}
+
+void ShadowObject::SetShadowColor(int R, int G, int B, int A){
+	ShadowRed   = R/255.0;
+	ShadowGreen = G/255.0;
+	ShadowBlue  = B/255.0;
+	ShadowAlpha = A;
+}
+
+void ShadowObject::ShadowInit(){
+		int StencilBits;
+		glGetIntegerv(GL_STENCIL_BITS, &StencilBits);
+		midStencilVal = (StencilBits - 1)^2;
+		glClearStencil(midStencilVal);
+}
+
+ShadowObject* ShadowObject::Create(Mesh* Parent, char Static){
+		ShadowObject* S = new ShadowObject;
+		S->ShadowMesh=Mesh::CreateMesh();
+		Global::root_ent->child_list.remove(S->ShadowMesh);
+		S->ShadowMesh->EntityBlend(0);
+		S->ShadowMesh->EntityAlpha (0.2);
+		S->ShadowMesh->EntityColor  (255, 0, 0);
+		S->ShadowMesh->EntityFX (17);
+		S->ShadowVolume = S->ShadowMesh->CreateSurface();
+		S->Parent = Parent;
+		S->Static = Static;
+		shadow_list.push_back(S);
+		S->Init();
+		return S;
+}
+
+void ShadowObject::RemoveShadowfromMesh(Mesh* M) {
+	list<ShadowObject*>::iterator it;
+	for(it=shadow_list.begin();it!=shadow_list.end();it++){
+		ShadowObject* S=*it;
+		if (S->Parent == M){
+			shadow_list.remove(S);
+			return;
+		}
+	}
+}
+
+void ShadowObject::Update(Camera* Cam){
+	//RenderedVolumes = 0;
+	//Global::RenderWorld();
+		/*If TGlobal.Buffer <> Null
+				Cam.SaveViewport()
+				Cam.vx=0
+				Cam.vy=0
+				Cam.vwidth = TGlobal.Buffer.W
+				Cam.vheight = TGlobal.Buffer.H
+				TGlobal.Buffer.Setbuffer()
+		End If*/
+	vector<Light*>::iterator it;
+	for(it=Light::light_list.begin();it!=Light::light_list.end();++it){
+		Light* Light=*it;
+
+		light_x = Light->EntityX(true) * (1 + parallel * 1);
+		light_y = Light->EntityY(true) * (1 + parallel * 1);
+		light_z = Light->EntityZ(true) * (1 + parallel * 1);
+
+		Cam->CameraClsMode(false,false);
+		Cam->Update();
+
+		list<ShadowObject*>::iterator it2;
+		for(it2=shadow_list.begin();it2!=shadow_list.end();it2++){
+			ShadowObject* S=*it2;
+			if (S->Parent->hide==false && Light->EntityDistance(S->Parent)<1/Light->range){
+				VolumeLength=(Cam->range_far-S->Parent->EntityDistance(Cam))/(S->Parent->EntityDistance(Light)+abs(S->Parent->cull_radius));
+				S->ShadowMesh->reset_bounds = true;
+				S->ShadowMesh->GetBounds();
+				S->UpdateCaster();
+				S->Render = true;
+			}else{
+				S->Render = false;
+			}
+			//RenderedVolumes++;
+		}
+
+		Cam->CameraClsMode(false,false);
+
+		ShadowRenderWorldZFail();
+
+	}
+	Cam->CameraClsMode(true , true) ;
+	/*	If TGlobal.Buffer <> Null Then
+			TGLobal.Buffer.UnSetBuffer()
+			Cam.RestoreViewPort()
+		End If
+
+	Frame++;*/
+}
+
+void ShadowObject::RenderVolume(){
+	glEnable(GL_POLYGON_OFFSET_FILL);
+	glPolygonOffset(0.0, 4.0);
+	list<ShadowObject*>::iterator it;
+	for(it=shadow_list.begin();it!=shadow_list.end();it++){
+		ShadowObject* S=*it;
+		if (S->Render == true) {S->ShadowMesh->UpdateShadow();}
+	}
+	glDisable(GL_POLYGON_OFFSET_FILL);
+}
+
+void ShadowObject::UpdateAnim(){
+	Surface* surf;// = Parent->GetSurface(1);
+	Surface* anim_surf;
+
+	list<Surface*>::iterator surf_it;
+	surf_it=Parent->surf_list.begin();
+
+	list<Surface*>::iterator an_it;
+	an_it=Parent->anim_surf_list.begin();
+
+	vector<ShadowTriangle*>::iterator it;
+
+	int cnt;
+	int cnt_surf = Parent->CountSurfaces();
+	it=Tri.begin();
+  // for(it=Tri.begin();it!=Tri.end();it++){
+
+	for (int s = 1; s<= cnt_surf;s++){
+		surf = *surf_it;
+		anim_surf = *an_it;
+		cnt = surf->CountTriangles() - 1;
+
+		for (int v = 0;v<=cnt;v++){
+			ShadowTriangle* T=*it;
+			int vert0 = surf->TriangleVertex(T->tris, 0);
+			int vert1 = surf->TriangleVertex(T->tris, 1);
+			int vert2 = surf->TriangleVertex(T->tris, 2);
+			T->v1x = anim_surf->VertexX(vert0);
+			T->v1y = anim_surf->VertexY(vert0);
+			T->v1z = anim_surf->VertexZ(vert0);
+			T->v2x = anim_surf->VertexX(vert1);
+			T->v2y = anim_surf->VertexY(vert1);
+			T->v2z = anim_surf->VertexZ(vert1);
+			T->v3x = anim_surf->VertexX(vert2);
+			T->v3y = anim_surf->VertexY(vert2);
+			T->v3z = anim_surf->VertexZ(vert2);
+			it++;
+		}
+		surf_it++;
+		an_it++;
+	}
+}
+
+void ShadowObject::Init(){
+	int cnt = -1;
+	cnt_tris = - 1;
+	int cnt_surf = Parent->CountSurfaces();
+
+	for (int s = 1; s<= cnt_surf;s++){
+		Surface* surf = Parent->GetSurface(s);
+		cnt = surf->CountTriangles() - 1;
+
+		for (int v = 0;v<=cnt;v++){
+			cnt_tris = cnt_tris + 1;
+			/*if (cnt+1 > Tri.size){
+					tri = tri[..tri.length + 1]
+			}*/
+			ShadowTriangle* etet = new ShadowTriangle;
+			Tri.push_back(etet);
+			etet->tris = v;
+			int vert0 = surf->TriangleVertex(v, 0);
+			int vert1 = surf->TriangleVertex(v, 1);
+			int vert2 = surf->TriangleVertex(v, 2);
+			etet->v1x = surf->VertexX(vert0);
+			etet->v1y = surf->VertexY(vert0);
+			etet->v1z = surf->VertexZ(vert0);
+			etet->v2x = surf->VertexX(vert1);
+			etet->v2y = surf->VertexY(vert1);
+			etet->v2z = surf->VertexZ(vert1);
+			etet->v3x = surf->VertexX(vert2);
+			etet->v3y = surf->VertexY(vert2);
+			etet->v3z = surf->VertexZ(vert2);
+			etet->ta = -1;
+			etet->tb = -1;
+			etet->tc = -1;
+		}
+	}
+	//int cnt_tris = cnt_tris
+	float v1a_x, v1a_y, v1a_z, v1b_x, v1b_y, v1b_z, v1c_x, v1c_y, v1c_z;
+
+	bool v1a_v2a, v1a_v2b, v1a_v2c, v1b_v2a, v1b_v2b, v1b_v2c, v1c_v2a, v1c_v2b, v1c_v2c;
+
+	for (int a = 0;a<= cnt_tris;a++){
+		ShadowTriangle* at = Tri[a];
+		v1a_x  = at->v1x;
+		v1a_y  = at->v1y;
+		v1a_z  = at->v1z;
+		v1b_x  = at->v2x;
+		v1b_y  = at->v2y;
+		v1b_z  = at->v2z;
+		v1c_x  = at->v3x;
+		v1c_y  = at->v3y;
+		v1c_z  = at->v3z;
+		for (int b = a + 1;b<= cnt_tris; b++){
+			ShadowTriangle* bt = Tri[b];
+			v1a_v2a = (v1a_x == bt->v1x && v1a_y == bt->v1y && v1a_z == bt->v1z);
+			v1a_v2b = (v1a_x == bt->v2x && v1a_y == bt->v2y && v1a_z == bt->v2z);
+			v1a_v2c = (v1a_x == bt->v3x && v1a_y == bt->v3y && v1a_z == bt->v3z);
+			v1b_v2a = (v1b_x == bt->v1x && v1b_y == bt->v1y && v1b_z == bt->v1z);
+			v1b_v2b = (v1b_x == bt->v2x && v1b_y == bt->v2y && v1b_z == bt->v2z);
+			v1b_v2c = (v1b_x == bt->v3x && v1b_y == bt->v3y && v1b_z == bt->v3z);
+			v1c_v2a = (v1c_x == bt->v1x && v1c_y == bt->v1y && v1c_z == bt->v1z);
+			v1c_v2b = (v1c_x == bt->v2x && v1c_y == bt->v2y && v1c_z == bt->v2z);
+			v1c_v2c = (v1c_x == bt->v3x && v1c_y == bt->v3y && v1c_z == bt->v3z);
+
+			if (bt->ta==-1){
+				if (v1a_v2b!=0 && v1b_v2a!=0 && at->ta==-1){
+					at->ta = b;
+					bt->ta = a;}
+				else if (v1b_v2b!=0 && v1c_v2a!=0 && at->tb==-1){
+					at->tb = b;
+					bt->ta = a;}
+				else if (v1c_v2b!=0 && v1a_v2a!=0 && at->ta==-1){
+					at->tc = b;
+					bt->ta = a;}
+			}
+			if (bt->tb==-1){
+				if (v1a_v2c!=0 && v1b_v2b!=0 && at->ta==-1){
+					at->ta = b;
+					bt->tb = a;}
+				else if (v1b_v2c!=0 && v1c_v2b!=0 && at->tb==-1){
+					at->tb = b;
+					bt->tb = a;}
+				else if (v1c_v2c!=0 && v1a_v2b!=0 && at->tc==-1){
+					at->tc = b;
+					bt->tb = a;}
+			}
+			if (bt->tc==-1){
+				if (v1a_v2a!=0 && v1b_v2c!=0 && at->ta==-1){
+					at->ta = b;
+					bt->tc = a;}
+				else if (v1b_v2a!=0 && v1c_v2c!=0 && at->tb==-1){
+					at->tb = b;
+					bt->tc = a;}
+				else if (v1c_v2a!=0 && v1a_v2c!=0 && at->tc==-1){
+					at->tc = b;
+					bt->tc = a;
+				}
+			}
+		}
+
+	}
+	InitShadow();
+}
+
+void ShadowObject::InitShadow(){
+	if (Global::Shadows_enabled==0){
+	  Global::Shadows_enabled=true;
+	  ShadowInit();
+	}
+	for (int v = 0;v<=cnt_tris;v++){
+		ShadowTriangle* etet = Tri[v];
+		if (etet->ta > -1) etet->id_ta = Tri[etet->ta];
+		if (etet->tb > -1) etet->id_tb = Tri[etet->tb];
+		if (etet->tc > -1) etet->id_tc = Tri[etet->tc];
+	}
+}
+
+void ShadowObject::UpdateCaster(){
+	if (Static!=0 && VCreated!=0) return;
+	VCreated = true;
+	if (ShadowVolume!=0) {ShadowVolume->ClearSurface();}
+	if (Parent->anim!=0) {UpdateAnim();}
+
+	float e0x, e0y, e0z, e1x, e1y, e1z;
+
+	float normlight_x, normlight_y, normlight_z;
+
+	float r1x, r1y, r1z, r2x, r2y, r2z, r3x, r3y, r3z;
+
+	int vert1, vert2, vert3, vert4;
+
+	char check1=0;
+	char check2=0;
+	char check3=0;
+
+	Matrix* mat1 = Parent->MQ_GetMatrix(true);
+
+	vector<ShadowTriangle*>::iterator it;
+
+
+/*	for (int v = 0;v<=cnt_tris;v++){
+		ShadowTriangle* etet = Tri[v];
+
+		Entity::TFormPoint (etet->v1x, etet->v1y, etet->v1z, Parent, 0);
+		etet->tf_v1x= Entity::TFormedX();
+		etet->tf_v1y= Entity::TFormedY();
+		etet->tf_v1z= Entity::TFormedZ();
+		Entity::TFormPoint (etet->v2x, etet->v2y, etet->v2z, Parent, 0);
+		etet->tf_v2x= Entity::TFormedX();
+		etet->tf_v2y= Entity::TFormedY();
+		etet->tf_v2z= Entity::TFormedZ();
+		Entity::TFormPoint (etet->v3x, etet->v3y, etet->v3z, Parent, 0);
+		etet->tf_v3x= Entity::TFormedX();
+		etet->tf_v3y= Entity::TFormedY();
+		etet->tf_v3z= Entity::TFormedZ();
+		*/
+	for(it=Tri.begin();it!=Tri.end();it++){
+		ShadowTriangle* etet = *it;
+
+		etet->tf_v1x= etet->v1x;
+		etet->tf_v1y= etet->v1y;
+		etet->tf_v1z= etet->v1z;
+		mat1->TransformVec(etet->tf_v1x, etet->tf_v1y, etet->tf_v1z, 1);
+
+		etet->tf_v2x= etet->v2x;
+		etet->tf_v2y= etet->v2y;
+		etet->tf_v2z= etet->v2z;
+		mat1->TransformVec(etet->tf_v2x, etet->tf_v2y, etet->tf_v2z, 1);
+
+		etet->tf_v3x= etet->v3x;
+		etet->tf_v3y= etet->v3y;
+		etet->tf_v3z= etet->v3z;
+		mat1->TransformVec(etet->tf_v3x, etet->tf_v3y, etet->tf_v3z, 1);
+
+		e0x= etet->tf_v3x - etet->tf_v2x;
+		e0y= etet->tf_v3y - etet->tf_v2y;
+		e0z= etet->tf_v3z - etet->tf_v2z;
+		e1x= etet->tf_v2x - etet->tf_v1x;
+		e1y= etet->tf_v2y - etet->tf_v1y;
+		e1z= etet->tf_v2z - etet->tf_v1z;
+		normlight_x  = (etet->tf_v1x  - light_x ) * (e0y  * e1z  - e0z  * e1y );
+		normlight_y  = (etet->tf_v1y  - light_y ) * (e0z  * e1x  - e0x  * e1z );
+		normlight_z  = (etet->tf_v1z  - light_z ) * (e0x  * e1y  - e0y  * e1x );
+		etet->cull = (normlight_x  + normlight_y  + normlight_z  > 0);
+	}
+	delete mat1;
+
+//	for (int v = 0;v<=cnt_tris;v++){
+//		ShadowTriangle* etet = Tri[v];
+	for(it=Tri.begin();it!=Tri.end();it++){
+		ShadowTriangle* etet = *it;
+		r1x  = etet->tf_v1x  + (etet->tf_v1x  - light_x ) * VolumeLength;
+		r1y  = etet->tf_v1y  + (etet->tf_v1y  - light_y ) * VolumeLength;
+		r1z  = etet->tf_v1z  + (etet->tf_v1z  - light_z ) * VolumeLength;
+		r2x  = etet->tf_v2x  + (etet->tf_v2x  - light_x ) * VolumeLength;
+		r2y  = etet->tf_v2y  + (etet->tf_v2y  - light_y ) * VolumeLength;
+		r2z  = etet->tf_v2z  + (etet->tf_v2z  - light_z ) * VolumeLength;
+		r3x  = etet->tf_v3x  + (etet->tf_v3x  - light_x ) * VolumeLength;
+		r3y  = etet->tf_v3y  + (etet->tf_v3y  - light_y ) * VolumeLength;
+		r3z  = etet->tf_v3z  + (etet->tf_v3z  - light_z ) * VolumeLength;
+
+
+
+		if (etet->cull == 0) {
+			if (etet->ta > -1) {check1 = etet->id_ta->cull;} else {check1 = 1;}
+			if (etet->tb > -1) {check2 = etet->id_tb->cull;} else {check2 = 1;}
+			if (etet->tc > -1) {check3 = etet->id_tc->cull;} else {check3 = 1;}
+
+			if (check1!=0){
+				vert1 = ShadowVolume->AddVertex(etet->tf_v1x , etet->tf_v1y , etet->tf_v1z);
+				vert2 = ShadowVolume->AddVertex(etet->tf_v2x , etet->tf_v2y , etet->tf_v2z);
+				vert3 = ShadowVolume->AddVertex(r1x , r1y , r1z);
+				vert4 = ShadowVolume->AddVertex(r2x , r2y , r2z);
+				ShadowVolume->AddTriangle (vert1, vert3, vert4);
+				ShadowVolume->AddTriangle (vert1, vert4, vert2);
+			}
+			if (check2!=0){
+				vert1 = ShadowVolume->AddVertex(etet->tf_v2x , etet->tf_v2y , etet->tf_v2z);
+				vert2 = ShadowVolume->AddVertex(etet->tf_v3x , etet->tf_v3y , etet->tf_v3z);
+				vert3 = ShadowVolume->AddVertex(r2x , r2y , r2z);
+				vert4 = ShadowVolume->AddVertex(r3x , r3y , r3z);
+				ShadowVolume->AddTriangle (vert1, vert3, vert4);
+				ShadowVolume->AddTriangle (vert1, vert4, vert2);
+			}
+			if (check3!=0){
+				vert1 = ShadowVolume->AddVertex(etet->tf_v1x , etet->tf_v1y , etet->tf_v1z);
+				vert2 = ShadowVolume->AddVertex(etet->tf_v3x , etet->tf_v3y , etet->tf_v3z);
+				vert3 = ShadowVolume->AddVertex(r1x , r1y , r1z);
+				vert4 = ShadowVolume->AddVertex(r3x , r3y , r3z);
+				ShadowVolume->AddTriangle (vert1, vert4, vert3);
+				ShadowVolume->AddTriangle (vert1, vert2, vert4);
+			}
+			if (top_caps!=0){
+				vert1 = ShadowVolume->AddVertex(etet->tf_v1x , etet->tf_v1y , etet->tf_v1z);
+				vert2 = ShadowVolume->AddVertex(etet->tf_v2x , etet->tf_v2y , etet->tf_v2z);
+				vert3 = ShadowVolume->AddVertex(etet->tf_v3x , etet->tf_v3y , etet->tf_v3z);
+
+				ShadowVolume->AddTriangle (vert1, vert2, vert3);
+			}
+		/*} else */
+			if (parallel == 0){
+				vert1 = ShadowVolume->AddVertex(r1x , r1y , r1z);
+				vert2 = ShadowVolume->AddVertex(r2x , r2y , r2z);
+				vert3 = ShadowVolume->AddVertex(r3x , r3y , r3z);
+				ShadowVolume->AddTriangle (vert1, vert3, vert2);
+			}
+		}
+	}
+}
+
+void ShadowObject::ShadowRenderWorldZFail(){
+	glEnable(GL_STENCIL_TEST);
+	/*Pass 1 Ambient Pass
+	 First clear the stencil Buffer */
+	glClearStencil(midStencilVal);
+
+	glClear(GL_STENCIL_BUFFER_BIT);
+
+	glDepthMask(GL_FALSE);
+	glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
+	// we wanted the first ambient pass above in the Color Buffer but we don't want the volumes in
+	// there ..removing the above line is fun though :P
+	glEnable( GL_CULL_FACE );
+	glEnable( GL_STENCIL_TEST );
+
+	// Render the shadow volume And increment the stencil every where a front
+	// facing polygon is rendered.
+
+	// Incrementing the stencil Buffer when back face depth fails
+	glStencilFunc( GL_ALWAYS, midStencilVal, 0xffffffff); // ~0 is like 0xFFFFFFFF Or something :P
+	glStencilOp( GL_KEEP, GL_INCR_WRAP, GL_KEEP ); // incrementing on the depth fail
+	glCullFace( GL_BACK   ); // cull front facing polys For this pass
+
+	RenderVolume();
+
+	// Render the shadow volume And decrement the stencil every where a back
+	// facing polygon is rendered.
+	glStencilOp( GL_KEEP, GL_DECR_WRAP, GL_KEEP ); // decrementing on the depth fail
+	glCullFace( GL_FRONT   ); // And now culling back facing polys
+
+	RenderVolume();
+
+	// When done, set the states back To something more typical.
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	glEnable(GL_LIGHTING);
+	glDepthMask(GL_TRUE);
+
+	glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
+	glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
+
+	//
+	// Render the lit part...
+	//
+	glStencilFunc( GL_EQUAL, midStencilVal, 0xffffffff); // again with the ~0 :P
+	// When done, set the states back To something more typical.
+	glEnable(GL_DEPTH_TEST);
+	glCullFace( GL_BACK   ); // cull front facing polys For this pass
+
+	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	glEnable(GL_LIGHTING);
+	glDepthMask(GL_TRUE);
+
+	glCullFace(GL_BACK);
+	glStencilFunc(GL_NOTEQUAL, midStencilVal, 0xffffff);
+	glStencilOp(GL_KEEP , GL_KEEP , GL_KEEP);
+
+// NOTE: is it the projektion matrix ?
+	glPushMatrix();
+	  glLoadIdentity();
+	  glMatrixMode(GL_MODELVIEW);
+	  glPushMatrix();
+	    glLoadIdentity();
+	    glOrtho(0 , 1 , 1 , 0 , 0 , 1);
+
+	    //float no_mat[]={0.0,0.0};
+	    float mat_ambient[]={ShadowRed,ShadowGreen,ShadowBlue,.5};
+	    float mat_diffuse[]={0,0,0,0.5};
+	    float mat_specular[]={0,0,0,0.5};
+	    float mat_shininess[]={0.0}; // upto 128
+
+	    glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
+	    glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
+	    glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
+	    glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
+
+	    glEnable(GL_BLEND);
+	    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+	    glDisable(GL_DEPTH_TEST);
+	    glColor4f(0.0, 0.0, 0.0, 1.0);
+
+	    /*glBegin(GL_QUADS);
+		    glVertex2i(0, 0);
+		    glVertex2i(0, 1);
+		    glVertex2i(1, 1);
+		    glVertex2i(1, 0);
+	    glEnd();*/
+	    if(Global::fx1!=true){
+		Global::fx1=true;
+		glDisableClientState(GL_NORMAL_ARRAY);
+	    }
+	    if(Global::fx2!=false){
+		Global::fx2=false;
+		glDisableClientState(GL_COLOR_ARRAY);
+	    }
+
+	    GLfloat q3[] = {0,0,0,1,1,1,1,0};
+	 
+	    glVertexPointer(2, GL_FLOAT, 0, q3);
+	    glDrawArrays(GL_TRIANGLE_FAN,0,4);
+
+
+	    glEnable(GL_DEPTH_TEST);
+	  glPopMatrix();
+	  // NOTE: is it the projektion matrix ?
+	  glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	glCullFace( GL_BACK   ); // cull front facing polys For this pass
+	glDisable(GL_STENCIL_TEST);
+
+}
+
+

+ 3 - 0
openb3dlib.mod/openb3d/src/sprite_batch.h

@@ -55,6 +55,7 @@ public:
 		sprite_batch=new SpriteBatch;
 		sprite_batch->surf=new Surface;
 		sprite_batch->surf->vbo_enabled=false;
+		sprite_batch->surf->ShaderMat=0;
 		sprite_batch->texture=tex;
 		sprite_batch->blend=blend;
 		sprite_batch->order=order;
@@ -76,6 +77,8 @@ public:
 		mesh->reset_col_tree=true;
 		
 		mesh->brush.tex[0]=texture;
+		mesh->brush.cache_frame[0]=texture->texture;
+
 		mesh->brush.no_texs=1;
 		mesh->brush.blend=blend;
 		mesh->brush.fx=35;

+ 1 - 0
openb3dlib.mod/openb3d/src/stb_image.c

@@ -4676,3 +4676,4 @@ int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int
              on 'test' only check type, not whether we support this variant
       0.50   first released version
 */
+

+ 216 - 202
openb3dlib.mod/openb3d/src/stencil.cpp

@@ -1,202 +1,216 @@
-#include "glew.h"
-
-/*
-#ifdef linux
-#define GL_GLEXT_PROTOTYPES
-#include <GL/gl.h>
-#include <GL/glext.h>
-#endif
-#ifdef WIN32
-#include "GLee.h"
-#endif
-#ifdef __APPLE__
-#include "GLee.h"
-#endif
-*/
-
-#include "stencil.h"
-#include "mesh.h"
-#include "global.h"
-
-int Stencil::midStencilVal;
-
-Stencil* Stencil::CreateStencil(){
-
-	int StencilBits;
-	glGetIntegerv(GL_STENCIL_BITS, &StencilBits);
-	midStencilVal = (StencilBits - 1)^2;
-
-	Stencil* stencil=new Stencil;
-	return stencil;
-}
-
-void Stencil::StencilMesh(Mesh* mesh, int mode){
-	if (mesh->parent != 0) {
-		mesh->parent->child_list.remove(mesh);
-	}else{
-		Global::root_ent->child_list.remove(mesh);
-	}
-	StencilMesh_list.push_back(mesh);
-	StencilMode_list.push_back(mode);
-
-}
-
-void Stencil::StencilClsColor(float r,float g,float b){
-
-	cls_r=r/255.0;
-	cls_g=g/255.0;
-	cls_b=b/255.0;
-
-}
-
-void Stencil::StencilClsMode(int color,int zbuffer){
-
-	cls_color=color;
-	cls_zbuffer=zbuffer;
-
-}
-
-void Stencil::StencilAlpha(float a){
-	alpha=a;
-}
-
-void Stencil::StencilMode(int m, int o){
-	stencil_mode=m;
-	stencil_operator=o;
-}
-
-
-void Stencil::UseStencil(){
-	//glEnable(GL_POLYGON_OFFSET_FILL);
-	//glPolygonOffset(0.0, 4.0);
-
-	glClearStencil(midStencilVal);
-	glClear(GL_STENCIL_BUFFER_BIT);
-	//glDepthMask(GL_FALSE);
-	glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
-
-	glEnable(GL_STENCIL_TEST);
-	glStencilFunc(GL_ALWAYS, 1, 1);                // Always Passes, 1 Bit Plane, 1 As Mask
-	glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);              // We Set The Stencil Buffer To 1 Where We Draw Any Polygon
-
-	//glDisable(GL_DEPTH_TEST);
-	list<Mesh*>::iterator it;
-	list<int>::iterator it2;
-	it2=StencilMode_list.begin();
-
-	for(it=StencilMesh_list.begin();it!=StencilMesh_list.end();it++){
-		Mesh* mesh=*it;
-		int mode=*it2;
-		switch(mode){
-		case 1:
-			glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
-			break;
-		case -1:
-			glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
-			break;
-		case 2:
-			glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
-			glCullFace(GL_FRONT);
-			mesh->UpdateShadow();
-			glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
-			glCullFace(GL_BACK);
-			break;
-		case -2:
-			glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
-			glCullFace(GL_FRONT);
-			mesh->UpdateShadow();
-			glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
-			glCullFace(GL_BACK);
-			break;
-
-		}
-
-		mesh->UpdateShadow();
-		it2++;
-	}
-	//glEnable(GL_DEPTH_TEST);
-	//glClear(GL_DEPTH_BUFFER_BIT);
-
-	if (cls_color!=0) {
-		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	}else{
-		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
-	}
-
-	switch (stencil_operator){
-	case 0:
-		glStencilFunc(GL_NOTEQUAL, stencil_mode + midStencilVal, 0xffffffff);  // We Draw Only Where The Stencil Is Not Equal to stencil_mode
-		break;
-	case 1:
-		glStencilFunc(GL_EQUAL, stencil_mode + midStencilVal, 0xffffffff);     // We Draw Only Where The Stencil Is Equal to stencil_mode
-		break;
-	case 2:
-		glStencilFunc(GL_LEQUAL, stencil_mode + midStencilVal, 0xffffffff);    // We Draw Only Where The Stencil Is Smaller or Equal to stencil_mode
-		break;
-	case 3:
-		glStencilFunc(GL_GEQUAL, stencil_mode + midStencilVal, 0xffffffff);    // We Draw Only Where The Stencil Is Greater or Equal to stencil_mode
-		break;
-	}
-	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);                 // Don't Change The Stencil Buffer
-
-	//glDisable(GL_POLYGON_OFFSET_FILL);
-
-	glPushMatrix();
-		glLoadIdentity();
-		glMatrixMode(GL_MODELVIEW);
-		glPushMatrix();
-		glLoadIdentity();
-		glOrtho(0 , 1 , 1 , 0 , 0 , 1);
-
-		//float no_mat[]={0.0,0.0};
-
-		float mat_ambient[]={cls_r,cls_g,cls_b,alpha};
-		float mat_diffuse[]={0,0,0,0.5};
-		float mat_specular[]={0,0,0,0.5};
-		float mat_shininess[]={0.0}; // upto 128
-
-		glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
-		glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
-		glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
-		glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
-
-		if (alpha<1){
-			glEnable(GL_BLEND);
-			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
-		}
-
-		if (cls_zbuffer!=0){
-			glDepthRange(1,1);
-			glDepthFunc(GL_ALWAYS);
-			glColor4f(0.0, 0.0, 0.0, 1.0);
-		}else{
-			glDisable(GL_DEPTH_TEST);
-		}
-
-		glBegin(GL_QUADS);
-			glVertex2i(0, 0);
-			glVertex2i(0, 1);
-			glVertex2i(1, 1);
-			glVertex2i(1, 0);
-		glEnd();
-
-		if (cls_zbuffer!=0){
-			glDepthRange(0,1);
-			glDepthFunc(GL_LEQUAL);
-		}else{
-			glEnable(GL_DEPTH_TEST);
-		}
-
-		glPopMatrix();
-		// NOTE: is it the projektion matrix ?
-		glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-	if (cls_color==0) {
-		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-	}
-
-
-
-
-}
-
+#include "glew.h"
+
+/*
+#ifdef linux
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+#endif
+#ifdef WIN32
+#include "GLee.h"
+#endif
+#ifdef __APPLE__
+#include "GLee.h"
+#endif
+*/
+
+#include "stencil.h"
+#include "mesh.h"
+#include "global.h"
+
+int Stencil::midStencilVal;
+
+Stencil* Stencil::CreateStencil(){
+
+	int StencilBits;
+	glGetIntegerv(GL_STENCIL_BITS, &StencilBits);
+	midStencilVal = (StencilBits - 1)^2;
+
+	Stencil* stencil=new Stencil;
+	return stencil;
+}
+
+void Stencil::StencilMesh(Mesh* mesh, int mode){
+	if (mesh->parent != 0) {
+		mesh->parent->child_list.remove(mesh);
+	}else{
+		Global::root_ent->child_list.remove(mesh);
+	}
+	StencilMesh_list.push_back(mesh);
+	StencilMode_list.push_back(mode);
+
+}
+
+void Stencil::StencilClsColor(float r,float g,float b){
+
+	cls_r=r/255.0;
+	cls_g=g/255.0;
+	cls_b=b/255.0;
+
+}
+
+void Stencil::StencilClsMode(int color,int zbuffer){
+
+	cls_color=color;
+	cls_zbuffer=zbuffer;
+
+}
+
+void Stencil::StencilAlpha(float a){
+	alpha=a;
+}
+
+void Stencil::StencilMode(int m, int o){
+	stencil_mode=m;
+	stencil_operator=o;
+}
+
+
+void Stencil::UseStencil(){
+	//glEnable(GL_POLYGON_OFFSET_FILL);
+	//glPolygonOffset(0.0, 4.0);
+
+	glClearStencil(midStencilVal);
+	glClear(GL_STENCIL_BUFFER_BIT);
+	//glDepthMask(GL_FALSE);
+	glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
+
+	glEnable(GL_STENCIL_TEST);
+	glStencilFunc(GL_ALWAYS, 1, 1);                // Always Passes, 1 Bit Plane, 1 As Mask
+	glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);              // We Set The Stencil Buffer To 1 Where We Draw Any Polygon
+
+	//glDisable(GL_DEPTH_TEST);
+	list<Mesh*>::iterator it;
+	list<int>::iterator it2;
+	it2=StencilMode_list.begin();
+
+	for(it=StencilMesh_list.begin();it!=StencilMesh_list.end();it++){
+		Mesh* mesh=*it;
+		int mode=*it2;
+		switch(mode){
+		case 1:
+			glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+			break;
+		case -1:
+			glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
+			break;
+		case 2:
+			glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
+			glCullFace(GL_FRONT);
+			mesh->UpdateShadow();
+			glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+			glCullFace(GL_BACK);
+			break;
+		case -2:
+			glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+			glCullFace(GL_FRONT);
+			mesh->UpdateShadow();
+			glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
+			glCullFace(GL_BACK);
+			break;
+
+		}
+
+		mesh->UpdateShadow();
+		it2++;
+	}
+	//glEnable(GL_DEPTH_TEST);
+	//glClear(GL_DEPTH_BUFFER_BIT);
+
+	if (cls_color!=0) {
+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	}else{
+		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+	}
+
+	switch (stencil_operator){
+	case 0:
+		glStencilFunc(GL_NOTEQUAL, stencil_mode + midStencilVal, 0xffffffff);  // We Draw Only Where The Stencil Is Not Equal to stencil_mode
+		break;
+	case 1:
+		glStencilFunc(GL_EQUAL, stencil_mode + midStencilVal, 0xffffffff);     // We Draw Only Where The Stencil Is Equal to stencil_mode
+		break;
+	case 2:
+		glStencilFunc(GL_LEQUAL, stencil_mode + midStencilVal, 0xffffffff);    // We Draw Only Where The Stencil Is Smaller or Equal to stencil_mode
+		break;
+	case 3:
+		glStencilFunc(GL_GEQUAL, stencil_mode + midStencilVal, 0xffffffff);    // We Draw Only Where The Stencil Is Greater or Equal to stencil_mode
+		break;
+	}
+	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);                 // Don't Change The Stencil Buffer
+
+	//glDisable(GL_POLYGON_OFFSET_FILL);
+
+	glPushMatrix();
+		glLoadIdentity();
+		glMatrixMode(GL_MODELVIEW);
+		glPushMatrix();
+		glLoadIdentity();
+		glOrtho(0 , 1 , 1 , 0 , 0 , 1);
+
+		//float no_mat[]={0.0,0.0};
+
+		float mat_ambient[]={cls_r,cls_g,cls_b,alpha};
+		float mat_diffuse[]={0,0,0,0.5};
+		float mat_specular[]={0,0,0,0.5};
+		float mat_shininess[]={0.0}; // upto 128
+
+		glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
+		glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
+		glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
+		glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
+
+		if (alpha<1){
+			glEnable(GL_BLEND);
+			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+		}
+
+		if (cls_zbuffer!=0){
+			glDepthRange(1,1);
+			glDepthFunc(GL_ALWAYS);
+			glColor4f(0.0, 0.0, 0.0, 1.0);
+		}else{
+			glDisable(GL_DEPTH_TEST);
+		}
+
+		/*glBegin(GL_QUADS);
+			glVertex2i(0, 0);
+			glVertex2i(0, 1);
+			glVertex2i(1, 1);
+			glVertex2i(1, 0);
+		glEnd();*/
+		if(Global::fx1!=true){
+			Global::fx1=true;
+			glDisableClientState(GL_NORMAL_ARRAY);
+		}
+		if(Global::fx2!=false){
+			Global::fx2=false;
+			glDisableClientState(GL_COLOR_ARRAY);
+		}
+
+		GLfloat q3[] = {0,0,0,1,1,1,1,0};
+	 
+		glVertexPointer(2, GL_FLOAT, 0, q3);
+		glDrawArrays(GL_TRIANGLE_FAN,0,4);
+
+
+		if (cls_zbuffer!=0){
+			glDepthRange(0,1);
+			glDepthFunc(GL_LEQUAL);
+		}else{
+			glEnable(GL_DEPTH_TEST);
+		}
+
+		glPopMatrix();
+		// NOTE: is it the projektion matrix ?
+		glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+	if (cls_color==0) {
+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+	}
+
+
+
+
+}
+

+ 65 - 75
openb3dlib.mod/openb3d/src/terrain.cpp

@@ -41,6 +41,7 @@ static Line Ray;
 static float radius;
 
 
+static vector<float> vertices;
 
 
 MeshInfo* Terrain::mesh_info;
@@ -184,8 +185,9 @@ Terrain* Terrain::CreateTerrain(int tsize, Entity* parent_ent){
 
 void Terrain::UpdateTerrain(){
 
-	int fog=false;
-	if (glIsEnabled(GL_FOG)==GL_TRUE) fog=true; // if fog enabled, we'll enable it again at end of each surf loop in case of fx flag disabling it
+	glBindBuffer(GL_ARRAY_BUFFER,0);
+
+	RecreateROAM();
 
 	glDisable(GL_ALPHA_TEST);
 
@@ -216,22 +218,37 @@ void Terrain::UpdateTerrain(){
 
 	// fx flag 1 - full bright ***todo*** disable all lights?
 	if (brush.fx & 1){
+		if(Global::fx1!=true){
+			Global::fx1=true;
+			glDisableClientState(GL_NORMAL_ARRAY);
+		}
 		ambient_red  =1.0;
 		ambient_green=1.0;
 		ambient_blue =1.0;
 	}else{
+		if(Global::fx1!=false){
+			Global::fx1=false;
+			glEnableClientState(GL_NORMAL_ARRAY);
+		}
 		ambient_red  =Global::ambient_red;
 		ambient_green=Global::ambient_green;
 		ambient_blue =Global::ambient_blue;
 	}
 
 	// fx flag 2 - vertex colours
-	if(brush.fx&2){
+	/*if(brush.fx&2){
+
 			glEnable(GL_COLOR_MATERIAL);
 	}else{
 			glDisable(GL_COLOR_MATERIAL);
+	}*/
+	if(Global::fx2!=false){
+		Global::fx2=false;
+		glDisableClientState(GL_COLOR_ARRAY);
+		glDisable(GL_COLOR_MATERIAL);
 	}
 
+
 	// fx flag 4 - flatshaded
 	if(brush.fx&4){
 		glShadeModel(GL_FLAT);
@@ -241,7 +258,9 @@ void Terrain::UpdateTerrain(){
 
 	// fx flag 8 - disable fog
 	if(brush.fx&8){
+		if(Global::fog_enabled==true){ // only disable if fog enabled in camera update
 			glDisable(GL_FOG);
+		}
 	}
 
 	// fx flag 16 - disable backface culling
@@ -399,7 +418,7 @@ void Terrain::UpdateTerrain(){
 			switch(tex_blend){
 				case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
 				break;
-				case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
+				case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
 				break;
 				case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 				//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
@@ -418,6 +437,9 @@ void Terrain::UpdateTerrain(){
 				default: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 			}
 
+			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+			glTexCoordPointer(2,GL_FLOAT,32,&vertices[6]);
+
 
 			// reset texture matrix
 			glMatrixMode(GL_TEXTURE);
@@ -478,7 +500,10 @@ void Terrain::UpdateTerrain(){
 
 	glPushMatrix();
 	glMultMatrixf(&mat.grid[0][0]);
-	RecreateROAM();
+	glVertexPointer(3,GL_FLOAT,32,&vertices[0]);
+	glNormalPointer(GL_FLOAT,32,&vertices[3]);
+
+	glDrawArrays(GL_TRIANGLES, 0, triangleindex*3);
 	glPopMatrix();
 
 	// disable all texture layers
@@ -503,8 +528,10 @@ void Terrain::UpdateTerrain(){
 		}
 
 	}
+	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
 
-	if (fog==true){
+	if (brush.fx&8 && Global::fog_enabled==true){
 		glEnable(GL_FOG);
 	}
 
@@ -551,24 +578,15 @@ void Terrain::RecreateROAM(){
 
 
 
-/*	if(c_col_tree!=NULL){
-		C_DeleteColTree(c_col_tree);
-		c_col_tree=NULL;
-	}
-	mesh_info=C_NewMeshInfo();
-*/
 	triangleindex = 0;
 
-	glBegin(GL_TRIANGLES);
+	vertices.clear();
 
 	/* recurse on the two base triangles */
 	drawsub(0, v[0], v[1], v[2]);
 	drawsub(0, v[2], v[3], v[0]);
 
-	glEnd();
-/*	c_col_tree=C_CreateColTree(mesh_info);
-	C_DeleteMeshInfo(mesh_info);
-*/	delete tmat;
+	delete tmat;
 
 
 }
@@ -645,58 +663,30 @@ void Terrain::drawsub(int l, float v0[], float v1[], float v2[]){
 		}
 
 	 }
-	float uv[3];
-
-	/*float ax,ay,az,bx,by,bz;
-	float nx,ny,nz,ns;
-	ax = v1[0]-v0[0];
-	ay = v1[1]-v0[1];
-	az = v1[2]-v0[2];
-	bx = v2[0]-v1[0];
-	by = v2[1]-v1[1];
-	bz = v2[2]-v1[2];
-	nx = ( ay * bz ) - ( az * by );
-	ny = ( az * bx ) - ( ax * bz );
-	nz = ( ax * by ) - ( ay * bx );
-	ns = sqrt( nx * nx + ny*ny + nz*nz );
-	if (ns != 0) ns = 1;
-	nx /= ns;
-	ny /= ns;
-	nz /= ns;*/
-
-
-
-	uv[0]=v0[0]; uv[1]=v0[2]; uv[2]=0;
-	glMultiTexCoord2f(GL_TEXTURE0, uv[0], uv[1]);
-	glMultiTexCoord2f(GL_TEXTURE1, uv[0], uv[1]);
-	//glNormal3f(nx,ny,nz);
-	glNormal3fv (&NormalsMap[3*(int)(v0[0]*size+ v0[2])]);
-	//glTexCoord2fv(&uv[0]);
-	glVertex3fv(&v0[0]);
-
-	uv[0]=v1[0]; uv[1]=v1[2]; uv[2]=0;
-	glMultiTexCoord2f(GL_TEXTURE0, uv[0], uv[1]);
-	glMultiTexCoord2f(GL_TEXTURE1, uv[0], uv[1]);
-	//glNormal3f(nx,ny,nz);
-	glNormal3fv (&NormalsMap[3*(int)(v1[0]*size+ v1[2])]);
-	//glTexCoord2fv(&uv[0]);
-	glVertex3fv(&v1[0]);
-
-	uv[0]=v2[0]; uv[1]=v2[2]; uv[2]=0;
-	glMultiTexCoord2f(GL_TEXTURE0, uv[0], uv[1]);
-	glMultiTexCoord2f(GL_TEXTURE1, uv[0], uv[1]);
-	//glNormal3f(nx,ny,nz);
-	glNormal3fv (&NormalsMap[3*(int)(v2[0]*size+ v2[2])]);
-	//glTexCoord2fv(&uv[0]);
-	glVertex3fv(&v2[0]);
+	vertices.push_back(v0[0]); vertices.push_back(v0[1]); vertices.push_back(v0[2]);
+	vertices.push_back(NormalsMap[3*(int)(v0[0]*size+ v0[2])+0]);
+	vertices.push_back(NormalsMap[3*(int)(v0[0]*size+ v0[2])+1]);
+	vertices.push_back(NormalsMap[3*(int)(v0[0]*size+ v0[2])+2]);
+	vertices.push_back(v0[0]);
+	vertices.push_back(v0[2]);
+
+
+	vertices.push_back(v1[0]); vertices.push_back(v1[1]); vertices.push_back(v1[2]);
+	vertices.push_back(NormalsMap[3*(int)(v1[0]*size+ v1[2])+0]);
+	vertices.push_back(NormalsMap[3*(int)(v1[0]*size+ v1[2])+1]);
+	vertices.push_back(NormalsMap[3*(int)(v1[0]*size+ v1[2])+2]);
+	vertices.push_back(v1[0]);
+	vertices.push_back(v1[2]);
+
+
+	vertices.push_back(v2[0]); vertices.push_back(v2[1]); vertices.push_back(v2[2]);
+	vertices.push_back(NormalsMap[3*(int)(v2[0]*size+ v2[2])+0]);
+	vertices.push_back(NormalsMap[3*(int)(v2[0]*size+ v2[2])+1]);
+	vertices.push_back(NormalsMap[3*(int)(v2[0]*size+ v2[2])+2]);
+	vertices.push_back(v2[0]);
+	vertices.push_back(v2[2]);
 
-	//add to collisiontree
-/*	C_AddVertex(mesh_info,v0[0],v0[1],-v0[2],0);
-	C_AddVertex(mesh_info,v1[0],v1[1],-v1[2],0);
-	C_AddVertex(mesh_info,v2[0],v2[1],-v2[2],0);
-	C_AddTriangle(mesh_info, triangleindex, triangleindex*3+2, triangleindex*3+1, triangleindex*3+0, 0);
 	triangleindex++;
-*/
 
 }
 
@@ -954,22 +944,22 @@ float Terrain::TerrainX (float x, float y, float z){
 float Terrain::TerrainY (float x, float y, float z){
 	TFormPoint(x, y, z, 0, this);
 	float p0[3],p1[3],p2[3];
-	p0[0]=tformed_x;
-	p0[2]=tformed_z;
+	p0[0]=(int)tformed_x;
+	p0[2]=(int)tformed_z;
 	p0[1]=height[(int)((int)tformed_x*size-tformed_z)] * vsize;
 
-	p2[0]=tformed_x+1;
-	p2[2]=tformed_z;
+	p2[0]=(int)tformed_x+1;
+	p2[2]=(int)tformed_z;
 	p2[1]=height[(int)(((int)(tformed_x+1)*size)- tformed_z)] * vsize;
 
 	if (tformed_x-floor(tformed_x)-tformed_z+floor(tformed_z)<.5){
-		p1[0]=tformed_x;
-		p1[2]=tformed_z+1;
+		p1[0]=(int)tformed_x;
+		p1[2]=(int)tformed_z+1;
 		p1[1]=height[(int)(((int)tformed_x*size)- tformed_z-1)] * vsize;
 	}else
 	{
-		p1[0]=tformed_x+1;
-		p1[2]=tformed_z+1;
+		p1[0]=(int)tformed_x+1;
+		p1[2]=(int)tformed_z+1;
 		p1[1]=height[(int)(((int)(tformed_x+1)*size)- tformed_z-1)] * vsize;
 	}
 

+ 3 - 0
openb3dlib.mod/openb3d/src/texture.cpp

@@ -436,6 +436,9 @@ void Texture::BackBufferToTex(int frame){
 void Texture::CameraToTex(Camera* cam, int frame){
 
 	GLenum target;
+
+	Global::camera_in_use=cam;
+
 	if(flags&128){
 		target=GL_TEXTURE_CUBE_MAP;
 	}else{

+ 0 - 3
openb3dlib.mod/openb3d/src/turn.cpp

@@ -1,6 +1,3 @@
-
-#include "maths_helper.h"
-
 class Quaternion{
  
 public:

+ 1 - 1
openb3dlib.mod/openb3d/src/voxel.cpp

@@ -265,7 +265,7 @@ void VoxelSprite::Render(){
 		switch(material[ix]->blend){
 			case 0: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
 			break;
-			case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
+			case 1: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
 			break;
 			case 2: glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 			//case 2 glTexEnvf(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);

+ 622 - 622
openb3dlib.mod/openb3d/src/x.cpp

@@ -1,622 +1,622 @@
-#include "string_helper.h"
-#include "model.h"
-#include "entity.h"
-#include "bone.h"
-#include "mesh.h"
-#include "texture.h"
-#include "file.h"
-#include <list>
-#include<cctype>
-#include<algorithm>
-
-namespace loadX{
-
-File*  Stream;
-
-
-	class XLoader_TreeNode{
-	public:
-		list<XLoader_TreeNode*> children;
-		string content;
-		string Template;
-		string name;
-	
-		/*Method New()
-			Self.children = New TList
-		End Method*/
-	
-		void Add(XLoader_TreeNode* element){
-			children.push_back(element);
-		}
-	};
-
-list<int>      MovedTris;
-
-string xReadString(File* file, int lenght){
-	string t="";
-	for(int i=1;i<=lenght;i++){
-		char ch=file->ReadByte();
-		t=t+ch;
-	}
-	return t;
-}
-
-string xReadAll(File* file){
-	string t="";
-	while (!file->Eof()){
-		char ch=file->ReadByte();
-		t=t+ch;
-	}
-	return t;
-}
-
-void string_find_and_replace( string &source, string find, string replace ) {
-     
-	size_t j;
-	for ( ; (j = source.find( find )) != string::npos ; ) {
-		source.replace( j, find.length(), replace );
-	}
-}
-
-inline double convertToDouble(std::string const& s)
-{
-  std::istringstream i(s);
-  double x;
-  i >> x;
-  return x;
-}
-
-/*inline vector<string> split( const string& s, const string& f ) {
-    vector<string> temp;
-    if ( f.empty() ) {
-        temp.push_back( s );
-        return temp;
-    }
-    typedef string::const_iterator iter;
-    const iter::difference_type f_size( distance( f.begin(), f.end() ) );
-    iter i( s.begin() );
-    for ( iter pos; ( pos = search( i , s.end(), f.begin(), f.end() ) ) != s.end(); ) {
-        temp.push_back( string( i, pos ) );
-        advance( pos, f_size );
-        i = pos;
-    }
-    temp.push_back( string( i, s.end() ) );
-    return temp;
-}*/
-
-inline vector<string> split(const string& strValue, char separator){
-	vector<string> vecstrResult;
-	int startpos=0;
-	int endpos=0;
-
-	endpos = strValue.find_first_of(separator, startpos);
-	while (endpos != -1)
-	{       
-		vecstrResult.push_back(strValue.substr(startpos, endpos-startpos)); // add to vector
-		startpos = endpos+1; //jump past sep
-		endpos = strValue.find_first_of(separator, startpos); // find next
-	}
-	//lastone, so no 2nd param required to go to end of string
-	vecstrResult.push_back(strValue.substr(startpos));
-        
-	    
-
-	return vecstrResult;
-}
-
-
-string XLoader_RemoveUnprintables(string s){
-		
-	for (char i = 0; i<= 31;i++){
-		string s1;
-		s1.resize(1, i);
-		string_find_and_replace( s, s1, "");
-	}
-		
-	return s;
-	
-}
-
-int XLoader_FindBracketMatch(string s){
-		
-	int index = 1;
-		
-	for (unsigned int i = 0;i < s.length();i++){
-		switch (s[i]){
-			case '{':
-				index++;
-				break;
-			case '}':
-				index--;
-			}
-				 
-			if (index == 0)
-				return i;
-	}
-	
-	return -1;
-		
-}
-
-int XLoader_FindAlphaChar(string s){
-		
-	for (unsigned int i = 0;i < s.length();i++){
-		if (s[i] >= 65 && s[i] <= 90)
-			return i; // A-Z	
-		if (s[i] >= 97 && s[i] <= 122)
-			return i; // a-z
-	}
-		
-	return -1;
-	
-}
-
-
-XLoader_TreeNode* XLoader_MakeTree(string s, XLoader_TreeNode* parent = 0){
-		
-		XLoader_TreeNode* root = new XLoader_TreeNode;
-		size_t pointer = 0;
-		size_t find = 0;
-		
-		s = Trim(s);
-		
-		while (s.length() > 0){
-			find = s.find("{", pointer);
-			
-			if (find == string::npos) 
-				break;
-			
-			string header = s.substr(pointer,find-pointer);
-
-			vector<string> bits = split (header,' ');
-	
-			pointer = find + 1;
-
-			root->Template = bits[0];
-
-
-
-
-			if (bits.size() > 1) 
-				root->name = bits[1];
-			
-			int frameend = XLoader_FindBracketMatch(s.substr(pointer));
-			string framecontent = s.substr(pointer,frameend);
-			
-			root->content = framecontent;
-			
-			s = s.substr(pointer + 1 + frameend);
-
-			transform(root->Template.begin(), root->Template.end(),root->Template.begin(),::tolower);			
-
-			if (root->Template=="frame" || root->Template=="mesh"){
-				int contentend = XLoader_FindAlphaChar(framecontent);
-				root->content = framecontent.substr(0,contentend);
-				XLoader_TreeNode* newNode = XLoader_MakeTree(framecontent.substr(contentend), root);
-				if (newNode) 
-					 root->Add(newNode);
-			}else if (root->Template=="meshmateriallist"){
-				int contentend = XLoader_FindAlphaChar(framecontent);
-				//root->content = framecontent.substr(0,contentend);
-				XLoader_TreeNode* newNode = XLoader_MakeTree(framecontent.substr(contentend), root);
-				if (newNode) 
-					root->Add(newNode);
-
-				parent->Add(root);
-				root = new XLoader_TreeNode;
-					
-			}else{
-				XLoader_TreeNode* newNode = XLoader_MakeTree(s, root);
-				if (newNode) 
-					root->Add(newNode);
-
-				return root;
-
-			}
-			
-			pointer = 0;
-		}
-		
-		return root;
-		
-}
-
-
-void loadBrush(list<XLoader_TreeNode*> matlist, Brush* brushes[], vector<string> &brushnames){
-	int count = 0;
-	list<XLoader_TreeNode*>::iterator material2;
-	XLoader_TreeNode* material;
-
-	for (material2 = matlist.begin(); material2 != matlist.end(); material2++){
-		material=*material2;
-
-		brushnames.push_back(material->name);
-							
-		vector<string> brushrgba = split(material->content.substr(0,material->content.find(";;")), ';');
-		brushes[count] = Brush::CreateBrush(
-			convertToDouble(brushrgba[0])* 255.0,
-			convertToDouble(brushrgba[1])* 255.0,
-			convertToDouble(brushrgba[2])* 255.0);
-
-
-
-		brushes[count]->BrushAlpha(convertToDouble(brushrgba[3]));
-								
-		int texturefilestart = material->content.find('"');
-								
-		if (texturefilestart != -1){
-			string texturefilename = material->content.substr(texturefilestart + 1,material->content.find('"', texturefilestart + 1) - texturefilestart - 1);
-			Texture* tex = Texture::LoadTexture(texturefilename);
-			if (tex != 0)
-				brushes[count]->BrushTexture(tex);
-		}
-			
-		count++;
-	}
-
-}
-
-list<XLoader_TreeNode*> XLoader_FindTreeElements(XLoader_TreeNode* tree, string Template, int recur=0){
-		
-	list<XLoader_TreeNode*> l;
-	
-	string lTemplate=tree->Template;
-
-	transform(lTemplate.begin(), lTemplate.end(),lTemplate.begin(), ::tolower);
-		
-	if (lTemplate == Template)
-		l.push_back(tree);
-
-	if (recur==1 && Template!="mesh")
-		{if (lTemplate=="mesh")	
-			{return l;}
-		}
-	
-	list<XLoader_TreeNode*>::iterator element;
-	for (element = tree->children.begin(); element != tree->children.end(); element++){
-		XLoader_TreeNode* elem=*element;
-		if (elem->Template == Template && elem->children.size()==0) {
-			l.push_back(elem);
-		}
-	}
-
-	for (element = tree->children.begin(); element != tree->children.end(); element++){
-		XLoader_TreeNode* elem=*element;
-
-		/*if (elem->Template == Template)
-			l.push_back(elem);*/
-		if (elem->children.size()!=0){
-			list<XLoader_TreeNode*> l2;
-			l2=XLoader_FindTreeElements(elem, Template, 1);
-			l.merge(l2);}
-	}
-		
-	return l;
-	
-}
-
-
-
-Mesh* LoadX(string URL, Entity* parent_ent){
-	Stream = File::ReadFile(URL);
-	if (Stream == 0) return 0;
-
-	string header = xReadString(Stream, 4);
-	string version = xReadString(Stream, 4);
-	string format = xReadString(Stream, 4);
-	string floatsize= xReadString(Stream,4);
-		
-	if (header == "xof "){
-		if (version == "0302"){
-			if (format == "txt "){
-					
-				Mesh* submesh = Mesh::CreateMesh(parent_ent);
-								
-				while (!Stream->Eof()){
-					// check first byte
-					char checkbyte = Stream->ReadByte();
-					Stream->SeekFile(Stream->FilePos() - 1);
-	
-					if (!(checkbyte<=32 || checkbyte == '/' || checkbyte == '#')){
-						string read = xReadAll(Stream);
-						read = XLoader_RemoveUnprintables(read);
-						string_find_and_replace(read, " {", "{");
-						string_find_and_replace(read, "{ ", "{");
-						string_find_and_replace(read, " }", "}");
-						string_find_and_replace(read, "} ", "}");
-							
-						XLoader_TreeNode* tree = XLoader_MakeTree(read);
-							
-						// fetch material data
-						list<XLoader_TreeNode*> matlist = XLoader_FindTreeElements(tree, "material");
-						Brush* brushes[matlist.size()];
-						vector<string> brushnames;
-
-						loadBrush(matlist, brushes, brushnames);
-
-						list<XLoader_TreeNode*> framelist = XLoader_FindTreeElements(tree, "frame");
-						XLoader_TreeNode* frametree;
-						list<XLoader_TreeNode*>::iterator frametree2;
-						if (framelist.empty())
-							framelist.push_back(tree);
-
-						for (frametree2 = framelist.begin(); frametree2 != framelist.end(); frametree2++){
-							frametree=*frametree2;
-							transform(frametree->name.begin(), frametree->name.end(),frametree->name.begin(), ::tolower);			
-							
-							if (frametree->name != "world"){
-							
-								// read transformation matrix
-								list<XLoader_TreeNode*> tmatlist = XLoader_FindTreeElements(frametree, "frametransformmatrix");
-																		
-								// assemble mesh
-								list<XLoader_TreeNode*> meshnodes = XLoader_FindTreeElements(frametree, "mesh");
-
-								XLoader_TreeNode* meshnode;
-								//int currentmeshnode = 0;
-								Matrix tformmat;
-								
-								list<XLoader_TreeNode*>::iterator meshnode2;	
-
-
-								list<XLoader_TreeNode*>::iterator meshlistelm;
-								meshlistelm=tmatlist.begin();
-
-								for (meshnode2=meshnodes.begin(); meshnode2!=meshnodes.end();meshnode2++){
-									meshnode=*meshnode2;
-									
-									// create corresponding tformmatrix
-									//Local meshlistelm:Object = tmatlist.ValueAtIndex(currentmeshnode)
-
-										
-									if (meshlistelm != tmatlist.end()){
-										XLoader_TreeNode* meshlistelm2;
-										meshlistelm2=*meshlistelm;
-
-										vector<string> tmat = split(meshlistelm2->content,',');
-										//currentmeshnode:+1
-										meshlistelm++;
-																			
-										//tformmat:TMatrix = New TMatrix
-										tformmat.LoadIdentity();
-										int maty = -1;
-										int matx = 0;
-											
-										for (matx = 0; matx <= 15; matx++){
-											if (matx % 4 == 0){
-												maty++;
-											}
-											tformmat.grid[matx - maty * 4][maty] = ::atof(tmat[matx].c_str());
-										}
-									}
-									
-									// create surface
-									Surface* surf = submesh->CreateSurface();
-									string meshdata = Trim(meshnode->content);
-									string_find_and_replace(meshdata, " ", "");
-										
-									// read vertex count
-									int offset = meshdata.find(";");
-									int vertexcount = ::atoi(meshdata.substr(0,offset).c_str());
-										
-									meshdata = meshdata.substr(offset+1);
-									offset = meshdata.find(";;");
-
-									string meshdata2=meshdata.substr(0,offset);
-									string_find_and_replace(meshdata2, ",", "");
-									
-									vector<string> vertexdata = split(meshdata2,';');
-
-									
-									// add vertices
-									int vcount = 0;
-										
-									for (vcount = 0; vcount<= (vertexcount - 1) * 3; vcount+=3){
-										float vertx = ::atof(vertexdata[vcount].c_str());
-										float verty = ::atof(vertexdata[vcount + 1].c_str());
-										float vertz = ::atof(vertexdata[vcount + 2].c_str());
-											
-										float x = vertx * tformmat.grid[0][0] + verty * tformmat.grid[0][1] + vertz * tformmat.grid[0][2] + tformmat.grid[0][3];
-										float y = vertx * tformmat.grid[1][0] + verty * tformmat.grid[1][1] + vertz * tformmat.grid[1][2] + tformmat.grid[1][3];
-										float z = vertx * tformmat.grid[2][0] + verty * tformmat.grid[2][1] + vertz * tformmat.grid[2][2] + tformmat.grid[2][3];
-										float w = tformmat.grid[3][0] + tformmat.grid[3][1] + tformmat.grid[3][2] + tformmat.grid[3][3];
-											
-										surf->AddVertex(x, y, z);
-									}
-										
-									// read face count
-									meshdata = meshdata.substr(offset+2);
-									offset = meshdata.find(";");
-									int facecount = ::atoi(meshdata.substr(0,offset).c_str());
-										
-									meshdata = meshdata.substr(offset+1);
-									offset = meshdata.find(";;");
-
-									meshdata2=meshdata.substr(0,offset);
-									string_find_and_replace(meshdata2, ";,", ";");
-										
-									vector<string> facedata = split(meshdata2,';');
-										
-									// draw faces
-									int fcount = 0;
-			
-									for (fcount = 1; fcount<= facecount * 2; fcount+=2){
-										vector<string> faces = split(facedata[fcount],',');
-																			
-										if (faces.size() == 3){
-											surf->AddTriangle(
-											::atoi(faces[0].c_str()),
-											::atoi(faces[1].c_str()),
-											::atoi(faces[2].c_str()));
-										} else if (faces.size() == 4){
-											surf->AddTriangle(
-											::atoi(faces[0].c_str()),
-											::atoi(faces[1].c_str()),
-											::atoi(faces[2].c_str()));
-
-											surf->AddTriangle(
-											::atoi(faces[2].c_str()),
-											::atoi(faces[3].c_str()),
-											::atoi(faces[0].c_str()));
-										}
-									}
-										
-									// lookup mesh normals
-									list<XLoader_TreeNode*> normals = XLoader_FindTreeElements(meshnode, "meshnormals");
-										
-									if (normals.empty()){
-										submesh->UpdateNormals();
-									}else{
-										string normaldata = (*normals.begin())->content;
-
-
-										int normalcount = ::atoi(normaldata.substr(0,normaldata.find(";")).c_str());
-
-										normaldata = normaldata.substr(normaldata.find(";"));
-										normaldata = normaldata.substr(0,normaldata.find(";;"));
-										string_find_and_replace(normaldata, ",", "");
-
-
-										vector<string> normalbits = split(normaldata, ';');
-											
-										for (int i = 0; i< normalcount;i++){
-											surf->VertexNormal(i,
-											::atof(normalbits[i * 3].c_str()),
-											::atof(normalbits[i * 3+1].c_str()),
-											::atof(normalbits[i * 3+2].c_str()));
-
-										}
-									}
-										
-									// texture coordinates
-									list<XLoader_TreeNode*> textcoords = XLoader_FindTreeElements(meshnode, "meshtexturecoords");
-
-										
-									if (!textcoords.empty()){
-										string texturecoordsdata = (*textcoords.begin())->content;
-
-										int texturecoordscount = ::atoi(texturecoordsdata.substr(0,texturecoordsdata.find(";")).c_str());
-
-										texturecoordsdata = texturecoordsdata.substr(texturecoordsdata.find(";")+1);
-										texturecoordsdata = texturecoordsdata.substr(0,texturecoordsdata.find(";;"));
-										string_find_and_replace(texturecoordsdata, ",", "");
-										vector<string> tcoords = split(texturecoordsdata,';');
-
-										for (int i = 0; i< texturecoordscount;i++){
-											surf->VertexTexCoords(i,
-											::atof(tcoords[i * 2].c_str()),
-											::atof(tcoords[i * 2+1].c_str()));
-										}
-									}
-										
-									// apply materials
-									list<XLoader_TreeNode*> texlist = XLoader_FindTreeElements(meshnode, "meshmateriallist");
-									if (!texlist.empty()){
-
-										string texdata = (*texlist.begin())->content;
-
-										int materialscount = ::atoi(texdata.substr(0,texdata.find(";")).c_str());
-
-										texdata = texdata.substr(texdata.find(";")+1);
-
-										int facescount = ::atoi(texdata.substr(0,texdata.find(";")).c_str());
-
-										texdata = texdata.substr(texdata.find(";")+1);
-
-										vector<string> mats = split(texdata,',');
-
-										texdata = texdata.substr(texdata.find(";;") + 3);
-
-										list<XLoader_TreeNode*> Lmatlist = XLoader_FindTreeElements(meshnode, "material");
-										Brush* Lbrushes[Lmatlist.size()];
-										vector<string> Lbrushnames;
-
-										loadBrush(Lmatlist, Lbrushes, Lbrushnames);
-										//string texname = texdata.substr(0,texdata.find("}"));
-										string_find_and_replace(texdata, "{", "");
-										vector<string> texname = split(texdata,'}');
-
-										/*for (unsigned int i = 0; i< matlist.size();i++){
-											if (brushnames[i] == texname)
-												{surf->PaintSurface(brushes[i]);}
-										}*/
-										for (int m = 0; m< materialscount;m++){
-											Surface* New_surface = submesh->CreateSurface();
-											for (int Index = 0; Index<facescount;Index++){
-												if(::atoi(mats[Index].c_str())==m){
-													int v0[3];
-													for (int i=0;i <3;i++){
-														v0[i]=surf->TriangleVertex(Index,i);
-														float x,y,z,u,v,w,nx,ny,nz;
-														x=surf->VertexX(v0[i]);
-														y=surf->VertexY(v0[i]);
-														z=surf->VertexZ(v0[i]);
-														u=surf->VertexU(v0[i]);
-														v=surf->VertexV(v0[i]);
-														w=surf->VertexW(v0[i]);
-														nx=surf->VertexNX(v0[i]);
-														ny=surf->VertexNY(v0[i]);
-														nz=surf->VertexNZ(v0[i]);
-														v0[i]=New_surface->AddVertex(x,y,z,u,v,w);
-														New_surface->VertexNormal(v0[i],nx,ny,nz);
-													}
-													New_surface->AddTriangle(v0[0],v0[1],v0[2]);
-													MovedTris.push_back(Index);
-
-												}
-											}
-
-											if (Lmatlist.size()==0){
-												for (unsigned int i = 0; i< matlist.size();i++){
-													if (brushnames[i] == texname[m])
-														{New_surface->PaintSurface(brushes[i]);}
-												}
-											}else{
-												New_surface->PaintSurface(Lbrushes[m]);
-											}
-										}
-
-										MovedTris.sort();
-										int CheckSurface=0;
-										for(list<int>::const_reverse_iterator it = MovedTris.rbegin(); it != MovedTris.rend(); it++){
-											surf->RemoveTri(*it);
-											CheckSurface=1;
-										}
-										MovedTris.clear();
-										if (surf->no_tris==0 && CheckSurface !=0) {
-											delete surf;
-											submesh->surf_list.remove(surf);
-											submesh->no_surfs=submesh->no_surfs-1;
-										}
-
-
-									}
-								}
-							}
-						}
-					}else{
-						if (checkbyte<=32)
-							{Stream->SeekFile(Stream->FilePos() + 1);
-						}else{
-							Stream->ReadLine();
-						}
-					}
-				}
-					
-				Stream->CloseFile();
-					
-				return submesh;
-			}else{
-				//cout<<"X Mesh Loader: Unsupported format '"<<format<<"'!";
-			}
-		}else{
-			//cout<<"X Mesh Loader: Unsupported version '"<< version << "'!";
-		}
-	}else{
-		//cout<<"X Mesh Loader: Invalid x-mesh!";
-	}
-	
-	return Mesh::CreateCube();
-	
-}
-}
+#include "string_helper.h"
+#include "model.h"
+#include "entity.h"
+#include "bone.h"
+#include "mesh.h"
+#include "texture.h"
+#include "file.h"
+#include <list>
+#include<cctype>
+#include<algorithm>
+
+namespace loadX{
+
+File*  Stream;
+
+
+	class XLoader_TreeNode{
+	public:
+		list<XLoader_TreeNode*> children;
+		string content;
+		string Template;
+		string name;
+	
+		/*Method New()
+			Self.children = New TList
+		End Method*/
+	
+		void Add(XLoader_TreeNode* element){
+			children.push_back(element);
+		}
+	};
+
+list<int>      MovedTris;
+
+string xReadString(File* file, int lenght){
+	string t="";
+	for(int i=1;i<=lenght;i++){
+		char ch=file->ReadByte();
+		t=t+ch;
+	}
+	return t;
+}
+
+string xReadAll(File* file){
+	string t="";
+	while (!file->Eof()){
+		char ch=file->ReadByte();
+		t=t+ch;
+	}
+	return t;
+}
+
+void string_find_and_replace( string &source, string find, string replace ) {
+     
+	size_t j;
+	for ( ; (j = source.find( find )) != string::npos ; ) {
+		source.replace( j, find.length(), replace );
+	}
+}
+
+inline double convertToDouble(std::string const& s)
+{
+  std::istringstream i(s);
+  double x;
+  i >> x;
+  return x;
+}
+
+/*inline vector<string> split( const string& s, const string& f ) {
+    vector<string> temp;
+    if ( f.empty() ) {
+        temp.push_back( s );
+        return temp;
+    }
+    typedef string::const_iterator iter;
+    const iter::difference_type f_size( distance( f.begin(), f.end() ) );
+    iter i( s.begin() );
+    for ( iter pos; ( pos = search( i , s.end(), f.begin(), f.end() ) ) != s.end(); ) {
+        temp.push_back( string( i, pos ) );
+        advance( pos, f_size );
+        i = pos;
+    }
+    temp.push_back( string( i, s.end() ) );
+    return temp;
+}*/
+
+inline vector<string> split(const string& strValue, char separator){
+	vector<string> vecstrResult;
+	int startpos=0;
+	int endpos=0;
+
+	endpos = strValue.find_first_of(separator, startpos);
+	while (endpos != -1)
+	{       
+		vecstrResult.push_back(strValue.substr(startpos, endpos-startpos)); // add to vector
+		startpos = endpos+1; //jump past sep
+		endpos = strValue.find_first_of(separator, startpos); // find next
+	}
+	//lastone, so no 2nd param required to go to end of string
+	vecstrResult.push_back(strValue.substr(startpos));
+        
+	    
+
+	return vecstrResult;
+}
+
+
+string XLoader_RemoveUnprintables(string s){
+		
+	for (char i = 0; i<= 31;i++){
+		string s1;
+		s1.resize(1, i);
+		string_find_and_replace( s, s1, "");
+	}
+		
+	return s;
+	
+}
+
+int XLoader_FindBracketMatch(string s){
+		
+	int index = 1;
+		
+	for (unsigned int i = 0;i < s.length();i++){
+		switch (s[i]){
+			case '{':
+				index++;
+				break;
+			case '}':
+				index--;
+			}
+				 
+			if (index == 0)
+				return i;
+	}
+	
+	return -1;
+		
+}
+
+int XLoader_FindAlphaChar(string s){
+		
+	for (unsigned int i = 0;i < s.length();i++){
+		if (s[i] >= 65 && s[i] <= 90)
+			return i; // A-Z	
+		if (s[i] >= 97 && s[i] <= 122)
+			return i; // a-z
+	}
+		
+	return -1;
+	
+}
+
+
+XLoader_TreeNode* XLoader_MakeTree(string s, XLoader_TreeNode* parent = 0){
+		
+		XLoader_TreeNode* root = new XLoader_TreeNode;
+		size_t pointer = 0;
+		size_t find = 0;
+		
+		s = Trim(s);
+		
+		while (s.length() > 0){
+			find = s.find("{", pointer);
+			
+			if (find == string::npos) 
+				break;
+			
+			string header = s.substr(pointer,find-pointer);
+
+			vector<string> bits = split (header,' ');
+	
+			pointer = find + 1;
+
+			root->Template = bits[0];
+
+
+
+
+			if (bits.size() > 1) 
+				root->name = bits[1];
+			
+			int frameend = XLoader_FindBracketMatch(s.substr(pointer));
+			string framecontent = s.substr(pointer,frameend);
+			
+			root->content = framecontent;
+			
+			s = s.substr(pointer + 1 + frameend);
+
+			transform(root->Template.begin(), root->Template.end(),root->Template.begin(),::tolower);			
+
+			if (root->Template=="frame" || root->Template=="mesh"){
+				int contentend = XLoader_FindAlphaChar(framecontent);
+				root->content = framecontent.substr(0,contentend);
+				XLoader_TreeNode* newNode = XLoader_MakeTree(framecontent.substr(contentend), root);
+				if (newNode) 
+					 root->Add(newNode);
+			}else if (root->Template=="meshmateriallist"){
+				int contentend = XLoader_FindAlphaChar(framecontent);
+				//root->content = framecontent.substr(0,contentend);
+				XLoader_TreeNode* newNode = XLoader_MakeTree(framecontent.substr(contentend), root);
+				if (newNode) 
+					root->Add(newNode);
+
+				parent->Add(root);
+				root = new XLoader_TreeNode;
+					
+			}else{
+				XLoader_TreeNode* newNode = XLoader_MakeTree(s, root);
+				if (newNode) 
+					root->Add(newNode);
+
+				return root;
+
+			}
+			
+			pointer = 0;
+		}
+		
+		return root;
+		
+}
+
+
+void loadBrush(list<XLoader_TreeNode*> matlist, Brush* brushes[], vector<string> &brushnames){
+	int count = 0;
+	list<XLoader_TreeNode*>::iterator material2;
+	XLoader_TreeNode* material;
+
+	for (material2 = matlist.begin(); material2 != matlist.end(); material2++){
+		material=*material2;
+
+		brushnames.push_back(material->name);
+							
+		vector<string> brushrgba = split(material->content.substr(0,material->content.find(";;")), ';');
+		brushes[count] = Brush::CreateBrush(
+			convertToDouble(brushrgba[0])* 255.0,
+			convertToDouble(brushrgba[1])* 255.0,
+			convertToDouble(brushrgba[2])* 255.0);
+
+
+
+		brushes[count]->BrushAlpha(convertToDouble(brushrgba[3]));
+								
+		int texturefilestart = material->content.find('"');
+								
+		if (texturefilestart != -1){
+			string texturefilename = material->content.substr(texturefilestart + 1,material->content.find('"', texturefilestart + 1) - texturefilestart - 1);
+			Texture* tex = Texture::LoadTexture(texturefilename);
+			if (tex != 0)
+				brushes[count]->BrushTexture(tex);
+		}
+			
+		count++;
+	}
+
+}
+
+list<XLoader_TreeNode*> XLoader_FindTreeElements(XLoader_TreeNode* tree, string Template, int recur=0){
+		
+	list<XLoader_TreeNode*> l;
+	
+	string lTemplate=tree->Template;
+
+	transform(lTemplate.begin(), lTemplate.end(),lTemplate.begin(), ::tolower);
+		
+	if (lTemplate == Template)
+		l.push_back(tree);
+
+	if (recur==1 && Template!="mesh")
+		{if (lTemplate=="mesh")	
+			{return l;}
+		}
+	
+	list<XLoader_TreeNode*>::iterator element;
+	for (element = tree->children.begin(); element != tree->children.end(); element++){
+		XLoader_TreeNode* elem=*element;
+		if (elem->Template == Template && elem->children.size()==0) {
+			l.push_back(elem);
+		}
+	}
+
+	for (element = tree->children.begin(); element != tree->children.end(); element++){
+		XLoader_TreeNode* elem=*element;
+
+		/*if (elem->Template == Template)
+			l.push_back(elem);*/
+		if (elem->children.size()!=0){
+			list<XLoader_TreeNode*> l2;
+			l2=XLoader_FindTreeElements(elem, Template, 1);
+			l.merge(l2);}
+	}
+		
+	return l;
+	
+}
+
+
+
+Mesh* LoadX(string URL, Entity* parent_ent){
+	Stream = File::ReadFile(URL);
+	if (Stream == 0) return 0;
+
+	string header = xReadString(Stream, 4);
+	string version = xReadString(Stream, 4);
+	string format = xReadString(Stream, 4);
+	string floatsize= xReadString(Stream,4);
+		
+	if (header == "xof "){
+		if (version == "0302"){
+			if (format == "txt "){
+					
+				Mesh* submesh = Mesh::CreateMesh(parent_ent);
+								
+				while (!Stream->Eof()){
+					// check first byte
+					char checkbyte = Stream->ReadByte();
+					Stream->SeekFile(Stream->FilePos() - 1);
+	
+					if (!(checkbyte<=32 || checkbyte == '/' || checkbyte == '#')){
+						string read = xReadAll(Stream);
+						read = XLoader_RemoveUnprintables(read);
+						string_find_and_replace(read, " {", "{");
+						string_find_and_replace(read, "{ ", "{");
+						string_find_and_replace(read, " }", "}");
+						string_find_and_replace(read, "} ", "}");
+							
+						XLoader_TreeNode* tree = XLoader_MakeTree(read);
+							
+						// fetch material data
+						list<XLoader_TreeNode*> matlist = XLoader_FindTreeElements(tree, "material");
+						Brush* brushes[matlist.size()];
+						vector<string> brushnames;
+
+						loadBrush(matlist, brushes, brushnames);
+
+						list<XLoader_TreeNode*> framelist = XLoader_FindTreeElements(tree, "frame");
+						XLoader_TreeNode* frametree;
+						list<XLoader_TreeNode*>::iterator frametree2;
+						if (framelist.empty())
+							framelist.push_back(tree);
+
+						for (frametree2 = framelist.begin(); frametree2 != framelist.end(); frametree2++){
+							frametree=*frametree2;
+							transform(frametree->name.begin(), frametree->name.end(),frametree->name.begin(), ::tolower);			
+							
+							if (frametree->name != "world"){
+							
+								// read transformation matrix
+								list<XLoader_TreeNode*> tmatlist = XLoader_FindTreeElements(frametree, "frametransformmatrix");
+																		
+								// assemble mesh
+								list<XLoader_TreeNode*> meshnodes = XLoader_FindTreeElements(frametree, "mesh");
+
+								XLoader_TreeNode* meshnode;
+								//int currentmeshnode = 0;
+								Matrix tformmat;
+								
+								list<XLoader_TreeNode*>::iterator meshnode2;	
+
+
+								list<XLoader_TreeNode*>::iterator meshlistelm;
+								meshlistelm=tmatlist.begin();
+
+								for (meshnode2=meshnodes.begin(); meshnode2!=meshnodes.end();meshnode2++){
+									meshnode=*meshnode2;
+									
+									// create corresponding tformmatrix
+									//Local meshlistelm:Object = tmatlist.ValueAtIndex(currentmeshnode)
+
+										
+									if (meshlistelm != tmatlist.end()){
+										XLoader_TreeNode* meshlistelm2;
+										meshlistelm2=*meshlistelm;
+
+										vector<string> tmat = split(meshlistelm2->content,',');
+										//currentmeshnode:+1
+										meshlistelm++;
+																			
+										//tformmat:TMatrix = New TMatrix
+										tformmat.LoadIdentity();
+										int maty = -1;
+										int matx = 0;
+											
+										for (matx = 0; matx <= 15; matx++){
+											if (matx % 4 == 0){
+												maty++;
+											}
+											tformmat.grid[matx - maty * 4][maty] = ::atof(tmat[matx].c_str());
+										}
+									}
+									
+									// create surface
+									Surface* surf = submesh->CreateSurface();
+									string meshdata = Trim(meshnode->content);
+									string_find_and_replace(meshdata, " ", "");
+										
+									// read vertex count
+									int offset = meshdata.find(";");
+									int vertexcount = ::atoi(meshdata.substr(0,offset).c_str());
+										
+									meshdata = meshdata.substr(offset+1);
+									offset = meshdata.find(";;");
+
+									string meshdata2=meshdata.substr(0,offset);
+									string_find_and_replace(meshdata2, ",", "");
+									
+									vector<string> vertexdata = split(meshdata2,';');
+
+									
+									// add vertices
+									int vcount = 0;
+										
+									for (vcount = 0; vcount<= (vertexcount - 1) * 3; vcount+=3){
+										float vertx = ::atof(vertexdata[vcount].c_str());
+										float verty = ::atof(vertexdata[vcount + 1].c_str());
+										float vertz = ::atof(vertexdata[vcount + 2].c_str());
+											
+										float x = vertx * tformmat.grid[0][0] + verty * tformmat.grid[0][1] + vertz * tformmat.grid[0][2] + tformmat.grid[0][3];
+										float y = vertx * tformmat.grid[1][0] + verty * tformmat.grid[1][1] + vertz * tformmat.grid[1][2] + tformmat.grid[1][3];
+										float z = vertx * tformmat.grid[2][0] + verty * tformmat.grid[2][1] + vertz * tformmat.grid[2][2] + tformmat.grid[2][3];
+										float w = tformmat.grid[3][0] + tformmat.grid[3][1] + tformmat.grid[3][2] + tformmat.grid[3][3];
+											
+										surf->AddVertex(x, y, z);
+									}
+										
+									// read face count
+									meshdata = meshdata.substr(offset+2);
+									offset = meshdata.find(";");
+									int facecount = ::atoi(meshdata.substr(0,offset).c_str());
+										
+									meshdata = meshdata.substr(offset+1);
+									offset = meshdata.find(";;");
+
+									meshdata2=meshdata.substr(0,offset);
+									string_find_and_replace(meshdata2, ";,", ";");
+										
+									vector<string> facedata = split(meshdata2,';');
+										
+									// draw faces
+									int fcount = 0;
+			
+									for (fcount = 1; fcount<= facecount * 2; fcount+=2){
+										vector<string> faces = split(facedata[fcount],',');
+																			
+										if (faces.size() == 3){
+											surf->AddTriangle(
+											::atoi(faces[0].c_str()),
+											::atoi(faces[1].c_str()),
+											::atoi(faces[2].c_str()));
+										} else if (faces.size() == 4){
+											surf->AddTriangle(
+											::atoi(faces[0].c_str()),
+											::atoi(faces[1].c_str()),
+											::atoi(faces[2].c_str()));
+
+											surf->AddTriangle(
+											::atoi(faces[2].c_str()),
+											::atoi(faces[3].c_str()),
+											::atoi(faces[0].c_str()));
+										}
+									}
+										
+									// lookup mesh normals
+									list<XLoader_TreeNode*> normals = XLoader_FindTreeElements(meshnode, "meshnormals");
+										
+									if (normals.empty()){
+										submesh->UpdateNormals();
+									}else{
+										string normaldata = (*normals.begin())->content;
+
+
+										int normalcount = ::atoi(normaldata.substr(0,normaldata.find(";")).c_str());
+
+										normaldata = normaldata.substr(normaldata.find(";"));
+										normaldata = normaldata.substr(0,normaldata.find(";;"));
+										string_find_and_replace(normaldata, ",", "");
+
+
+										vector<string> normalbits = split(normaldata, ';');
+											
+										for (int i = 0; i< normalcount;i++){
+											surf->VertexNormal(i,
+											::atof(normalbits[i * 3].c_str()),
+											::atof(normalbits[i * 3+1].c_str()),
+											::atof(normalbits[i * 3+2].c_str()));
+
+										}
+									}
+										
+									// texture coordinates
+									list<XLoader_TreeNode*> textcoords = XLoader_FindTreeElements(meshnode, "meshtexturecoords");
+
+										
+									if (!textcoords.empty()){
+										string texturecoordsdata = (*textcoords.begin())->content;
+
+										int texturecoordscount = ::atoi(texturecoordsdata.substr(0,texturecoordsdata.find(";")).c_str());
+
+										texturecoordsdata = texturecoordsdata.substr(texturecoordsdata.find(";")+1);
+										texturecoordsdata = texturecoordsdata.substr(0,texturecoordsdata.find(";;"));
+										string_find_and_replace(texturecoordsdata, ",", "");
+										vector<string> tcoords = split(texturecoordsdata,';');
+
+										for (int i = 0; i< texturecoordscount;i++){
+											surf->VertexTexCoords(i,
+											::atof(tcoords[i * 2].c_str()),
+											::atof(tcoords[i * 2+1].c_str()));
+										}
+									}
+										
+									// apply materials
+									list<XLoader_TreeNode*> texlist = XLoader_FindTreeElements(meshnode, "meshmateriallist");
+									if (!texlist.empty()){
+
+										string texdata = (*texlist.begin())->content;
+
+										int materialscount = ::atoi(texdata.substr(0,texdata.find(";")).c_str());
+
+										texdata = texdata.substr(texdata.find(";")+1);
+
+										int facescount = ::atoi(texdata.substr(0,texdata.find(";")).c_str());
+
+										texdata = texdata.substr(texdata.find(";")+1);
+
+										vector<string> mats = split(texdata,',');
+
+										texdata = texdata.substr(texdata.find(";;") + 3);
+
+										list<XLoader_TreeNode*> Lmatlist = XLoader_FindTreeElements(meshnode, "material");
+										Brush* Lbrushes[Lmatlist.size()];
+										vector<string> Lbrushnames;
+
+										loadBrush(Lmatlist, Lbrushes, Lbrushnames);
+										//string texname = texdata.substr(0,texdata.find("}"));
+										string_find_and_replace(texdata, "{", "");
+										vector<string> texname = split(texdata,'}');
+
+										/*for (unsigned int i = 0; i< matlist.size();i++){
+											if (brushnames[i] == texname)
+												{surf->PaintSurface(brushes[i]);}
+										}*/
+										for (int m = 0; m< materialscount;m++){
+											Surface* New_surface = submesh->CreateSurface();
+											for (int Index = 0; Index<facescount;Index++){
+												if(::atoi(mats[Index].c_str())==m){
+													int v0[3];
+													for (int i=0;i <3;i++){
+														v0[i]=surf->TriangleVertex(Index,i);
+														float x,y,z,u,v,w,nx,ny,nz;
+														x=surf->VertexX(v0[i]);
+														y=surf->VertexY(v0[i]);
+														z=surf->VertexZ(v0[i]);
+														u=surf->VertexU(v0[i]);
+														v=surf->VertexV(v0[i]);
+														w=surf->VertexW(v0[i]);
+														nx=surf->VertexNX(v0[i]);
+														ny=surf->VertexNY(v0[i]);
+														nz=surf->VertexNZ(v0[i]);
+														v0[i]=New_surface->AddVertex(x,y,z,u,v,w);
+														New_surface->VertexNormal(v0[i],nx,ny,nz);
+													}
+													New_surface->AddTriangle(v0[0],v0[1],v0[2]);
+													MovedTris.push_back(Index);
+
+												}
+											}
+
+											if (Lmatlist.size()==0){
+												for (unsigned int i = 0; i< matlist.size();i++){
+													if (brushnames[i] == texname[m])
+														{New_surface->PaintSurface(brushes[i]);}
+												}
+											}else{
+												New_surface->PaintSurface(Lbrushes[m]);
+											}
+										}
+
+										MovedTris.sort();
+										int CheckSurface=0;
+										for(list<int>::const_reverse_iterator it = MovedTris.rbegin(); it != MovedTris.rend(); it++){
+											surf->RemoveTri(*it);
+											CheckSurface=1;
+										}
+										MovedTris.clear();
+										if (surf->no_tris==0 && CheckSurface !=0) {
+											delete surf;
+											submesh->surf_list.remove(surf);
+											submesh->no_surfs=submesh->no_surfs-1;
+										}
+
+
+									}
+								}
+							}
+						}
+					}else{
+						if (checkbyte<=32)
+							{Stream->SeekFile(Stream->FilePos() + 1);
+						}else{
+							Stream->ReadLine();
+						}
+					}
+				}
+					
+				Stream->CloseFile();
+					
+				return submesh;
+			}else{
+				//cout<<"X Mesh Loader: Unsupported format '"<<format<<"'!";
+			}
+		}else{
+			//cout<<"X Mesh Loader: Unsupported version '"<< version << "'!";
+		}
+	}else{
+		//cout<<"X Mesh Loader: Invalid x-mesh!";
+	}
+	
+	return Mesh::CreateCube();
+	
+}
+}

+ 17 - 0
openb3dlib.mod/openb3d/whatsnew.txt

@@ -1,3 +1,20 @@
+V0.9
+Added:
+-Metaballs (CreateFluid and CreateBlob)
+-MD2 support (transitional animations are not yet supported)
+-Manual animation (mode 4): it's now possible the bones of an animated mesh, and the mesh will deform
+-Pre-rendered mesh animations: when a mesh is copied using RepeatMesh, all frames of the animation are rendered and stored in video memory, to be used for every instance of the mesh: animation is less smooth, but if many animated meshes are rendered at the same time, less system resources are used
+
+
+-Fixed
+-Some bugs in Octrees
+-SpriteRenderMode now works
+-Geosphere LOD works better
+-Upgraded image loader
+-Removed all the glBegin..glEnd pairs from the code: now, compiling for GLES should be easier
+
+
+V0.8
 Added:
 - ClearCollisions
 - Geospheres: now it's possible to make planets (spherical terrains)

+ 3 - 0
openb3dlib.mod/source.bmx

@@ -45,9 +45,12 @@ Import "openb3d/src/light.cpp"
 Import "openb3d/src/material.cpp"
 Import "openb3d/src/maths_helper.cpp"
 Import "openb3d/src/matrix.cpp"
+Import "openb3d/src/md2.cpp"
 Import "openb3d/src/mesh.cpp"
+Import "openb3d/src/metaball.cpp"
 Import "openb3d/src/model.cpp"
 Import "openb3d/src/octree.cpp"
+Import "openb3d/src/particle.cpp"
 Import "openb3d/src/pick.cpp"
 Import "openb3d/src/pivot.cpp"
 Import "openb3d/src/project.cpp"