MORGE MESH

suncc

07-12-2009 09:16:08

CAN MOGRE create new meshs? and how?

AndroidAdam

08-12-2009 03:52:22

How to generate a mesh using an index and vertex buffer
I hope this is what you're looking for, typically you create your mesh in an external 3d modeling tool such 3ds max or maya. OGRE doesn't create the models, it just renders them.

suncc

08-12-2009 08:11:42

Thank you very much, you offer a great help.

WarehouseJim

08-12-2009 14:33:34

It's generally easier to use ManualObject, not the method AndroidAdam mentioned. I've started writing some documentation on it, but haven't attacked it for a while. Below is some (not necessarily perfect) C# sample code that I created when I was learning the ropes:

It might not be that clear, but the basic idea is that you build up triangles by providing 3 points in anticlockwise order from the perspective of someone looking at it. These are sent to the vertex buffer with manualObject.Position() sequentially, then referenced in the order they were sent to the buffer to build a triangle with manualObject.Triangle(). You also associate normals, which should be normalised, with these points (used for lighting). If you want a sharp edged object like the tetrahedron below, then you define new vertices for each corner of the triangle with the same normal on all vertices pointing perpendicular to the face of the triangle. If you want a smoother look, you can have the normal pointing somewhere between the perpediculars to the faces around it, and use a common vertex for all the faces it touches. You start the whole building process with manualObject.Begin() and end it with manualObject.End().

Eventually, you will also want to define UV coordinates for each vertex (sorry, not done below), but do manualObject.TextureCoord() just after manualObject.Position().

You can also create lines, define quads rather than triangles etc. The ManualObject class documentation will help you.

Below I have attached the manual object to a node directly, but you may want to do manualObject.ConvertToMesh() which allows you to re-use the object, and may help with some issues with things like shadows, static geometry etc.

Have a go at it, I'm happy to answer any questions.


private SceneNode CreateTestTetrahedron(string name, float scale, Vector3 position, String materialName)
{

var mo = sceneManager.CreateManualObject(name);
mo.CastShadows = true;
var node = sceneManager.RootSceneNode.CreateChildSceneNode();

Vector3[] c = new Vector3[4]; // corners

// calculate corners of tetrahedron (with point of origin in middle of volume)
Single mbot = scale * 0.2f; // distance middle to bottom
Single mtop = scale * 0.62f; // distance middle to top
Single mf = scale * 0.289f; // distance middle to front
Single mb = scale * 0.577f; // distance middle to back
Single mlr = scale * 0.5f; // distance middle to left right
// width / hight / depth
c[0] = new Vector3(-mlr, -mbot, mf); // left bottom front
c[1] = new Vector3(mlr, -mbot, mf); // right bottom front
c[2] = new Vector3(0, -mbot, -mb); // (middle) bottom back
c[3] = new Vector3(0, mtop, 0); // (middle) top (middle)

// add position offset for all corners (move tetrahedron)
for (Int16 i = 0; i <= 3; i++)
c[i] += position;

// create bottom
mo.Begin(materialName, RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
var normal = (c[1] - c[0]).CrossProduct(c[1] - c[2]).NormalisedCopy;
var normalA = normal;
var normalB = normal;
var normalC = normal;



//this is an attempt to try to make it seem softer.
normalA.x += 2f;
normalA.y += 0.5f;
normalB.y -= 2f;
normalB.x -= 0.5f;

mo.Position(c[0]);
mo.Normal(normalA);
mo.TextureCoord(0,0);

mo.Position(c[1]);
mo.Normal(normalB);
mo.TextureCoord(0,1);

mo.Position(c[2]);
mo.Normal(normalC);
mo.TextureCoord(1,1);

mo.Triangle(0, 1, 2);
mo.Triangle(0, 2, 1);
mo.End();

float lineLen = scale/3;



// create right back side
mo.Begin(materialName, RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
normal = (c[1] - c[2]).CrossProduct(c[1] - c[3]).NormalisedCopy;
normalA = normal;
normalB = normal;
normalC = normal;

normalA.x += 2f;
normalA.y += 0.5f;
normalB.y -= 2f;
normalB.x -= 0.5f;

mo.Position(c[1]);
mo.Normal(normalA);
mo.Position(c[2]);
mo.Normal(normalB);
mo.Position(c[3]);
mo.Normal(normalC);
mo.Triangle(0, 1, 2);
mo.Triangle(0, 2, 1);
mo.End();


// create left back side
normal = (c[0] - c[2]).CrossProduct(c[2] - c[3]);
mo.Begin(materialName, RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
mo.Position(c[3]);
mo.Normal(normal);
mo.Position(c[2]);
mo.Normal(normal);
mo.Position(c[0]);
mo.Normal(normal);
mo.Triangle(0, 1, 2);
mo.Triangle(0, 2, 1);
mo.End();


// create front side
normal = (c[1] - c[3]).CrossProduct(c[0] - c[3]);
mo.Begin(materialName, RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
mo.Position(c[0]);
mo.Normal(normal);
mo.Position(c[1]);
mo.Normal(normal);
mo.Position(c[3]);
mo.Normal(normal);
mo.Triangle(0, 1, 2);
mo.Triangle(0, 2, 1);
mo.End();

node.AttachObject(mo);
return node;


}


MatrixAlgebra

09-12-2009 09:36:15

Hi I need help in updating the color of vertices in loaded mesh. I have search the internet, most of the example provided is using material instead of working on the A LIST OF VERTICES. I found this c++ codes which I am not sure how to do it correctly

//ColourValue mColor;
//// Convert to system-specific
//RGBA color;
//Root::getSingleton().convertColourValue(mColor, &color);
//HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING);
//RGBA *pDest = static_cast<RGBA*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
//for (uint i = 0; i < mRenderOp.vertexData->vertexCount; ++i)
// *pDest++ = color;
//vbuf->unlock();
//mUpdateColors = false;

Question A: What is the equivalent of RGBA variable in Mogre. After assigning the color to the buffer associated with Diffuse vertexelement, is there a need to update or refresh to see the new color change. I


Question B. have looked at the Triangle example and using MeshHelper. I wonder how to for example after getting the MeshPtr back from the Triangle, How to randomly change the color of each vertice dynamically. Appreciate any feedback

Thanks.

MatrixAlgebra

09-12-2009 09:47:21

Hi, there are two methods of creating mesh discussed here. Using RenderOperation using MovableObject or SubMesh using the example of MeshHelper where one go through the lock and unlock vertexData buffer. What is the difference?

a) Is the following approach a reasonable way to proceed. Create a structure of customized vertex.

Struct Vertex
Vector3 position
Vector3 Color

Struct Index
ushort pos1, pos2, pos3
Create an Array of these vectors e.g. Vertex[] vertexList and Index[] indexList and pass it to a MeshBuilderAndRendere class using e.g. reanderOperation method that take these array and return either a movableObject or MeshPtr.

(i) Can these be done? can someone kindly provide some help.
(ii) likewise, the same class also provide a RenderOnDemand method that Take a parameter such as Vertex[] vertexList with new color information and update the SubMesh (e.g. triangle) associated with it .

I am search and not found any such example. Appreciate some help and feedback

Thanks.

MatrixAlgebra

09-12-2009 10:09:25

I just found http://www.ogre3d.org/wiki/index.php/ManualObject
http://www.ogre3d.org/addonforums/viewtopic.php?f=8&t=11753
WharehouseJIM is right.

WarehouseJim

09-12-2009 10:23:00

I can't help with changing a mesh as I haven't done it myself.

As far as I understand it, the difference between the ManualObject method, which I have used a reasonable amount, and the method suggested by AndroidAdam, which I haven't used, is mostly that the ManualObject method was created later to try to make the process a bit easier. You also benefit in that you don't have to include unsafe code. I expect there are some complex & obscure things you can do with AndroidAdam's method that you can't do with ManualObject.

The method you suggest should work, although you will want to include a Normal in your Vertex struct. I tend not to set the Colour as I use materials that override it. If you do use textured materials, then you will want to include texture (UV) coordinates for each Vertex as well.

To actually make the mesh, using ManualObject, you would do something like:


public MeshPtr CreateMesh(Vertex[] vertexList, Index[] indexList, string meshName, string materialName)
{
ManualObject mo = sceneManager.CreateManualObject(meshName+"ManualObject");
mo.Begin(materialName, RenderOperation.OperationTypes.OT_TRIANGLE_LIST); //Set the material and state that you are making a mesh out of triangles

//Create all the vertices
foreach(Vertex v in vertexList)
{
mo.Position(v.Position);
mo.Normal(v.Normal);
mo.Colour(v.Color); //NB Ogre uses British English spelling of Colour.
mo.TextureCoord(v.textureCoord.U, v.textureCoord.V);

}

//Create the triangles
foreach(Index index in indexList)
{
mo.Triangle(index.pos1, index.pos2, index.pos3);
}

mo.End(); // End creating the manual object.

return mo.ConvertToMesh(meshName); //Create an actual mesh from the ManualObject, and return.

}