Exemplo n.º 1
0
// Generate normals for polygon meshes
void IndexedGeometry::createIndexedFaceSet()
{
	if (_coords.empty())
		throw std::runtime_error("No coordinates given.");

	if (_coordIndex.empty())
		throw std::runtime_error("No coordinate index given.");

	MeshPtr mesh = MeshManager::getSingleton().createManual(_name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	SubMesh *sub = mesh->createSubMesh();

	bool hasTextureCoordinates = !_texCoords.empty();
	bool hasPointColors = !_colors.empty() && _colorPerVertex;
	bool hasPointNormals = !_normals.empty() && _normalPerVertex;
	bool hasCellColors = !_colors.empty() && !hasPointColors;
	bool hasCellNormals = !_normals.empty() && !hasPointNormals;
	bool calcPointNormals = _normals.empty() && _normalPerVertex;

	std::vector<face> faces;
	face f;
	for (std::vector<int>::const_iterator I=_coordIndex.begin(); I !=_coordIndex.end(); ++I) {
		if (*I == -1) {
			faces.resize(faces.size()+1);
			faces.back().indices.swap(f.indices);
		} else
			f.indices.push_back(I - _coordIndex.begin());
	}
	if (!f.indices.empty()) {
		faces.resize(faces.size()+1);
		faces.back().indices.swap(f.indices);
	}


	std::vector<vertex> vertices;
	std::vector<triangle> triangles;


	VertMap vertexMap;

	// triangulate and expand vertices
	for (std::vector<face>::const_iterator f=faces.begin(), e=faces.end(); f!=e; ++f) {
		int faceNr = f - faces.begin();
		int triVertNr = 0;
		int triVerts[2] = { -1, -1 };
		for (std::vector<int>::const_iterator i = f->indices.begin(), e=f->indices.end(); i!=e; ++i, ++triVertNr) {
			int triVertNr = i - f->indices.begin();
			int index = *i;

			vertex vert;

			// get full indices for vertex data
			vert.pos = _coordIndex[index];
			vert.normal = !_normals.empty() ? getIndex(_coordIndex, _normalIndex,
				_normalPerVertex, faceNr, index) : 0;
			vert.colour = !_colors.empty() ? getIndex(_coordIndex, _colorIndex,
				_colorPerVertex, faceNr, index) : 0;
			vert.tc = hasTextureCoordinates ? getIndex(_coordIndex, _texCoordIndex,
				true, faceNr, index) : 0;

			// avoid duplication
			//int nvert = vertexMap.size();
			//int &vpos = vertexMap[vert];
			//if (nvert != vertexMap.size()) {
				int vpos = vertices.size();
				vertices.push_back(vert);
			//}

			// emit triangle (maybe)
			if (triVertNr == 0)
				triVerts[0] = vpos;
			else if (triVertNr == 1)
				triVerts[1] = vpos;
			else {
				triangle t;
				t.vertices[0] = triVerts[0];
				t.vertices[1] = triVerts[1];
				t.vertices[2] = vpos;

				if (!_ccw)
					std::swap(t.vertices[1], t.vertices[2]);

				triangles.push_back(t);

				triVerts[1] = vpos;
			}
		}
	}
	
	// createOgreMesh
	int nvertices = vertices.size();
	int nfaces = triangles.size();

	VertexData* vertexData = new VertexData();
	sub->vertexData = vertexData;

	IndexData* indexData = sub->indexData;
	VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
	size_t currOffset = 0;
	
	// positions
	vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
	currOffset += VertexElement::getTypeSize(VET_FLOAT3);

	if (hasPointNormals)
	{
		// normals
		vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL);
		currOffset += VertexElement::getTypeSize(VET_FLOAT3);

	}
	// two dimensional texture coordinates
	if (hasTextureCoordinates)
	{
		vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
		currOffset += VertexElement::getTypeSize(VET_FLOAT2);
	}

	std::cout << std::endl;

	// allocate index buffer
	indexData->indexCount = nfaces * 3;
	indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer;
	unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD));

	std::cout << triangles.size() << ": ";
	for(std::vector<triangle>::const_iterator T = triangles.begin(); T != triangles.end(); T++)
	{
		const triangle &t = (*T);
		*pIndices++ = t.vertices[0];
		*pIndices++ = t.vertices[1];
		*pIndices++ = t.vertices[2];
		std::cout << t.vertices[0] << " " << t.vertices[1] << " "  << t.vertices[2] << " ";
	}
	std::cout << std::endl;

	// allocate the vertex buffer
	vertexData->vertexCount = nvertices;
	HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	VertexBufferBinding* binding = vertexData->vertexBufferBinding;
	binding->setBinding(0, vBuf);
	float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD));

	AxisAlignedBox aabox;
	std::cout << vertices.size() << ": ";
	for(std::vector<vertex>::const_iterator V = vertices.begin(); V != vertices.end(); V++)
	{

		const vertex &v = (*V);
		SFVec3f pos = _coords.at(v.pos);
		*pVertex++ = pos.x;
		*pVertex++ = pos.y;
		*pVertex++ = pos.z;
		aabox.merge(Vector3(pos.x, pos.y, pos.z));
		std::cout << pos.x << " " << pos.y << " "  << pos.z << " " << std::endl;
		//std::cout << v.pos << " ";
		if (hasPointNormals)
		{
			const SFVec3f normal = _normals.at(v.normal);
			*pVertex++ = normal.x;
			*pVertex++ = normal.y;
			*pVertex++ = normal.z;
		}
	}

std::cout << std::endl;
	// Unlock
	vBuf->unlock();
	iBuf->unlock();

	sub->useSharedVertices = false;

	// the original code was missing this line:
	mesh->_setBounds(aabox);
	mesh->_setBoundingSphereRadius((aabox.getMaximum()-aabox.getMinimum()).length()/2.0);
	// this line makes clear the mesh is loaded (avoids memory leaks)
	mesh->load();

}
Exemplo n.º 2
0
FlexObj::FlexObj(node_t *nds, int numtexcoords, Vector3* texcoords, int numtriangles, int* triangles, int numsubmeshes, int* subtexindex, int* subtriindex, char* texname, char* name, int* subisback, char* backtexname, char* transtexname)
{
	unsigned int i;
	int j;
	triangleCount = numtriangles;
	/*
	//okay, we munch a bit the data to optimize submesh count
	Vector3* texcoords=(Vector3*)malloc(sizeof(Vector3)*numtexcoords);
	int* triangles=(int*)malloc(sizeof(int)*3*numtriangles);
	int numsubmeshes=3;
	int subtexindex[4];
	int subtriindex[4];
	int subisback[3]={0,1,2};
	int numtex[3]={0,0,0};
	int numtri[3]={0,0,0};
	int postex[3]={0,0,0};
	int postri[3]={0,0,0};
	for (j=0; j<onumsubmeshes; j++)
	{
		int type=0;
// 			if (j<numsubmeshes-1)
		{
			type=osubisback[j+1];
		}
		numtex[type]+=osubtexindex[j+1]-osubtexindex[j];
		numtri[type]+=osubtriindex[j+1]-osubtriindex[j];
	}
	postex[0]=0; postex[1]=numtex[0]; postex[2]=numtex[0]+numtex[1];
	subtexindex[0]=0; subtexindex[1]=numtex[0]; subtexindex[2]=numtex[0]+numtex[1]; subtexindex[3]=numtex[0]+numtex[1]+numtex[2];
	postri[0]=0; postri[1]=numtri[0]; postri[2]=numtri[0]+numtri[1];
	subtriindex[0]=0; subtriindex[1]=numtri[0]; subtriindex[2]=numtri[0]+numtri[1]; subtriindex[3]=numtri[0]+numtri[1]+numtri[2];
	for (j=0; j<onumsubmeshes; j++)
	{
		int type=0;
		if (j<numsubmeshes-1)
		{
			type=osubisback[j+1];
		}
		for (i=0; i<osubtexindex[j+1]-osubtexindex[j]; i++)
		{
			texcoords[postex[type]]=otexcoords[osubtexindex[j]+i];
		}
		postex[type]+=osubtexindex[j+1]-osubtexindex[j];
		for (i=0; i<osubtriindex[j+1]-osubtriindex[j]; i++)
		{
			int k;
			for (k=0; k<3; k++)
				triangles[postri[type]*3+k]=otriangles[(osubtriindex[j]+i)*3+k];
		}
		postri[type]+=osubtriindex[j+1]-osubtriindex[j];
	}
*/
	//finished munching
	gEnv->sceneManager=gEnv->sceneManager;
	nodes=nds;
	/// Create the mesh via the MeshManager
    msh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,new ResourceBuffer());

    /// Create submeshes
	subs=(SubMesh**)malloc(numsubmeshes*sizeof(SubMesh*));
	for (j=0; j<numsubmeshes; j++)
	{
		subs[j] = msh->createSubMesh();
		//materials
		if (j<numsubmeshes-1)
		{
			if (subisback[j+1]==0) subs[j]->setMaterialName(texname);
			if (subisback[j+1]==1) subs[j]->setMaterialName(backtexname);
			if (subisback[j+1]==2) subs[j]->setMaterialName(transtexname);
		}
		else
			subs[j]->setMaterialName(texname);
	};

    /// Define the vertices (8 vertices, each consisting of 3 groups of 3 floats
    nVertices = numtexcoords;
    vbufCount = (2*3+2)*nVertices;
	vertices=(float*)malloc(vbufCount*sizeof(float));
	//shadow
	shadownorvertices=(float*)malloc(nVertices*(3+2)*sizeof(float));
	shadowposvertices=(float*)malloc(nVertices*3*2*sizeof(float));
	nodeIDs=(int*)malloc(nVertices*sizeof(int));

	//define node ids
	for (i=0; i<nVertices; i++)
	{
		nodeIDs[i]=(int)(texcoords[i].x);
	}

	//textures coordinates
	for (i=0; i<nVertices; i++)
	{
		covertices[i].texcoord=Vector2(texcoords[i].y,texcoords[i].z);
	}

    /// Define triangles
    /// The values in this table refer to vertices in the above table
    ibufCount = 3*numtriangles;
    faces=(unsigned short*)malloc(ibufCount*sizeof(unsigned short));
	for (i=0; i<ibufCount; i++)
	{
		faces[i]=findID(i/3, triangles[i], numsubmeshes, subtexindex, subtriindex);
	}

	sref=(float*)malloc(numtriangles*sizeof(float));

	for (i=0; i<(unsigned int)numtriangles;i++)
	{
		Vector3 v1, v2;
		v1=nodes[nodeIDs[faces[i*3+1]]].RelPosition-nodes[nodeIDs[faces[i*3]]].RelPosition;
		v2=nodes[nodeIDs[faces[i*3+2]]].RelPosition-nodes[nodeIDs[faces[i*3]]].RelPosition;
		v1=v1.crossProduct(v2);
		sref[i]=v1.length()*2.0;
	}


	//update coords
	updateVertices();



    /// Create vertex data structure for vertices shared between submeshes
    msh->sharedVertexData = new VertexData();
    msh->sharedVertexData->vertexCount = nVertices;


    /// Create declaration (memory format) of vertex data
    decl = msh->sharedVertexData->vertexDeclaration;
    size_t offset = 0;
    decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
    offset += VertexElement::getTypeSize(VET_FLOAT3);
    decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
    offset += VertexElement::getTypeSize(VET_FLOAT3);
//        decl->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE);
//        offset += VertexElement::getTypeSize(VET_FLOAT3);
    decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
    offset += VertexElement::getTypeSize(VET_FLOAT2);


    /// Allocate vertex buffer of the requested number of vertices (vertexCount)
    /// and bytes per vertex (offset)
    vbuf =
      HardwareBufferManager::getSingleton().createVertexBuffer(
          offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);

    /// Upload the vertex data to the card
    vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);


    /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer
    VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
    bind->setBinding(0, vbuf);




    /// Set parameters of the submeshes
	for (j=0; j<numsubmeshes; j++)
	{
		int smcount=3*(subtriindex[j+1]-subtriindex[j]);
        subs[j]->useSharedVertices = true;
		/// Allocate index buffer of the requested number of vertices (ibufCount)
		HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
		 createIndexBuffer(
			 HardwareIndexBuffer::IT_16BIT,
				smcount,
				HardwareBuffer::HBU_STATIC_WRITE_ONLY);

		/// Upload the index data to the card
		ibuf->writeData(0, ibuf->getSizeInBytes(), &faces[subtriindex[j]*3], true);
	    subs[j]->indexData->indexBuffer = ibuf;
		subs[j]->indexData->indexCount = smcount;
        subs[j]->indexData->indexStart = 0;
	}


    /// Set bounding information (for culling)
    msh->_setBounds(AxisAlignedBox(-100,-100,-100,100,100,100), true);
    //msh->_setBoundingSphereRadius(100);


    /// Notify Mesh object that it has been loaded
    msh->load();
	msh->buildEdgeList();

}
Exemplo n.º 3
0
FlexAirfoil::FlexAirfoil(char* name, node_t *nds, int pnfld, int pnfrd, int pnflu, int pnfru, int pnbld, int pnbrd, int pnblu, int pnbru, char* texband, Vector2 texlf, Vector2 texrf, Vector2 texlb, Vector2 texrb, char mtype, float controlratio, float mind, float maxd, char* afname, float lift_coef, AeroEngine** tps, bool break_able)
{
//		innan=0;
	liftcoef=lift_coef;
	breakable=break_able;
	broken=false;
	debug[0]=0;
	free_wash=0;
	aeroengines=tps;
	nodes=nds;
	useInducedDrag=false;
	nfld=pnfld; nodes[nfld].iIsSkin=true;
	nfrd=pnfrd; nodes[nfrd].iIsSkin=true;
	nflu=pnflu; nodes[nflu].iIsSkin=true;
	nfru=pnfru; nodes[nfru].iIsSkin=true;
	nbld=pnbld; nodes[nbld].iIsSkin=true;
	nbrd=pnbrd; nodes[nbrd].iIsSkin=true;
	nblu=pnblu; nodes[nblu].iIsSkin=true;
	nbru=pnbru; nodes[nbru].iIsSkin=true;
	mindef=mind;
	maxdef=maxd;
	airfoil=new Airfoil(afname);
	//airfoil->getcl(-180.0, 0, 0);
	//airfoil->dumpcl();
	int i;
	for (i=0; i<90; i++) airfoilpos[i]=refairfoilpos[i];
	type=mtype;
	hascontrol=(mtype!='n' && mtype!='S'&& mtype!='T' && mtype!='U'&& mtype!='V');
	isstabilator=(mtype=='S' || mtype=='T' || mtype=='U' || mtype=='V');
	stabilleft=(mtype=='T' || mtype=='V');
	deflection=0.0;
	chordratio=controlratio;

	if (hascontrol)
	{
		//setup control surface
		airfoilpos[56]=controlratio;
		airfoilpos[56+3]=controlratio;
		airfoilpos[56+6]=controlratio;
		airfoilpos[56+9]=controlratio;

		airfoilpos[55]=-controlratio+1.5;
		airfoilpos[55+3]=-controlratio+1.5;
		airfoilpos[55+6]=controlratio-0.5;
		airfoilpos[55+9]=controlratio-0.5;
		for (i=0; i<12; i++) airfoilpos[54+12+i]=airfoilpos[54+i];
	}
	/// Create the mesh via the MeshManager
    msh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, new ResourceBuffer());

    /// Create submeshes
    subface = msh->createSubMesh();
    subband = msh->createSubMesh();
	subcup=msh->createSubMesh();
	subcdn=msh->createSubMesh();

	//materials
	subface->setMaterialName(texband);
	subband->setMaterialName(texband);
	subcup->setMaterialName(texband);
	subcdn->setMaterialName(texband);

    /// Define the vertices
    nVertices = 24*2+4+2;
    vbufCount = (2*3+2)*nVertices;
	vertices=(float*)malloc(vbufCount*sizeof(float));
	//shadow
	shadownorvertices=(float*)malloc(nVertices*(3+2)*sizeof(float));
	shadowposvertices=(float*)malloc(nVertices*3*2*sizeof(float));

	//textures coordinates
	covertices[0].texcoord=texlf;
	covertices[1].texcoord=texrf;

	covertices[2].texcoord=texlf+(texlb-texlf)*0.03;
	covertices[3].texcoord=texrf+(texrb-texrf)*0.03;
	covertices[4].texcoord=texlf+(texlb-texlf)*0.03;
	covertices[5].texcoord=texrf+(texrb-texrf)*0.03;

	covertices[6].texcoord=texlf+(texlb-texlf)*0.10;
	covertices[7].texcoord=texrf+(texrb-texrf)*0.10;
	covertices[8].texcoord=texlf+(texlb-texlf)*0.10;
	covertices[9].texcoord=texrf+(texrb-texrf)*0.10;

	covertices[10].texcoord=texlf+(texlb-texlf)*0.25;
	covertices[11].texcoord=texrf+(texrb-texrf)*0.25;
	covertices[12].texcoord=texlf+(texlb-texlf)*0.25;
	covertices[13].texcoord=texrf+(texrb-texrf)*0.25;

	covertices[14].texcoord=texlf+(texlb-texlf)*0.45;
	covertices[15].texcoord=texrf+(texrb-texrf)*0.45;
	covertices[16].texcoord=texlf+(texlb-texlf)*0.45;
	covertices[17].texcoord=texrf+(texrb-texrf)*0.45;

	covertices[18].texcoord=texlf+(texlb-texlf)*airfoilpos[56];
	covertices[19].texcoord=texrf+(texrb-texrf)*airfoilpos[56];
	covertices[20].texcoord=texlf+(texlb-texlf)*airfoilpos[56];
	covertices[21].texcoord=texrf+(texrb-texrf)*airfoilpos[56];

	covertices[22].texcoord=covertices[18].texcoord;
	covertices[23].texcoord=covertices[19].texcoord;
	covertices[24].texcoord=covertices[20].texcoord;
	covertices[25].texcoord=covertices[21].texcoord;

	covertices[26].texcoord=texlb;
	covertices[27].texcoord=texrb;
	covertices[28].texcoord=texlb;
	covertices[29].texcoord=texrb;

	for (i=0; i<24; i++) covertices[i+30].texcoord=covertices[i].texcoord;

	/// Define triangles
    /// The values in this table refer to vertices in the above table
    bandibufCount = 3*20;
    faceibufCount = 3*20;
	cupibufCount=3*2;
	cdnibufCount=3*2;
    facefaces=(unsigned short*)malloc(faceibufCount*sizeof(unsigned short));
    bandfaces=(unsigned short*)malloc(bandibufCount*sizeof(unsigned short));
    cupfaces=(unsigned short*)malloc(cupibufCount*sizeof(unsigned short));
    cdnfaces=(unsigned short*)malloc(cdnibufCount*sizeof(unsigned short));
	
	//attack
	bandfaces[0]=0;
	bandfaces[1]=2;
	bandfaces[2]=1;

	bandfaces[3]=2;
	bandfaces[4]=3;
	bandfaces[5]=1;

	bandfaces[6]=0;
	bandfaces[7]=1;
	bandfaces[8]=4;

	bandfaces[9]=4;
	bandfaces[10]=1;
	bandfaces[11]=5;
	for (i=0; i<5; i++)
	{
		//band
		int v=i*4+2;
		if (i!=4)
		{
			bandfaces[i*12+12]=v;
			bandfaces[i*12+13]=v+4;
			bandfaces[i*12+14]=v+1;

			bandfaces[i*12+15]=v+4;
			bandfaces[i*12+16]=v+5;
			bandfaces[i*12+17]=v+1;

			bandfaces[i*12+18]=v+2;
			bandfaces[i*12+19]=v+3;
			bandfaces[i*12+20]=v+6;

			bandfaces[i*12+21]=v+6;
			bandfaces[i*12+22]=v+3;
			bandfaces[i*12+23]=v+7;
		}
/*			if (i==4)
		{
			bandfaces[i*12+20]=v+4;
			bandfaces[i*12+21]=v+4;
			bandfaces[i*12+23]=v+5;
		}
*/

		//sides
		facefaces[i*12]=30+0;
		facefaces[i*12+1]=30+v+4;
		facefaces[i*12+2]=30+v;

		facefaces[i*12+3]=30+0;
		facefaces[i*12+4]=30+v+2;
		facefaces[i*12+5]=30+v+6;

		facefaces[i*12+6]=30+1;
		facefaces[i*12+7]=30+v+1;
		facefaces[i*12+8]=30+v+5;

		facefaces[i*12+9]=30+1;
		facefaces[i*12+10]=30+v+7;
		facefaces[i*12+11]=30+v+3;
		if (i==4)
		{
//				facefaces[i*12+5]=20+v+4;
//				facefaces[i*12+10]=20+v+5;
			facefaces[i*12]=30+0;
			facefaces[i*12+1]=30+v+2;
			facefaces[i*12+2]=30+v;

			facefaces[i*12+3]=30+v+4;
			facefaces[i*12+4]=30+v;
			facefaces[i*12+5]=30+v+2;

			facefaces[i*12+6]=30+1;
			facefaces[i*12+7]=30+v+1;
			facefaces[i*12+8]=30+v+3;

			facefaces[i*12+9]=30+v+5;
			facefaces[i*12+10]=30+v+3;
			facefaces[i*12+11]=30+v+1;
		}

	}
	cupfaces[0]=22;
	cupfaces[1]=26;
	cupfaces[2]=23;
	cupfaces[3]=26;
	cupfaces[4]=27;
	cupfaces[5]=23;

	cdnfaces[0]=24;
	cdnfaces[1]=25;
	cdnfaces[2]=29;
	cdnfaces[3]=24;
	cdnfaces[4]=29;
	cdnfaces[5]=28;

	float tsref=2.0*(nodes[nfrd].RelPosition-nodes[nfld].RelPosition).crossProduct(nodes[nbld].RelPosition-nodes[nfld].RelPosition).length();
	sref=2.0*(nodes[nfrd].RelPosition-nodes[nfld].RelPosition).crossProduct(nodes[nbrd].RelPosition-nodes[nfrd].RelPosition).length();
	if (tsref>sref) sref=tsref;
	sref=sref*sref;

	lratio=(nodes[nfld].RelPosition-nodes[nflu].RelPosition).length()/(nodes[nfld].RelPosition-nodes[nbld].RelPosition).length();
	rratio=(nodes[nfrd].RelPosition-nodes[nfru].RelPosition).length()/(nodes[nfrd].RelPosition-nodes[nbrd].RelPosition).length();

	thickness=(nodes[nfld].RelPosition-nodes[nflu].RelPosition).length();

	//update coords
	updateVertices();

	/// Create vertex data structure for 8 vertices shared between submeshes
    msh->sharedVertexData = new VertexData();
    msh->sharedVertexData->vertexCount = nVertices;

    /// Create declaration (memory format) of vertex data
    decl = msh->sharedVertexData->vertexDeclaration;
    size_t offset = 0;
    decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
    offset += VertexElement::getTypeSize(VET_FLOAT3);
    decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
    offset += VertexElement::getTypeSize(VET_FLOAT3);
//        decl->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE);
//        offset += VertexElement::getTypeSize(VET_FLOAT3);
    decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
    offset += VertexElement::getTypeSize(VET_FLOAT2);

    /// Allocate vertex buffer of the requested number of vertices (vertexCount)
    /// and bytes per vertex (offset)
    vbuf =
      HardwareBufferManager::getSingleton().createVertexBuffer(
          offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);

    /// Upload the vertex data to the card
    vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);

    /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer
    VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
    bind->setBinding(0, vbuf);

    //for the face
	/// Allocate index buffer of the requested number of vertices (ibufCount)
    HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton().
     createIndexBuffer(
         HardwareIndexBuffer::IT_16BIT,
            faceibufCount,
            HardwareBuffer::HBU_STATIC_WRITE_ONLY);

    /// Upload the index data to the card
    faceibuf->writeData(0, faceibuf->getSizeInBytes(), facefaces, true);

    /// Set parameters of the submesh
    subface->useSharedVertices = true;
    subface->indexData->indexBuffer = faceibuf;
    subface->indexData->indexCount = faceibufCount;
    subface->indexData->indexStart = 0;

    //for the band
	/// Allocate index buffer of the requested number of vertices (ibufCount)
    HardwareIndexBufferSharedPtr bandibuf = HardwareBufferManager::getSingleton().
     createIndexBuffer(
         HardwareIndexBuffer::IT_16BIT,
            bandibufCount,
            HardwareBuffer::HBU_STATIC_WRITE_ONLY);

    /// Upload the index data to the card
    bandibuf->writeData(0, bandibuf->getSizeInBytes(), bandfaces, true);

    /// Set parameters of the submesh
    subband->useSharedVertices = true;
    subband->indexData->indexBuffer = bandibuf;
    subband->indexData->indexCount = bandibufCount;
    subband->indexData->indexStart = 0;

    //for the aileron up
	/// Allocate index buffer of the requested number of vertices (ibufCount)
    HardwareIndexBufferSharedPtr cupibuf = HardwareBufferManager::getSingleton().
     createIndexBuffer(
         HardwareIndexBuffer::IT_16BIT,
            cupibufCount,
            HardwareBuffer::HBU_STATIC_WRITE_ONLY);

    /// Upload the index data to the card
    cupibuf->writeData(0, cupibuf->getSizeInBytes(), cupfaces, true);

    /// Set parameters of the submesh
    subcup->useSharedVertices = true;
    subcup->indexData->indexBuffer = cupibuf;
    subcup->indexData->indexCount = cupibufCount;
    subcup->indexData->indexStart = 0;

    //for the aileron down
	/// Allocate index buffer of the requested number of vertices (ibufCount)
    HardwareIndexBufferSharedPtr cdnibuf = HardwareBufferManager::getSingleton().
     createIndexBuffer(
         HardwareIndexBuffer::IT_16BIT,
            cdnibufCount,
            HardwareBuffer::HBU_STATIC_WRITE_ONLY);

    /// Upload the index data to the card
    cdnibuf->writeData(0, cdnibuf->getSizeInBytes(), cdnfaces, true);

    /// Set parameters of the submesh
    subcdn->useSharedVertices = true;
    subcdn->indexData->indexBuffer = cdnibuf;
    subcdn->indexData->indexCount = cdnibufCount;
    subcdn->indexData->indexStart = 0;

    /// Set bounding information (for culling)
    msh->_setBounds(AxisAlignedBox(-20,-20,-20,20,20,20), true);
    //msh->_setBoundingSphereRadius(20.0);

    /// Notify Mesh object that it has been loaded
	//MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(false);
	msh->buildEdgeList();
	//msh->prepareForShadowVolume();
	msh->load();
	//MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes()
}
Exemplo n.º 4
0
void OgreToBulletMesh::getMeshInformation(MeshPtr mesh, unsigned& vertex_count, std::vector<Vector3>& vertices,
									unsigned& index_count, std::vector<unsigned>& indices, const Vector3& position,
									const Quaternion& orientation, const Vector3& scale)
{
	bool added_shared = false;
	unsigned current_offset = 0;
	unsigned shared_offset = 0;
	unsigned next_offset = 0;
	unsigned index_offset = 0;

	vertex_count = index_count = 0;

	for (uint16_t i = 0; i < mesh->getNumSubMeshes(); ++i) 
	{
		SubMesh* submesh = mesh->getSubMesh(i);
		if (submesh->useSharedVertices) 
		{
			if (!added_shared) 
			{
				vertex_count += mesh->sharedVertexData->vertexCount;
				added_shared = true;
			}
		}
		else
			vertex_count += submesh->vertexData->vertexCount;

		index_count += submesh->indexData->indexCount;
	}

	vertices.clear();
	vertices.reserve(vertex_count);
	indices.clear();
	indices.reserve(index_count);
	added_shared = false;

	for (uint16_t i = 0; i < mesh->getNumSubMeshes(); ++i) 
	{
		SubMesh* submesh = mesh->getSubMesh(i);
		VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;

		if (!submesh->useSharedVertices || (submesh->useSharedVertices && !added_shared)) 
		{
			if (submesh->useSharedVertices) 
			{
				added_shared = true;
				shared_offset = current_offset;
			}

			const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(VertexElementSemantic::VES_POSITION);
			HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

			uint8_t* vertex = (uint8_t*)vbuf->lock(HardwareBuffer::LockOptions::HBL_READ_ONLY);
			float* pReal;

			for (int j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) 
			{
				posElem->baseVertexPointerToElement(vertex, &pReal);
				Vector3 pt(pReal[0], pReal[1], pReal[2]);
				vertices[current_offset + j] = (orientation * (pt * scale)) + position;
			}
			vbuf->unlock();
			next_offset += vertex_data->vertexCount;
		}

		IndexData* index_data = submesh->indexData;
		uint numTris = index_data->indexCount / 3;
		HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;

		bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IndexType::IT_32BIT);

		uint* pLong = (uint*)ibuf->lock(HardwareBuffer::LockOptions::HBL_READ_ONLY);
		ushort* pShort = (ushort*)pLong;
		uint offset = submesh->useSharedVertices ? shared_offset : current_offset;
		if (use32bitindexes)
			for (int k = 0; k < index_data->indexCount; ++k)
				indices[index_offset++] = pLong[k] + offset;
		else
			for (int k = 0; k < index_data->indexCount; ++k)
				indices[index_offset++] = (uint)pShort[k] + (uint)offset;
		ibuf->unlock();
		current_offset = next_offset;
	}
}
Exemplo n.º 5
0
// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given
// mesh.
void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std::list<VertexBoneAssignment> &vertexBoneAssignments)
{
    //  cout << "s:" << shape << "\n";
    NiTriShapeData *data = shape->data.getPtr();
    SubMesh *sub = mesh->createSubMesh(shape->name.toString());

    int nextBuf = 0;

    // This function is just one long stream of Ogre-barf, but it works
    // great.

    // Add vertices
    int numVerts = data->vertices.length / 3;
    sub->vertexData = new VertexData();
    sub->vertexData->vertexCount = numVerts;
    sub->useSharedVertices = false;

    VertexDeclaration *decl = sub->vertexData->vertexDeclaration;
    decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION);

    HardwareVertexBufferSharedPtr vbuf =
        HardwareBufferManager::getSingleton().createVertexBuffer(
            VertexElement::getTypeSize(VET_FLOAT3),
            numVerts, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);

    if(flip)
	{
		float *datamod = new float[data->vertices.length];
		//std::cout << "Shape" << shape->name.toString() << "\n";
		for(int i = 0; i < numVerts; i++)
		{
			int index = i * 3;
			const float *pos = data->vertices.ptr + index;
		    Ogre::Vector3 original = Ogre::Vector3(*pos  ,*(pos+1), *(pos+2));
			original = mTransform * original;
			mBoundingBox.merge(original);
			datamod[index] = original.x;
			datamod[index+1] = original.y;
			datamod[index+2] = original.z;
		}
        vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false);
        delete [] datamod;
	}
	else
	{
		vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, false);
	}


    VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
    bind->setBinding(nextBuf++, vbuf);

    if (data->normals.length)
    {
        decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL);
        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
                   VertexElement::getTypeSize(VET_FLOAT3),
                   numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);

		if(flip)
		{
			Quaternion rotation = mTransform.extractQuaternion();
			rotation.normalise();

			float *datamod = new float[data->normals.length];
			for(int i = 0; i < numVerts; i++)
		    {
			    int index = i * 3;
			    const float *pos = data->normals.ptr + index;
		        Ogre::Vector3 original = Ogre::Vector3(*pos  ,*(pos+1), *(pos+2));
				original = rotation * original;
				if (mNormaliseNormals)
			    {
                    original.normalise();
				}


			    datamod[index] = original.x;
			    datamod[index+1] = original.y;
			    datamod[index+2] = original.z;
		    }
			vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false);
            delete [] datamod;
		}
		else
		{
            vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, false);
		}
        bind->setBinding(nextBuf++, vbuf);
    }

    
    // Vertex colors
    if (data->colors.length)
    {
        const float *colors = data->colors.ptr;
        RenderSystem* rs = Root::getSingleton().getRenderSystem();
        std::vector<RGBA> colorsRGB(numVerts);
        RGBA *pColour = &colorsRGB.front();
        for (int i=0; i<numVerts; i++)
        {
            rs->convertColourValue(ColourValue(colors[0],colors[1],colors[2],
                                               colors[3]),pColour++);
            colors += 4;
        }
        decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE);
        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
                   VertexElement::getTypeSize(VET_COLOUR),
                   numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
        vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true);
        bind->setBinding(nextBuf++, vbuf);
    }

     if (data->uvlist.length)
    {

        decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
        vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
                   VertexElement::getTypeSize(VET_FLOAT2),
                   numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY,false);

		if(flip)
		{
		    float *datamod = new float[data->uvlist.length];

		    for(unsigned int i = 0; i < data->uvlist.length; i+=2){
			    float x = *(data->uvlist.ptr + i);

			    float y = *(data->uvlist.ptr + i + 1);

			    datamod[i] =x;
				datamod[i + 1] =y;
		    }
			vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false);
            delete [] datamod;
		}
		else
			vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, false);
        bind->setBinding(nextBuf++, vbuf);
    }

   // Triangle faces - The total number of triangle points
    int numFaces = data->triangles.length;

    if (numFaces)
    {

		sub->indexData->indexCount = numFaces;
        sub->indexData->indexStart = 0;
        HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
                                            createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
                                                              numFaces,
                                                              HardwareBuffer::HBU_STATIC_WRITE_ONLY, true);

		if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){

			sub->indexData->indexBuffer = ibuf;

			uint16 *datamod = new uint16[numFaces];
			int index = 0;
			for (size_t i = 0; i < sub->indexData->indexCount; i+=3)
			{

			     const short *pos = data->triangles.ptr + index;
				uint16 i0 = (uint16) *(pos+0);
				uint16 i1 = (uint16) *(pos+1);
				uint16 i2 = (uint16) *(pos+2);

				//std::cout << "i0: " << i0 << "i1: " << i1 << "i2: " << i2 << "\n";


				datamod[index] = i2;
				datamod[index+1] = i1;
				datamod[index+2] = i0;

				index += 3;
			}

            ibuf->writeData(0, ibuf->getSizeInBytes(), datamod, false);
            delete [] datamod;

		}
		else
            ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, false);
        sub->indexData->indexBuffer = ibuf;
    }

    // Set material if one was given
    if (!material.empty()) sub->setMaterialName(material);

    //add vertex bone assignments

    for (std::list<VertexBoneAssignment>::iterator it = vertexBoneAssignments.begin();
        it != vertexBoneAssignments.end(); it++)
    {
            sub->addBoneAssignment(*it);
    }
    if(mSkel.isNull())
       needBoneAssignments.push_back(sub);
}
Exemplo n.º 6
0
// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given
// mesh.
static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material)
{
  NiTriShapeData *data = shape->data.getPtr();
  SubMesh *sub = mesh->createSubMesh(shape->name.toString());

  int nextBuf = 0;

  // This function is just one long stream of Ogre-barf, but it works
  // great.

  // Add vertices
  int numVerts = data->vertices.length / 3;
  sub->vertexData = new VertexData();
  sub->vertexData->vertexCount = numVerts;
  sub->useSharedVertices = false;
  VertexDeclaration *decl = sub->vertexData->vertexDeclaration;
  decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION);
  HardwareVertexBufferSharedPtr vbuf =
    HardwareBufferManager::getSingleton().createVertexBuffer(
      VertexElement::getTypeSize(VET_FLOAT3),
      numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true);
  VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
  bind->setBinding(nextBuf++, vbuf);

  // Vertex normals
  if(data->normals.length)
    {
      decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL);
      vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
          VertexElement::getTypeSize(VET_FLOAT3),
          numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
      vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, true);
      bind->setBinding(nextBuf++, vbuf);
    }

  // Vertex colors
  if(data->colors.length)
    {
      const float *colors = data->colors.ptr;
      RenderSystem* rs = Root::getSingleton().getRenderSystem();
      std::vector<RGBA> colorsRGB(numVerts);
      RGBA *pColour = &colorsRGB.front();
      for(int i=0; i<numVerts; i++)
	{
	  rs->convertColourValue(ColourValue(colors[0],colors[1],colors[2],
                                             colors[3]),pColour++);
	  colors += 4;
	}
      decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE);
      vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
          VertexElement::getTypeSize(VET_COLOUR),
	  numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
      vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true);
      bind->setBinding(nextBuf++, vbuf);
    }

  // Texture UV coordinates
  if(data->uvlist.length)
    {
      decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
      vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
          VertexElement::getTypeSize(VET_FLOAT2),
          numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);

      vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, true);
      bind->setBinding(nextBuf++, vbuf);
    }

  // Triangle faces
  int numFaces = data->triangles.length;
  if(numFaces)
    {
      HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
	createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
			  numFaces,
			  HardwareBuffer::HBU_STATIC_WRITE_ONLY);
      ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, true);
      sub->indexData->indexBuffer = ibuf;
      sub->indexData->indexCount = numFaces;
      sub->indexData->indexStart = 0;
    }

  // Set material if one was given
  if(!material.empty()) sub->setMaterialName(material);

  /* Old commented D code. Might be useful when reimplementing
     animation.
  // Assign this submesh to the given bone
  VertexBoneAssignment v;
  v.boneIndex = ((Bone*)bone)->getHandle();
  v.weight = 1.0;

  std::cerr << "+ Assigning bone index " << v.boneIndex << "\n";

  for(int i=0; i < numVerts; i++)
    {
      v.vertexIndex = i;
      sub->addBoneAssignment(v);
    }
  */
}
Exemplo n.º 7
0
//-----------------------------------------------------------------------
void MeshManager::tesselate2DMesh(SubMesh* sm, unsigned short meshWidth, unsigned short meshHeight,
                                  bool doubleSided, HardwareBuffer::Usage indexBufferUsage, bool indexShadowBuffer)
{
    // The mesh is built, just make a list of indexes to spit out the triangles
    unsigned short vInc, v, iterations;

    if (doubleSided)
    {
        iterations = 2;
        vInc = 1;
        v = 0; // Start with front
    }
    else
    {
        iterations = 1;
        vInc = 1;
        v = 0;
    }

    // Allocate memory for faces
    // Num faces, width*height*2 (2 tris per square), index count is * 3 on top
    sm->indexData->indexCount = (meshWidth-1) * (meshHeight-1) * 2 * iterations * 3;
    sm->indexData->indexBuffer = HardwareBufferManager::getSingleton().
                                 createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
                                         sm->indexData->indexCount, indexBufferUsage, indexShadowBuffer);

    unsigned short v1, v2, v3;
    //bool firstTri = true;
    HardwareIndexBufferSharedPtr ibuf = sm->indexData->indexBuffer;
    // Lock the whole buffer
    unsigned short* pIndexes = static_cast<unsigned short*>(
                                   ibuf->lock(HardwareBuffer::HBL_DISCARD) );

    while (iterations--)
    {
        // Make tris in a zigzag pattern (compatible with strips)
        unsigned short u = 0;
        unsigned short uInc = 1; // Start with moving +u
        unsigned short vCount = meshHeight - 1;

        while (vCount--)
        {
            unsigned short uCount = meshWidth - 1;
            while (uCount--)
            {
                // First Tri in cell
                // -----------------
                v1 = ((v + vInc) * meshWidth) + u;
                v2 = (v * meshWidth) + u;
                v3 = ((v + vInc) * meshWidth) + (u + uInc);
                // Output indexes
                *pIndexes++ = v1;
                *pIndexes++ = v2;
                *pIndexes++ = v3;
                // Second Tri in cell
                // ------------------
                v1 = ((v + vInc) * meshWidth) + (u + uInc);
                v2 = (v * meshWidth) + u;
                v3 = (v * meshWidth) + (u + uInc);
                // Output indexes
                *pIndexes++ = v1;
                *pIndexes++ = v2;
                *pIndexes++ = v3;

                // Next column
                u += uInc;
            }
            // Next row
            v += vInc;
            u = 0;


        }

        // Reverse vInc for double sided
        v = meshHeight - 1;
        vInc = -vInc;

    }
    // Unlock
    ibuf->unlock();

}
Exemplo n.º 8
0
void GeomUtils::createSphere(VertexData*& vertexData, IndexData*& indexData
						 , float radius
						 , int nRings, int nSegments
						 , bool bNormals
						 , bool bTexCoords)
{
	assert(vertexData && indexData);

	// define the vertex format
	VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
	size_t currOffset = 0;
	// positions
	vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
	currOffset += VertexElement::getTypeSize(VET_FLOAT3);

	if (bNormals)
	{
		// normals
		vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL);
		currOffset += VertexElement::getTypeSize(VET_FLOAT3);

	}
	// two dimensional texture coordinates
	if (bTexCoords)
	{
		vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
		currOffset += VertexElement::getTypeSize(VET_FLOAT2);
	}

	// allocate the vertex buffer
	vertexData->vertexCount = (nRings + 1) * (nSegments+1);
	HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	VertexBufferBinding* binding = vertexData->vertexBufferBinding;
	binding->setBinding(0, vBuf);
	float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD));

	// allocate index buffer
	indexData->indexCount = 6 * nRings * (nSegments + 1);
	indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
	HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer;
	unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD));

	float fDeltaRingAngle = (Math::PI / nRings);
	float fDeltaSegAngle = (2 * Math::PI / nSegments);
	unsigned short wVerticeIndex = 0 ;

	// Generate the group of rings for the sphere
	for( int ring = 0; ring <= nRings; ring++ ) {
		float r0 = radius * sinf (ring * fDeltaRingAngle);
		float y0 = radius * cosf (ring * fDeltaRingAngle);

		// Generate the group of segments for the current ring
		for(int seg = 0; seg <= nSegments; seg++) {
			float x0 = r0 * sinf(seg * fDeltaSegAngle);
			float z0 = r0 * cosf(seg * fDeltaSegAngle);

			// Add one vertex to the strip which makes up the sphere
			*pVertex++ = x0;
			*pVertex++ = y0;
			*pVertex++ = z0;

			if (bNormals)
			{
				Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy();
				*pVertex++ = vNormal.x;
				*pVertex++ = vNormal.y;
				*pVertex++ = vNormal.z;
			}
			if (bTexCoords)
			{
				*pVertex++ = (float) seg / (float) nSegments;
				*pVertex++ = (float) ring / (float) nRings;			
			}

			if (ring != nRings) 
			{
				// each vertex (except the last) has six indices pointing to it
				*pIndices++ = wVerticeIndex + nSegments + 1;
				*pIndices++ = wVerticeIndex;               
				*pIndices++ = wVerticeIndex + nSegments;
				*pIndices++ = wVerticeIndex + nSegments + 1;
				*pIndices++ = wVerticeIndex + 1;
				*pIndices++ = wVerticeIndex;
				wVerticeIndex ++;
			}
		}; // end for seg
	} // end for ring

	// Unlock
	vBuf->unlock();
	iBuf->unlock();
}
Exemplo n.º 9
0
/// reads out mesh vertices and indices
/// must be called before rayintersect if the mesh has moved/deformed, probably every frame for animated meshes and mousepicking
/// calling it once for static meshes is enough
/// code is based on OgreOpCode MeshCollisionShape::convertMeshData
void	MeshShape::Update			(Ogre::Entity *pEntity) {
	// if (!pEntity) return;
	if (mpMesh.isNull()) return;
	if (pEntity && mbInitialised && !pEntity->hasSkeleton()) return; // no need to update static models every frame...
	mbInitialised = true;
	//printf("#### MeshShape::Update\n");
	//printf("MeshShape::Update skeleton=%d\n",pEntity->hasSkeleton()?1:0);
		
	//assert(pEntity->getMesh().get() == mpMesh.get() && "mesh pointer changed ! (ogrecaching/garbage collection?)");
	
	mlVertices.clear();
	mlIndices.clear();
		
	bool added_shared = false;
	size_t current_offset = 0;
	size_t shared_offset = 0;
	size_t next_offset = 0;
	size_t index_offset = 0;
	int numOfSubs = 0;

	// true if the entity is possibly animated (=has skeleton) , this means Update should be called every frame
	bool useSoftwareBlendingVertices = pEntity && pEntity->hasSkeleton();

	if (useSoftwareBlendingVertices)
	{
		pEntity->_updateAnimation();
	}

	// Run through the submeshes again, adding the data into the arrays
	for ( size_t i = 0; i < mpMesh->getNumSubMeshes(); ++i) {
		SubMesh* submesh = mpMesh->getSubMesh(i);
		bool useSharedVertices = submesh->useSharedVertices;

		//----------------------------------------------------------------
		// GET VERTEXDATA
		//----------------------------------------------------------------
		const VertexData * vertex_data;
		if(useSoftwareBlendingVertices)
				vertex_data = useSharedVertices ? pEntity->_getSkelAnimVertexData() : pEntity->getSubEntity(i)->_getSkelAnimVertexData();
		else	vertex_data = useSharedVertices ? mpMesh->sharedVertexData : submesh->vertexData;

		if((!useSharedVertices)||(useSharedVertices && !added_shared))
		{
			if(useSharedVertices)
			{
				added_shared = true;
				shared_offset = current_offset;
			}

			const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
			
			HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

			unsigned char* vertex =
				static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY));

			// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
			//  as second argument. So make it float, to avoid trouble when Ogre::Real is
			//  comiled/typedefed as double:
			float* pReal;

			mlVertices.reserve(mlVertices.size()+vertex_data->vertexCount);
			for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
			{
				posElem->baseVertexPointerToElement(vertex, &pReal);
				if (mlVertices.size() == 0) {
					mvMin.x = mvMax.x = pReal[0];
					mvMin.y = mvMax.y = pReal[1];
					mvMin.z = mvMax.z = pReal[2];
				} else {
					if (mvMin.x > pReal[0]) mvMin.x = pReal[0];
					if (mvMin.y > pReal[1]) mvMin.y = pReal[1];
					if (mvMin.z > pReal[2]) mvMin.z = pReal[2];
					if (mvMax.x < pReal[0]) mvMax.x = pReal[0];
					if (mvMax.y < pReal[1]) mvMax.y = pReal[1];
					if (mvMax.z < pReal[2]) mvMax.z = pReal[2];
				}
				mlVertices.push_back(Vector3(pReal[0],pReal[1],pReal[2]));
			}

			vbuf->unlock();
			next_offset += vertex_data->vertexCount;
		}
		
		
		// TODO : GET TEXCOORD DATA
		// TODO : GET FACE-MATERIAL MAP, or at least material cound....
		// TODO : no need to update index, texcoord and material buffers for animation !
		
		// TODO : const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
		// for texture alpha checking, VertexElementType should be VET_FLOAT2 

		//----------------------------------------------------------------
		// GET INDEXDATA
		//----------------------------------------------------------------
		IndexData* index_data = submesh->indexData;
		size_t numTris = index_data->indexCount / 3;
		HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;

		bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);

		::uint32 *pLong = static_cast< ::uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
		::uint16* pShort = reinterpret_cast< ::uint16*>(pLong);

		size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;

		mlIndices.reserve(mlIndices.size()+3*numTris);
		if ( use32bitindexes )
		{
			for ( size_t k = 0; k < numTris*3; ++k)
			{
				mlIndices.push_back(pLong[k] + static_cast<int>(offset));
			}
		}
		else
		{
			for ( size_t k = 0; k < numTris*3; ++k)
			{
				mlIndices.push_back(static_cast<int>(pShort[k]) + static_cast<int>(offset));
			}
		}

		ibuf->unlock();

		current_offset = next_offset;
	}
	//mvMid = 0.5*(mvMin + mvMax);
	//mfBoundRad = 0.5 * (mvMax - mvMin).length();
}
Exemplo n.º 10
0
void createSphereMesh(const String &name, const float radius, const int slices, const int stacks)
{
  MeshPtr mesh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
  mesh->sharedVertexData = new VertexData();
  mesh->_setBounds(AxisAlignedBox(Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius)));
  mesh->_setBoundingSphereRadius(radius);

  VertexData *vertexData = mesh->sharedVertexData;
  vertexData->vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
  vertexData->vertexDeclaration->addElement(1, 0, VET_FLOAT3, VES_NORMAL);
  vertexData->vertexCount = slices * (stacks + 1);
  HardwareVertexBufferSharedPtr positionBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
      vertexData->vertexDeclaration->getVertexSize(0),
      vertexData->vertexCount,
      HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  HardwareVertexBufferSharedPtr normalBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
      vertexData->vertexDeclaration->getVertexSize(1),
      vertexData->vertexCount,
      HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  float *position = static_cast<float *>(positionBuffer->lock(HardwareBuffer::HBL_DISCARD));
  float *normal = static_cast<float *>(normalBuffer->lock(HardwareBuffer::HBL_DISCARD));
  for (int ring = 0; ring <= stacks; ring++) {
    float r = radius * sinf(ring * Math::PI / stacks);
    float y = radius * cosf(ring * Math::PI / stacks);
    for (int segment = 0; segment < slices; segment++) {
      float x = r * sinf(segment * 2 * Math::PI / slices);
      float z = r * cosf(segment * 2 * Math::PI / slices);
      *position++ = x;
      *position++ = y;
      *position++ = z;
      Vector3 tmp = Vector3(x, y, z).normalisedCopy();
      *normal++ = tmp.x;
      *normal++ = tmp.y;
      *normal++ = tmp.z;
    }
  }
  positionBuffer->unlock();
  normalBuffer->unlock();
  vertexData->vertexBufferBinding->setBinding(0, positionBuffer);
  vertexData->vertexBufferBinding->setBinding(1, normalBuffer);

  SubMesh *subMesh = mesh->createSubMesh();
  subMesh->useSharedVertices = true;

  IndexData *indexData = subMesh->indexData;
  indexData->indexCount = 6 * slices * stacks;
  HardwareIndexBufferSharedPtr indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(
      HardwareIndexBuffer::IT_16BIT,
      indexData->indexCount,
      HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  unsigned short *index = static_cast<unsigned short *>(indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
  unsigned short i = 0;
  for (int ring = 0; ring < stacks; ring++) {
    for (int segment = 0; segment < slices - 1; segment++) {
      *index++ = i;
      *index++ = i + slices;
      *index++ = i + slices + 1;
      *index++ = i;
      *index++ = i + slices + 1;
      *index++ = i + 1;
      i++;
    }
    *index++ = i;
    *index++ = i + slices;
    *index++ = i + 1;
    *index++ = i;
    *index++ = i + 1;
    *index++ = i + 1 - slices;
    i++;
  }
  indexBuffer->unlock();
  indexData->indexBuffer = indexBuffer;

  mesh->load();
}
Exemplo n.º 11
0
void Obstacle::createSphere(const std::string& strName, const float r, const int nRings, const int nSegments)
{
	MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	SubMesh *pSphereVertex = pSphere->createSubMesh();
 
     pSphere->sharedVertexData = new VertexData();
     VertexData* vertexData = pSphere->sharedVertexData;
 
     // define the vertex format
     VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
     size_t currOffset = 0;
     // positions
     vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
     currOffset += VertexElement::getTypeSize(VET_FLOAT3);
     // normals
     vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL);
     currOffset += VertexElement::getTypeSize(VET_FLOAT3);
     // two dimensional texture coordinates
     vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
     currOffset += VertexElement::getTypeSize(VET_FLOAT2);
 
     // allocate the vertex buffer
     vertexData->vertexCount = (nRings + 1) * (nSegments+1);
     HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
     VertexBufferBinding* binding = vertexData->vertexBufferBinding;
     binding->setBinding(0, vBuf);
     float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD));
 
     // allocate index buffer
     pSphereVertex->indexData->indexCount = 6 * nRings * (nSegments + 1);
     pSphereVertex->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
     HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer;
     unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD));
 
     float fDeltaRingAngle = (Math::PI / nRings);
     float fDeltaSegAngle = (2 * Math::PI / nSegments);
     unsigned short wVerticeIndex = 0 ;
 
     // Generate the group of rings for the sphere
     for( int ring = 0; ring <= nRings; ring++ ) {
         float r0 = r * sinf (ring * fDeltaRingAngle);
         float y0 = r * cosf (ring * fDeltaRingAngle);
 
         // Generate the group of segments for the current ring
         for(int seg = 0; seg <= nSegments; seg++) {
             float x0 = r0 * sinf(seg * fDeltaSegAngle);
             float z0 = r0 * cosf(seg * fDeltaSegAngle);
 
             // Add one vertex to the strip which makes up the sphere
             *pVertex++ = x0;
             *pVertex++ = y0;
             *pVertex++ = z0;
 
             Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy();
             *pVertex++ = vNormal.x;
             *pVertex++ = vNormal.y;
             *pVertex++ = vNormal.z;
 
             *pVertex++ = (float) seg / (float) nSegments;
             *pVertex++ = (float) ring / (float) nRings;
 
             if (ring != nRings) {
                                // each vertex (except the last) has six indices pointing to it
                 *pIndices++ = wVerticeIndex + nSegments + 1;
                 *pIndices++ = wVerticeIndex;               
                 *pIndices++ = wVerticeIndex + nSegments;
                 *pIndices++ = wVerticeIndex + nSegments + 1;
                 *pIndices++ = wVerticeIndex + 1;
                 *pIndices++ = wVerticeIndex;
                 wVerticeIndex ++;
             }
         }; // end for seg
     } // end for ring
 
     // Unlock
     vBuf->unlock();
     iBuf->unlock();
     // Generate face list
     pSphereVertex->useSharedVertices = true;
 
     // the original code was missing this line:
	 pSphere->_setBounds( AxisAlignedBox( Vector3(-r, -r, -r), Vector3(r, r, r) ), false );
	 pSphere->_setBoundingSphereRadius(r);
         // this line makes clear the mesh is loaded (avoids memory leaks)
	 pSphere->load();
}
Exemplo n.º 12
0
void ModelConverter::WriteSubMesh( DiSubMesh* subMod, const Ogre::SubMesh* s )
{
	switch(s->operationType)
	{
	case RenderOperation::OT_LINE_LIST:
		subMod->SetPrimitiveType(D3DPT_LINELIST);
		break;
	case RenderOperation::OT_LINE_STRIP:
		subMod->SetPrimitiveType(D3DPT_LINESTRIP);
		break;
	case RenderOperation::OT_POINT_LIST:
		subMod->SetPrimitiveType(D3DPT_POINTLIST);
		break;
	case RenderOperation::OT_TRIANGLE_FAN:
		subMod->SetPrimitiveType(D3DPT_TRIANGLEFAN);
		break;
	case RenderOperation::OT_TRIANGLE_LIST:
		subMod->SetPrimitiveType(PT_TRIANGLELIST);
		break;
	case RenderOperation::OT_TRIANGLE_STRIP:
		subMod->SetPrimitiveType(D3DPT_TRIANGLESTRIP);
		break;
	}

	VertexData* vertexData = nullptr;
	if (mMesh->sharedVertexData)
	{
		vertexData = mMesh->sharedVertexData;
	}
	else
	{
		vertexData = s->vertexData;
	}

	int numFaces = 0;
	switch(s->operationType)
	{
	case RenderOperation::OT_TRIANGLE_LIST:
		// triangle list
		numFaces = s->indexData->indexCount / 3;

		break;
	case RenderOperation::OT_LINE_LIST:
		numFaces = s->indexData->indexCount / 2;

		break;
	case RenderOperation::OT_TRIANGLE_FAN:
	case RenderOperation::OT_TRIANGLE_STRIP:
		// triangle fan or triangle strip
		numFaces = s->indexData->indexCount - 2;

		break;
	default:
		OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
			"Unsupported render operation type", 
			__FUNCTION__);
	}

	subMod->SetPrimitiveCount(numFaces);
	subMod->SetVerticeNum(vertexData->vertexCount);

	// material name
	DiString matName;
	matName.Format("%s_%d.mtl",subMod->GetParentMesh()->GetName().c_str(),subMod->GetIndex());
	subMod->SetMaterialName(matName);

	bool use32BitIndexes = (!s->indexData->indexBuffer.isNull() && 
		s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT);

	// Write each face in turn
	unsigned int* pInt = 0;
	unsigned short* pShort = 0;
	HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer;

	// index data
	if (use32BitIndexes)
	{
		pInt = static_cast<unsigned int*>(
			ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); 
	}
	else
	{
		pShort = static_cast<unsigned short*>(
			ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); 
	}

	void* indata = subMod->CreateIndexData(s->indexData->indexCount,use32BitIndexes?TRUE:FALSE);
	if (use32BitIndexes)
	{
		memcpy(indata,pInt,sizeof(unsigned int)*s->indexData->indexCount);
	}
	else
	{
		memcpy(indata,pShort,sizeof(unsigned short)*s->indexData->indexCount);
	}

	ibuf->unlock();

	// vertex declaration
	VertexDeclaration* decl = vertexData->vertexDeclaration;
	VertexBufferBinding* bind = vertexData->vertexBufferBinding;

	VertexBufferBinding::VertexBufferBindingMap::const_iterator b, bend;
	bend = bind->getBindings().end();
	// iterate over buffers
	int bindCount = 0;
	for(b = bind->getBindings().begin(); b != bend; ++b,++bindCount)
	{
		const HardwareVertexBufferSharedPtr vbuf = b->second;
		unsigned short bufferIdx = b->first;
		// get all the elements that relate to this buffer			
		VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx);
		VertexDeclaration::VertexElementList::iterator i, iend;
		iend = elems.end();

		unsigned short nuDemiureCoords = 0;
		for (i = elems.begin(); i != iend; ++i)
		{
			VertexElement& elem = *i;

			D3DDECLTYPE type = ConverteVertType(elem.getType());
			D3DDECLUSAGE usage;
			bool texcoord = false;
			switch(elem.getSemantic())
			{
			case VES_POSITION:
				usage = D3DDECLUSAGE_POSITION;
				break;
			case VES_NORMAL:
				usage = D3DDECLUSAGE_NORMAL;
				break;
			case VES_TANGENT:
				usage = D3DDECLUSAGE_TANGENT;
				break;
			case VES_BINORMAL:
				usage = D3DDECLUSAGE_BINORMAL;
				break;
			case VES_DIFFUSE:
			case VES_SPECULAR:
				usage = D3DDECLUSAGE_COLOR;
				break;
			case VES_TEXTURE_COORDINATES:
				usage = D3DDECLUSAGE_TEXCOORD;
				++nuDemiureCoords;
				texcoord = true;
				break;
			default:
				DI_ERROR("Unsupported semantic");
			}

			subMod->GetVertexElements().AddElement(bindCount,type,usage,texcoord?nuDemiureCoords-1:0);
		}

		int stride = subMod->GetVertexElements().GetStreamElementsSize(bindCount);
		void* vertData = subMod->CreateSourceData(bindCount,vertexData->vertexCount,stride);

		unsigned char* pVert = static_cast<unsigned char*>(
			vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
		memcpy(vertData,pVert,vertexData->vertexCount*stride);
		vbuf->unlock();
	}

	// vertex weight
	if (mMesh->hasSkeleton())
	{
		LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments...");

		if(const_cast<SubMesh*>(s)->getBoneAssignments().empty())
		{
			SubMesh::BoneAssignmentIterator bi = mMesh->getBoneAssignmentIterator();
			while (bi.hasMoreElements())
			{
				const VertexBoneAssignment& assign = bi.getNext();
				if (assign.weight > 0.0f)
				{
					subMod->AddWeight(assign.vertexIndex,assign.boneIndex,assign.weight);
				}
			}
		}
		else
		{
			SubMesh::BoneAssignmentIterator bi = (const_cast<SubMesh*>(s))->getBoneAssignmentIterator();
			while (bi.hasMoreElements())
			{
				const VertexBoneAssignment& assign = bi.getNext();
				if (assign.weight > 0.0f)
				{
					subMod->AddWeight(assign.vertexIndex,assign.boneIndex,assign.weight);
				}
			}
		}
		
		subMod->RationaliseBoneWeights();
	}
}
Exemplo n.º 13
0
	// ------------------------------------------------------------------------
	void ShadowCaster::generateShadowVolume(EdgeData* edgeData, 
		const HardwareIndexBufferSharedPtr& indexBuffer, const Light* light,
		ShadowRenderableList& shadowRenderables, unsigned long flags)
	{
		// Edge groups should be 1:1 with shadow renderables
		assert(edgeData->edgeGroups.size() == shadowRenderables.size());

		// Whether to use the McGuire method, a triangle fan covering all silhouette
		// this won't work properly with multiple separate edge groups
		bool useMcGuire = edgeData->edgeGroups.size() <= 1;
		EdgeData::EdgeGroupList::const_iterator egi, egiend;
		ShadowRenderableList::const_iterator si;

		Light::LightTypes lightType = light->getType();

		// pre-count the size of index data we need since it makes a big perf difference
		// to GL in particular if we lock a smaller area of the index buffer
		size_t preCountIndexes = 0;

		si = shadowRenderables.begin();
		egiend = edgeData->edgeGroups.end();
		for (egi = edgeData->edgeGroups.begin(); egi != egiend; ++egi, ++si)
		{
			const EdgeData::EdgeGroup& eg = *egi;
			bool  firstDarkCapTri = true;

			EdgeData::EdgeList::const_iterator i, iend;
			iend = eg.edges.end();
			for (i = eg.edges.begin(); i != iend; ++i)
			{
				const EdgeData::Edge& edge = *i;

				// Silhouette edge, when two tris has opposite light facing, or
				// degenerate edge where only tri 1 is valid and the tri light facing
				char lightFacing = edgeData->triangleLightFacings[edge.triIndex[0]];
				if ((edge.degenerate && lightFacing) ||
					(!edge.degenerate && (lightFacing != edgeData->triangleLightFacings[edge.triIndex[1]])))
				{

					preCountIndexes += 3;

					// Are we extruding to infinity?
					if (!(lightType == Light::LT_DIRECTIONAL &&
						flags & SRF_EXTRUDE_TO_INFINITY))
					{
						preCountIndexes += 3;
					}

					if(useMcGuire)
					{
						// Do dark cap tri
						// Use McGuire et al method, a triangle fan covering all silhouette
						// edges and one point (taken from the initial tri)
						if (flags & SRF_INCLUDE_DARK_CAP)
						{
							if (firstDarkCapTri)
							{
								firstDarkCapTri = false;
							}
							else
							{
								preCountIndexes += 3;
							}
						}
					}
				}

			}

			if(useMcGuire)
			{
				// Do light cap
				if (flags & SRF_INCLUDE_LIGHT_CAP) 
				{
					// Iterate over the triangles which are using this vertex set
					EdgeData::TriangleList::const_iterator ti, tiend;
					EdgeData::TriangleLightFacingList::const_iterator lfi;
					ti = edgeData->triangles.begin() + eg.triStart;
					tiend = ti + eg.triCount;
					lfi = edgeData->triangleLightFacings.begin() + eg.triStart;
					for ( ; ti != tiend; ++ti, ++lfi)
					{
						const EdgeData::Triangle& t = *ti;
						assert(t.vertexSet == eg.vertexSet);
						// Check it's light facing
						if (*lfi)
						{
							preCountIndexes += 3;
						}
					}

				}
			}
			else
			{
				// Do both caps
				int increment = ((flags & SRF_INCLUDE_DARK_CAP) ? 3 : 0) + ((flags & SRF_INCLUDE_LIGHT_CAP) ? 3 : 0);
				if(increment != 0)
				{
					// Iterate over the triangles which are using this vertex set
					EdgeData::TriangleList::const_iterator ti, tiend;
					EdgeData::TriangleLightFacingList::const_iterator lfi;
					ti = edgeData->triangles.begin() + eg.triStart;
					tiend = ti + eg.triCount;
					lfi = edgeData->triangleLightFacings.begin() + eg.triStart;
					for ( ; ti != tiend; ++ti, ++lfi)
					{
						const EdgeData::Triangle& t = *ti;
						assert(t.vertexSet == eg.vertexSet);
						// Check it's light facing
						if (*lfi)
							preCountIndexes += increment;
					}
					break;
				}
			}
		}
		// End pre-count


		// Lock index buffer for writing, just enough length as we need
		unsigned short* pIdx = static_cast<unsigned short*>(
			indexBuffer->lock(0, sizeof(unsigned short) * preCountIndexes, 
			HardwareBuffer::HBL_DISCARD));
		size_t numIndices = 0;

		// Iterate over the groups and form renderables for each based on their
		// lightFacing
		si = shadowRenderables.begin();
		egiend = edgeData->edgeGroups.end();
		for (egi = edgeData->edgeGroups.begin(); egi != egiend; ++egi, ++si)
		{
			const EdgeData::EdgeGroup& eg = *egi;
			// Initialise the index start for this shadow renderable
			IndexData* indexData = (*si)->getRenderOperationForUpdate()->indexData;
			indexData->indexStart = numIndices;
			// original number of verts (without extruded copy)
			size_t originalVertexCount = eg.vertexData->vertexCount;
			bool  firstDarkCapTri = true;
			unsigned short darkCapStart;

			EdgeData::EdgeList::const_iterator i, iend;
			iend = eg.edges.end();
			for (i = eg.edges.begin(); i != iend; ++i)
			{
				const EdgeData::Edge& edge = *i;

				// Silhouette edge, when two tris has opposite light facing, or
				// degenerate edge where only tri 1 is valid and the tri light facing
				char lightFacing = edgeData->triangleLightFacings[edge.triIndex[0]];
				if ((edge.degenerate && lightFacing) ||
					(!edge.degenerate && (lightFacing != edgeData->triangleLightFacings[edge.triIndex[1]])))
				{
					size_t v0 = edge.vertIndex[0];
					size_t v1 = edge.vertIndex[1];
					if (!lightFacing)
					{
						// Inverse edge indexes when t1 is light away
						std::swap(v0, v1);
					}

					/* Note edge(v0, v1) run anticlockwise along the edge from
					the light facing tri so to point shadow volume tris outward,
					light cap indexes have to be backwards

					We emit 2 tris if light is a point light, 1 if light 
					is directional, because directional lights cause all
					points to converge to a single point at infinity.

					First side tri = near1, near0, far0
					Second tri = far0, far1, near1

					'far' indexes are 'near' index + originalVertexCount
					because 'far' verts are in the second half of the 
					buffer
					*/
					assert(v1 < 65536 && v0 < 65536 && (v0 + originalVertexCount) < 65536 &&
						"Vertex count exceeds 16-bit index limit!");
					*pIdx++ = static_cast<unsigned short>(v1);
					*pIdx++ = static_cast<unsigned short>(v0);
					*pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount);
					numIndices += 3;

					// Are we extruding to infinity?
					if (!(lightType == Light::LT_DIRECTIONAL &&
						flags & SRF_EXTRUDE_TO_INFINITY))
					{
						// additional tri to make quad
						*pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount);
						*pIdx++ = static_cast<unsigned short>(v1 + originalVertexCount);
						*pIdx++ = static_cast<unsigned short>(v1);
						numIndices += 3;
					}

					if(useMcGuire)
					{
						// Do dark cap tri
						// Use McGuire et al method, a triangle fan covering all silhouette
						// edges and one point (taken from the initial tri)
						if (flags & SRF_INCLUDE_DARK_CAP)
						{
							if (firstDarkCapTri)
							{
								darkCapStart = static_cast<unsigned short>(v0 + originalVertexCount);
								firstDarkCapTri = false;
							}
							else
							{
								*pIdx++ = darkCapStart;
								*pIdx++ = static_cast<unsigned short>(v1 + originalVertexCount);
								*pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount);
								numIndices += 3;
							}

						}
					}
				}

			}

			if(!useMcGuire)
			{
				// Do dark cap
				if (flags & SRF_INCLUDE_DARK_CAP) 
				{
					// Iterate over the triangles which are using this vertex set
					EdgeData::TriangleList::const_iterator ti, tiend;
					EdgeData::TriangleLightFacingList::const_iterator lfi;
					ti = edgeData->triangles.begin() + eg.triStart;
					tiend = ti + eg.triCount;
					lfi = edgeData->triangleLightFacings.begin() + eg.triStart;
					for ( ; ti != tiend; ++ti, ++lfi)
					{
						const EdgeData::Triangle& t = *ti;
						assert(t.vertexSet == eg.vertexSet);
						// Check it's light facing
						if (*lfi)
						{
							assert(t.vertIndex[0] < 65536 && t.vertIndex[1] < 65536 &&
								t.vertIndex[2] < 65536 && 
								"16-bit index limit exceeded!");
							*pIdx++ = static_cast<unsigned short>(t.vertIndex[1] + originalVertexCount);
							*pIdx++ = static_cast<unsigned short>(t.vertIndex[0] + originalVertexCount);
							*pIdx++ = static_cast<unsigned short>(t.vertIndex[2] + originalVertexCount);
							numIndices += 3;
						}
					}

				}
			}

			// Do light cap
			if (flags & SRF_INCLUDE_LIGHT_CAP) 
			{
				// separate light cap?
				if ((*si)->isLightCapSeparate())
				{
					// update index count for this shadow renderable
					indexData->indexCount = numIndices - indexData->indexStart;

					// get light cap index data for update
					indexData = (*si)->getLightCapRenderable()->getRenderOperationForUpdate()->indexData;
					// start indexes after the current total
					indexData->indexStart = numIndices;
				}

				// Iterate over the triangles which are using this vertex set
				EdgeData::TriangleList::const_iterator ti, tiend;
				EdgeData::TriangleLightFacingList::const_iterator lfi;
				ti = edgeData->triangles.begin() + eg.triStart;
				tiend = ti + eg.triCount;
				lfi = edgeData->triangleLightFacings.begin() + eg.triStart;
				for ( ; ti != tiend; ++ti, ++lfi)
				{
					const EdgeData::Triangle& t = *ti;
					assert(t.vertexSet == eg.vertexSet);
					// Check it's light facing
					if (*lfi)
					{
						assert(t.vertIndex[0] < 65536 && t.vertIndex[1] < 65536 &&
							t.vertIndex[2] < 65536 && 
							"16-bit index limit exceeded!");
						*pIdx++ = static_cast<unsigned short>(t.vertIndex[0]);
						*pIdx++ = static_cast<unsigned short>(t.vertIndex[1]);
						*pIdx++ = static_cast<unsigned short>(t.vertIndex[2]);
						numIndices += 3;
					}
				}

			}

			// update index count for current index data (either this shadow renderable or its light cap)
			indexData->indexCount = numIndices - indexData->indexStart;

		}


		// Unlock index buffer
		indexBuffer->unlock();

		// In debug mode, check we didn't overrun the index buffer
		assert(numIndices <= indexBuffer->getNumIndexes() &&
			"Index buffer overrun while generating shadow volume!! "
			"You must increase the size of the shadow index buffer.");

	}