//------------------------------------------------------------------------------------------------
void VertexIndexToShape::addIndexData(IndexData* data, const unsigned int offset) {
    const unsigned int prev_size = mIndexCount;
    mIndexCount += (unsigned int)data->indexCount;

    unsigned int* tmp_ind = new unsigned int[mIndexCount];
    if(mIndexBuffer) {
        memcpy(tmp_ind, mIndexBuffer, sizeof(unsigned int) * prev_size);
        delete[] mIndexBuffer;
    }
    mIndexBuffer = tmp_ind;

    const unsigned int numTris = (unsigned int) data->indexCount / 3;
    HardwareIndexBufferSharedPtr ibuf = data->indexBuffer;
    const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
    unsigned int index_offset = prev_size;

    if(use32bitindexes) {
        const unsigned int* pInt = static_cast<unsigned int*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
        for(unsigned int k = 0; k < numTris; ++k) {
            mIndexBuffer[index_offset ++] = offset + *pInt++;
            mIndexBuffer[index_offset ++] = offset + *pInt++;
            mIndexBuffer[index_offset ++] = offset + *pInt++;
        }
        ibuf->unlock();
    } else {
        const unsigned short* pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
        for(unsigned int k = 0; k < numTris; ++k) {
            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int>(*pShort++);
            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int>(*pShort++);
            mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int>(*pShort++);
        }
        ibuf->unlock();
    }

}
Esempio n. 2
0
void GeomUtils::createCone(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData, 
					   float radius , float height, int nVerticesInBase)
{
	assert(vertexData && indexData);

	// define the vertex format
	VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
	// positions
	vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION);
	
	// allocate the vertex buffer
	vertexData->vertexCount = nVerticesInBase + 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 - cone and base
	indexData->indexCount = (3 * nVerticesInBase) + (3 * (nVerticesInBase - 2));
	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));

	//Positions : cone head and base
	for (int i=0; i<3; i++)
		*pVertex++ = 0.0f;

	//Base :
	float fDeltaBaseAngle = (2 * Math::PI) / nVerticesInBase;
	for (int i=0; i<nVerticesInBase; i++)
	{
		float angle = i * fDeltaBaseAngle;
		*pVertex++ = radius * cosf(angle);
		*pVertex++ = height;
		*pVertex++ = radius * sinf(angle);
	}

	//Indices :
	//Cone head to vertices
	for (int i=0; i<nVerticesInBase; i++)
	{
		*pIndices++ = 0;
		*pIndices++ = (i%nVerticesInBase) + 1;
		*pIndices++ = ((i+1)%nVerticesInBase) + 1;
	}
	//Cone base
	for (int i=0; i<nVerticesInBase-2; i++)
	{
		*pIndices++ = 1;
		*pIndices++ = i + 3;
		*pIndices++ = i + 2;
	}

	// Unlock
	vBuf->unlock();
	iBuf->unlock();
}
  void DebugRectangle2D::setCorners(Real left, Real top, Real right, Real bottom)
  {
    VertexDeclaration * const decl = mRenderOp.vertexData->vertexDeclaration;
    const VertexElement* poselem = decl->findElementBySemantic(VES_POSITION);
    const VertexElement* colorelem = decl->findElementBySemantic(VES_DIFFUSE);

    HardwareVertexBufferSharedPtr vbuf =
    mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);

    const size_t vertexSize = vbuf->getVertexSize ();
    float *pPos;
    RGBA *pColor;
    Root * const root = Root::getSingletonPtr();

    uchar* pMain = static_cast<uchar *>(
        vbuf->lock(HardwareBuffer::HBL_DISCARD));

//    #define V3(AX, AY, AZ, ACOLOR) poselem->baseVertexPointerToElement(pMain, &pPos); \
//            *pPos++ = AX; *pPos++ =  AY; *pPos++ =  AZ; \
//            pMain += vertexSize;

#define V3(A_X, A_Y, A_Z, ACOLOR) poselem->baseVertexPointerToElement(pMain, &pPos); \
			*pPos++ = static_cast <float> (A_X); \
			*pPos++ = static_cast <float> (A_Y); \
			*pPos++ = static_cast <float> (A_Z); \
            colorelem->baseVertexPointerToElement(pMain, &pColor); \
            root->convertColourValue (ACOLOR, pColor); \
            pMain += vertexSize;

    V3(left, top, -1.0f, ColourValue::White)
    V3(left, bottom, -1.0f, ColourValue::White)
    V3(right, bottom, -1.0f, ColourValue::White)
    V3(right, top, -1.0f, ColourValue::White)

    vbuf->unlock();

    HardwareIndexBufferSharedPtr iBuf = mRenderOp.indexData->indexBuffer;
    ushort* pIdx = static_cast<ushort*>(
        iBuf->lock(0, iBuf->getSizeInBytes(),HardwareBuffer::HBL_DISCARD));

    *pIdx++ = static_cast<ushort> (0); *pIdx++ = static_cast<ushort> (1); // line 1
    *pIdx++ = static_cast<ushort> (1); *pIdx++ = static_cast<ushort> (2);// line 2
    *pIdx++ = static_cast<ushort> (2); *pIdx++ = static_cast<ushort> (3);// line 3
    *pIdx++ = static_cast<ushort> (3); *pIdx++ = static_cast<ushort> (0);// line 4

    iBuf->unlock();
  }
Esempio n. 4
0
void createSphere(const std::string& strName, const float r, const int nRings = 16, const int nSegments = 16)
{
	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();
}
void SurfacePatchRenderable::createHardwareBuffers()
{
	VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding;

	HardwareVertexBufferSharedPtr vbuf =
		HardwareBufferManager::getSingleton().createVertexBuffer(
		mRenderOp.vertexData->vertexDeclaration->getVertexSize(0),
		mRenderOp.vertexData->vertexCount,
  		HardwareBuffer::HBU_STATIC_WRITE_ONLY,
		false);

	bind->setBinding(0, vbuf);

	HardwareIndexBufferSharedPtr ibuf =
		HardwareBufferManager::getSingleton().createIndexBuffer(
		HardwareIndexBuffer::IT_32BIT, // type of index
		mRenderOp.indexData->indexCount, // number of indexes
  		HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage
		false); // no shadow buffer	

	mRenderOp.indexData->indexBuffer = ibuf;	

	Vector3 vaabMin(std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max());
	Vector3 vaabMax(0.0, 0.0, 0.0);
	
	Real* prPos = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));

	const float textureWeights[3][3] = {{1, 0, 0},
										{0, 1, 0},
  										{0, 0, 1}};
										
	/*const int textureNumberOffsets[3][3] = {{0, 1, 2},
											{-1, 0, 1},
		   									{-2, -1, 0}};*/
	
	for (int v = 0; v < patch->numVertices * 2; v += 2)
	{
		// Position
		*prPos++ = patch->vertices[v].x;
		*prPos++ = patch->vertices[v].y;
		*prPos++ = patch->vertices[v].z;

		// Normal
		*prPos++ = patch->vertices[v+1].x;
		*prPos++ = patch->vertices[v+1].y;
		*prPos++ = patch->vertices[v+1].z;

		// texture weights
		const int curIndex = patch->vertNumbers[v/2];
		const int posInTriangle = curIndex % 3;
		*prPos++ = textureWeights[posInTriangle][0];
		*prPos++ = textureWeights[posInTriangle][1];
		*prPos++ = textureWeights[posInTriangle][2];

		// texture numbers
		for (int i = 0; i < posInTriangle; i++)
			*prPos++ = patch->textures[patch->indices[curIndex - (posInTriangle - i)]];
		*prPos++ = patch->textures[patch->indices[curIndex]];
		for (int i = posInTriangle + 1; i < 3; i++)
			*prPos++ = patch->textures[patch->indices[curIndex + (i - posInTriangle)]];

		// texture numbers
		//*prPos++ = patch->textures[(v/2)/3*3 + 0] + 0.5f;	// 0.5f: number between 0 and 1 as offset because in the shader,
		//*prPos++ = patch->textures[(v/2)/3*3 + 1] + 0.5f;	// floor() is used to determine the texture number as integer and this is
		//*prPos++ = patch->textures[(v/2)/3*3 + 2] + 0.5f;	// much too imprecise if the real texture numbers are passed in!

		// Adjust bounding box ...
		if (patch->vertices[v].x < vaabMin.x)
			vaabMin.x = patch->vertices[v].x;
		if (patch->vertices[v].y < vaabMin.y)
			vaabMin.y = patch->vertices[v].y;
		if (patch->vertices[v].z < vaabMin.z)
			vaabMin.z = patch->vertices[v].z;

		if (patch->vertices[v].x > vaabMax.x)
			vaabMax.x = patch->vertices[v].x;
		if (patch->vertices[v].y > vaabMax.y)
			vaabMax.y = patch->vertices[v].y;
		if (patch->vertices[v].z > vaabMax.z)
			vaabMax.z = patch->vertices[v].z;
	}		

	vbuf->unlock();

	mBox.setExtents(vaabMin, vaabMax);
	
	Ogre::uint* pIdx = static_cast<Ogre::uint*>(ibuf->lock(HardwareBuffer::HBL_DISCARD));
	for (int i = 0; i < patch->numIndices; i++)
	{
		*pIdx++ = patch->indices[i];
	}	

	ibuf->unlock();

	// Clean up the surface patch as much as possible
	delete[] patch->textures;
	delete[] patch->vertNumbers;
}
Esempio n. 6
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();

    }
Esempio n. 7
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);
	}

	// 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();
}
Esempio n. 8
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();
}
	//---------------------------------------------------------------------
	void TangentSpaceCalc::processFaces(Result& result)
	{
		// Quick pre-check for triangle strips / fans
		for (OpTypeList::iterator ot = mOpTypes.begin(); ot != mOpTypes.end(); ++ot)
		{
			if (*ot != RenderOperation::OT_TRIANGLE_LIST)
			{
				// Can't split strips / fans
				setSplitMirrored(false);
				setSplitRotated(false);
			}
		}

		for (size_t i = 0; i < mIDataList.size(); ++i)
		{
			IndexData* i_in = mIDataList[i];
			RenderOperation::OperationType opType = mOpTypes[i];

			// Read data from buffers
			uint16 *p16 = 0;
			uint32 *p32 = 0;

			HardwareIndexBufferSharedPtr ibuf = i_in->indexBuffer;
			if (ibuf->getType() == HardwareIndexBuffer::IT_32BIT)
			{
				p32 = static_cast<uint32*>(
					ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
				// offset by index start
				p32 += i_in->indexStart;
			}
			else
			{
				p16 = static_cast<uint16*>(
					ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
				// offset by index start
				p16 += i_in->indexStart;
			}
			// current triangle
			size_t vertInd[3] = { 0, 0, 0 };
			// loop through all faces to calculate the tangents and normals
			size_t faceCount = opType == RenderOperation::OT_TRIANGLE_LIST ? 
				i_in->indexCount / 3 : i_in->indexCount - 2;
			for (size_t f = 0; f < faceCount; ++f)
			{
				bool invertOrdering = false;
				// Read 1 or 3 indexes depending on type
				if (f == 0 || opType == RenderOperation::OT_TRIANGLE_LIST)
				{
					vertInd[0] = p32? *p32++ : *p16++;
					vertInd[1] = p32? *p32++ : *p16++;
					vertInd[2] = p32? *p32++ : *p16++;
				}
				else if (opType == RenderOperation::OT_TRIANGLE_FAN)
				{
					// Element 0 always remains the same
					// Element 2 becomes element 1
					vertInd[1] = vertInd[2];
					// read new into element 2
					vertInd[2] = p32? *p32++ : *p16++;
				}
				else if (opType == RenderOperation::OT_TRIANGLE_STRIP)
				{
					// Shunt everything down one, but also invert the ordering on 
					// odd numbered triangles (== even numbered i's)
					// we interpret front as anticlockwise all the time but strips alternate
					if (f & 0x1)
					{
						// odd tris (index starts at 3, 5, 7)
						invertOrdering = true;
					}
					vertInd[0] = vertInd[1];
					vertInd[1] = vertInd[2];			
					vertInd[2] = p32? *p32++ : *p16++;
				}

				// deal with strip inversion of winding
				size_t localVertInd[3];
				localVertInd[0] = vertInd[0];
				if (invertOrdering)
				{
					localVertInd[1] = vertInd[2];
					localVertInd[2] = vertInd[1];
				}
				else
				{
					localVertInd[1] = vertInd[1];
					localVertInd[2] = vertInd[2];
				}


				// For each triangle
				//   Calculate tangent & binormal per triangle
				//   Note these are not normalised, are weighted by UV area
				Vector3 faceTsU, faceTsV, faceNorm;
				calculateFaceTangentSpace(localVertInd, faceTsU, faceTsV, faceNorm);

				// Skip invalid UV space triangles
				if (faceTsU.isZeroLength() || faceTsV.isZeroLength())
					continue;

				addFaceTangentSpaceToVertices(i, f, localVertInd, faceTsU, faceTsV, faceNorm, result);

			}


			ibuf->unlock();
		}

	}
Esempio n. 10
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());

        EdgeData::EdgeGroupList::const_iterator egi, egiend;
        ShadowRenderableList::const_iterator si;

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

        // Lock index buffer for writing
        unsigned short* pIdx = static_cast<unsigned short*>(
            indexBuffer->lock(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
                    */
                    *pIdx++ = v1;
                    *pIdx++ = v0;
                    *pIdx++ = 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++ = v0 + originalVertexCount;
                        *pIdx++ = v1 + originalVertexCount;
                        *pIdx++ = v1;
                        numIndices += 3;
                    }

                    // 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 = v0 + originalVertexCount;
                            firstDarkCapTri = false;
                        }
                        else
                        {
                            *pIdx++ = darkCapStart;
                            *pIdx++ = v1 + originalVertexCount;
                            *pIdx++ = v0 + 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)
                    {
                        *pIdx++ = t.vertIndex[0];
                        *pIdx++ = t.vertIndex[1];
                        *pIdx++ = 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.");

    }
Esempio n. 11
0
//-----------------------------------------------------------------------------------------
bool TemplateUtils::getMeshInformation(const Mesh* mesh,
                        size_t &vertex_count,
						OgreVector3Array &vertices,
                        size_t &index_count,
                        LongArray &indices,
						const Vector3 position,
                        const Quaternion &orient,
                        const Vector3 &scale)
{
    bool added_shared = false;
    size_t current_offset = 0;
    size_t shared_offset = 0;
    size_t next_offset = 0;
    size_t index_offset = 0;
 
    vertex_count = index_count = 0;
 
    // Calculate how many vertices and indices we're going to need
    for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
    {
        SubMesh* submesh = mesh->getSubMesh(i);
		if(!submesh) {
			Exception(Exception::ERR_INTERNAL_ERROR,"Could not load submesh at index :" + i,"Mesh::getSubMesh");
		}
        // We only need to add the shared vertices once
        if(submesh->useSharedVertices)
        {
            if( !added_shared )
            {
                vertex_count += mesh->sharedVertexData->vertexCount;
                added_shared = true;
            }
        }
        else
        {
            vertex_count += submesh->vertexData->vertexCount;
        }
        // Add the indices
        index_count += submesh->indexData->indexCount;
    }
 
    // Allocate space for the vertices and indices

	// NO VALID DATA SHOULD BE PRESENT IN THE FOLLOWING 2 ARRAYS
	// UNTIL AFTER THE NEXT FOR LOOP

	/*
    vertices = new Ogre::Vector3 [vertex_count];
	std::vector<Ogre::Vector3> vertices [vertex_count];
    indices = new unsigned long [index_count];
	std::vector<long> indices [index_count];
	*/

	vertices.resize(vertex_count);
    indices.resize(index_count);

    added_shared = false;
 
    // Run through the submeshes again, adding the data into the arrays
    for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
    {
        SubMesh* submesh = mesh->getSubMesh(i);
		if(!submesh) {
			Exception(Exception::ERR_INTERNAL_ERROR,"Could not load submesh at index :" + i,"Mesh::getSubMesh");
		}
        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(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 will
            //  be comiled/typedefed as double:
            //Ogre::Real* pReal;
            float* pReal;
 
            for( size_t 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] = (orient * (pt * scale)) + position;
            }
 
            vbuf->unlock();
            next_offset += vertex_data->vertexCount;
        }
 
        IndexData* index_data = submesh->indexData;
        size_t numTris = index_data->indexCount / 3;
        HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
 
        bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
 
        unsigned int* pLong = static_cast<unsigned int*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY));
        unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
 
        size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset;
 
        if ( use32bitindexes )
        {
            for ( size_t k = 0; k < numTris*3; ++k)
            {
                indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset);
            }
        }
        else
        {
            for ( size_t k = 0; k < numTris*3; ++k)
            {
                indices[index_offset++] = static_cast<unsigned long>(pShort[k]) +
                                          static_cast<unsigned long>(offset);
            }
        }
 
        ibuf->unlock();
        current_offset = next_offset;
    }
	return true;
}
static MeshPtr importObject(QDataStream &stream)
{
    using namespace Ogre;

    QVector4D bbMin, bbMax;
    stream >> bbMin >> bbMax;

    float distance, distanceSquared; // Here's a bug for you: writes "double"'s instead of floats
    stream >> distanceSquared >> distance;

    MeshPtr ogreMesh = MeshManager::getSingleton().createManual("conversion",
                                                               ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

    int vertexCount, indexCount;
    stream >> vertexCount >> indexCount;

    VertexData *vertexData = new VertexData();
    ogreMesh->sharedVertexData = vertexData;

    LogManager::getSingleton().logMessage("Reading geometry...");
    VertexDeclaration* decl = vertexData->vertexDeclaration;
    VertexBufferBinding* bind = vertexData->vertexBufferBinding;
    unsigned short bufferId = 0;

    // Information for calculating bounds
    Vector3 min = Vector3::ZERO, max = Vector3::UNIT_SCALE, pos = Vector3::ZERO;
    Real maxSquaredRadius = -1;
    bool firstVertex = true;

    /*
      Create a vertex definition for our buffer
      */
    size_t offset = 0;

    const VertexElement &positionElement = decl->addElement(bufferId, offset, VET_FLOAT3, VES_POSITION);
    offset += VertexElement::getTypeSize(VET_FLOAT3);

    const VertexElement &normalElement = decl->addElement(bufferId, offset, VET_FLOAT3, VES_NORMAL);
    offset += VertexElement::getTypeSize(VET_FLOAT3);

    // calculate how many vertexes there actually are
    vertexData->vertexCount = vertexCount;

    // Now create the vertex buffer
    HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().
            createVertexBuffer(offset, vertexData->vertexCount,
                               HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);

    // Bind it
    bind->setBinding(bufferId, vbuf);

    // Lock it
    unsigned char *pVert = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
    unsigned char *pVertStart = pVert;

    QVector<float> positions;
    positions.reserve(vertexCount * 3);

    // Iterate over all children (vertexbuffer entries)
    for (int i = 0; i < vertexCount; ++i) {
        float *pFloat;

        QVector4D vertex;
        stream >> vertex;
		vertex.setZ(vertex.z() * -1);

        /* Copy over the position */
        positionElement.baseVertexPointerToElement(pVert, &pFloat);
        *(pFloat++) = (float)vertex.x();
        *(pFloat++) = (float)vertex.y();
        *(pFloat++) = (float)vertex.z();

        positions.append(vertex.x());
        positions.append(vertex.y());
        positions.append(vertex.z());

        /* While we're at it, calculate the bounding sphere */
        pos.x = vertex.x();
        pos.y = vertex.y();
        pos.z = vertex.z();

        if (firstVertex) {
            min = max = pos;
            maxSquaredRadius = pos.squaredLength();
            firstVertex = false;
        } else {
            min.makeFloor(pos);
            max.makeCeil(pos);
            maxSquaredRadius = qMax(pos.squaredLength(), maxSquaredRadius);
        }

        pVert += vbuf->getVertexSize();
    }

    // Set bounds
    const AxisAlignedBox& currBox = ogreMesh->getBounds();
    Real currRadius = ogreMesh->getBoundingSphereRadius();
    if (currBox.isNull())
    {
        //do not pad the bounding box
        ogreMesh->_setBounds(AxisAlignedBox(min, max), false);
        ogreMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius));
    }
    else
    {
        AxisAlignedBox newBox(min, max);
        newBox.merge(currBox);
        //do not pad the bounding box
        ogreMesh->_setBounds(newBox, false);
        ogreMesh->_setBoundingSphereRadius(qMax(Math::Sqrt(maxSquaredRadius), currRadius));
    }

    /*
       Create faces
     */
    // All children should be submeshes
    SubMesh* sm = ogreMesh->createSubMesh();
    sm->setMaterialName("clippingMaterial");
    sm->operationType = RenderOperation::OT_TRIANGLE_LIST;
    sm->useSharedVertices = true;

    // tri list
    sm->indexData->indexCount = indexCount;

    // Allocate space
    HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
            createIndexBuffer(
                HardwareIndexBuffer::IT_16BIT,
                sm->indexData->indexCount,
                HardwareBuffer::HBU_DYNAMIC,
                false);
    sm->indexData->indexBuffer = ibuf;

    unsigned short *pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_DISCARD));

    QVector<EdgeData::Triangle> triangles(indexCount / 3);

    for (int i = 0; i < indexCount / 3; ++i) {
        quint16 i1, i2, i3;

        stream >> i1 >> i2 >> i3;
        *pShort++ = i1;
        *pShort++ = i2;
        *pShort++ = i3;

        triangles[i].vertIndex[0] = i1;
        triangles[i].vertIndex[1] = i2;
        triangles[i].vertIndex[2] = i3;

    }

    /* Recalculate the vertex normals */
    Vector4 *faceNormals = (Vector4*)_aligned_malloc(sizeof(Vector4) * triangles.size(), 16);

    OptimisedUtil *util = OptimisedUtil::getImplementation();
    util->calculateFaceNormals(positions.constData(),
                               triangles.data(),
                               faceNormals,
                               indexCount / 3);

	 // Iterate over all children (vertexbuffer entries)
	pVert = pVertStart;
    for (int i = 0; i < vertexCount; ++i) {
        float *pFloat;

		Vector3 normal = Vector3::ZERO;
		
		int count = 0;

		/* Search for all faces that use this vertex */
		for (int j = 0; j < triangles.size(); ++j) {
			if (triangles[j].vertIndex[0] == i 
				|| triangles[j].vertIndex[1] == i 
				|| triangles[j].vertIndex[2] == i) {
				normal.x += faceNormals[j].x / faceNormals[j].w;
				normal.y += faceNormals[j].y / faceNormals[j].w;
				normal.z += faceNormals[j].z / faceNormals[j].w;
				count++;
			}
		}

		normal.normalise();

        /* Copy over the position */
		normalElement.baseVertexPointerToElement(pVert, &pFloat);
        *(pFloat++) = normal.x;
        *(pFloat++) = normal.y;
        *(pFloat++) = normal.z;
		
        pVert += vbuf->getVertexSize();
    }

    _aligned_free(faceNormals);

    vbuf->unlock();
    ibuf->unlock();

    return ogreMesh;
}
Esempio n. 13
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();

}
Esempio n. 14
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;
	}
}
Esempio n. 15
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();
}
Esempio n. 16
0
    //---------------------------------------------------------------------
    void ProgressiveMesh::addWorkingData(const VertexData * vertexData, 
        const IndexData * indexData)
    {
        // Insert blank working data, then fill 
        mWorkingData.push_back(PMWorkingData());

        PMWorkingData& work = mWorkingData.back();

        // Build vertex list
		// Resize face list (this will always be this big)
		work.mFaceVertList.resize(vertexData->vertexCount);
		// Also resize common vert list to max, to avoid reallocations
		work.mVertList.resize(vertexData->vertexCount);

		// locate position element & hte buffer to go with it
		const VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
		HardwareVertexBufferSharedPtr vbuf = 
			vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
		// lock the buffer for reading
		unsigned char* pVertex = static_cast<unsigned char*>(
			vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
		float* pFloat;
		Vector3 pos;
		// Map for identifying duplicate position vertices
		typedef std::map<Vector3, size_t, vectorLess> CommonVertexMap;
		CommonVertexMap commonVertexMap;
		CommonVertexMap::iterator iCommonVertex;
		size_t numCommon = 0;
        size_t i = 0;
        for (i = 0; i < vertexData->vertexCount; ++i, pVertex += vbuf->getVertexSize())
        {
			posElem->baseVertexPointerToElement(pVertex, &pFloat);

            pos.x = *pFloat++;
            pos.y = *pFloat++;
            pos.z = *pFloat++;

			// Try to find this position in the existing map 
			iCommonVertex = commonVertexMap.find(pos);
			if (iCommonVertex == commonVertexMap.end())
			{
				// Doesn't exist, so create it
				PMVertex* commonVert = &(work.mVertList[numCommon]);
				commonVert->setDetails(pos, numCommon);
				commonVert->removed = false;
				commonVert->toBeRemoved = false;
				commonVert->seam = false;

				// Enter it in the map
				commonVertexMap.insert(CommonVertexMap::value_type(pos, numCommon) );
				// Increment common index
				++numCommon;

				work.mFaceVertList[i].commonVertex = commonVert;
				work.mFaceVertList[i].realIndex = i;
			}
			else
			{
				// Exists already, reference it
				PMVertex* existingVert = &(work.mVertList[iCommonVertex->second]);
				work.mFaceVertList[i].commonVertex = existingVert;
				work.mFaceVertList[i].realIndex = i;

				// Also tag original as a seam since duplicates at this location
				work.mFaceVertList[i].commonVertex->seam = true;

			}
			
        }
		vbuf->unlock();

		mNumCommonVertices = numCommon;

        // Build tri list
        size_t numTris = indexData->indexCount / 3;
		unsigned short* pShort;
		unsigned int* pInt;
		HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer;
		bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT);
		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));
		}
        work.mTriList.resize(numTris); // assumed tri list
        for (i = 0; i < numTris; ++i)
        {
			PMFaceVertex *v0, *v1, *v2;
			// use 32-bit index always since we're not storing
			unsigned int vindex = use32bitindexes? *pInt++ : *pShort++;
			v0 = &(work.mFaceVertList[vindex]);
			vindex = use32bitindexes? *pInt++ : *pShort++;
			v1 = &(work.mFaceVertList[vindex]);
			vindex = use32bitindexes? *pInt++ : *pShort++;
			v2 = &(work.mFaceVertList[vindex]);

			work.mTriList[i].setDetails(i, v0, v1, v2);

            work.mTriList[i].removed = false;

        }
		ibuf->unlock();

    }
	//---------------------------------------------------------------------
	void TangentSpaceCalc::extendBuffers(VertexSplits& vertexSplits)
	{
		if (!vertexSplits.empty())
		{
			// ok, need to increase the vertex buffer size, and alter some indexes

			// vertex buffers first
			VertexBufferBinding* newBindings = HardwareBufferManager::getSingleton().createVertexBufferBinding();
			const VertexBufferBinding::VertexBufferBindingMap& bindmap = 
				mVData->vertexBufferBinding->getBindings();
			for (VertexBufferBinding::VertexBufferBindingMap::const_iterator i = 
				bindmap.begin(); i != bindmap.end(); ++i)
			{
				HardwareVertexBufferSharedPtr srcbuf = i->second;
				// Derive vertex count from buffer not vertex data, in case using
				// the vertexStart option in vertex data
				size_t newVertexCount = srcbuf->getNumVertices() + vertexSplits.size();
				// Create new buffer & bind
				HardwareVertexBufferSharedPtr newBuf = 
					HardwareBufferManager::getSingleton().createVertexBuffer(
					srcbuf->getVertexSize(), newVertexCount, srcbuf->getUsage(), 
					srcbuf->hasShadowBuffer());
				newBindings->setBinding(i->first, newBuf);

				// Copy existing contents (again, entire buffer, not just elements referenced)
				newBuf->copyData(*(srcbuf.get()), 0, 0, srcbuf->getNumVertices() * srcbuf->getVertexSize(), true);

				// Split vertices, read / write from new buffer
				char* pBase = static_cast<char*>(newBuf->lock(HardwareBuffer::HBL_NORMAL));
				for (VertexSplits::iterator spliti = vertexSplits.begin(); 
					spliti != vertexSplits.end(); ++spliti)
				{
					const char* pSrcBase = pBase + spliti->first * newBuf->getVertexSize();
					char* pDstBase = pBase + spliti->second * newBuf->getVertexSize();
					memcpy(pDstBase, pSrcBase, newBuf->getVertexSize());
				}
				newBuf->unlock();

			}

			// Update vertex data
			// Increase vertex count according to num splits
			mVData->vertexCount += vertexSplits.size();
			// Flip bindings over to new buffers (old buffers released)
			HardwareBufferManager::getSingleton().destroyVertexBufferBinding(mVData->vertexBufferBinding);
			mVData->vertexBufferBinding = newBindings;

			// If vertex size requires 32bit index buffer
			if (mVData->vertexCount > 65536)
			{
				for (size_t i = 0; i < mIDataList.size(); ++i)
				{
					// check index size
					IndexData* idata = mIDataList[i];
					HardwareIndexBufferSharedPtr srcbuf = idata->indexBuffer;
					if (srcbuf->getType() == HardwareIndexBuffer::IT_16BIT)
					{
						size_t indexCount = srcbuf->getNumIndexes();

						// convert index buffer to 32bit.
						HardwareIndexBufferSharedPtr newBuf =
							HardwareBufferManager::getSingleton().createIndexBuffer(
							HardwareIndexBuffer::IT_32BIT, indexCount,
							srcbuf->getUsage(), srcbuf->hasShadowBuffer());

						uint16* pSrcBase = static_cast<uint16*>(srcbuf->lock(HardwareBuffer::HBL_NORMAL));
						uint32* pBase = static_cast<uint32*>(newBuf->lock(HardwareBuffer::HBL_NORMAL));

						size_t j = 0;
						while (j < indexCount)
						{
							*pBase++ = *pSrcBase++;
							++j;
						}

						srcbuf->unlock();
						newBuf->unlock();

						// assign new index buffer.
						idata->indexBuffer = newBuf;
					}
				}
			}
		}

	}
Esempio n. 18
0
FarPlanetMesh::FarPlanetMesh(uint32 resolution, float radius)
{
	this->resolution = resolution;
	this->radius = radius;
	float invRes = 1.0f / resolution;

	//Load vertex buffer
	uint32 vertCount = 6 * (resolution+1) * (resolution+1);
	assert(vertCount < 0xFFFF);
	size_t offset = 0;
	vertexData.vertexDeclaration->addElement(0, offset, VET_FLOAT3, VES_POSITION);
	offset += VertexElement::getTypeSize(VET_FLOAT3);
	vertexData.vertexDeclaration->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
	HardwareVertexBufferSharedPtr vertBuff = HardwareBufferManager::getSingleton().createVertexBuffer(
		vertexData.vertexDeclaration->getVertexSize(0), vertCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);

	float *vBuff = static_cast<float*>(vertBuff->lock(HardwareBuffer::HBL_DISCARD));

	for (uint32 face = 0; face < 6; ++face) {
		float faceNormalOffsetV = (face % 2) / 2.0f;
		float faceNormalOffsetU = (face / 2) / 4.0f;

		for (uint32 y = 0; y <= resolution; ++y)
		{
			for (uint32 x = 0; x <= resolution; ++x)
			{
				//Calculate UVs and terrain height
				Real tx = x * invRes;
				Real ty = y * invRes;

				//Calculate vertex position
				Vector3 pos = mapCubeToUnitSphere(mapPlaneToCube(tx, ty, (CubeFace)face)) * radius;

				//Add vertex
				*vBuff++ = pos.x; *vBuff++ = pos.y; *vBuff++ = pos.z;
				*vBuff++ = faceNormalOffsetU + tx * 0.25f; *vBuff++ = faceNormalOffsetV + ty * 0.5f;
			}
		}
	}

	vertBuff->unlock();
	vertexData.vertexStart = 0;
	vertexData.vertexCount = vertCount;
	vertexData.vertexBufferBinding->setBinding(0, vertBuff);

	//Load index buffer
	uint32 indexCount = 6 * 6 * resolution * resolution;
	HardwareIndexBufferSharedPtr indexBuff = HardwareBufferManager::getSingleton().createIndexBuffer(
		HardwareIndexBuffer::IT_16BIT, indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);

	uint16 *iBuff = static_cast<uint16*>(indexBuff->lock(HardwareBuffer::HBL_DISCARD));

	//Index the chunk grid
	for (uint32 face = 0; face < 6; ++face) {
		uint32 faceOffset = face * ((resolution+1) * (resolution+1));
		for (uint32 y = 0; y < resolution; ++y){
			for (uint32 x = 0; x < resolution; ++x){
				uint16 vTopLeft = faceOffset + (y * (resolution+1) + x);
				uint16 vBottomLeft = faceOffset + ((y+1) * (resolution+1) + x);
				*iBuff++ = vBottomLeft;
				*iBuff++ = vTopLeft+1;
				*iBuff++ = vTopLeft;
				*iBuff++ = vBottomLeft;
				*iBuff++ = vBottomLeft+1;
				*iBuff++ = vTopLeft+1;
			}
		}
	}

	indexBuff->unlock();
	indexData.indexStart = 0;
	indexData.indexCount = indexCount;
	indexData.indexBuffer = indexBuff;
}
	//---------------------------------------------------------------------
	void PrefabFactory::createSphere(Mesh* mesh)
	{
		// sphere creation code taken from the DeferredShading sample, originally from the wiki
		SubMesh *pSphereVertex = mesh->createSubMesh();

		const int NUM_SEGMENTS = 16;
		const int NUM_RINGS = 16;
		const Real SPHERE_RADIUS = 50.0;

		mesh->sharedVertexData = OGRE_NEW VertexData();
		VertexData* vertexData = mesh->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);

		// allocate the vertex buffer
		vertexData->vertexCount = (NUM_RINGS + 1) * (NUM_SEGMENTS+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 * NUM_RINGS * (NUM_SEGMENTS + 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 / NUM_RINGS);
		float fDeltaSegAngle = (2 * Math::PI / NUM_SEGMENTS);
		unsigned short wVerticeIndex = 0 ;

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

			// Generate the group of segments for the current ring
			for(int seg = 0; seg <= NUM_SEGMENTS; 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) NUM_SEGMENTS;
				*pVertex++ = (float) ring / (float) NUM_RINGS;

				if (ring != NUM_RINGS) {
					// each vertex (except the last) has six indicies pointing to it
					*pIndices++ = wVerticeIndex + NUM_SEGMENTS + 1;
					*pIndices++ = wVerticeIndex;               
					*pIndices++ = wVerticeIndex + NUM_SEGMENTS;
					*pIndices++ = wVerticeIndex + NUM_SEGMENTS + 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:
		mesh->_setBounds( AxisAlignedBox( Vector3(-SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS), 
			Vector3(SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS) ), false );

		mesh->_setBoundingSphereRadius(SPHERE_RADIUS);
	}
Esempio n. 20
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();
	}
}