Example #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);
}
void ImGuiInterface::RenderDrawLists(ImDrawList** const cmdLists, int cmdListsCount)
{
    // Assume render system is configured according to InterfaceManager::_configureRenderSystem
    mRenderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY);
    
    // For each command list
    for (int i = 0; i < cmdListsCount; i++)
    {
        ImVector<ImDrawCmd>& commands = cmdLists[i]->commands;

        // Allocate more space if needed
        if (mSize < cmdLists[i]->vtx_buffer.size())
        {
            mSize = cmdLists[i]->vtx_buffer.size();
            AllocateVertexBuffer(mSize);
        }

        // Copy vertices into VB
        Ogre::HardwareVertexBufferSharedPtr vb =
            mRenderOp.vertexData->vertexBufferBinding->getBuffer(0);
        ImDrawVert* vertices = static_cast<ImDrawVert*>(
            vb->lock(0, vb->getSizeInBytes(), Ogre::HardwareBuffer::HBL_DISCARD));
        memcpy(vertices, &cmdLists[i]->vtx_buffer[0], cmdLists[i]->vtx_buffer.size() * sizeof(ImDrawVert));
        vb->unlock();

        // Execute draw calls
        int offset = 0;
        for (auto c : commands)
        {
            mRenderSystem->setScissorTest(true, c.clip_rect.x, c.clip_rect.y, c.clip_rect.z, c.clip_rect.w);

            // Set texture
            if (c.texture_id)
            {
                ImguiTextureHandle* handle = reinterpret_cast<ImguiTextureHandle*>(c.texture_id);
                mRenderSystem->_setTexture(0, true, handle->texturePtr);
                mRenderSystem->_setTextureBlendMode(0, mAlphaBlendMode);
            }
            else
            {
                mRenderSystem->_disableTextureUnit(0);
            }

            // Draw vertices
            mRenderOp.vertexData->vertexStart = offset;
            mRenderOp.vertexData->vertexCount = c.vtx_count;
            mRenderSystem->_render(mRenderOp);
            offset += c.vtx_count;
        }
    }
    mRenderSystem->setScissorTest(false);
}
Example #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++;
		}
	}
}
Example #4
0
void EMDOgre::createOgreMesh(EMDSubmesh *submesh, string mesh_name) {
	string ogre_mesh_name = mesh_name + "_" + submesh->getMaterialName();
	Ogre::MeshPtr ogre_mesh = Ogre::MeshManager::getSingleton().createManual(ogre_mesh_name, XENOVIEWER_RESOURCE_GROUP);

	LibXenoverse::AABB mesh_aabb;
	mesh_aabb.reset();

	if (skeleton) {
		ogre_mesh->setSkeletonName(skeleton->getName());
	}

	// Create Vertex Pool
	vector<EMDVertex> submesh_vertices = submesh->getVertices();
	const size_t nVertices = submesh_vertices.size();
	const size_t nVertCount = 8;
	const size_t vbufCount = nVertCount*nVertices;
	float *vertices = (float *)malloc(sizeof(float)*vbufCount);
	for (size_t i = 0; i < nVertices; i++) {
		vertices[i*nVertCount] = submesh_vertices[i].x;
		vertices[i*nVertCount + 1] = submesh_vertices[i].y;
		vertices[i*nVertCount + 2] = submesh_vertices[i].z;
		vertices[i*nVertCount + 3] = submesh_vertices[i].nx;
		vertices[i*nVertCount + 4] = submesh_vertices[i].ny;
		vertices[i*nVertCount + 5] = submesh_vertices[i].nz;
		vertices[i*nVertCount + 6] = submesh_vertices[i].u;
		vertices[i*nVertCount + 7] = submesh_vertices[i].v;
		mesh_aabb.addPoint(submesh_vertices[i].x, submesh_vertices[i].y, submesh_vertices[i].z);
	}

	// Create Submeshes for each Triangle List
	vector<EMDTriangles> submesh_triangles = submesh->getTriangles();
	for (size_t i = 0; i < submesh_triangles.size(); i++) {
		Ogre::SubMesh *sub = createOgreSubmesh(&submesh_triangles[i], ogre_mesh);
	}

	// Create Shared Vertex Data for all submeshes
	Ogre::VertexData *vertex_data = new Ogre::VertexData();
	ogre_mesh->sharedVertexData = vertex_data;
	vertex_data->vertexCount = nVertices;

	Ogre::VertexDeclaration* decl = vertex_data->vertexDeclaration;
	size_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, nVertices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
	Ogre::VertexBufferBinding* bind = vertex_data->vertexBufferBinding;
	bind->setBinding(0, vbuf);


	// Create Bone Assignments if Skeleton name exists
	if (skeleton) {
		Ogre::Skeleton *ogre_skeleton = skeleton->getOgreSkeleton();
		if (ogre_skeleton) {
			for (size_t i = 0; i < submesh_triangles.size(); i++) {
				EMDTriangles *triangles = &submesh_triangles[i];
				vector<unsigned int> vertex_indices;
				size_t face_count = triangles->faces.size();

				// Make a list of all vertex indices being used in the submesh
				vertex_indices.reserve(face_count);
				for (size_t j = 0; j < face_count; j++) {
					bool found = false;

					for (size_t k = 0; k < vertex_indices.size(); k++) {
						if (vertex_indices[k] == triangles->faces[j]) {
							found = true;
							break;
						}
					}

					if (!found) vertex_indices.push_back(triangles->faces[j]);
				}

				// Build Bone Mapping Table
				vector<unsigned short> bone_table;
				bone_table.resize(triangles->bone_names.size());

				for (size_t j = 0; j < bone_table.size(); j++) {
					string bone_name = triangles->bone_names[j];

					LOG_DEBUG("Bone Skin Table %d: %s\n", j, bone_name.c_str());
					if (ogre_skeleton->hasBone(bone_name)) {
						Ogre::Bone *mBone = ogre_skeleton->getBone(bone_name);
						bone_table[j] = mBone->getHandle();
					}
					else {
						LOG_DEBUG("Couldn't find %s in ogre skeleton!\n", bone_name.c_str());
					}
				}

				// Add bone assignments to all the vertices that were found
				for (size_t j = 0; j < vertex_indices.size(); j++) {
					Ogre::VertexBoneAssignment vba;
					vba.vertexIndex = vertex_indices[j];
					EMDVertex *vertex = &submesh_vertices[vba.vertexIndex];

					for (size_t k = 0; k < 4; k++) {
						unsigned char bone_index = vertex->bone[3 - k];
						float bone_weight = vertex->bone_weight[k];

						if (bone_weight > 0.0f) {
							vba.boneIndex = bone_table[bone_index];
							vba.weight = bone_weight;
							ogre_mesh->addBoneAssignment(vba);
						}
					}
				}
			}

			// Apply changes, build the buffer
			ogre_mesh->_compileBoneAssignments();
			ogre_mesh->sharedVertexData->reorganiseBuffers(decl->getAutoOrganisedDeclaration(true, false, false));
		}
	}

	//ogre_mesh->_setBounds(Ogre::AxisAlignedBox(mesh_aabb.start_x, mesh_aabb.start_y, mesh_aabb.start_z, mesh_aabb.end_x, mesh_aabb.end_y, mesh_aabb.end_z));
	ogre_mesh->_setBounds(Ogre::AxisAlignedBox(-1000, -1000, -1000, 1000, 1000, 1000));
	ogre_mesh->_setBoundingSphereRadius(mesh_aabb.sizeMax());
	ogre_mesh->load();

	free(vertices);

	created_meshes.push_back(ogre_mesh_name);
}
Example #5
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 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);
}