Ejemplo n.º 1
0
	void init(const HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver)
	{
		Scale = scale;

		const u32 mp = driver -> getMaximalPrimitiveCount();
		Width = hm.width();
		Height = hm.height();

		const u32 sw = mp / (6 * Height); // the width of each piece

		u32 i=0;
		for(u32 y0 = 0; y0 < Height; y0 += sw)
		{
			u16 y1 = y0 + sw;
			if (y1 >= Height)
				y1 = Height - 1; // the last one might be narrower
			addstrip(hm, cf, y0, y1, i);
			++i;
		}
		if (i<Mesh->getMeshBufferCount())
		{
			// clear the rest
			for (u32 j=i; j<Mesh->getMeshBufferCount(); ++j)
			{
				Mesh->getMeshBuffer(j)->drop();
			}
			Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i);
		}
		// set dirty flag to make sure that hardware copies of this
		// buffer are also updated, see IMesh::setHardwareMappingHint
		Mesh->setDirty();
		Mesh->recalculateBoundingBox();
	}
Ejemplo n.º 2
0
	void init(const HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver)
	{
		Scale = scale;

		const u32 mp = driver -> getMaximalPrimitiveCount();
		Width = hm.width();
		Height = hm.height();
		
		const u32 sw = mp / (6 * Height); // the width of each piece

		u32 i=0;
		for(u32 y0 = 0; y0 < Height; y0 += sw)
		{
			u16 y1 = y0 + sw;
			if (y1 >= Height)
				y1 = Height - 1; // the last one might be narrower
			addstrip(hm, cf, y0, y1, i);
			++i;
		}
		if (i<Mesh->getMeshBufferCount())
		{
			// clear the rest
			for (u32 j=i; j<Mesh->getMeshBufferCount(); ++j)
			{
				Mesh->getMeshBuffer(j)->drop();
			}
			Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i);
		}

		Mesh->recalculateBoundingBox();
	}
Ejemplo n.º 3
0
//! Creates/loads an animated mesh from the file.
IAnimatedMesh* CSMFMeshFileLoader::createMesh(io::IReadFile* file)
{
     // create empty mesh
     SMesh *mesh = new SMesh();

     // load file
     u16 version;
     u8  flags;
     s32 limbCount;
     s32 i;

     io::BinaryFile::read(file, version);
     io::BinaryFile::read(file, flags);
     io::BinaryFile::read(file, limbCount);

     // load mesh data
     core::matrix4 identity;
     for (i=0; i < limbCount; ++i)
          loadLimb(file, mesh, identity);

     // recalculate buffer bounding boxes
     for (i=0; i < (s32)mesh->getMeshBufferCount(); ++i)
          mesh->getMeshBuffer(i)->recalculateBoundingBox();

     mesh->recalculateBoundingBox();
     SAnimatedMesh *am = new SAnimatedMesh();
     am->addMesh(mesh);
     mesh->drop();
     am->recalculateBoundingBox();

     return am;
}
Ejemplo n.º 4
0
	void addstrip(const HeightMap &hm, colour_func cf, u16 y0, u16 y1, u32 bufNum)
	{
		SMeshBuffer *buf = 0;
		if (bufNum<Mesh->getMeshBufferCount())
		{
			buf = (SMeshBuffer*)Mesh->getMeshBuffer(bufNum);
		}
		else
		{
			// create new buffer
			buf = new SMeshBuffer();
			Mesh->addMeshBuffer(buf);
			// to simplify things we drop here but continue using buf
			buf->drop();
		}
		buf->Vertices.set_used((1 + y1 - y0) * Width);

		u32 i=0;
		for (u16 y = y0; y <= y1; ++y)
		{
			for (u16 x = 0; x < Width; ++x)
			{
				const f32 z = hm.get(x, y);
				const f32 xx = (f32)x/(f32)Width;
				const f32 yy = (f32)y/(f32)Height;

				S3DVertex& v = buf->Vertices[i++];
				v.Pos.set(x, Scale * z, y);
				v.Normal.set(hm.getnormal(x, y, Scale));
				v.Color=cf(xx, yy, z);
				v.TCoords.set(xx, yy);
			}
		}

		buf->Indices.set_used(6 * (Width - 1) * (y1 - y0));
		i=0;
		for(u16 y = y0; y < y1; ++y)
		{
			for(u16 x = 0; x < Width - 1; ++x)
			{
				const u16 n = (y-y0) * Width + x;
				buf->Indices[i]=n;
				buf->Indices[++i]=n + Width;
				buf->Indices[++i]=n + Width + 1;
				buf->Indices[++i]=n + Width + 1;
				buf->Indices[++i]=n + 1;
				buf->Indices[++i]=n;
				++i;
			}
		}

		buf->recalculateBoundingBox();
	}
Ejemplo n.º 5
0
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file)
{
	const long filesize = file->getSize();
	if (filesize < 6) // we need a header
		return 0;

	const u32 WORD_BUFFER_LENGTH = 512;

	SMesh* mesh = new SMesh();
	SMeshBuffer* meshBuffer = new SMeshBuffer();
	mesh->addMeshBuffer(meshBuffer);
	meshBuffer->drop();

	core::vector3df vertex[3];
	core::vector3df normal;

	c8 buffer[WORD_BUFFER_LENGTH];

	bool binary = false;
	file->read(buffer, 5);
	if (strncmp("solid", buffer, 5))
		binary = true;
	// read/skip header
	u32 binFaceCount = 0;
	if (binary)
	{
		file->seek(80);
		file->read(&binFaceCount, 4);
#ifdef __BIG_ENDIAN__
		binFaceCount = os::Byteswap::byteswap(binFaceCount);
#endif
	}
	else
		goNextLine(file);

	u16 attrib=0;
	core::stringc token;
	token.reserve(32);

	while (file->getPos() < filesize)
	{
		if (!binary)
		{
			if (getNextToken(file, token) != "facet")
			{
				if (token=="endsolid")
					break;
				mesh->drop();
				return 0;
			}
			if (getNextToken(file, token) != "normal")
			{
				mesh->drop();
				return 0;
			}
		}
		getNextVector(file, normal, binary);
		if (!binary)
		{
			if (getNextToken(file, token) != "outer")
			{
				mesh->drop();
				return 0;
			}
			if (getNextToken(file, token) != "loop")
			{
				mesh->drop();
				return 0;
			}
		}
		for (u32 i=0; i<3; ++i)
		{
			if (!binary)
			{
				if (getNextToken(file, token) != "vertex")
				{
					mesh->drop();
					return 0;
				}
			}
			getNextVector(file, vertex[i], binary);
		}
		if (!binary)
		{
			if (getNextToken(file, token) != "endloop")
			{
				mesh->drop();
				return 0;
			}
			if (getNextToken(file, token) != "endfacet")
			{
				mesh->drop();
				return 0;
			}
		}
		else
		{
			file->read(&attrib, 2);
#ifdef __BIG_ENDIAN__
			attrib = os::Byteswap::byteswap(attrib);
#endif
		}

		SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1));
		u32 vCount = mb->getVertexCount();
		video::SColor color(0xffffffff);
		if (attrib & 0x8000)
			color = video::A1R5G5B5toA8R8G8B8(attrib);
		if (normal==core::vector3df())
			normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal;
		mb->Vertices.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df()));
		mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df()));
		mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df()));
		mb->Indices.push_back(vCount);
		mb->Indices.push_back(vCount+1);
		mb->Indices.push_back(vCount+2);
	}	// end while (file->getPos() < filesize)
	mesh->getMeshBuffer(0)->recalculateBoundingBox();

	// Create the Animated mesh if there's anything in the mesh
	SAnimatedMesh* pAM = 0;
	if ( 0 != mesh->getMeshBufferCount() )
	{
		mesh->recalculateBoundingBox();
		pAM = new SAnimatedMesh();
		pAM->Type = EAMT_OBJ;
		pAM->addMesh(mesh);
		pAM->recalculateBoundingBox();
	}

	mesh->drop();

	return pAM;
}
Ejemplo n.º 6
0
    GLlink(ISceneNode *i_parent, ISceneManager *i_mgr, s32 i_id,
           const LinkInfo &i_li, BodyInfo_var i_binfo) :
        ISceneNode(i_parent, i_mgr, i_id),
        m_jointId(i_li.jointId) {
        setAutomaticCulling(scene::EAC_OFF);


        setPosition(vector3df( i_li.translation[0],
                               -i_li.translation[1],
                               i_li.translation[2]));
        Vector3 axis(i_li.rotation[0],
                     i_li.rotation[1],
                     i_li.rotation[2]);
        Matrix33 R;
        hrp::calcRodrigues(R, axis, i_li.rotation[3]);
        Vector3 rpy(rpyFromRot(R));
        //std::cout << "rpy:" << rpy << std::endl;
        setRotation(vector3df(-180/M_PI*rpy[0],
                              180/M_PI*rpy[1],
                              -180/M_PI*rpy[2]));

        m_axis << i_li.jointAxis[0], i_li.jointAxis[1], i_li.jointAxis[2];

        ShapeInfoSequence_var sis = i_binfo->shapes();
        AppearanceInfoSequence_var ais = i_binfo->appearances();
        MaterialInfoSequence_var mis = i_binfo->materials();
        TextureInfoSequence_var txs = i_binfo->textures();
        const TransformedShapeIndexSequence& tsis = i_li.shapeIndices;


        core::vector3df vertex;
        core::vector3df normal;

        for (unsigned int l=0; l<tsis.length(); l++) {
            SMesh* mesh = new SMesh();
            SMeshBuffer* meshBuffer = new SMeshBuffer();
            mesh->addMeshBuffer(meshBuffer);
            meshBuffer->drop();

            const TransformedShapeIndex &tsi = tsis[l];
            short index = tsi.shapeIndex;
            ShapeInfo& si = sis[index];
            const float *vertices = si.vertices.get_buffer();
            const LongSequence& triangles = si.triangles;
            const AppearanceInfo& ai = ais[si.appearanceIndex];
            const float *normals = ai.normals.get_buffer();
            //std::cout << "length of normals = " << ai.normals.length() << std::endl;
            const LongSequence& normalIndices = ai.normalIndices;
            //std::cout << "length of normalIndices = " << normalIndices.length() << std::endl;
            const int numTriangles = triangles.length() / 3;
            //std::cout << "numTriangles = " << numTriangles << std::endl;

            video::SColor color(0xffffffff);
            if (ai.colors.length()) {
                color.set(0xff,
                          0xff*ai.colors[0],
                          0xff*ai.colors[1],
                          0xff*ai.colors[2]);
            } else if (ai.materialIndex >= 0) {
                const MaterialInfo& mi = mis[ai.materialIndex];
                color.set(0xff,
                          0xff*mi.diffuseColor[0],
                          0xff*mi.diffuseColor[1],
                          0xff*mi.diffuseColor[2]);
            } else {
                std::cout << "no material" << std::endl;
            }


            SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1));
            u32 vCount = mb->getVertexCount();

            const DblArray12& tfm = tsi.transformMatrix;
            CMatrix4<f32> cmat;
            for (int i=0; i<3; i++) {
                for (int j=0; j<4; j++) {
                    cmat[j*4+i] = tfm[i*4+j];
                }
            }
            cmat[3] = cmat[7] = cmat[11] = 0.0;
            cmat[15] = 1.0;
            vector3df pos = cmat.getTranslation();
            pos.Y *= -1;
            vector3df rpy = cmat.getRotationDegrees();
            rpy.X *= -1;
            rpy.Z *= -1;
            vector3df scale = cmat.getScale();

            const float *textureCoordinate = NULL;
            if (ai.textureIndex >= 0) {
                textureCoordinate = ai.textureCoordinate.get_buffer();
                //std::cout << "length of textureCoordinate:" << ai.textureCoordinate.length() << std::endl;
                //std::cout << "length of vertices:" << si.vertices.length() << std::endl;

            }

            for(int j=0; j < numTriangles; ++j) {
                if (!ai.normalPerVertex) {
                    int p;
                    if (normalIndices.length() == 0) {
                        p = j*3;
                    } else {
                        p = normalIndices[j]*3;
                    }
                    if ( normals != NULL ) {
                        normal.X =  normals[p];
                        normal.Y = -normals[p+1]; //left-handed->right-handed
                        normal.Z =  normals[p+2];
                    } else {
                        normal.X = 0;
                        normal.Y = 0;
                        normal.Z = 1;
                    }
                }
                for(int k=0; k < 3; ++k) {
                    long orgVertexIndex = si.triangles[j * 3 + k];
                    if (ai.normalPerVertex) {
                        int p;
                        if (normalIndices.length()) {
                            p = normalIndices[j*3+k]*3;
                        } else {
                            p = orgVertexIndex*3;
                        }
                        normal.X =  normals[p];
                        normal.Y = -normals[p+1]; //left-handed -> right-handed
                        normal.Z =  normals[p+2];
                    }
                    int p = orgVertexIndex * 3;
                    vertex.X =  scale.X*vertices[p];
                    vertex.Y = -scale.Y*vertices[p+1]; // left-handed -> right-handed
                    vertex.Z =  scale.Z*vertices[p+2];
                    //std::cout << vertices[p] <<"," << vertices[p+1] << "," << vertices[p+2] << std::endl;
                    vector2df texc;
                    if (textureCoordinate) {

                        texc.X = textureCoordinate[ai.textureCoordIndices[j*3+k]*2];
                        texc.Y = textureCoordinate[ai.textureCoordIndices[j*3+k]*2+1];
                    }
                    // redundant vertices
                    mb->Vertices.push_back(video::S3DVertex(vertex,normal,color, texc));
                }
                mb->Indices.push_back(vCount);
                mb->Indices.push_back(vCount+2);
                mb->Indices.push_back(vCount+1);
                vCount += 3;
            }
            mesh->getMeshBuffer(0)->recalculateBoundingBox();

            // Create the Animated mesh if there's anything in the mesh
            SAnimatedMesh* pAM = 0;
            if ( 0 != mesh->getMeshBufferCount() )
            {
                mesh->recalculateBoundingBox();
                pAM = new SAnimatedMesh();
                pAM->Type = EAMT_OBJ;
                pAM->addMesh(mesh);
                pAM->recalculateBoundingBox();
            }

            mesh->drop();

            vector3df noscale(1,1,1);

            IMeshSceneNode *node
                = i_mgr->addMeshSceneNode(mesh, this, -1,
                                          pos,
                                          rpy,
                                          noscale);

            if (ai.textureIndex >= 0) {
                const TextureInfo& ti = txs[ai.textureIndex];
                //std::cout << "url:" << ti.url << std::endl;
                video::IVideoDriver* driver = i_mgr->getVideoDriver();
                const char *path = ti.url;
                SMaterial& mat = node->getMaterial(0);
                ITexture *texture = driver->getTexture(path);
                mat.setTexture( 0, texture);
            }

        }

        const SensorInfoSequence& sensors = i_li.sensors;
        for (unsigned int i=0; i<sensors.length(); i++) {
            const SensorInfo& si = sensors[i];
            std::string type(si.type);
            if (type == "Vision") {
                //std::cout << si.name << std::endl;
                ISceneNode *camera = i_mgr->addEmptySceneNode(this);
                camera->setName(si.name);
                camera->setPosition(vector3df( si.translation[0],
                                               -si.translation[1],
                                               si.translation[2]));
                Vector3 axis(si.rotation[0],
                             si.rotation[1],
                             si.rotation[2]);
                Matrix33 R;
                hrp::calcRodrigues(R, axis, si.rotation[3]);
                Vector3 rpy(rpyFromRot(R));
                camera->setRotation(vector3df(-180/M_PI*rpy[0],
                                              180/M_PI*rpy[1],
                                              -180/M_PI*rpy[2]));
                m_cameraInfos.push_back(new GLcamera(si, camera));
            }
        }
    }
Ejemplo n.º 7
0
/**Creates/loads an animated mesh from the file.
 \return Pointer to the created mesh. Returns 0 if loading failed.
 If you no longer need the mesh, you should call IAnimatedMesh::drop().
 See IReferenceCounted::drop() for more information.*/
IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file)
{
	if (!file)
		return 0;
	video::IVideoDriver* driver = SceneMgr->getVideoDriver();

	//Load stringlist
	StringList dmfRawFile;
	LoadFromFile(file, dmfRawFile);

	if (dmfRawFile.size()==0)
		return 0;

	SMesh * mesh = new SMesh();

	u32 i;

	dmfHeader header;

	//load header
	core::array<dmfMaterial> materiali;
	if (GetDMFHeader(dmfRawFile, header))
	{
		//let's set ambient light
		SceneMgr->setAmbientLight(header.dmfAmbient);

		//let's create the correct number of materials, vertices and faces
		dmfVert *verts=new dmfVert[header.numVertices];
		dmfFace *faces=new dmfFace[header.numFaces];

		//let's get the materials
#ifdef _IRR_DMF_DEBUG_
		os::Printer::log("Loading materials", core::stringc(header.numMaterials).c_str());
#endif
		GetDMFMaterials(dmfRawFile, materiali, header.numMaterials);

		//let's get vertices and faces
#ifdef _IRR_DMF_DEBUG_
		os::Printer::log("Loading geometry");
#endif
		GetDMFVerticesFaces(dmfRawFile, verts, faces);

		//create a meshbuffer for each material, then we'll remove empty ones
#ifdef _IRR_DMF_DEBUG_
		os::Printer::log("Creating meshbuffers.");
#endif
		for (i=0; i<header.numMaterials; i++)
		{
			//create a new SMeshBufferLightMap for each material
			SSkinMeshBuffer* buffer = new SSkinMeshBuffer();
			buffer->Material.MaterialType = video::EMT_LIGHTMAP_LIGHTING;
			buffer->Material.Wireframe = false;
			buffer->Material.Lighting = true;
			mesh->addMeshBuffer(buffer);
			buffer->drop();
		}

		// Build the mesh buffers
#ifdef _IRR_DMF_DEBUG_
		os::Printer::log("Adding geometry to mesh.");
#endif
		for (i = 0; i < header.numFaces; i++)
		{
#ifdef _IRR_DMF_DEBUG_
		os::Printer::log("Polygon with #vertices", core::stringc(faces[i].numVerts).c_str());
#endif
			if (faces[i].numVerts < 3)
				continue;

			const core::vector3df normal =
				core::triangle3df(verts[faces[i].firstVert].pos,
						verts[faces[i].firstVert+1].pos,
						verts[faces[i].firstVert+2].pos).getNormal().normalize();

			SSkinMeshBuffer* meshBuffer = (SSkinMeshBuffer*)mesh->getMeshBuffer(
					faces[i].materialID);

			const bool use2TCoords = meshBuffer->Vertices_2TCoords.size() ||
				materiali[faces[i].materialID].lightmapName.size();
			if (use2TCoords && meshBuffer->Vertices_Standard.size())
				meshBuffer->convertTo2TCoords();
			const u32 base = meshBuffer->Vertices_2TCoords.size()?meshBuffer->Vertices_2TCoords.size():meshBuffer->Vertices_Standard.size();

			// Add this face's verts
			if (use2TCoords)
			{
				// make sure we have the proper type set
				meshBuffer->VertexType=video::EVT_2TCOORDS;
				for (u32 v = 0; v < faces[i].numVerts; v++)
				{
					const dmfVert& vv = verts[faces[i].firstVert + v];
					video::S3DVertex2TCoords vert(vv.pos,
						normal, video::SColor(255,255,255,255), vv.tc, vv.lc);
					if (materiali[faces[i].materialID].textureBlend==4 &&
							SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
					{
						vert.TCoords.set(vv.tc.X,-vv.tc.Y);
					}
					meshBuffer->Vertices_2TCoords.push_back(vert);
				}
			}
			else
			{
				for (u32 v = 0; v < faces[i].numVerts; v++)
				{
					const dmfVert& vv = verts[faces[i].firstVert + v];
					video::S3DVertex vert(vv.pos,
						normal, video::SColor(255,255,255,255), vv.tc);
					if (materiali[faces[i].materialID].textureBlend==4 &&
							SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
					{
						vert.TCoords.set(vv.tc.X,-vv.tc.Y);
					}
					meshBuffer->Vertices_Standard.push_back(vert);
				}
			}

			// Now add the indices
			// This weird loop turns convex polygons into triangle strips.
			// I do it this way instead of a simple fan because it usually
			// looks a lot better in wireframe, for example.
			u32 h = faces[i].numVerts - 1, l = 0, c; // High, Low, Center
			for (u32 v = 0; v < faces[i].numVerts - 2; v++)
			{
				if (v & 1) // odd
					c = h - 1;
				else // even
					c = l + 1;

				meshBuffer->Indices.push_back(base + h);
				meshBuffer->Indices.push_back(base + l);
				meshBuffer->Indices.push_back(base + c);

				if (v & 1) // odd
					h--;
				else // even
					l++;
			}
		}

		delete [] verts;
		delete [] faces;
	}

	// delete all buffers without geometry in it.
#ifdef _IRR_DMF_DEBUG_
	os::Printer::log("Cleaning meshbuffers.");
#endif
	i = 0;
	while(i < mesh->MeshBuffers.size())
	{
		if (mesh->MeshBuffers[i]->getVertexCount() == 0 ||
			mesh->MeshBuffers[i]->getIndexCount() == 0)
		{
			// Meshbuffer is empty -- drop it
			mesh->MeshBuffers[i]->drop();
			mesh->MeshBuffers.erase(i);
			materiali.erase(i);
		}
		else
		{
			i++;
		}
	}


	{
		//load textures and lightmaps in materials.
		//don't worry if you receive a could not load texture, cause if you don't need
		//a particular material in your scene it will be loaded and then destroyed.
#ifdef _IRR_DMF_DEBUG_
		os::Printer::log("Loading textures.");
#endif
		const bool use_mat_dirs=!SceneMgr->getParameters()->getAttributeAsBool(DMF_IGNORE_MATERIALS_DIRS);

		core::stringc path;
		if ( SceneMgr->getParameters()->existsAttribute(DMF_TEXTURE_PATH) )
			path = SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH);
		else
			path = FileSystem->getFileDir(file->getFileName());
		path += ('/');

		for (i=0; i<mesh->getMeshBufferCount(); i++)
		{
			//texture and lightmap
			video::ITexture *tex = 0;
			video::ITexture *lig = 0;

			//current buffer to apply material
			video::SMaterial& mat = mesh->getMeshBuffer(i)->getMaterial();

			//Primary texture is normal
			if (materiali[i].textureFlag==0)
			{
				if (materiali[i].textureBlend==4)
					driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
				findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].textureName);
				tex = driver->getTexture(materiali[i].textureName);
			}
			//Primary texture is just a colour
			else if(materiali[i].textureFlag==1)
			{
				video::SColor color(axtoi(materiali[i].textureName.c_str()));

				//just for compatibility with older Irrlicht versions
				//to support transparent materials
				if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
					driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);

				video::IImage *immagine= driver->createImage(video::ECF_A8R8G8B8,
					core::dimension2d<u32>(8,8));
				immagine->fill(color);
				tex = driver->addTexture("", immagine);
				immagine->drop();

				//to support transparent materials
				if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
				{
					mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
					mat.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f);
				}
			}

			//Lightmap is present
			if (materiali[i].lightmapFlag == 0)
			{
				findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].lightmapName);
				lig = driver->getTexture(materiali[i].lightmapName);
			}
			else //no lightmap
			{
				mat.MaterialType = video::EMT_SOLID;
				const f32 mult = 100.0f - header.dmfShadow;
				mat.AmbientColor=header.dmfAmbient.getInterpolated(video::SColor(255,0,0,0),mult/100.f);
			}

			if (materiali[i].textureBlend==4)
			{
				mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
				mat.MaterialTypeParam =
					SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF);
			}

			//if texture is present mirror vertically owing to DeleD representation
			if (tex && header.dmfVersion<1.1)
			{
				const core::dimension2d<u32> texsize = tex->getSize();
				void* pp = tex->lock();
				if (pp)
				{
					const video::ECOLOR_FORMAT format = tex->getColorFormat();
					if (format == video::ECF_A1R5G5B5)
					{
						s16* p = (s16*)pp;
						s16 tmp=0;
						for (u32 x=0; x<texsize.Width; x++)
							for (u32 y=0; y<texsize.Height/2; y++)
							{
								tmp=p[y*texsize.Width + x];
								p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
								p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
							}
					}
					else
					if (format == video::ECF_A8R8G8B8)
					{
						s32* p = (s32*)pp;
						s32 tmp=0;
						for (u32 x=0; x<texsize.Width; x++)
							for (u32 y=0; y<texsize.Height/2; y++)
							{
								tmp=p[y*texsize.Width + x];
								p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
								p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
							}
					}
				}
				tex->unlock();
				tex->regenerateMipMapLevels();
			}

			//if lightmap is present mirror vertically owing to DeleD rapresentation
			if (lig && header.dmfVersion<1.1)
			{
				const core::dimension2d<u32> ligsize=lig->getSize();
				void* pp = lig->lock();
				if (pp)
				{
					video::ECOLOR_FORMAT format = lig->getColorFormat();
					if (format == video::ECF_A1R5G5B5)
					{
						s16* p = (s16*)pp;
						s16 tmp=0;
						for (u32 x=0; x<ligsize.Width; x++)
						{
							for (u32 y=0; y<ligsize.Height/2; y++)
							{
								tmp=p[y*ligsize.Width + x];
								p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
								p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
							}
						}
					}
					else if (format == video::ECF_A8R8G8B8)
					{
						s32* p = (s32*)pp;
						s32 tmp=0;
						for (u32 x=0; x<ligsize.Width; x++)
						{
							for (u32 y=0; y<ligsize.Height/2; y++)
							{
								tmp=p[y*ligsize.Width + x];
								p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
								p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
							}
						}
					}
				}
				lig->unlock();
				lig->regenerateMipMapLevels();
			}

			mat.setTexture(0, tex);
			mat.setTexture(1, lig);
		}
	}

	// create bounding box
	for (i = 0; i < mesh->MeshBuffers.size(); ++i)
	{
		mesh->MeshBuffers[i]->recalculateBoundingBox();
	}
	mesh->recalculateBoundingBox();

	// Set up an animated mesh to hold the mesh
	SAnimatedMesh* AMesh = new SAnimatedMesh();
	AMesh->Type = EAMT_UNKNOWN;
	AMesh->addMesh(mesh);
	AMesh->recalculateBoundingBox();
	mesh->drop();

	return AMesh;
}
IAnimatedMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture,
        video::IImage* heightmap, const core::dimension2d<f32>& stretchSize,
        f32 maxHeight, video::IVideoDriver* driver,
        const core::dimension2d<s32> maxVtxBlockSize,
        bool debugBorders)
{
    u32 tm = os::Timer::getRealTime()/1000;

    if (!texture || !heightmap)
        return 0;

    video::SMaterial material;
    c8 textureName[64];
    c8 tmp[255];


    // debug border
    s32 borderSkip = debugBorders ? 0 : 1;

    video::S3DVertex vtx;
    vtx.Color.set(255,255,255,255);

    SMesh* mesh = new SMesh();

    core::dimension2d<s32> hMapSize= heightmap->getDimension();
    core::dimension2d<s32> tMapSize= texture->getDimension();
    core::position2d<f32> thRel((f32)tMapSize.Width / (s32)hMapSize.Width, (f32)tMapSize.Height / (s32)hMapSize.Height);
    core::position2d<s32> processed(0,0);

    while (processed.Y<hMapSize.Height)
    {
        while(processed.X<hMapSize.Width)
        {
            core::dimension2d<s32> blockSize = maxVtxBlockSize;
            if (processed.X + blockSize.Width > hMapSize.Width)
                blockSize.Width = hMapSize.Width - processed.X;
            if (processed.Y + blockSize.Height > hMapSize.Height)
                blockSize.Height = hMapSize.Height - processed.Y;

            SMeshBuffer* buffer = new SMeshBuffer();
            s32 x,y;

            // add vertices of vertex block
            for (y=0; y<blockSize.Height; ++y)
                for (x=0; x<blockSize.Width; ++x)
                {
                    video::SColor clr = heightmap->getPixel(x+processed.X, y+processed.Y);
                    f32 height = ((clr.getRed() + clr.getGreen() + clr.getBlue()) / 3.0f)/255.0f * maxHeight;

                    vtx.Pos.set((f32)(x+processed.X) * stretchSize.Width,
                                height, (f32)(y+processed.Y) * stretchSize.Height);

                    vtx.TCoords.set((f32)(x+0.5f) / ((f32)blockSize.Width),
                                    (f32)(y+0.5f) / ((f32)blockSize.Height));

                    buffer->Vertices.push_back(vtx);
                }

            // add indices of vertex block
            for (y=0; y<blockSize.Height-1; ++y)
                for (x=0; x<blockSize.Width-1; ++x)
                {
                    s32 c = (y*blockSize.Width) + x;

                    buffer->Indices.push_back(c);
                    buffer->Indices.push_back(c + blockSize.Width);
                    buffer->Indices.push_back(c + 1);

                    buffer->Indices.push_back(c + 1);
                    buffer->Indices.push_back(c + blockSize.Width);
                    buffer->Indices.push_back(c + 1 + blockSize.Width);
                }

            // recalculate normals
            for (s32 i=0; i<(s32)buffer->Indices.size(); i+=3)
            {
                core::plane3d<f32> p(
                    buffer->Vertices[buffer->Indices[i+0]].Pos,
                    buffer->Vertices[buffer->Indices[i+1]].Pos,
                    buffer->Vertices[buffer->Indices[i+2]].Pos);
                p.Normal.normalize();

                buffer->Vertices[buffer->Indices[i+0]].Normal = p.Normal;
                buffer->Vertices[buffer->Indices[i+1]].Normal = p.Normal;
                buffer->Vertices[buffer->Indices[i+2]].Normal = p.Normal;
            }

            if (buffer->Vertices.size())
            {
                // create texture for this block
                video::IImage* img = new video::CImage(texture,
                                                       core::position2d<s32>((s32)(processed.X*thRel.X), (s32)(processed.Y*thRel.Y)),
                                                       core::dimension2d<s32>((s32)(blockSize.Width*thRel.X), (s32)(blockSize.Height*thRel.Y)));

                sprintf(textureName, "terrain%d_%d", tm, mesh->getMeshBufferCount());

                material.Texture1 = driver->addTexture(textureName, img);

                if (material.Texture1)
                {
                    sprintf(tmp, "Generated terrain texture (%dx%d): %s",
                            material.Texture1->getSize().Width,
                            material.Texture1->getSize().Height,
                            textureName);
                    os::Printer::log(tmp);
                }
                else
                    os::Printer::log("Could not create terrain texture.", textureName, ELL_ERROR);

                buffer->Material = material;
                img->drop();
            }

            buffer->recalculateBoundingBox();
            mesh->addMeshBuffer(buffer);
            buffer->drop();

            // keep on processing
            processed.X += maxVtxBlockSize.Width - borderSkip;
        }

        // keep on processing
        processed.X = 0;
        processed.Y += maxVtxBlockSize.Height - borderSkip;
    }

    SAnimatedMesh* animatedMesh = new SAnimatedMesh();
    mesh->recalculateBoundingBox();
    animatedMesh->addMesh(mesh);
    animatedMesh->recalculateBoundingBox();

    mesh->drop();

    return animatedMesh;
}