
extern "C" 
{

//------------------------------------------------------------------------------------
// irr::scene::IMeshBuffer wrappers
//------------------------------------------------------------------------------------

	void IrrScene_IMeshBuffer_fillS3DVertexVerticesPtrs(IMeshBuffer* mb,f32* pos,f32* normals,f32* tcoords,f32* colors,bool bSwap)
	{
		if (mb) {			
			if (mb->getVertexType()==EVT_STANDARD) {
				s32 vertCnt=mb->getVertexCount();
				for (int i=0; i<vertCnt; i++) {
					pos[(i*3)]=((S3DVertex*)mb->getVertices())[i].Pos.X;
					pos[(i*3)+1]=((S3DVertex*)mb->getVertices())[i].Pos.Y;
					if (bSwap) {
						pos[(i*3)+2]=-((S3DVertex*)mb->getVertices())[i].Pos.Z;
					} else {
						pos[(i*3)+2]=((S3DVertex*)mb->getVertices())[i].Pos.Z;
					}
									
					normals[(i*3)]=((S3DVertex*)mb->getVertices())[i].Normal.X;
					normals[(i*3)+1]=((S3DVertex*)mb->getVertices())[i].Normal.Y;
					normals[(i*3)+2]=((S3DVertex*)mb->getVertices())[i].Normal.Z;
				
					tcoords[(i*2)]=((S3DVertex*)mb->getVertices())[i].TCoords.X;
					tcoords[(i*2)+1]=((S3DVertex*)mb->getVertices())[i].TCoords.Y;
				
					colors[(i*4)]=SColorf(((S3DVertex*)mb->getVertices())[i].Color).r;
					colors[(i*4)+1]=SColorf(((S3DVertex*)mb->getVertices())[i].Color).g;
					colors[(i*4)+2]=SColorf(((S3DVertex*)mb->getVertices())[i].Color).b;
					colors[(i*4)+3]=SColorf(((S3DVertex*)mb->getVertices())[i].Color).a;
				}	
			}
		}
	}

	void IrrScene_IMeshBuffer_fillS3DVertex2TCoordsVerticesPtrs(IMeshBuffer* mb,f32* pos,f32* normals,f32* tcoords,f32* colors,f32* tcoords2,bool bSwap)
	{
		if (mb) {			
			if (mb->getVertexType()==EVT_2TCOORDS) {
				s32 vertCnt=mb->getVertexCount();
				for (int i=0; i<vertCnt; i++) {
					pos[(i*3)]=((S3DVertex2TCoords*)mb->getVertices())[i].Pos.X;
					pos[(i*3)+1]=((S3DVertex2TCoords*)mb->getVertices())[i].Pos.Y;
					if (bSwap) {
						pos[(i*3)+2]=-((S3DVertex2TCoords*)mb->getVertices())[i].Pos.Z;
					} else {
						pos[(i*3)+2]=((S3DVertex2TCoords*)mb->getVertices())[i].Pos.Z;
					}
									
					normals[(i*3)]=((S3DVertex2TCoords*)mb->getVertices())[i].Normal.X;
					normals[(i*3)+1]=((S3DVertex2TCoords*)mb->getVertices())[i].Normal.Y;
					normals[(i*3)+2]=((S3DVertex2TCoords*)mb->getVertices())[i].Normal.Z;
				
					tcoords[(i*2)]=((S3DVertex2TCoords*)mb->getVertices())[i].TCoords.X;
					tcoords[(i*2)+1]=((S3DVertex2TCoords*)mb->getVertices())[i].TCoords.Y;
	
					tcoords2[(i*2)]=((S3DVertex2TCoords*)mb->getVertices())[i].TCoords2.X;
					tcoords2[(i*2)+1]=((S3DVertex2TCoords*)mb->getVertices())[i].TCoords2.Y;
				
					colors[(i*4)]=SColorf(((S3DVertex2TCoords*)mb->getVertices())[i].Color).r;
					colors[(i*4)+1]=SColorf(((S3DVertex2TCoords*)mb->getVertices())[i].Color).g;
					colors[(i*4)+2]=SColorf(((S3DVertex2TCoords*)mb->getVertices())[i].Color).b;
					colors[(i*4)+3]=SColorf(((S3DVertex2TCoords*)mb->getVertices())[i].Color).a;
				}	
			}
		}
	}

	void IrrScene_IMeshBuffer_fillS3DVertexTangentsVerticesPtrs(IMeshBuffer* mb,f32* pos,f32* normals,f32* tcoords,f32* colors,f32* tangents,f32* binormals,bool bSwap)
	{
		if (mb) {			
			if (mb->getVertexType()==EVT_TANGENTS) {
				s32 vertCnt=mb->getVertexCount();
				for (int i=0; i<vertCnt; i++) {
					pos[(i*3)]=((S3DVertexTangents*)mb->getVertices())[i].Pos.X;
					pos[(i*3)+1]=((S3DVertexTangents*)mb->getVertices())[i].Pos.Y;
					if (bSwap) {
						pos[(i*3)+2]=-((S3DVertexTangents*)mb->getVertices())[i].Pos.Z;
					} else {
						pos[(i*3)+2]=((S3DVertexTangents*)mb->getVertices())[i].Pos.Z;
					}
									
					normals[(i*3)]=((S3DVertexTangents*)mb->getVertices())[i].Normal.X;
					normals[(i*3)+1]=((S3DVertexTangents*)mb->getVertices())[i].Normal.Y;
					normals[(i*3)+2]=((S3DVertexTangents*)mb->getVertices())[i].Normal.Z;
				
					tcoords[(i*2)]=((S3DVertexTangents*)mb->getVertices())[i].TCoords.X;
					tcoords[(i*2)+1]=((S3DVertexTangents*)mb->getVertices())[i].TCoords.Y;

					tangents[(i*3)]=((S3DVertexTangents*)mb->getVertices())[i].Tangent.X;
					tangents[(i*3)+1]=((S3DVertexTangents*)mb->getVertices())[i].Tangent.Y;
					tangents[(i*3)+2]=((S3DVertexTangents*)mb->getVertices())[i].Tangent.Z;
					
					binormals[(i*3)]=((S3DVertexTangents*)mb->getVertices())[i].Binormal.X;
					binormals[(i*3)+1]=((S3DVertexTangents*)mb->getVertices())[i].Binormal.Y;
					binormals[(i*3)+2]=((S3DVertexTangents*)mb->getVertices())[i].Binormal.Z;

					colors[(i*4)]=SColorf(((S3DVertexTangents*)mb->getVertices())[i].Color).r;
					colors[(i*4)+1]=SColorf(((S3DVertexTangents*)mb->getVertices())[i].Color).g;
					colors[(i*4)+2]=SColorf(((S3DVertexTangents*)mb->getVertices())[i].Color).b;
					colors[(i*4)+3]=SColorf(((S3DVertexTangents*)mb->getVertices())[i].Color).a;
				}	
			}
		}
	}

	void IrrScene_IMeshBuffer_fillIndicesPtr(IMeshBuffer* mb,u16* indicies,bool bSwap)
	{
		if (mb) {
			s32 idxCnt=mb->getIndexCount();
			for (int i=0; i<(idxCnt/3); i++) {
				
				if (bSwap) {
					indicies[(i*3)+2]=mb->getIndices()[i*3];
					indicies[(i*3)+1]=mb->getIndices()[(i*3)+1];
					indicies[i*3]=mb->getIndices()[(i*3)+2];
				} else {
					indicies[i*3]=mb->getIndices()[i*3];
					indicies[(i*3)+1]=mb->getIndices()[(i*3)+1];
					indicies[(i*3)+2]=mb->getIndices()[(i*3)+2];
				}

			}
		}
	}

	// do not delete
	aabbox3d<f32>* IrrScene_IMeshBuffer_getBoundingBox(IMeshBuffer* mb)
	{
		if (mb)
			return new aabbox3d<f32>(mb->getBoundingBox());
		else return 0;
	}
	
	u32 IrrScene_IMeshBuffer_getIndexCount(IMeshBuffer* mb)
	{
		if (mb)
			return mb->getIndexCount();
		else return 0;
	}
	
	u16* IrrScene_IMeshBuffer_getIndices(IMeshBuffer* mb)
	{
		if (mb) {
			return mb->getIndices();
		} else return 0;
	}
	
	// do not delete
	SMaterial* IrrScene_IMeshBuffer_getMaterial(IMeshBuffer* mb)
	{
		if (mb)
			return &mb->getMaterial();
		else return 0;
	}
	
	u32 IrrScene_IMeshBuffer_getVertexCount(IMeshBuffer* mb)
	{
		if (mb)
			return mb->getVertexCount();
		else return 0;
	}
	
	// returns a pointer to a S3DVertex array
	u32 IrrScene_IMeshBuffer_getVertices(IMeshBuffer* mb, u32** outPtrs)
	{
		if (mb) {
			s32 size = mb->getVertexCount();
			
			Irr_ptrarray_allocate(outPtrs,size);			

			S3DVertex* verts = (S3DVertex*)mb->getVertices();

			for (int i=0; i<size; i++) {	
				((u32*)*outPtrs)[i]=(u32)&(verts[i]);
			}

			return size;
		} else return 0;
	}
	
	s32 IrrScene_IMeshBuffer_getVertexType(IMeshBuffer* mb)
	{
		if (mb)
			return mb->getVertexType();
		else return -1;
	}
	
	// do not delete
	S3DVertex* IrrScene_IMeshBuffer_getVertex(IMeshBuffer* mb,s32 idx)
	{
		if (mb)
			return &((S3DVertex*)mb->getVertices())[idx];
		else return 0;
	}
	
	void IrrScene_IMeshBuffer_setBoundingBox(IMeshBuffer* mb,const core::aabbox3df& box)
	{
		if (mb)
			mb->setBoundingBox(box);
	}

	bool IrrScene_IMeshBuffer_drop(IMeshBuffer* unk)
	{
		if (unk)
			return unk->drop();
		else return 0;
	}
	
	const c8* IrrScene_IMeshBuffer_getDebugName(IMeshBuffer* unk)
	{
		if (unk)
			return unk->getDebugName();
		else return "";
	}
	
	void IrrScene_IMeshBuffer_grab(IMeshBuffer* unk)
	{
		if (unk)
			unk->grab();
	}

	void IrrScene_IMeshBuffer_appendFromOther(IMeshBuffer* mb,const IMeshBuffer* const other) 
	{
		if (mb) {
			mb->append(other);
		}
	}	

	void IrrScene_IMeshBuffer_append_S3DVertex(IMeshBuffer* mb,S3DVertex** vertices, u32 numVertices, const u16* const indices, u32 numIndices)
	{
		if (mb) {
			array<S3DVertex> vertices_array;
			for (int i=0; i<numVertices; i++) {	
				vertices_array.push_back(*vertices[i]);
			}
		
			mb->append(vertices_array.const_pointer(), numVertices, indices, numIndices);
		}
	}

	void IrrScene_IMeshBuffer_append_S3DVertexTangents(IMeshBuffer* mb,S3DVertexTangents** vertices, u32 numVertices, const u16* const indices, u32 numIndices)
	{
		if (mb) {
			array<S3DVertexTangents> vertices_array;
			for (int i=0; i<numVertices; i++) {	
				vertices_array.push_back(*vertices[i]);
			}
		
			mb->append(vertices_array.const_pointer(), numVertices, indices, numIndices);
		}
	}			
	
	void IrrScene_IMeshBuffer_append_S3DVertex2TCoords(IMeshBuffer* mb,S3DVertex2TCoords** vertices, u32 numVertices, const u16* const indices, u32 numIndices)
	{
		if (mb) {
			array<S3DVertex2TCoords> vertices_array;
			for (int i=0; i<numVertices; i++) {	
				vertices_array.push_back(*vertices[i]);
			}
		
			mb->append(vertices_array.const_pointer(), numVertices, indices, numIndices);
		}
	}		
	
	void IrrScene_IMeshBuffer_append(IMeshBuffer* mb,void** vertices, u32 numVertices, const u16* const indices, u32 numIndices)
	{
		if (mb) {
			if (mb->getVertexType()==EVT_STANDARD) {
				IrrScene_IMeshBuffer_append_S3DVertex(mb,(S3DVertex**)vertices, numVertices, indices, numIndices);
			} else if (mb->getVertexType()==EVT_TANGENTS) {
				IrrScene_IMeshBuffer_append_S3DVertexTangents(mb, (S3DVertexTangents**)vertices, numVertices, indices, numIndices);
			} else if (mb->getVertexType()==EVT_2TCOORDS) {
				IrrScene_IMeshBuffer_append_S3DVertex2TCoords(mb, (S3DVertex2TCoords**)vertices, numVertices, indices, numIndices);
			}
		}
	}

	void IrrScene_IMeshBuffer_recalculateBoundingBox(IMeshBuffer* mb)
	{
		if (mb)
			mb->recalculateBoundingBox();
	}
	
	s32 IrrScene_IMeshBuffer_getIndexType(IMeshBuffer* mb) // returns E_INDEX_TYPE
	{
		if (mb)
			return mb->getIndexType();
		else return -1;
	}
	
	vector3df* IrrScene_IMeshBuffer_getPosition(IMeshBuffer* mb, u32 i)
	{
		if (mb)
			return new vector3df(mb->getPosition(i));
		else return 0;
	}
	
	vector3df* IrrScene_IMeshBuffer_getNormal(IMeshBuffer* mb, u32 i)
	{
		if (mb)
			return new vector3df(mb->getNormal(i));
		else return 0;
	}

	vector2df* IrrScene_IMeshBuffer_getTCoords(IMeshBuffer* mb, u32 i)
	{
		if (mb)
			return new vector2df(mb->getTCoords(i));
		else return 0;
	}

	s32 IrrScene_IMeshBuffer_getHardwareMappingHint_Vertex(IMeshBuffer* mb) // return E_HARDWARE_MAPPING
	{
		if (mb)
			return mb->getHardwareMappingHint_Vertex();
		else return -1;
	}
	
	s32 IrrScene_IMeshBuffer_getHardwareMappingHint_Index(IMeshBuffer* mb) // returns E_HARDWARE_MAPPING
	{
		if (mb)
			return mb->getHardwareMappingHint_Index();
		else return -1;
	}
	
	void IrrScene_IMeshBuffer_setHardwareMappingHint(IMeshBuffer* mb, E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer = EBT_VERTEX_AND_INDEX)
	{
		if (mb)
			mb->setHardwareMappingHint(newMappingHint, buffer);
	}
	
	void IrrScene_IMeshBuffer_setDirty(IMeshBuffer* mb, E_BUFFER_TYPE buffer = EBT_VERTEX_AND_INDEX)
	{
		if (mb)
			mb->setDirty(buffer);
	}
	
	u32 IrrScene_IMeshBuffer_getChangedID_Vertex(IMeshBuffer* mb)
	{
		if (mb)
			return mb->getChangedID_Vertex();
		else return 0;
	}
	
	u32 IrrScene_IMeshBuffer_getChangedID_Index(IMeshBuffer* mb)
	{
		if (mb)
			return mb->getChangedID_Index();
		else return 0;
	}		
}
