www.pudn.com > map_editor.rar > 3d_objects.c


#include 
#include 
#include 
#include "global.h"
#include "e3d.h"
#include "../elc/platform.h"
#include "../elc/asc.h"

#ifdef NEW_E3D_FORMAT
#include "../elc/md5.h"
#include "../elc/io/e3d_io.h"

typedef struct
{
	float x, y, z;
} float3;

static __inline__ void get_texture_object_linear_plane(float obj_z_rot, float obj_x_pos, float obj_y_pos, float* s_plane, float* t_plane)
{
	float w, cos_w, sin_w;

	w = -obj_z_rot * M_PI / 180.0f;
	cos_w = cos(w);
	sin_w = sin(w);
	
	s_plane[0] = cos_w / texture_scale;
	s_plane[1] = sin_w / texture_scale;
	s_plane[2] = 1.0f / texture_scale;
	s_plane[3] = obj_x_pos / texture_scale + clouds_movement_u;
	t_plane[0] = -sin_w / texture_scale;
	t_plane[1] = cos_w / texture_scale;
	t_plane[2] = 1.0f / texture_scale;
	t_plane[3] = obj_y_pos / texture_scale + clouds_movement_v;
}

void draw_3d_object(object3d * object_id)
{
	int texture_id, i;
	float s_plane[4], t_plane[4];
	float x_pos,y_pos,z_pos;
	float x_rot,y_rot,z_rot;
	void* data_ptr;
	int vertex_size;

	//also, update the last time this object was used
	object_id->last_acessed_time=cur_time;

	if(object_id->blended)
	{
		glEnable(GL_BLEND);
		glBlendFunc(GL_ONE,GL_ONE);
	}

	if(object_id->self_lit && (night_shadows_on || dungeon))
	{
		glDisable(GL_LIGHTING);
		//set_material(object_id->r,object_id->g,object_id->b);
		glColor3f(object_id->r,object_id->g,object_id->b);
	}

	CHECK_GL_ERRORS();

	glPushMatrix();//we don't want to affect the rest of the scene
	x_pos = object_id->x_pos;
	y_pos = object_id->y_pos;
	z_pos = object_id->z_pos;
	glTranslatef (x_pos, y_pos, z_pos);

	x_rot = object_id->x_rot;
	y_rot = object_id->y_rot;
	z_rot = object_id->z_rot;
	glRotatef(z_rot, 0.0f, 0.0f, 1.0f);
	glRotatef(x_rot, 1.0f, 0.0f, 0.0f);
	glRotatef(y_rot, 0.0f, 1.0f, 0.0f);

	CHECK_GL_ERRORS();

	if (have_multitexture && clouds_shadows)
	{
		glClientActiveTextureARB(GL_TEXTURE1_ARB);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		ELglActiveTextureARB(GL_TEXTURE1_ARB);
		get_texture_object_linear_plane(object_id->z_rot, object_id->x_pos, object_id->y_pos, s_plane, t_plane);
		glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
		glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
		ELglActiveTextureARB(GL_TEXTURE0_ARB);
	
		glClientActiveTextureARB(GL_TEXTURE0_ARB);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	}

	if (have_vertex_buffers)
	{
		ELglBindBufferARB(GL_ARRAY_BUFFER_ARB, object_id->e3d_data->vertex_vbo);
		data_ptr = 0;
	}
	else
	{
		data_ptr = object_id->e3d_data->vertex_data;
	}
	vertex_size = get_vertex_size(object_id->e3d_data->vertex_options);

	if (has_normal(object_id->e3d_data->vertex_options))
	{
		glEnableClientState(GL_NORMAL_ARRAY);
		glNormalPointer(GL_FLOAT, vertex_size,
			data_ptr + get_normal_offset(object_id->e3d_data->vertex_options));
	}
	else
	{
		glNormal3f(0, 0, 1);
	}

#ifdef	USE_TANGENT
	if (use_tangent && has_tangen(object_id->e3d_data->vertex_options))
	{
		EnableVertexAttribArray(tangent_attribut);
		VertexAttribPointer(tangent_attribut, TANGENT_FLOAT_COUNT, GL_FLOAT,
			GL_FALSE, vertex_size, data_ptr + get_tangent_offset(vertex_options));
	}
#endif	//USE_TANGENT
#ifdef	USE_EXTRA_TEXTURE
	if (use_extra_texture && has_extra_texture(object_id->e3d_data->vertex_options))
	{
		glClientActiveTextureARB(GL_TEXTURE2_ARB);
		ELglActiveTextureARB(GL_TEXTURE2_ARB);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(EXTRA_TEXTURE_FLOAT_COUNT, GL_FLOAT, vertex_size,
			data_ptr + get_extra_texture_offset(vertex_options));
		ELglActiveTextureARB(GL_TEXTURE0_ARB);
		glClientActiveTextureARB(GL_TEXTURE0_ARB);
	}
#endif	//USE_EXTRA_TEXTURE

	glTexCoordPointer(TEXTURE_FLOAT_COUNT, GL_FLOAT, vertex_size,
		data_ptr + get_texture_offset(object_id->e3d_data->vertex_options));
	glVertexPointer(VERTEX_FLOAT_COUNT, GL_FLOAT, vertex_size,
		data_ptr + get_vertex_offset(object_id->e3d_data->vertex_options));
	if (have_vertex_buffers)
	{
		ELglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object_id->e3d_data->indicies_vbo);
	}

	CHECK_GL_ERRORS();

	for (i = 0; i < object_id->e3d_data->material_no; i++)
	{
		if (material_is_transparent(object_id->e3d_data->materials[i].options))
		{
			//enable alpha filtering, so we have some alpha key
			glEnable(GL_ALPHA_TEST);
			if (is_ground(object_id->e3d_data->vertex_options)) glAlphaFunc(GL_GREATER, 0.23f);
			else glAlphaFunc(GL_GREATER, 0.06f);
			glDisable(GL_CULL_FACE);
		}
		else
		{
			glDisable(GL_ALPHA_TEST);
			glEnable(GL_CULL_FACE);
		}

		texture_id = get_texture_id(object_id->e3d_data->materials[i].diffuse_map);
		if (last_texture != texture_id)
		{
			glBindTexture(GL_TEXTURE_2D, texture_id);
			last_texture = texture_id;
		}

		ELglDrawRangeElementsEXT(GL_TRIANGLES,
			object_id->e3d_data->materials[i].triangles_indicies_min,
			object_id->e3d_data->materials[i].triangles_indicies_max,
			object_id->e3d_data->materials[i].triangles_indicies_count,
			object_id->e3d_data->index_type,
			object_id->e3d_data->materials[i].triangles_indicies_index);
	}

	glPopMatrix();//restore the scene
	CHECK_GL_ERRORS();

	if (have_multitexture && clouds_shadows)
	{
		glClientActiveTextureARB(GL_TEXTURE1_ARB);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glClientActiveTextureARB(GL_TEXTURE0_ARB);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}

	if (!is_ground(object_id->e3d_data->vertex_options))
	{
		glDisableClientState(GL_NORMAL_ARRAY);
	}

#ifdef	USE_TANGENT
	if (use_tangent && has_tangen(object_id->e3d_data->vertex_options))
	{
		DisableVertexAttribArray(tangent_attribut);
	}
#endif	//USE_TANGENT
#ifdef	USE_EXTRA_TEXTURE
	if (use_extra_texture && has_extra_texture(object_id->e3d_data->vertex_options))
	{
		glClientActiveTextureARB(GL_TEXTURE2_ARB);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glClientActiveTextureARB(GL_TEXTURE0_ARB);
	}
#endif	//USE_EXTRA_TEXTURE

	if (object_id->blended) glDisable(GL_BLEND);
	if (object_id->self_lit && (night_shadows_on || dungeon)) glEnable(GL_LIGHTING);
	if (material_is_transparent(object_id->e3d_data->materials[object_id->e3d_data->material_no-1].options))
	{
		glDisable(GL_ALPHA_TEST);
		glEnable(GL_CULL_FACE);
	}
	CHECK_GL_ERRORS();
}

#else	//NEW_E3D_FORMAT

void draw_3d_object(object3d * object_id)
{
	float x_pos,y_pos,z_pos;
	float x_rot,y_rot,z_rot;

	int materials_no,texture_id;
	int i;

	e3d_array_vertex *array_vertex;
	e3d_array_normal *array_normal;
	e3d_array_uv_main *array_uv_main;
	e3d_array_uv_detail *clouds_uv;
	e3d_array_order *array_order;

	int is_transparent;
	int is_ground;

	is_transparent=object_id->e3d_data->is_transparent;
	is_ground=object_id->e3d_data->is_ground;
	materials_no=object_id->e3d_data->materials_no;

	array_vertex=object_id->e3d_data->array_vertex;
	array_normal=object_id->e3d_data->array_normal;
	array_uv_main=object_id->e3d_data->array_uv_main;
	array_order=object_id->e3d_data->array_order;

	CHECK_GL_ERRORS();
	if(have_multitexture && clouds_shadows)
		if(!object_id->clouds_uv)
			compute_clouds_map(object_id);

	CHECK_GL_ERRORS();
	//also, update the last time this object was used
	object_id->last_acessed_time=cur_time;

	clouds_uv=object_id->clouds_uv;

	//debug

	if(object_id->blended)
		{
			glEnable(GL_BLEND);
			glBlendFunc(GL_ONE,GL_ONE);
		}

	if(object_id->self_lit && (night_shadows_on || dungeon))
		{
			glDisable(GL_LIGHTING);
			//set_material(object_id->r,object_id->g,object_id->b);
			glColor3f(object_id->r,object_id->g,object_id->b);
		}

	if(is_transparent)
		{
			//enable alpha filtering, so we have some alpha key
			glEnable(GL_ALPHA_TEST);
			if(is_ground)glAlphaFunc(GL_GREATER,0.23f);
			else glAlphaFunc(GL_GREATER,0.06f);
			glDisable(GL_CULL_FACE);
		}
	CHECK_GL_ERRORS();

	glPushMatrix();//we don't want to affect the rest of the scene
	x_pos=object_id->x_pos;
	y_pos=object_id->y_pos;
	z_pos=object_id->z_pos;
	glTranslatef (x_pos, y_pos, z_pos);

	x_rot=object_id->x_rot;
	y_rot=object_id->y_rot;
	z_rot=object_id->z_rot;
	glRotatef(z_rot, 0.0f, 0.0f, 1.0f);
	glRotatef(x_rot, 1.0f, 0.0f, 0.0f);
	glRotatef(y_rot, 0.0f, 1.0f, 0.0f);

	CHECK_GL_ERRORS();
	if(!have_multitexture || !clouds_shadows)
		{
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glVertexPointer(3,GL_FLOAT,0,array_vertex);
			glTexCoordPointer(2,GL_FLOAT,0,array_uv_main);
			if(!is_ground)
				{
					glEnableClientState(GL_NORMAL_ARRAY);
					glNormalPointer(GL_FLOAT,0,array_normal);
	CHECK_GL_ERRORS();
					for(i=0;ifile_name, i,
										array_order[i].start, array_order[i].count);
									log_error(str);
								}
#endif	// DEBUG
						//if(have_compiled_vertex_array)glLockArraysEXT(array_order[i].start, array_order[i].count);
						glDrawArrays(GL_TRIANGLES,array_order[i].start,array_order[i].count);
						//if(have_compiled_vertex_array)glUnlockArraysEXT();
	CHECK_GL_ERRORS();
						}
					glDisableClientState(GL_NORMAL_ARRAY);
				}//is ground
			else
				{
					glNormal3f(0,0,1);

					for(i=0;ifile_name, i,
										array_order[i].start, array_order[i].count);
									log_error(str);
								}
#endif	// DEBUG
						//if(have_compiled_vertex_array)glLockArraysEXT(array_order[i].start, array_order[i].count);
						glDrawArrays(GL_TRIANGLES,array_order[i].start,array_order[i].count);
						//if(have_compiled_vertex_array)glUnlockArraysEXT();
	CHECK_GL_ERRORS();
						}
				}
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		}
	else//draw a texture detail
		{
			glClientActiveTextureARB(GL_TEXTURE1_ARB);
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glTexCoordPointer(2,GL_FLOAT,0,clouds_uv);
			glClientActiveTextureARB(GL_TEXTURE0_ARB);
			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
			glTexCoordPointer(2,GL_FLOAT,0,array_uv_main);

			if(!is_ground)
				{
					glEnableClientState(GL_NORMAL_ARRAY);
					glVertexPointer(3,GL_FLOAT,0,array_vertex);
					glNormalPointer(GL_FLOAT,0,array_normal);
	CHECK_GL_ERRORS();

					for(i=0;ifile_name, i,
										array_order[i].start, array_order[i].count);
									log_error(str);
								}
#endif	// DEBUG
							//if(have_compiled_vertex_array)glLockArraysEXT(array_order[i].start, array_order[i].count);
							glDrawArrays(GL_TRIANGLES,array_order[i].start,array_order[i].count);
							//if(have_compiled_vertex_array)glUnlockArraysEXT();
	CHECK_GL_ERRORS();
						}
				}

			glClientActiveTextureARB(GL_TEXTURE1_ARB);
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
			glClientActiveTextureARB(GL_TEXTURE0_ARB);
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		}
	glPopMatrix();//restore the scene
	CHECK_GL_ERRORS();


	if(object_id->blended)glDisable(GL_BLEND);
	if(object_id->self_lit && (night_shadows_on || dungeon))glEnable(GL_LIGHTING);
	if(is_transparent)
		{
			glDisable(GL_ALPHA_TEST);
			glEnable(GL_CULL_FACE);
		}
	CHECK_GL_ERRORS();

}
#endif	//NEW_E3D_FORMAT

//Tests to see if an e3d object is already loaded. If it is, return the handle.
//If not, load it, and return the handle
e3d_object * load_e3d_cache(char * file_name)
{
	e3d_object * e3d_id;

	int i;
	int j;
	int file_name_lenght;
	file_name_lenght=strlen(file_name);

	for (i = 0; i < MAX_E3D_CACHE; i++)
		{
			j=0;
			while(jfile_name, file_name, sizeof(e3d_id->file_name));	
	e3d_id = load_e3d_detail(e3d_id);

	if (e3d_id == NULL) 
	{
		LOG_ERROR("Can't load file \"%s\"!", file_name);
		return NULL;
	}

#else	//NEW_E3D_FORMAT
	e3d_id=load_e3d(file_name);
	if(e3d_id==NULL)return NULL;
#endif	//NEW_E3D_FORMAT

	//find a place to store it
	i=0;
	while (i < MAX_E3D_CACHE)
		{
			if(!e3d_cache[i].file_name[0])//we found a place to store it
				{
					sprintf(e3d_cache[i].file_name, "%s", file_name);
					e3d_cache[i].e3d_id=e3d_id;
					e3d_cache[i].flag_for_destruction=0;
					return e3d_id;
				}
			i++;
		}

	return e3d_id;
}

int add_e3d_at_id (int id, char * file_name, float x_pos, float y_pos, float z_pos, float x_rot, float y_rot, float z_rot, char self_lit, char blended, float r, float g, float b)
{
	char fname[128];
	e3d_object *returned_e3d;
	object3d *our_object;
	
	if (id < 0 || id >= MAX_OBJ_3D)
		return 0;

	//but first convert any '\' in '/'
	clean_file_name(fname, file_name, sizeof(fname));
	my_tolower(fname);

	returned_e3d=load_e3d_cache(fname);
	if(returned_e3d==NULL)
	{
		char str[120];
		sprintf (str, "Error: Something nasty happened while trying to process: %s\n", fname);
		LOG_ERROR(str);

    		//replace it with the null object, to avoid object IDs corruption
    		returned_e3d = load_e3d_cache ("./3dobjects/misc_objects/badobject.e3d");
    		if (returned_e3d == NULL)
			return 0; // umm, not even found the place holder, this is teh SUKC!!!
	}

	// now, allocate the memory
	our_object = calloc (1, sizeof(object3d));

	// and fill it in
	snprintf (our_object->file_name, 80, "%s", fname);
	our_object->x_pos = x_pos;
	our_object->y_pos = y_pos;
	our_object->z_pos = z_pos;

	our_object->x_rot = x_rot;
	our_object->y_rot = y_rot;
	our_object->z_rot = z_rot;

	our_object->r = r;
	our_object->g = g;
	our_object->b = b;

#ifndef	NEW_E3D_FORMAT
	our_object->clouds_uv = NULL;
#endif	//NEW_E3D_FORMAT

	our_object->self_lit = self_lit;
	our_object->blended = blended;

	our_object->e3d_data = returned_e3d;

	objects_list[id] = our_object;
	return id;
}

int add_e3d (char * file_name, float x_pos, float y_pos, float z_pos, float x_rot, float y_rot, float z_rot, char self_lit, char blended, float r, float g, float b)
{
	int id;

	//find a free spot, in the e3d_list
	id = 0;
	while (id < MAX_OBJ_3D)
	{
		if (objects_list[id] == NULL || objects_list[id]->blended==20) 
			break;
		id++;
	}
	
	if (id >= MAX_OBJ_3D) return 0;
	return add_e3d_at_id (id, file_name, x_pos, y_pos, z_pos, x_rot, y_rot, z_rot, self_lit, blended, r, g, b);
}

int add_e3d_keep_deleted (char * file_name, float x_pos, float y_pos, float z_pos, float x_rot, float y_rot, float z_rot, char self_lit, char blended, float r, float g, float b)
{
	int id;

	//find a free spot, in the e3d_list
	id = 0;
	while (id < MAX_OBJ_3D)
	{
		if (objects_list[id] == NULL) 
			break;
		id++;
	}
	
	if (id >= MAX_OBJ_3D) return 0;
	return add_e3d_at_id (id, file_name, x_pos, y_pos, z_pos, x_rot, y_rot, z_rot, self_lit, blended, r, g, b);
}

void display_objects()
{
	int i;
	int x,y;

	x=(int) -camera_x;
	y=(int) -camera_y;
	CHECK_GL_ERRORS();
	glEnable(GL_CULL_FACE);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	if(have_multitexture && clouds_shadows)
		{
			//bind the detail texture
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D,  texture_cache[ground_detail_text].texture_id);
			glActiveTextureARB(GL_TEXTURE0_ARB);
			glEnable(GL_TEXTURE_2D);
		}

	CHECK_GL_ERRORS();
	for (i = 0; i < MAX_OBJ_3D; i++)
		{
			if(objects_list[i] && objects_list[i]->blended!=20)
				{
					int dist1;
					int dist2;

					dist1=x-(int)objects_list[i]->x_pos;
					dist2=y-(int)objects_list[i]->y_pos;
					if(dist1*dist1+dist2*dist2<=((40*40)*(zoom_level/15.75f)))
						{
#ifdef	NEW_E3D_FORMAT
	                     				draw_3d_object(objects_list[i]);
#else	//NEW_E3D_FORMAT
							float x_len;
							float y_len;
							float z_len;
							float radius;

							z_len=objects_list[i]->e3d_data->max_z-objects_list[i]->e3d_data->min_z;
							x_len=objects_list[i]->e3d_data->max_x-objects_list[i]->e3d_data->min_x;
							y_len=objects_list[i]->e3d_data->max_y-objects_list[i]->e3d_data->min_y;
							//do some checks, to see if we really have to display this object
							radius=x_len/2;
							if(radiusx_pos,objects_list[i]->y_pos,
							//				   objects_list[i]->z_pos,radius))
								{
                     				draw_3d_object(objects_list[i]);
	CHECK_GL_ERRORS();
									//anything_under_the_mouse(i,UNDER_MOUSE_3D_OBJ);
	//CHECK_GL_ERRORS();
								}
#endif	//NEW_E3D_FORMAT
						}
				}
		}
	CHECK_GL_ERRORS();
	glDisable(GL_CULL_FACE);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	if(have_multitexture && clouds_shadows)
		{
			//disable the second texture unit
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glDisable(GL_TEXTURE_2D);
			glActiveTextureARB(GL_TEXTURE0_ARB);
		}
	CHECK_GL_ERRORS();
}

#ifndef	NEW_E3D_FORMAT
e3d_object * load_e3d(char *file_name)
{
	int vertex_no,faces_no,materials_no;
	int i,k,l;
	e3d_vertex *vertex_list;
	e3d_face *face_list;
	e3d_material *material_list;
	char cur_dir[200]={0};
	e3d_object *cur_object;
	//int transparency=0; unused?
	e3d_header our_header;
	char *our_header_pointer=(char *)&our_header;
	e3d_array_vertex *array_vertex;
	e3d_array_normal *array_normal;
	e3d_array_uv_main *array_uv_main;
	e3d_array_order *array_order;
#ifdef	ZLIB
	gzFile *f = NULL;
#else	//ZLIB
	FILE *f = NULL;
#endif	//ZLIB

	//get the current directory
	l=strlen(file_name);
	//parse the string backwards, until we find a /
	while(l>0)
		{
			if(file_name[l]=='/' || file_name[l]=='\\')break;
			l--;
		}

	i=0;
	if(l)//prevent invalid dir names
		{
			while(l>=0)
				{
					cur_dir[i]=file_name[i];
					i++;
					l--;
				}
			cur_dir[i+1]=0;
		}


#ifdef	ZLIB
	f= my_gzopen(file_name, "rb");
#else	//ZLIB
	f= fopen(file_name, "rb");
#endif	//ZLIB
	if(!f)
        {
            char str[120];
            sprintf(str,"Error: Can't open %s\n",file_name);
            log_error(str);
            return NULL;
        }

	//load and parse the header
#ifdef	ZLIB
	gzread(f, our_header_pointer, sizeof(e3d_header));
#else	//ZLIB
	fread(our_header_pointer, 1, sizeof(e3d_header), f);
#endif	//ZLIB

	faces_no=our_header.face_no;
	vertex_no=our_header.vertex_no;
	materials_no=our_header.material_no;

	//read the rest of the file (vertex,faces, materials)
	face_list=(e3d_face*) calloc(faces_no, our_header.face_size);
#ifdef	ZLIB
	gzread(f, face_list, faces_no*our_header.face_size);
#else	//ZLIB
	fread(face_list, faces_no, our_header.face_size, f);
#endif	//ZLIB

	vertex_list=(e3d_vertex*) calloc(vertex_no, our_header.vertex_size);
  	if(!vertex_list)
		{
			char str[200];
			sprintf(str,"Hmm, object name:%s seems to be corrupted. Skipping the object. Warning: This might cause further problems.",file_name);
			//log_to_console(c_red2,str);
			free(face_list);
#ifdef	ZLIB
			gzclose(f);
#else	//ZLIB
			fclose(f);
#endif	//ZLIB
			return NULL;
		}
#ifdef	ZLIB
	gzread(f, vertex_list, vertex_no*our_header.vertex_size);
#else	//ZLIB
	fread(vertex_list, vertex_no, our_header.vertex_size, f);
#endif	//ZLIB

	material_list=(e3d_material*) calloc(materials_no, our_header.material_size);
#ifdef	ZLIB
	gzread(f, material_list, materials_no*our_header.material_size);
#else	//ZLIB
	fread(material_list, materials_no, our_header.material_size, f);
#endif	//ZLIB

#ifdef	ZLIB
	gzclose (f);
#else	//ZLIB
	fclose (f);
#endif	//ZLIB

	//allocate memory for our new, converted structures
	array_order=(e3d_array_order*) calloc(materials_no, sizeof(e3d_array_order));
	array_vertex=(e3d_array_vertex*) calloc(faces_no*3, sizeof(e3d_array_vertex));
	array_normal=(e3d_array_normal*) calloc(faces_no*3, sizeof(e3d_array_normal));
	array_uv_main=(e3d_array_uv_main*) calloc(faces_no*3, sizeof(e3d_array_uv_main));

	// allocate the memory
	cur_object=(e3d_object*) calloc(1, sizeof(e3d_object));
	// and fill in the data
	cur_object->min_x=our_header.min_x;
	cur_object->min_y=our_header.min_y;
	cur_object->min_z=our_header.min_z;
	cur_object->max_x=our_header.max_x;
	cur_object->max_y=our_header.max_y;
	cur_object->max_z=our_header.max_z;

	cur_object->is_transparent=our_header.is_transparent;
	cur_object->is_ground=our_header.is_ground;
	cur_object->face_no=faces_no;

	//now, load all the materials, and use the material ID (which isn't used now) to
	//temporary store the texture_ids

	for(i=0;iis_transparent)material_list[i].material_id=load_texture_cache(text_file_name,0);
			else material_list[i].material_id=load_texture_cache(text_file_name,0);
*/
			material_list[i].material_id=load_texture_cache(text_file_name,0);
		}

	//assign the proper texture to each face

	for(i=0;iarray_order=array_order;
	cur_object->array_vertex=array_vertex;
	cur_object->array_normal=array_normal;
	cur_object->array_uv_main=array_uv_main;
	cur_object->materials_no=materials_no;

	free(material_list);
	free(vertex_list);
	free(face_list);

	return cur_object;
}

void compute_clouds_map(object3d * object_id)
{
	float x1,y1,x,y,z,m;
	float cos_m,sin_m;
	float x_pos,y_pos,z_pos;
	float x_rot,y_rot,z_rot;
	int i,face_no;

	e3d_array_vertex *array_vertex;
	e3d_array_uv_detail *array_detail;

	array_vertex=object_id->e3d_data->array_vertex;
	face_no=object_id->e3d_data->face_no;
	array_detail=(e3d_array_uv_detail*) calloc(face_no*3,sizeof(e3d_array_uv_detail));

	x_pos=object_id->x_pos;
	y_pos=object_id->y_pos;
	z_pos=object_id->z_pos;

	x_rot=object_id->x_rot;
	y_rot=object_id->y_rot;
	z_rot=object_id->z_rot;

	m=(-z_rot)*3.1415926/180;
	cos_m=cos(m);
	sin_m=sin(m);

	for(i=0;iclouds_uv=array_detail;
}

void clear_clouds_cache()
{
	int i;

	last_clear_clouds=cur_time;
	for (i = 0; i < MAX_OBJ_3D; i++)
		{
			if(objects_list[i])
				{
					if(objects_list[i]->clouds_uv && objects_list[i]->last_acessed_time+20000clouds_uv);
							objects_list[i]->clouds_uv=NULL;
						}
				}
		}
}
#endif	//NEW_E3D_FORMAT

void destroy_3d_object(int i)
{
	free(objects_list[i]);
	objects_list[i]=0;
}

void destroy_e3d(e3d_object *e3d_id)
{
#ifdef	NEW_E3D_FORMAT
	if (e3d_id != NULL)
	{
		if (e3d_id->vertex_data != NULL)
		{
			free(e3d_id->vertex_data);
			e3d_id->vertex_data = NULL;
		}
		if (e3d_id->indicies != NULL)
		{
			free(e3d_id->indicies);
			e3d_id->indicies = NULL;
		}
		if (e3d_id->materials != NULL)
		{
			free(e3d_id->materials);
			e3d_id->materials= NULL;
			e3d_id->material_no= 0;
		}
		if (e3d_id->vertex_vbo != 0) 
		{		
			ELglDeleteBuffersARB(1, &e3d_id->vertex_vbo);
			e3d_id->vertex_vbo = 0;
		}
		if (e3d_id->indicies_vbo != 0) 
		{		
			ELglDeleteBuffersARB(1, &e3d_id->indicies_vbo);
			e3d_id->indicies_vbo = 0;
		}
		// and finally free the main object
		free(e3d_id);
	}
#else	//NEW_E3D_FORMAT
	if(e3d_id->array_vertex)
		{
			free(e3d_id->array_vertex);
			e3d_id->array_vertex=NULL;
		}

	if(e3d_id->array_normal)
		{
			free(e3d_id->array_normal);
			e3d_id->array_normal=NULL;
		}

	if(e3d_id->array_uv_main)
		{
			free(e3d_id->array_uv_main);
			e3d_id->array_uv_main=NULL;
		}

	if(e3d_id->array_order)
		{
			free(e3d_id->array_order);
			e3d_id->array_order=NULL;
		}
	// and finally free the main object
	free(e3d_id);
#endif	//NEW_E3D_FORMAT
}

void flag_for_destruction()
{
	int i;

	for (i = 0; i < MAX_E3D_CACHE; i++)
		if (e3d_cache[i].file_name[0])
			e3d_cache[i].flag_for_destruction = 1;
}

void destroy_the_flagged()
{
	int i;
	
	for (i = 0; i < MAX_E3D_CACHE; i++)
	{
		if (e3d_cache[i].file_name[0] && e3d_cache[i].flag_for_destruction)
		{
			destroy_e3d (e3d_cache[i].e3d_id);
			e3d_cache[i].file_name[0] = 0;
			e3d_cache[i].flag_for_destruction = 0;
		}
	}
}


void MulMatrix(float mat1[4][4], float mat2[4][4], float dest[4][4])
{
   int i,j;
   for(i=0; i<4; i++)
      for(j=0; j<4; j++)
         dest[i][j]=mat1[i][0]*mat2[0][j]+mat1[i][1]*mat2[1][j]+mat1[i][2]*mat2[2][j]+mat1[i][3]*mat2[3][j];
}

void VecMulMatrix(float s[3],float mat[4][4],float d[3])
{
    d[0]=s[0]*mat[0][0]+s[1]*mat[1][0]+s[2]*mat[2][0]+mat[3][0];
    d[1]=s[0]*mat[0][1]+s[1]*mat[1][1]+s[2]*mat[2][1]+mat[3][1];
    d[2]=s[0]*mat[0][2]+s[1]*mat[1][2]+s[2]*mat[2][2]+mat[3][2];
}

void CreateIdentityMatrix(float mat[4][4])
{
    mat[0][0]=1; mat[0][1]=0; mat[0][2]=0; mat[0][3]=0;
    mat[1][0]=0; mat[1][1]=1; mat[1][2]=0; mat[1][3]=0;
    mat[2][0]=0; mat[2][1]=0; mat[2][2]=1; mat[2][3]=0;
    mat[3][0]=0; mat[3][1]=0; mat[3][2]=0; mat[3][3]=1;
}

void CreateRotationMatrix(float matrix[4][4],float ax,float ay,float az)
{
   float xmat[4][4], ymat[4][4], zmat[4][4];
   float mat1[4][4], mat2[4][4];
   xmat[0][0]=1;	xmat[0][1]=0;		xmat[0][2]=0;		xmat[0][3]=0;
   xmat[1][0]=0;	xmat[1][1]=cos(ax); xmat[1][2]=sin(ax); xmat[1][3]=0;
   xmat[2][0]=0;	xmat[2][1]=-sin(ax);xmat[2][2]=cos(ax); xmat[2][3]=0;
   xmat[3][0]=0;    xmat[3][1]=0;		xmat[3][2]=0;		xmat[3][3]=1;

   ymat[0][0]=cos(ay);	ymat[0][1]=0;	ymat[0][2]=-sin(ay);ymat[0][3]=0;
   ymat[1][0]=0;		ymat[1][1]=1;	ymat[1][2]=0;		ymat[1][3]=0;
   ymat[2][0]=sin(ay);  ymat[2][1]=0;	ymat[2][2]=cos(ay); ymat[2][3]=0;
   ymat[3][0]=0;        ymat[3][1]=0;	ymat[3][2]=0;	ymat[3][3]=1;

   zmat[0][0]=cos(az);	zmat[0][1]=sin(az);	zmat[0][2]=0;	zmat[0][3]=0;
   zmat[1][0]=-sin(az); zmat[1][1]=cos(az); zmat[1][2]=0;	zmat[1][3]=0;
   zmat[2][0]=0;        zmat[2][1]=0;       zmat[2][2]=1;	zmat[2][3]=0;
   zmat[3][0]=0;        zmat[3][1]=0;       zmat[3][2]=0;	zmat[3][3]=1;

   MulMatrix(matrix,ymat,mat1);
   MulMatrix(mat1,xmat,mat2);
   MulMatrix(mat2,zmat,matrix);
}


#ifdef	NEW_E3D_FORMAT
void rotatehm(float xrot, float yrot, float zrot, float3* T, int nv)
{
	float TT[4][4];
	int i;
	float t[3];
	float d[3];

	CreateIdentityMatrix(TT);
	CreateRotationMatrix(TT,xrot,yrot,zrot);

	for (i = 0; i < nv; i++)
	{
		t[0] = T[i].x;
		t[1] = T[i].y;
		t[2] = T[i].z;

		VecMulMatrix(t, TT, d);

		T[i].x = d[0];
		T[i].y = d[1];
		T[i].z = d[2];
	}
}
#else	//NEW_E3D_FORMAT
void rotatehm(float xrot, float yrot, float zrot, e3d_array_vertex *T, int nv)
{
	float TT[4][4];
	int i;
	CreateIdentityMatrix(TT);
	CreateRotationMatrix(TT,xrot,yrot,zrot);

	for(i=0;i0 && b2>0 && b3>0) ? 1 : 0;
}

void clear_e3d_heightmap(int K)
{
#ifdef	NEW_E3D_FORMAT
	float3 *TF;
	void* T;
	int vertex_no;
	int minx, miny, maxx, maxy;							
	int i, j;
	float x_pos, y_pos;
	float min_x, min_y, max_x, max_y;

	vertex_no = objects_list[K]->e3d_data->vertex_no;

	T = objects_list[K]->e3d_data->vertex_data + get_vertex_offset(objects_list[K]->e3d_data->vertex_options);
	TF = malloc(vertex_no * sizeof(float3));
	for (i = 0; i < vertex_no; i++)
	{
		memcpy(TF, T, sizeof(float3));
		T += get_vertex_size(objects_list[K]->e3d_data->vertex_options);
	}

	x_pos = objects_list[K]->x_pos;
	y_pos = objects_list[K]->y_pos;
	min_x = 0;
	min_y = 0;
	max_x = 0;
	max_y = 0;

	// Check if we need to rotate the vertex
	if(objects_list[K]->x_rot!=0.0 || objects_list[K]->y_rot!=0.0 || objects_list[K]->z_rot!=0.0)
	{
		rotatehm(objects_list[K]->x_rot*(3.14159265/180), objects_list[K]->y_rot*(3.14159265/180), objects_list[K]->z_rot*(3.14159265/180), TF, vertex_no);
	}

	// Calculating min and max x and y values of the object
	for (i = 0; i < vertex_no; i++)
	{
		if (TF[i].x < min_x) min_x = TF[i].x;
		if (TF[i].x > max_x) max_x = TF[i].x;
		if (TF[i].y < min_y) min_y = TF[i].y;
		if (TF[i].y > max_y) max_y = TF[i].y;
	}
#else	// NEW_E3D_FORMAT
	int face_no = objects_list[K]->e3d_data->face_no;
	float x_pos = objects_list[K]->x_pos;
	float y_pos = objects_list[K]->y_pos;
	float min_x = 0, min_y = 0, max_x = 0, max_y = 0;
	e3d_array_vertex *T = objects_list[K]->e3d_data->array_vertex;
	int minx, miny, maxx, maxy;							
	int i, j;
	
	e3d_array_vertex *TT = NULL;
	
	// Check if we need to rotate the vertex
	if(objects_list[K]->x_rot!=0.0 || objects_list[K]->y_rot!=0.0 || objects_list[K]->z_rot!=0.0)
	{
		TT = (e3d_array_vertex *)malloc(face_no*3*sizeof(e3d_array_vertex));
		memcpy(TT,T,face_no*3*sizeof(e3d_array_vertex));
		T = TT;
		rotatehm(objects_list[K]->x_rot*(3.14159265/180),objects_list[K]->y_rot*(3.14159265/180),objects_list[K]->z_rot*(3.14159265/180),T,face_no*3);
	}

	// Calculating min and max x and y values of the object
	for(i = 0; i < face_no*3; i++){
		if(T[i].x < min_x) min_x = T[i].x;
		if(T[i].x > max_x) max_x = T[i].x;
		if(T[i].y < min_y) min_y = T[i].y;
		if(T[i].y > max_y) max_y = T[i].y;
	}
#endif	// NEW_3D_FORMAT

	// Calculating min and max positions on the heightmap
	minx = (x_pos + min_x) / 0.5f;
	miny = (y_pos + min_y) / 0.5f;
	maxx = (x_pos + max_x) / 0.5f + 1;
	maxy = (y_pos + max_y) / 0.5f + 1;

	for(i = minx; i < maxx; i++){
		for(j = miny; j< maxy; j++){
			height_map[(j*tile_map_size_x*6)+i]=11;
		}
	}
#ifdef	NEW_E3D_FORMAT
	free(TF);
#else	// NEW_E3D_FORMAT
	// Freeing if there is rotation
	if(TT!=NULL)
		free(TT);
#endif	// NEW_3D_FORMAT
}


int ccw(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y)
{
    double d = ((p1y - p2y) * (p3x - p2x)) - ((p3y - p2y) * (p1x - p2x));
	return (d > 0) ? 1 : ((d < 0) ? 2 : 3);
}


int between(float pax, float pay, float pbx, float pby, float pcx, float pcy)
{

	float p1x = pbx - pax, p1y = pby - pay, p2x = pcx - pax, p2y = pcy - pay;
	if (ccw (pax, pay, pbx, pby, pcx, pcy) != 3)
		return 0;
	return (p2x * p1x + p2y * p1y >= 0) && (p2x * p2x + p2y * p2y <= p1x * p1x + p1y * p1y);
}

int TestLines(float pax, float pay, float pbx, float pby, float pcx, float pcy, float pdx, float pdy)
{
	int ccw1, ccw2, ccw3, ccw4;
	if(pcx == pdx && pcy == pdy) return 0;
	if (ccw (pax, pay, pbx, pby, pcx, pcy) == 3 || ccw (pax, pay, pbx, pby, pdx, pdy) == 3 || ccw (pcx, pcy, pdx, pdy, pax, pay) == 3 || ccw (pcx, pcy, pdx, pdy, pbx, pby) == 3){
		if (between (pax, pay, pbx, pby, pcx, pcy) || between (pax, pay, pbx, pby, pdx, pdy) || between (pcx, pcy, pdx, pdy, pax, pay) || between (pcx, pcy, pdx, pdy, pbx, pby))
			return 1;
	}else{
		ccw1 = (ccw (pax, pay, pbx, pby, pcx, pcy) == 1) ? 1 : 0;
		ccw2 = (ccw (pax, pay, pbx, pby, pdx, pdy) == 1) ? 1 : 0;
		ccw3 = (ccw (pcx, pcy, pdx, pdy, pax, pay) == 1) ? 1 : 0;
		ccw4 = (ccw (pcx, pcy, pdx, pdy, pbx, pby) == 1) ? 1 : 0;
		return (ccw1 ^ ccw2) && (ccw3 ^ ccw4);
	}
	return 0;
}
 
void change_heightmap(unsigned char *hm, unsigned char h)
{
	//if(*hm==11 && h>21)return;
	if(*hm31)h=31;

	// We determine if the point is in the triangle
	if(TriangleTest(i*0.5f+0.25f, j*0.5f+0.25f, x1, y1, x2, y2, x3, y3)){
		height_map[(j*tile_map_size_x*6)+i]=h;	
		return;
	}
}

#ifdef	NEW_E3D_FORMAT
void method2(float3 *T, float x_pos, float y_pos, float z_pos, int i, int j)
#else	// NEW_E3D_FORMAT
void method2(e3d_array_vertex *T, float x_pos, float y_pos, float z_pos, int i, int j)
#endif	// NEW_E3D_FORMAT
{
	float x1 = T[0].x + x_pos, x2 = T[1].x + x_pos, x3 = T[2].x + x_pos;
	float y1 = T[0].y + y_pos, y2 = T[1].y + y_pos, y3 = T[2].y + y_pos;
	int h =(((T[0].z + T[1].z + T[2].z)/3+z_pos)+2.2f)/0.2f; // Average height of triangle
	if(h>31)h=31;

	// We determine if the point is in the triangle
	if(TriangleTest(i*0.5f+0.25f, j*0.5f+0.25f, x1, y1, x2, y2, x3, y3)){
		height_map[(j*tile_map_size_x*6)+i]=h;	
		return;
	}
	if(TriangleTest(i*0.5f, j*0.5f, x1, y1, x2, y2, x3, y3)){
		height_map[(j*tile_map_size_x*6)+i]=h;	
		return;
	}
	if(TriangleTest(i*0.5f+0.25f, j*0.5f, x1, y1, x2, y2, x3, y3)){
		height_map[(j*tile_map_size_x*6)+i]=h;	
		return;
	}
	if(TriangleTest(i*0.5f+0.25f, j*0.5f, x1, y1, x2, y2, x3, y3)){
		height_map[(j*tile_map_size_x*6)+i]=h;	
		return;
	}
}

#ifdef	NEW_E3D_FORMAT
void method3(float3 *T, float x_pos, float y_pos, float z_pos, int i, int j)
#else	// NEW_E3D_FORMAT
void method3(e3d_array_vertex *T, float x_pos, float y_pos, float z_pos, int i, int j)
#endif	// NEW_E3D_FORMAT
{
	float x1 = T[0].x + x_pos, x2 = T[1].x + x_pos, x3 = T[2].x + x_pos;
	float y1 = T[0].y + y_pos, y2 = T[1].y + y_pos, y3 = T[2].y + y_pos;
	unsigned char h =(((T[0].z + T[1].z + T[2].z)/3+z_pos)+2.2f)/0.2f; // Average height of triangle
	if(h>31)h=31;

	// Special case 1: triangle inside rect
	if( (x1 > i*0.5 && x1 < (i+1)*0.5 && y1 > j*0.5 && y1 < (j+1)*0.5)
	||  (x2 > i*0.5 && x2 < (i+1)*0.5 && y2 > j*0.5 && y2 < (j+1)*0.5)
	||  (x3 > i*0.5 && x3 < (i+1)*0.5 && y3 > j*0.5 && y3 < (j+1)*0.5)){
		change_heightmap(&height_map[(j*tile_map_size_x*6)+i],h);
		//height_map[(j*tile_map_size_x*6)+i]=h;	
		//return;
	}
	
	// Special case 2: rectangle inside triangle
	if(TriangleTest(i*0.5f+0.25f, j*0.5f+0.25f, x1, y1, x2, y2, x3, y3)){
		change_heightmap(&height_map[(j*tile_map_size_x*6)+i],h);
		//height_map[(j*tile_map_size_x*6)+i]=h;	
		//return;
	}

	// Checking triangle intersections
	if(TestLines(i*0.5, j*0.5, (i+1)*0.5, j*0.5, x1, y1, x2, y2)
	|| TestLines(i*0.5, j*0.5, (i+1)*0.5, j*0.5, x2, y2, x3, y3)
	|| TestLines(i*0.5, j*0.5, (i+1)*0.5, j*0.5, x3, y3, x1, y1)
	|| TestLines(i*0.5, j*0.5, i*0.5, (j+1)*0.5, x1, y1, x2, y2)
	|| TestLines(i*0.5, j*0.5, i*0.5, (j+1)*0.5, x2, y2, x3, y3)
	|| TestLines(i*0.5, j*0.5, i*0.5, (j+1)*0.5, x3, y3, x1, y1)
	|| TestLines((i+1)*0.5, (j+1)*0.5, (i+1)*0.5, j*0.5, x1, y1, x2, y2)
	|| TestLines((i+1)*0.5, (j+1)*0.5, (i+1)*0.5, j*0.5, x2, y2, x3, y3)
	|| TestLines((i+1)*0.5, (j+1)*0.5, (i+1)*0.5, j*0.5, x3, y3, x1, y1)
	|| TestLines((i+1)*0.5, (j+1)*0.5, i*0.5, (j+1)*0.5, x1, y1, x2, y2)
	|| TestLines((i+1)*0.5, (j+1)*0.5, i*0.5, (j+1)*0.5, x2, y2, x3, y3)
	|| TestLines((i+1)*0.5, (j+1)*0.5, i*0.5, (j+1)*0.5, x3, y3, x1, y1)){
		change_heightmap(&height_map[(j*tile_map_size_x*6)+i],h);
		//height_map[(j*tile_map_size_x*6)+i]=h;	
		//return;
	}


}

void add_e3d_heightmap(int K, int D)
{
#ifdef	NEW_E3D_FORMAT
	float3 *T3;
	void *T;
	void* index_pointer;
	unsigned char *u8;
	unsigned short *u16;
	unsigned int *u32;
	float3 *TF;
	int vertex_no;
	int minx, miny, maxx, maxy;							
	int i, j, k, index, size;
	int start, idx, face_no;
	float x_pos, y_pos, z_pos;
	float min_x, min_y, max_x, max_y;
	void (*method)(float3 *T, float x_pos, float y_pos, float z_pos, int i, int j);
	
	
	method = D==1 ? method1 : (D==2)?method2:method3;

	vertex_no = objects_list[K]->e3d_data->vertex_no;

	vertex_no = objects_list[K]->e3d_data->vertex_no;

	T = objects_list[K]->e3d_data->vertex_data + get_vertex_offset(objects_list[K]->e3d_data->vertex_options);
	TF = malloc(vertex_no * sizeof(float3));
	for (i = 0; i < vertex_no; i++)
	{
		memcpy(TF, T, sizeof(float3));
		T += get_vertex_size(objects_list[K]->e3d_data->vertex_options);
	}

	x_pos = objects_list[K]->x_pos;
	y_pos = objects_list[K]->y_pos;
	z_pos = objects_list[K]->z_pos;
	min_x = 0;
	min_y = 0;
	max_x = 0;
	max_y = 0;

	// Check if we need to rotate the vertex
	if(objects_list[K]->x_rot!=0.0 || objects_list[K]->y_rot!=0.0 || objects_list[K]->z_rot!=0.0)
	{
		rotatehm(objects_list[K]->x_rot*(3.14159265/180), objects_list[K]->y_rot*(3.14159265/180), objects_list[K]->z_rot*(3.14159265/180), T, vertex_no);
	}

	u8 = (unsigned char*)objects_list[K]->e3d_data->indicies;
	u16 = (unsigned short*)objects_list[K]->e3d_data->indicies;
	u32 = (unsigned int*)objects_list[K]->e3d_data->indicies;

	// Calculating min and max x and y values of the object
	for (i = 0; i < vertex_no; i++)
	{
		if (TF[i].x < min_x) min_x = TF[i].x;
		if (TF[i].x > max_x) max_x = TF[i].x;
		if (TF[i].y < min_y) min_y = TF[i].y;
		if (TF[i].y > max_y) max_y = TF[i].y;
	}

	if (objects_list[K]->e3d_data->index_no <= 256) size = 1;
	else
	{
		if (objects_list[K]->e3d_data->index_no <= 256*256) size = 2;
		else size = 4;
	}

	face_no = 0;
	for (i = 0; i < objects_list[K]->e3d_data->material_no; i++)
	{
		face_no += objects_list[K]->e3d_data->materials[i].triangles_indicies_count / 3;
	}

	T3 = (float3*)malloc(face_no * 3 * sizeof(float3));

	if (have_vertex_buffers) index_pointer = 0;
	else index_pointer = objects_list[K]->e3d_data->indicies;

	index = 0;
	for (i = 0; i < objects_list[K]->e3d_data->material_no; i++)
	{
		start = objects_list[K]->e3d_data->materials[i].triangles_indicies_index - index_pointer;
		start /= size;
		for (j = 0; j < objects_list[K]->e3d_data->materials[i].triangles_indicies_count; j++)
		{
			if (size == 1) idx = u8[start+j];
			else
			{
				if (size == 2) idx = u16[start+j];
				else idx = u32[start+j];
			}
			T3[index].x = TF[idx].x;
			T3[index].y = TF[idx].y;
			T3[index].z = TF[idx].z;
			index++;
		}
	}
	// Calculating min and max positions on the heightmap
	minx = (x_pos + min_x) / 0.5f;
	miny = (y_pos + min_y) / 0.5f;
	maxx = (x_pos + max_x) / 0.5f + 1;
	maxy = (y_pos + max_y) / 0.5f + 1;

	for(i = minx; i < maxx; i++){
		for(j = miny; j< maxy; j++){
			for(k = 0; k < face_no * 3; k +=3)
			{
				method(&T3[k], x_pos, y_pos, z_pos, i, j);
			}
		}
	}
	free(T3);
#else	// NEW_E3D_FORMAT
	int face_no = objects_list[K]->e3d_data->face_no;
	float x_pos = objects_list[K]->x_pos, y_pos = objects_list[K]->y_pos, z_pos = objects_list[K]->z_pos;
	float min_x = 0, min_y = 0, max_x = 0, max_y = 0;
	e3d_array_vertex *T = objects_list[K]->e3d_data->array_vertex, *TT = NULL;
	int minx, miny, maxx, maxy;							
	int i, j, k;
	void (*method)(e3d_array_vertex *T, float x_pos, float y_pos, float z_pos, int i, int j);
	
	
	method = D==1 ? method1 : (D==2)?method2:method3;

	// Check if we need to rotate the vertex
	if(objects_list[K]->x_rot!=0.0 || objects_list[K]->y_rot!=0.0 || objects_list[K]->z_rot!=0.0)
	{
		TT = (e3d_array_vertex *)malloc(face_no*3*sizeof(e3d_array_vertex));
		memcpy(TT,T,face_no*3*sizeof(e3d_array_vertex));
		T = TT;
		rotatehm(objects_list[K]->x_rot*(3.14159265/180),objects_list[K]->y_rot*(3.14159265/180),objects_list[K]->z_rot*(3.14159265/180),T,face_no*3);
	}

	// Calculating min and max x and y values of the object
	for(k = 0; k < face_no*3; k++){
		if(T[k].x < min_x) min_x = T[k].x;
		if(T[k].x > max_x) max_x = T[k].x;
		if(T[k].y < min_y) min_y = T[k].y;
		if(T[k].y > max_y) max_y = T[k].y;
	}
		
	// Calculating min and max positions on the heightmap
	minx = (x_pos + min_x) / 0.5f;
	miny = (y_pos + min_y) / 0.5f;
	maxx = (x_pos + max_x) / 0.5f + 1;
	maxy = (y_pos + max_y) / 0.5f + 1;

	for(i = minx; i < maxx; i++){
		for(j = miny; j< maxy; j++){
			for(k = 0; k < face_no*3; k +=3){
				method(&T[k], x_pos, y_pos, z_pos, i, j);
			}
		}
	}
#endif	// NEW_E3D_FORMAT
#ifdef	NEW_E3D_FORMAT
	free(TF);
#else	// NEW_E3D_FORMAT
	// Freeing if there is rotation
	if(TT!=NULL)
		free(TT);
#endif	// NEW_3D_FORMAT
}