Beispiel #1
0
void ESKOgre::createFakeEntity(Ogre::SceneManager *mSceneMgr) {
	Ogre::MeshPtr msh = Ogre::MeshManager::getSingleton().createManual(name + "_skeleton", XENOVIEWER_RESOURCE_GROUP);
	msh->setSkeletonName(name);

	Ogre::SubMesh* sub = msh->createSubMesh();
	const size_t nVertices = 3;
	const size_t nVertCount = 3;
	const size_t vbufCount = nVertCount*nVertices;
	float *vertices = (float *)malloc(sizeof(float)*vbufCount);

	for (size_t i = 0; i < nVertices; i++) {
		vertices[i*nVertCount] = 0.0;
		vertices[i*nVertCount + 1] = 0.0;
		vertices[i*nVertCount + 2] = 0.0;
	}

	const size_t ibufCount = 3;
	unsigned short *faces = (unsigned short *)malloc(sizeof(unsigned short) * ibufCount);

	for (size_t i = 0; i < ibufCount; i++) {
		faces[i] = i;
	}

	msh->sharedVertexData = new Ogre::VertexData();
	msh->sharedVertexData->vertexCount = nVertices;

	Ogre::VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration;
	size_t offset = 0;

	decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

	Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(offset, msh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
	Ogre::VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
	bind->setBinding(0, vbuf);
	Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, ibufCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
	sub->useSharedVertices = true;
	sub->indexData->indexBuffer = ibuf;
	sub->indexData->indexCount = ibufCount;
	sub->indexData->indexStart = 0;

	msh->_setBounds(Ogre::AxisAlignedBox(-100, -100, -100, 100, 100, 100));
	msh->_setBoundingSphereRadius(100);
	msh->load();

	free(faces);
	free(vertices);

	skeleton_entity = mSceneMgr->createEntity(name + "_skeleton");
	skeleton_node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	skeleton_node->attachObject(skeleton_entity);
	skeleton_node->setVisible(false);
}
Beispiel #2
0
Ogre::SubMesh *EMDOgre::createOgreSubmesh(EMDTriangles *triangles, Ogre::MeshPtr mesh) {
	Ogre::SubMesh *sub = mesh->createSubMesh();
	const size_t ibufCount = triangles->faces.size();
	unsigned short *faces = (unsigned short *)malloc(sizeof(unsigned short) * ibufCount);
	for (size_t i = 0; i<ibufCount; i++) {
		faces[i] = triangles->faces[i];
	}

	Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, ibufCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
	sub->useSharedVertices = true;
	sub->indexData->indexBuffer = ibuf;
	sub->indexData->indexCount = ibufCount;
	sub->indexData->indexStart = 0;
	free(faces);
	return sub;
}
Beispiel #3
0
void MapView::createTerrain()
{
	unsigned int sizeX = mMap->getTerrainSize().x;
	unsigned int sizeZ = mMap->getTerrainSize().z;

	mTileX = 33;
	mTileZ = 33;

	unsigned int tileCount = ((sizeX - 1) / (mTileX - 1)) * ((sizeZ - 1) / (mTileZ - 1));
	unsigned int vertexPerTile = mTileX * mTileZ;
	unsigned int trianglesPerTile = (mTileX - 1) * (mTileZ - 1) * 2;

	mMeshes.resize(tileCount);
	mEntities.resize(tileCount);
	mSceneNodes.resize(tileCount);

	// vertexPerTile * 3 vertices * 2 texture coordinates * 3 colours * 3 normals
	VertexVector vertices(vertexPerTile * 11);

	// trianglesPerTile * 3 indices per each triangle
	IndexVector indices[3] =
	{
		IndexVector(trianglesPerTile * 3    ),
		IndexVector(trianglesPerTile * 3 / 4),
		IndexVector(trianglesPerTile * 3 / 8)
	};

	unsigned int vertexIndex, indexIndex = 0, tileIndex = 0;

	for (unsigned int zIndex = 0; zIndex < mTileZ - 1; ++zIndex)
	{
		for (unsigned int xIndex = 0; xIndex < mTileX - 1; ++xIndex)
		{
			indices[0][indexIndex++] =  zIndex      * mTileX + xIndex;
			indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex;
			indices[0][indexIndex++] =  zIndex      * mTileX + xIndex + 1;

			indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex;
			indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex + 1;
			indices[0][indexIndex++] =  zIndex      * mTileX + xIndex + 1;
		}
	}

	indexIndex = 0;

	for (unsigned int zIndex = 0; zIndex < mTileZ - 1; zIndex += 2)
	{
		for (unsigned int xIndex = 0; xIndex < mTileX - 1; xIndex += 2)
		{
			indices[1][indexIndex++] =  zIndex      * mTileX + xIndex;
			indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex;
			indices[1][indexIndex++] =  zIndex      * mTileX + xIndex + 2;

			indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex;
			indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex + 2;
			indices[1][indexIndex++] =  zIndex      * mTileX + xIndex + 2;
		}
	}

	indexIndex = 0;

	for (unsigned int zIndex = 0; zIndex < mTileZ - 1; zIndex += 4)
	{
		for (unsigned int xIndex = 0; xIndex < mTileX - 1; xIndex += 4)
		{
			indices[2][indexIndex++] =  zIndex      * mTileX + xIndex;
			indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex;
			indices[2][indexIndex++] =  zIndex      * mTileX + xIndex + 4;

			indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex;
			indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex + 4;
			indices[2][indexIndex++] =  zIndex      * mTileX + xIndex + 4;
		}
	}

	float scaleX = mMap->getSize().x / (float)(sizeX - 1);
	float scaleZ = mMap->getSize().z / (float)(sizeZ - 1);

	for (unsigned int zTile = 0; zTile < (sizeZ - 1); zTile += (mTileZ - 1))
	{
		for (unsigned int xTile = 0; xTile < (sizeX - 1); xTile += (mTileX - 1))
		{
			vertexIndex = 0;

			for (unsigned int zVertex = zTile; zVertex < zTile + mTileZ; ++zVertex)
			{
				for (unsigned int xVertex = xTile; xVertex < xTile + mTileX; ++xVertex)
				{
					float yVertex = mMap->getTerrainData()[zVertex * sizeX + xVertex];

					vertices[vertexIndex++] = (float)xVertex * scaleX;
					vertices[vertexIndex++] = (float)yVertex;
					vertices[vertexIndex++] = (float)zVertex * scaleZ;

					vertices[vertexIndex++] = (float)xVertex / (float)(sizeX - 1);
					vertices[vertexIndex++] = (float)zVertex / (float)(sizeZ - 1);

					vertices[vertexIndex++] = 1.0f;
					vertices[vertexIndex++] = 1.0f;
					vertices[vertexIndex++] = 1.0f;

					vertices[vertexIndex++] = 0.0f;
					vertices[vertexIndex++] = 1.0f;
					vertices[vertexIndex++] = 0.0f;
				}
			}

			std::string name =
				"MapView_" + Convert::ToString(mID) +
				"_Tile_" + Convert::ToString(tileIndex);

			// Create mesh.
			mMeshes[tileIndex] = Ogre::MeshManager::getSingleton().createManual(
				name, "General").get();

			// Create one submesh.
			Ogre::SubMesh* subMesh = mMeshes[tileIndex]->createSubMesh();

			// Create vertex data structure for vertices shared between submeshes.
			mMeshes[tileIndex]->sharedVertexData = new Ogre::VertexData();
			mMeshes[tileIndex]->sharedVertexData->vertexCount = vertexPerTile;

			// Create declaration (memory format) of vertex data.
			Ogre::VertexDeclaration* decl =
				mMeshes[tileIndex]->sharedVertexData->vertexDeclaration;

			size_t offset = 0;

			// 1st buffer
			decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

			decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

			decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_DIFFUSE);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

			decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
			offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

			// Allocate vertex buffer of the requested number of vertices (vertexPerTile)
			// and bytes per vertex (offset).
			Ogre::HardwareVertexBufferSharedPtr vbuf =
				Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
				offset, vertexPerTile, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

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

			// Set vertex buffer binding so buffer 0 is bound to our vertex buffer.
			Ogre::VertexBufferBinding* bind =
				mMeshes[tileIndex]->sharedVertexData->vertexBufferBinding; 
			bind->setBinding(0, vbuf);

			// Allocate index buffer of the requested number of vertices .
			Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().
				createIndexBuffer(
				Ogre::HardwareIndexBuffer::IT_16BIT, 
				trianglesPerTile * 3,
				Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

			// Upload the index data to the card.
			ibuf->writeData(0, ibuf->getSizeInBytes(), &(indices[0].front()), true);

			/// Set parameters of the submesh
			subMesh->useSharedVertices = true;
			subMesh->indexData->indexBuffer = ibuf;
			subMesh->indexData->indexCount = indices[0].size();
			subMesh->indexData->indexStart = 0;
			subMesh->setMaterialName("terrain");

			float xMin = vertices[0];
			float yMin = vertices[1];
			float zMin = vertices[2];

			float xMax = vertices[0];
			float yMax = vertices[1];
			float zMax = vertices[2];

			for (unsigned int i = 0; i < vertexPerTile * 11; i += 11)
			{
				if (vertices[i    ] < xMin) xMin = vertices[i    ]; else
				if (vertices[i    ] > xMax) xMax = vertices[i    ];

				if (vertices[i + 1] < yMin) yMin = vertices[i + 1]; else
				if (vertices[i + 1] > yMax) yMax = vertices[i + 1];

				if (vertices[i + 2] < zMin) zMin = vertices[i + 2]; else
				if (vertices[i + 2] > zMax) zMax = vertices[i + 2];
			}

			// Set bounding information (for culling).
			mMeshes[tileIndex]->_setBounds(Ogre::AxisAlignedBox(xMin, yMin, zMin, xMax, yMax, zMax));
			mMeshes[tileIndex]->_setBoundingSphereRadius(1.0f);

			// Notify Mesh object that it has been loaded.
			mMeshes[tileIndex]->load();

			// Create entity.
			mEntities[tileIndex] = createEntity(name, name);
			mEntities[tileIndex]->setCastShadows(false);
			mEntities[tileIndex]->setUserAny(Ogre::Any(this));

			// Create scene node.
			mSceneNodes[tileIndex] = createSceneNode();
			mSceneNodes[tileIndex]->attachObject(mEntities[tileIndex]);

			// Advance to next tile.
			tileIndex++;
		}
	}
}
Beispiel #4
0
void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape)
{
    const Nif::NiTriShapeData *data = shape->data.getPtr();
    const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr());
    std::vector<Ogre::Vector3> srcVerts = data->vertices;
    std::vector<Ogre::Vector3> srcNorms = data->normals;
    Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC;
    bool vertShadowBuffer = false;

    bool geomMorpherController = false;
    if(!shape->controller.empty())
    {
        Nif::ControllerPtr ctrl = shape->controller;
        do {
            if(ctrl->recType == Nif::RC_NiGeomMorpherController)
            {
                vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY;
                vertShadowBuffer = true;
                geomMorpherController = true;
                break;
            }
        } while(!(ctrl=ctrl->next).empty());
    }

    if(skin != NULL)
    {
        vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY;
        vertShadowBuffer = true;

        // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be
        // explicitly attached later.
        mesh->setSkeletonName(mName);

        // Convert vertices and normals to bone space from bind position. It would be
        // better to transform the bones into bind position, but there doesn't seem to
        // be a reliable way to do that.
        std::vector<Ogre::Vector3> newVerts(srcVerts.size(), Ogre::Vector3(0.0f));
        std::vector<Ogre::Vector3> newNorms(srcNorms.size(), Ogre::Vector3(0.0f));

        const Nif::NiSkinData *data = skin->data.getPtr();
        const Nif::NodeList &bones = skin->bones;
        for(size_t b = 0;b < bones.length();b++)
        {
            Ogre::Matrix4 mat;
            mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale),
                              Ogre::Quaternion(data->bones[b].trafo.rotation));
            mat = bones[b]->getWorldTransform() * mat;

            const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights;
            for(size_t i = 0;i < weights.size();i++)
            {
                size_t index = weights[i].vertex;
                float weight = weights[i].weight;

                newVerts.at(index) += (mat*srcVerts[index]) * weight;
                if(newNorms.size() > index)
                {
                    Ogre::Vector4 vec4(srcNorms[index][0], srcNorms[index][1], srcNorms[index][2], 0.0f);
                    vec4 = mat*vec4 * weight;
                    newNorms[index] += Ogre::Vector3(&vec4[0]);
                }
            }
        }

        srcVerts = newVerts;
        srcNorms = newNorms;
    }
    else
    {
        Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr();
        if(skelMgr->getByName(mName).isNull())
        {
            // No skinning and no skeleton, so just transform the vertices and
            // normals into position.
            Ogre::Matrix4 mat4 = shape->getWorldTransform();
            for(size_t i = 0;i < srcVerts.size();i++)
            {
                Ogre::Vector4 vec4(srcVerts[i].x, srcVerts[i].y, srcVerts[i].z, 1.0f);
                vec4 = mat4*vec4;
                srcVerts[i] = Ogre::Vector3(&vec4[0]);
            }
            for(size_t i = 0;i < srcNorms.size();i++)
            {
                Ogre::Vector4 vec4(srcNorms[i].x, srcNorms[i].y, srcNorms[i].z, 0.0f);
                vec4 = mat4*vec4;
                srcNorms[i] = Ogre::Vector3(&vec4[0]);
            }
        }
    }

    // Set the bounding box first
    BoundsFinder bounds;
    bounds.add(&srcVerts[0][0], srcVerts.size());
    if(!bounds.isValid())
    {
        float v[3] = { 0.0f, 0.0f, 0.0f };
        bounds.add(&v[0], 1);
    }

    mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX()-0.5f, bounds.minY()-0.5f, bounds.minZ()-0.5f,
                                          bounds.maxX()+0.5f, bounds.maxY()+0.5f, bounds.maxZ()+0.5f));
    mesh->_setBoundingSphereRadius(bounds.getRadius());

    // This function is just one long stream of Ogre-barf, but it works
    // great.
    Ogre::HardwareBufferManager *hwBufMgr = Ogre::HardwareBufferManager::getSingletonPtr();
    Ogre::HardwareVertexBufferSharedPtr vbuf;
    Ogre::HardwareIndexBufferSharedPtr ibuf;
    Ogre::VertexBufferBinding *bind;
    Ogre::VertexDeclaration *decl;
    int nextBuf = 0;

    Ogre::SubMesh *sub = mesh->createSubMesh();

    // Add vertices
    sub->useSharedVertices = false;
    sub->vertexData = new Ogre::VertexData();
    sub->vertexData->vertexStart = 0;
    sub->vertexData->vertexCount = srcVerts.size();

    decl = sub->vertexData->vertexDeclaration;
    bind = sub->vertexData->vertexBufferBinding;
    if(srcVerts.size())
    {
        vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3),
                                            srcVerts.size(), vertUsage, vertShadowBuffer);
        vbuf->writeData(0, vbuf->getSizeInBytes(), &srcVerts[0][0], true);

        decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
        bind->setBinding(nextBuf++, vbuf);
    }

    // Vertex normals
    if(srcNorms.size())
    {
        vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3),
                                            srcNorms.size(), vertUsage, vertShadowBuffer);
        vbuf->writeData(0, vbuf->getSizeInBytes(), &srcNorms[0][0], true);

        decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
        bind->setBinding(nextBuf++, vbuf);
    }

    // Vertex colors
    const std::vector<Ogre::Vector4> &colors = data->colors;
    if(colors.size())
    {
        Ogre::RenderSystem *rs = Ogre::Root::getSingleton().getRenderSystem();
        std::vector<Ogre::RGBA> colorsRGB(colors.size());
        for(size_t i = 0;i < colorsRGB.size();i++)
        {
            Ogre::ColourValue clr(colors[i][0], colors[i][1], colors[i][2], colors[i][3]);
            rs->convertColourValue(clr, &colorsRGB[i]);
        }
        vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR),
                                            colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC);
        vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB[0], true);
        decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
        bind->setBinding(nextBuf++, vbuf);
    }

    // Texture UV coordinates
    size_t numUVs = data->uvlist.size();
    if (numUVs)
    {
        size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

        for(size_t i = 0; i < numUVs; i++)
            decl->addElement(nextBuf, elemSize*i, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i);

        vbuf = hwBufMgr->createVertexBuffer(decl->getVertexSize(nextBuf), srcVerts.size(),
                                            Ogre::HardwareBuffer::HBU_STATIC);

        std::vector<Ogre::Vector2> allUVs;
        allUVs.reserve(srcVerts.size()*numUVs);
        for (size_t vert = 0; vert<srcVerts.size(); ++vert)
            for(size_t i = 0; i < numUVs; i++)
                allUVs.push_back(data->uvlist[i][vert]);

        vbuf->writeData(0, elemSize*srcVerts.size()*numUVs, &allUVs[0], true);

        bind->setBinding(nextBuf++, vbuf);
    }

    // Triangle faces
    const std::vector<short> &srcIdx = data->triangles;
    if(srcIdx.size())
    {
        ibuf = hwBufMgr->createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, srcIdx.size(),
                                           Ogre::HardwareBuffer::HBU_STATIC);
        ibuf->writeData(0, ibuf->getSizeInBytes(), &srcIdx[0], true);
        sub->indexData->indexBuffer = ibuf;
        sub->indexData->indexCount = srcIdx.size();
        sub->indexData->indexStart = 0;
    }

    // Assign bone weights for this TriShape
    if(skin != NULL)
    {
        Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(mName);

        const Nif::NiSkinData *data = skin->data.getPtr();
        const Nif::NodeList &bones = skin->bones;
        for(size_t i = 0;i < bones.length();i++)
        {
            Ogre::VertexBoneAssignment boneInf;
            boneInf.boneIndex = skel->getBone(bones[i]->name)->getHandle();

            const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[i].weights;
            for(size_t j = 0;j < weights.size();j++)
            {
                boneInf.vertexIndex = weights[j].vertex;
                boneInf.weight = weights[j].weight;
                sub->addBoneAssignment(boneInf);
            }
        }
    }

    const Nif::NiTexturingProperty *texprop = NULL;
    const Nif::NiMaterialProperty *matprop = NULL;
    const Nif::NiAlphaProperty *alphaprop = NULL;
    const Nif::NiVertexColorProperty *vertprop = NULL;
    const Nif::NiZBufferProperty *zprop = NULL;
    const Nif::NiSpecularProperty *specprop = NULL;
    const Nif::NiWireframeProperty *wireprop = NULL;
    bool needTangents = false;

    shape->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop);
    std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup,
                                                         texprop, matprop, alphaprop,
                                                         vertprop, zprop, specprop,
                                                         wireprop, needTangents);
    if(matname.length() > 0)
        sub->setMaterialName(matname);

    // build tangents if the material needs them
    if (needTangents)
    {
        unsigned short src,dest;
        if (!mesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src,dest))
            mesh->buildTangentVectors(Ogre::VES_TANGENT, src,dest);
    }

    // Create a dummy vertex animation track if there's a geom morpher controller
    // This is required to make Ogre create the buffers we will use for software vertex animation
    if (srcVerts.size() && geomMorpherController)
        mesh->createAnimation("dummy", 0)->createVertexTrack(1, sub->vertexData, Ogre::VAT_MORPH);
}
Ogre::SceneNode *TutorialApplication::loadBSP(std::shared_ptr<l2p::UModel> m, bool ignoreNonVisible) {
  l2p::Name name = m->package->name;
  std::vector<float> vertex_data;
  std::vector<uint32_t> index_buf;
  l2p::Box bounds;

  // Build vertex and index buffer.
  for (auto ni = m->nodes.begin(), ne = m->nodes.end(); ni != ne; ++ni) {
    l2p::BSPNode &n = *ni;
    l2p::BSPSurface &s = m->surfaces[n.surface];

    if (ignoreNonVisible && ignoreNode(m.get(), n, s))
      continue;

    uint32_t vert_start = vertex_data.size() / 8;

    const Ogre::Vector3 uvec = ogre_cast(m->vectors[s.U]);
    const Ogre::Vector3 vvec = ogre_cast(m->vectors[s.V]);
    const Ogre::Vector3 base = ogre_cast(m->points[s.base]);
    int usize = 0;
    int vsize = 0;
    std::shared_ptr<l2p::UTexture> mat = s.material;
    if (mat) {
      usize = mat->USize;
      vsize = mat->VSize;
    }

    if (usize == 0 || vsize == 0)
      usize = vsize = 64;

    // Vertex buffer.
    if (n.num_verticies > 0) {
      l2p::Vector Normal = m->vectors[s.normal];

      for (uint32_t vert_index = 0; vert_index < n.num_verticies; ++vert_index) {
        const l2p::Vector &pos = m->points[m->vertexes[n.vert_pool + vert_index].vertex];
        const Ogre::Vector3 dist(ogre_cast(pos) - base);
        const Ogre::Vector2 tcoord((dist | uvec) / float(usize), (dist | vvec) / float(vsize));
        bounds += pos;
        vertex_data.push_back(pos.X);
        vertex_data.push_back(pos.Y);
        vertex_data.push_back(pos.Z);
        vertex_data.push_back(Normal.X);
        vertex_data.push_back(Normal.Y);
        vertex_data.push_back(Normal.Z);
        vertex_data.push_back(tcoord.x);
        vertex_data.push_back(tcoord.y);
      }

      if (s.flags & l2p::PF_TwoSided) {
        for (uint32_t vert_index = 0; vert_index < n.num_verticies; ++vert_index) {
          const l2p::Vector &pos = m->points[m->vertexes[n.vert_pool + vert_index].vertex];
          const Ogre::Vector3 dist(ogre_cast(pos) - base);
          const Ogre::Vector2 tcoord((dist | uvec) / float(usize), (dist | vvec) / float(vsize));
          vertex_data.push_back(pos.X);
          vertex_data.push_back(pos.Y);
          vertex_data.push_back(pos.Z);
          vertex_data.push_back(Normal.X);
          vertex_data.push_back(Normal.Y);
          vertex_data.push_back(-Normal.Z);
          vertex_data.push_back(tcoord.x);
          vertex_data.push_back(tcoord.y);
        }
      }
    }

    // Index buffer.
    for (int verti = 2; verti < n.num_verticies; ++verti) {
      index_buf.push_back(vert_start);
      index_buf.push_back(vert_start + verti - 1);
      index_buf.push_back(vert_start + verti);
    }
    if (s.flags & l2p::PF_TwoSided) {
      for (int verti = 2; verti < n.num_verticies; ++verti) {
        index_buf.push_back(vert_start);
        index_buf.push_back(vert_start + verti);
        index_buf.push_back(vert_start + verti - 1);
      }
    }
  }

  if (vertex_data.size() == 0 || index_buf.size() == 0)
    return nullptr;

  Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(Ogre::String(name) + Ogre::String(m->name), "General");
  Ogre::VertexData  *data = new Ogre::VertexData();
  mesh->sharedVertexData = data;
  data->vertexCount = vertex_data.size() / 8;

  Ogre::VertexDeclaration *decl = data->vertexDeclaration;
  uint32_t offset = 0;
  decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
  decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
  decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
  offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

  Ogre::HardwareVertexBufferSharedPtr vbuf =
    Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
      offset,
      data->vertexCount,
      Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
  vbuf->writeData(0, vbuf->getSizeInBytes(), &vertex_data.front(), true);
  data->vertexBufferBinding->setBinding(0, vbuf);

  // Setup index buffer.
  Ogre::HardwareIndexBufferSharedPtr ibuf =
    Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
      Ogre::HardwareIndexBuffer::IT_32BIT,
      index_buf.size(),
      Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

  ibuf->writeData(0, ibuf->getSizeInBytes(), &index_buf.front(), true);
  Ogre::SubMesh *subMesh = mesh->createSubMesh();
  subMesh->useSharedVertices = true;
  subMesh->indexData->indexBuffer = ibuf;
  subMesh->indexData->indexCount  = index_buf.size();
  subMesh->indexData->indexStart  = 0;

  mesh->_setBounds(Ogre::AxisAlignedBox(bounds.min.X, bounds.min.Y, bounds.min.Z, bounds.max.X, bounds.max.Y, bounds.max.Z));
  mesh->_setBoundingSphereRadius((std::max(bounds.max.X - bounds.min.X, std::max(bounds.max.Y - bounds.min.Y, bounds.max.Z - bounds.min.Z))) / 2.0);

  mesh->load();

  Ogre::Entity *ent = mSceneMgr->createEntity(Ogre::String(name) + Ogre::String(m->name) + "E", Ogre::String(name) + Ogre::String(m->name));
  ent->setUserAny(Ogre::Any(static_cast<l2p::UObject*>(m.get())));
  ent->setMaterialName("StaticMesh/Default");
  Ogre::SceneNode *node = mUnrealCordNode->createChildSceneNode();
  node->attachObject(ent);

  return node;
}
void RoR::GfxEnvmap::SetupEnvMap()
{
    m_rtt_texture = Ogre::TextureManager::getSingleton().getByName("EnvironmentTexture");

    for (int face = 0; face < NUM_FACES; face++)
    {
        m_render_targets[face] = m_rtt_texture->getBuffer(face)->getRenderTarget();
        m_cameras[face] = gEnv->sceneManager->createCamera("EnvironmentCamera-" + TOSTRING(face));
        m_cameras[face]->setAspectRatio(1.0);
        m_cameras[face]->setProjectionType(Ogre::PT_PERSPECTIVE);
        m_cameras[face]->setFixedYawAxis(false);
        m_cameras[face]->setFOVy(Ogre::Degree(90));
        m_cameras[face]->setNearClipDistance(0.1f);
        m_cameras[face]->setFarClipDistance(gEnv->mainCamera->getFarClipDistance());

        Ogre::Viewport* v = m_render_targets[face]->addViewport(m_cameras[face]);
        v->setOverlaysEnabled(false);
        v->setClearEveryFrame(true);
        v->setBackgroundColour(gEnv->mainCamera->getViewport()->getBackgroundColour());
        m_render_targets[face]->setAutoUpdated(false);
    }

    m_cameras[0]->setDirection(+Ogre::Vector3::UNIT_X);
    m_cameras[1]->setDirection(-Ogre::Vector3::UNIT_X);
    m_cameras[2]->setDirection(+Ogre::Vector3::UNIT_Y);
    m_cameras[3]->setDirection(-Ogre::Vector3::UNIT_Y);
    m_cameras[4]->setDirection(-Ogre::Vector3::UNIT_Z);
    m_cameras[5]->setDirection(+Ogre::Vector3::UNIT_Z);

    if (App::diag_envmap.GetActive())
    {
        // create fancy mesh for debugging the envmap
        Ogre::Overlay* overlay = Ogre::OverlayManager::getSingleton().create("EnvMapDebugOverlay");
        if (overlay)
        {
            Ogre::Vector3 position = Ogre::Vector3::ZERO;
            float scale = 1.0f;

            Ogre::MeshPtr mesh = Ogre::MeshManager::getSingletonPtr()->createManual("cubeMapDebug", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
            // create sub mesh
            Ogre::SubMesh* sub = mesh->createSubMesh();

            // Initialize render operation
            sub->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
            //
            sub->useSharedVertices = true;
            mesh->sharedVertexData = new Ogre::VertexData;
            sub->indexData = new Ogre::IndexData;

            // Create vertex declaration
            size_t offset = 0;
            mesh->sharedVertexData->vertexDeclaration->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
            offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
            mesh->sharedVertexData->vertexDeclaration->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_TEXTURE_COORDINATES);

            // Create and bind vertex buffer
            mesh->sharedVertexData->vertexCount = 14;
            Ogre::HardwareVertexBufferSharedPtr vertexBuffer =
                Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
                    mesh->sharedVertexData->vertexDeclaration->getVertexSize(0),
                    mesh->sharedVertexData->vertexCount,
                    Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
            mesh->sharedVertexData->vertexBufferBinding->setBinding(0, vertexBuffer);

            // Vertex data
            static const float vertexData[] = {
                // Position      Texture coordinates    // Index
                0.0, 2.0, -1.0, 1.0, 1.0, //  0
                0.0, 1.0, -1.0, -1.0, 1.0, //  1
                1.0, 2.0, -1.0, 1.0, -1.0, //  2
                1.0, 1.0, -1.0, -1.0, -1.0, //  3
                2.0, 2.0, 1.0, 1.0, -1.0, //  4
                2.0, 1.0, 1.0, -1.0, -1.0, //  5
                3.0, 2.0, 1.0, 1.0, 1.0, //  6
                3.0, 1.0, 1.0, -1.0, 1.0, //  7
                4.0, 2.0, -1.0, 1.0, 1.0, //  8
                4.0, 1.0, -1.0, -1.0, 1.0, //  9
                1.0, 3.0, -1.0, 1.0, 1.0, // 10
                2.0, 3.0, 1.0, 1.0, 1.0, // 11
                1.0, 0.0, -1.0, -1.0, 1.0, // 12
                2.0, 0.0, 1.0, -1.0, 1.0, // 13
            };

            // Fill vertex buffer
            float* pData = static_cast<float*>(vertexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD));
            for (size_t vertex = 0, i = 0; vertex < mesh->sharedVertexData->vertexCount; vertex++)
            {
                // Position
                *pData++ = position.x + scale * vertexData[i++];
                *pData++ = position.y + scale * vertexData[i++];
                *pData++ = 0.0;

                // Texture coordinates
                *pData++ = vertexData[i++];
                *pData++ = vertexData[i++];
                *pData++ = vertexData[i++];
            }
            vertexBuffer->unlock();

            // Create index buffer
            sub->indexData->indexCount = 36;
            Ogre::HardwareIndexBufferSharedPtr indexBuffer =
                Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
                    Ogre::HardwareIndexBuffer::IT_16BIT,
                    sub->indexData->indexCount,
                    Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
            sub->indexData->indexBuffer = indexBuffer;

            // Index data
            static const Ogre::uint16 indexData[] = {
                // Indices         // Face
                 0,  1,  2,        //  0
                 2,  1,  3,        //  1
                 2,  3,  4,        //  2
                 4,  3,  5,        //  3
                 4,  5,  6,        //  4
                 6,  5,  7,        //  5
                 6,  7,  8,        //  6
                 8,  7,  9,        //  7
                10,  2, 11,        //  8
                11,  2,  4,        //  9
                 3, 12,  5,        // 10
                 5, 12, 13,        // 11
            };

            // Fill index buffer
            indexBuffer->writeData(0, indexBuffer->getSizeInBytes(), indexData, true);

            mesh->_setBounds(Ogre::AxisAlignedBox::BOX_INFINITE);
            mesh->_setBoundingSphereRadius(10);
            mesh->load();

            Ogre::Entity* e = gEnv->sceneManager->createEntity(mesh->getName());
            e->setCastShadows(false);
            e->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - 1);
            e->setVisible(true);

            e->setMaterialName("tracks/EnvMapDebug");
            Ogre::SceneNode* mDebugSceneNode = new Ogre::SceneNode(gEnv->sceneManager);
            mDebugSceneNode->attachObject(e);
            mDebugSceneNode->setPosition(Ogre::Vector3(0, 0, -5));
            mDebugSceneNode->setFixedYawAxis(true, Ogre::Vector3::UNIT_Y);
            mDebugSceneNode->setVisible(true);
            mDebugSceneNode->_update(true, true);
            mDebugSceneNode->_updateBounds();
            overlay->add3D(mDebugSceneNode);
            overlay->show();
        }
    }
}
Beispiel #7
0
	/*求对象rend和射线ray的全部交点到射线原点的距离
	*/
	vector<Ogre::Real> BaseManager::Intersect(const Ogre::Ray& ray,Ogre::Renderable *rend){
		Ogre::RenderOperation op;
		Ogre::VertexElementType vtype;
		size_t offset,pkgsize,source,indexNums,vertexNums;
		vector<Ogre::Real> result;

		rend->getRenderOperation( op );

		if( !op.indexData || 
			op.operationType==Ogre::RenderOperation::OT_LINE_LIST || 
			op.operationType==Ogre::RenderOperation::OT_LINE_STRIP ||
			op.operationType==Ogre::RenderOperation::OT_POINT_LIST )
			return result;

		Ogre::VertexDeclaration* pvd = op.vertexData->vertexDeclaration;

		source = -1;
		for( size_t i = 0;i < pvd->getElementCount();++i ){
			if( pvd->getElement(i)->getSemantic()==Ogre::VES_POSITION ){
				source = pvd->getElement(i)->getSource();
				offset = pvd->getElement(i)->getOffset();
				vtype = pvd->getElement(i)->getType();
				break;
			}
		}
		if( source == - 1 || vtype != Ogre::VET_FLOAT3 ) //别的格式目前没有考虑
			return result;

		/*source对应与一个缓存区
		  getVertexSize(source)求缓存区中一个紧密数据包的大小
		  例如:一个数据包里面包括POSITION,COLOR,NORMAL,TEXCROOD然后在这个缓冲
			区中循环。而getVertexSize求出这个包的字节大小
		  例如POSITION(FLOAT3) TEXCROOD(FLOAT2) 这样前面的是12字节后面的是8字节
			getVertexSize返回20
		*/
		pkgsize = pvd->getVertexSize(source);

		Ogre::HardwareVertexBufferSharedPtr hvb = op.vertexData->vertexBufferBinding->getBuffer(source);
		Ogre::HardwareIndexBufferSharedPtr ivb = op.indexData->indexBuffer;
		Ogre::HardwareIndexBuffer::IndexType indexType = op.indexData->indexBuffer->getType();
		/*先将顶点数据复制一份,然后变换到世界坐标系
		*/
		vertexNums = hvb->getNumVertices();
		indexNums = ivb->getNumIndexes();
		 
		boost::scoped_array<float> vp( new float[3*vertexNums] );
		boost::scoped_array<unsigned int> ip( new unsigned int[indexNums] );
		
		{
			Ogre::Vector3 p3;
			Ogre::Matrix4 mat;
			rend->getWorldTransforms( &mat );
			float* preal = (float*)hvb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY );
			float* ptarget = vp.get();
			//这里考虑到对齐,我假设offset和pkgsize都可以被sizeof(float)整除
			preal += offset/sizeof(float);
			size_t strip = pkgsize/sizeof(float);
			for( size_t i = 0; i < vertexNums;++i ){
				p3.x = *preal;
				p3.y = *(preal+1);
				p3.z = *(preal+2);
				p3 = mat * p3;
				*ptarget++ = p3.x;
				*ptarget++ = p3.y;
				*ptarget++ = p3.z;
				preal += strip;
			}
			hvb->unlock();
		}
		//拷贝出顶点数据
		
		{
			unsigned int* pindex32 = ip.get();
			
			if( indexType==Ogre::HardwareIndexBuffer::IT_16BIT ){
				unsigned short* pi16 = (unsigned short*)ivb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY );
				copy( pi16,pi16+indexNums,pindex32 );
			}else
				memcpy( pindex32,ivb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY ),ivb->getSizeInBytes() );
			ivb->unlock();
		}
		/*数据都准备好了,vp保存了变换好的顶点,ip保存了顶点索引
			下面根据情况求交点
		*/
		switch( op.operationType ){
			case Ogre::RenderOperation::OT_TRIANGLE_LIST:
				{ /* 0,1,2 组成一个三角 3,4,5 下一个...
				  */
					Ogre::Vector3 a[3],n;
					int index,k = 0;
					float* preal = vp.get();
					unsigned int* pindex = ip.get();
					for( size_t i = 0;i<indexNums;++i ){
						if( pindex[i] < vertexNums ){
							index = pindex[i]*3; //对应与格式VET_FLOAT3
							a[k].x = preal[index];
							a[k].y = preal[index+1];
							a[k].z = preal[index+2];
							if( k == 2 ){//三个点都填满了
								//这里使用的是Math3d的求交函数,而不是Ogre::Math的
								//原因就在于Ogre::Math的求交点函数不能得到射线背面那个负的交点
								std::pair<bool,Ogre::Real> res = Math3d::intersects(ray,a[0],a[1],a[2],true,true);
								if( res.first )
									result.push_back( res.second );
								k = 0;
							}else
								k++;
						}else{
							WARNING_LOG("Game::Intersect"<<" Invalid index rang out" << " pindex["<<i<<"]="<<pindex[i] << "("<<vertexNums<<")");
							return result;
						}
					}
				}
				break;
			case Ogre::RenderOperation::OT_TRIANGLE_FAN:
				{/* 0,1,2组成一个三角 0,2,3 组成下一个 0,3,4...
				 */
					assert( false||"Game::Intersect can't support OT_TRIANGLE_FAN " );
				}
				break;
			case Ogre::RenderOperation::OT_TRIANGLE_STRIP:
				{//0,1,2组成第一个三角 1,2,3 组成下一个 2,3,4...
					assert( false||"Game::Intersect can't support OT_TRIANGLE_STRIP " );
				}
				break;
			default:;
		}
		return result;
	}
void WaterObjectView::createLine()
{
	size_t verticesCount = ((mWaterObject->getPointCount() - 1) * mSegments + 1) * 2;
	size_t verticesSize = verticesCount * 5;
	size_t indicesSize = ((mWaterObject->getPointCount() - 1) * mSegments) * 6;

	verticesCount = mWaterObject->getPointCount() * 2;
	verticesSize = verticesCount * 5;
	indicesSize = (mWaterObject->getPointCount() - 1) * 6;

	Ogre::Real* vertices  = new Ogre::Real[verticesSize];
	Ogre::uint16* indices = new Ogre::uint16[indicesSize];

	unsigned int i, index = 0;

	// Prepare vertices.
	for (i = 0; i < mWaterObject->getPointCount(); ++i)
	{
		const Point3D& point3D = mWaterObject->getPoint(i);

		vertices[index++] = point3D.x - mWaterObject->getWidth() * 0.5f;
		vertices[index++] = point3D.y;
		vertices[index++] = point3D.z + 1.0f;

		vertices[index++] = point3D.x - mWaterObject->getWidth() * 0.5f;;
		vertices[index++] = point3D.z;

		vertices[index++] = point3D.x + mWaterObject->getWidth() * 0.5f;
		vertices[index++] = point3D.y;
		vertices[index++] = point3D.z + 1.0f;

		vertices[index++] = point3D.x + mWaterObject->getWidth() * 0.5f;
		vertices[index++] = point3D.z;
	}

	index = 0;

	// Prepare indices.
	for (i = 0; i < verticesCount - 2; i += 2)
	{
		indices[index++] = (Ogre::uint16)i;
		indices[index++] = (Ogre::uint16)i + 2;
		indices[index++] = (Ogre::uint16)i + 1;

		indices[index++] = (Ogre::uint16)i + 2;
		indices[index++] = (Ogre::uint16)i + 3;
		indices[index++] = (Ogre::uint16)i + 1;
	}

	// Create mesh.
	mMesh = Ogre::MeshManager::getSingleton().createManual(
		Ogre::StringConverter::toString(mID), "General").get();

	// Create one submesh.
	Ogre::SubMesh* sub = mMesh->createSubMesh();

	// Create vertex data structure for 8 vertices shared between submeshes.
	mMesh->sharedVertexData = new Ogre::VertexData();
	mMesh->sharedVertexData->vertexCount = verticesCount;

	// Create declaration (memory format) of vertex data.
	Ogre::VertexDeclaration* decl = mMesh->sharedVertexData->vertexDeclaration;
	size_t offset = 0;

	// 1st buffer
	decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

	decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

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

	/// 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
	Ogre::VertexBufferBinding* bind =
		mMesh->sharedVertexData->vertexBufferBinding; 
	bind->setBinding(0, vbuf);

	/// Allocate index buffer of the requested number of vertices (ibufCount).
	Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().
		createIndexBuffer(
		Ogre::HardwareIndexBuffer::IT_16BIT, 
		indicesSize, 
		Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);

	/// Upload the index data to the card.
	ibuf->writeData(0, ibuf->getSizeInBytes(), indices, true);

	/// Set parameters of the submesh.
	sub->useSharedVertices = true;
	sub->indexData->indexBuffer = ibuf;
	sub->indexData->indexCount = indicesSize;
	sub->indexData->indexStart = 0;
	sub->setMaterialName("Ocean2_Cg");

	float xMin = vertices[0];
	float yMin = vertices[1];
	float zMin = vertices[2];

	float xMax = vertices[0];
	float yMax = vertices[1];
	float zMax = vertices[2];

	for (i = 0; i < verticesSize; i += 5)
	{
		if (vertices[i    ] < xMin) xMin = vertices[i    ]; else
		if (vertices[i    ] > xMax) xMax = vertices[i    ];

		if (vertices[i + 1] < yMin) yMin = vertices[i + 1]; else
		if (vertices[i + 1] > yMax) yMax = vertices[i + 1];

		if (vertices[i + 2] < zMin) zMin = vertices[i + 2]; else
		if (vertices[i + 2] > zMax) zMax = vertices[i + 2];
	}

	/// Set bounding information (for culling).
	mMesh->_setBounds(Ogre::AxisAlignedBox(xMin, yMin, zMin, xMax, yMax, zMax));
	mMesh->_setBoundingSphereRadius(1.0f);

	/// Notify Mesh object that it has been loaded.
	mMesh->load();

	delete [] vertices;
	delete [] indices;
}
Rocket::Core::CompiledGeometryHandle RocketInterface::CompileGeometry(
    Rocket::Core::Vertex* vertices, int numVertices, int* indices, int numIndices,
    Rocket::Core::TextureHandle texture)
{
    RocketOgreGeometry* geometry = new RocketOgreGeometry();
    geometry->texture = texture == 0 ? nullptr : reinterpret_cast<RocketOgreTexture*>(texture);
    geometry->renderOp.vertexData = new Ogre::VertexData();
    geometry->renderOp.vertexData->vertexStart = 0;
    geometry->renderOp.vertexData->vertexCount = numVertices;
    geometry->renderOp.indexData = new Ogre::IndexData();
    geometry->renderOp.indexData->indexStart = 0;
    geometry->renderOp.indexData->indexCount = numIndices;
    geometry->renderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;

    // Set up the vertex declaration
    Ogre::VertexDeclaration* vertexDecl = geometry->renderOp.vertexData->vertexDeclaration;
    size_t offset = 0;
    vertexDecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_POSITION);
    offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
    vertexDecl->addElement(0, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
    offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
    vertexDecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);

    // Create the vertex buffer
    Ogre::HardwareVertexBufferSharedPtr vb =
        Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
            vertexDecl->getVertexSize(0), numVertices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
    geometry->renderOp.vertexData->vertexBufferBinding->setBinding(0, vb);

    // Fill the vertex buffer
    RocketOgreVertex* vertexData = static_cast<RocketOgreVertex*>(
        vb->lock(0, vb->getSizeInBytes(), Ogre::HardwareBuffer::HBL_NORMAL));
    for (int i = 0; i < numVertices; ++i)
    {
        vertexData[i].position.x = vertices[i].position.x;
        vertexData[i].position.y = vertices[i].position.y;

        vertexData[i].uv.x = vertices[i].tex_coord[0];
        vertexData[i].uv.y = vertices[i].tex_coord[1];

        // Calculate colour value
        Ogre::ColourValue diffuse(
            vertices[i].colour.red / 255.0f, vertices[i].colour.green / 255.0f,
            vertices[i].colour.blue / 255.0f, vertices[i].colour.alpha / 255.0f);

        // Scale colour by gamma value (2.2)
        diffuse.r = Pow(diffuse.r, 2.2f);
        diffuse.g = Pow(diffuse.g, 2.2f);
        diffuse.b = Pow(diffuse.b, 2.2f);
        diffuse.a = Pow(diffuse.a, 2.2f);

        mRenderSystem->convertColourValue(diffuse, &vertexData[i].colour);
    }
    vb->unlock();

    // Create the index buffer
    Ogre::HardwareIndexBufferSharedPtr ib =
        Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
            Ogre::HardwareIndexBuffer::IT_32BIT, numIndices,
            Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
    geometry->renderOp.indexData->indexBuffer = ib;
    geometry->renderOp.useIndexes = true;

    // Fill the index buffer
    void* indexData = ib->lock(0, ib->getSizeInBytes(), Ogre::HardwareBuffer::HBL_NORMAL);
    memcpy(indexData, indices, sizeof(unsigned int) * numIndices);
    ib->unlock();

    return reinterpret_cast<Rocket::Core::CompiledGeometryHandle>(geometry);
}