ManualObject and SetCustomParameter

Auphim

24-06-2007 12:46:22

I'm trying to implement a Mogre-based example using a Cg vertex and a Cg fragment programs from Chapter 3 of "The Cg Tutorial".

My first idea was to create a manual object which uses a material with a custom parameter, but for some reason, I can´t set the paramenter.

My code is more or less this one:


class C3E1Tutorial : Mogre.Demo.ExampleApplication.Example
{
static void DrawStar(ManualObject obj, float x, float y, int starPoints, float R, float r)
{
int i;
float piOverStarPoints = 3.14159f / starPoints,
angle = 0.0f;

RenderOperation.OperationTypes operation = RenderOperation.OperationTypes.OT_TRIANGLE_FAN;

obj.Begin("CgTutorials/C3E1_Material", operation);
obj.Position(x, y, 0.0f); /* Center of star */
/* Emit exterior vertices for star's points. */
for (i = 0; i < starPoints; i++)
{
obj.Position(x + R * Math.Cos(angle), y + R * Math.Sin(angle), 0.0f);
angle += piOverStarPoints;
obj.Position(x + r * Math.Cos(angle), y + r * Math.Sin(angle), 0.0f);
angle += piOverStarPoints;
}
/* End by repeating first exterior vertex of star. */
angle = 0;
obj.Position(x + R * Math.Cos(angle), y + R * Math.Sin(angle), 0.0f);
obj.End();
}

public override void CreateScene()
{
const uint constantColor = 123;

SceneNode node1 = base.sceneMgr.RootSceneNode.CreateChildSceneNode("Tutorial03Node1");


ManualObject manualObj1 = sceneMgr.CreateManualObject("Tutorial03Object1");



/* star outer inner */
/* x y Points radius radius */
/* ===== ===== ====== ====== ====== */
node1.SetCustomParameter(constantColor, new Vector4(0.2f, 0.8f, 0.3f, 1.0f)); // Green
DrawStar(manualObj1, -0.1f, 0.0f, 5, 0.5f, 0.2f);

node1.AttachObject(manualObj1);
}

public override void CreateCamera()
{
// Create the camera
camera = sceneMgr.CreateCamera("PlayerCam");

// Position it at 30 in Z direction
camera.Position = new Vector3(0, 0, 5);
// Look at our triangle
camera.LookAt(new Vector3(0.0f, 0.0f, 0.0f));
camera.NearClipDistance = 1;
}
}


The material is defined as:


vertex_program CgTutorials/C3E1v_anycolor cg
{
source C3E1v_anycolor.cg
entry_point C3E1v_anycolor
profiles vs_1_1 arbvp1
}

material CgTutorials/C3E1_Material
{
technique
{
pass
{
vertex_program_ref CgTutorials/C3E1v_anycolor
{
param_named_auto worldViewProj worldviewproj_matrix
param_named_auto constantColor custom 123
}
}
}
}



The function C3E1v_anycolor is quite simple:

// This is C2E2f_passthru from "The Cg Tutorial" (Addison-Wesley, ISBN
// 0321194969) by Randima Fernando and Mark J. Kilgard. See page 62.

struct C3E1v_Output {
float4 position : POSITION;
float4 color : COLOR;
};

C3E1v_Output C3E1v_anycolor(float3 position : POSITION,
uniform float4x4 worldViewProj,
uniform float4 constantColor)
{
C3E1v_Output OUT;

OUT.position = mul(worldViewProj, float4(position,1));
OUT.color = constantColor; // some RGB color

return OUT;
}


My problem is that "SetCustomParameter" doesn't work. I obtain a black star.

I have no errors on the Ogre.log, and if I change the material definition with "param_name constantColor vector4 0.2 0.8 0.3 1.0" the star has a beautiful green.

Any idea what I'm doing wrong??

Auphim

24-06-2007 17:22:03

Looking for a solution, I see that the original C++ code of ManualObject.end() returns a ManualObjectSection pointer. But our Mogre version returns void. This seems to be a bug.

From the C++ API, this ManualObjectSection object has a setCustomParameter that could be used (??).

I dont known if using ManualObjectSection.setCustomParameter I could obtain better results.

Auphim

25-06-2007 18:19:00

Well, I tried with standard entities (SceneManager.PrefabType) and I found that SetCustomParameters DOES work. For instance:

public override void CreateScene()
{
const uint constantColor = 123;

Entity entity1 = base.sceneMgr.CreateEntity("Tutorial03Node1", SceneManager.PrefabType.PT_SPHERE);
entity1.SetMaterialName("CgTutorials/C3E1_Material");
entity1.GetSubEntity(0).SetCustomParameter(constantColor, new Vector4(0.2f, 0.0f, 1.0f, 1.0f));
base.sceneMgr.RootSceneNode.AttachObject(entity1);

Entity entity2 = base.sceneMgr.CreateEntity("Tutorial03Node2", SceneManager.PrefabType.PT_PLANE);
entity2.SetMaterialName("CgTutorials/C3E1_Material");
entity2.GetSubEntity(0).SetCustomParameter(constantColor, new Vector4(0.3f, 1.0f, 0.1f, 1.0f));
base.sceneMgr.RootSceneNode.AttachObject(entity2);
}


So my conclusion is I'm doing something wrong with ManualObject. But I don't known what!.
Any Help??

Auphim

28-06-2007 11:30:00

Finally, I found the solution.!!!

Each ManualObject creates a ManualObjectSection for each Begin/End. The End() function returns this section.

This ManualObjectSection has a SetCustomParameter member. So the code is now:


public override void CreateScene()
{
const uint constantColor = 123;

SceneNode node1 = base.sceneMgr.RootSceneNode.CreateChildSceneNode("Tutorial03Node1");
SceneNode node2 = base.sceneMgr.RootSceneNode.CreateChildSceneNode("Tutorial03Node2");

ManualObject manualObj1 = sceneMgr.CreateManualObject("Tutorial03Object1");
ManualObject manualObj2 = sceneMgr.CreateManualObject("Tutorial03Object2");
ManualObject manualObj3 = sceneMgr.CreateManualObject("Tutorial03Object3");
ManualObject manualObj4 = sceneMgr.CreateManualObject("Tutorial03Object4");
ManualObject manualObj5 = sceneMgr.CreateManualObject("Tutorial03Object5");
ManualObject manualObj6 = sceneMgr.CreateManualObject("Tutorial03Object6");


/* star outer inner */
/* x y Points radius radius */
/* ===== ===== ====== ====== ====== */
ManualObject.ManualObjectSection objSection;
objSection = DrawStar(manualObj1, -0.1f, 0.0f, 5, 0.5f, 0.2f);
objSection.SetCustomParameter(constantColor, new Vector4(0.0f, 1.0f, 0.0f, 1.0f));// Green
objSection = DrawStar(manualObj2, -0.84f, 0.1f, 5, 0.3f, 0.12f);
objSection.SetCustomParameter(constantColor, new Vector4(0.3f, 1.0f, 0.0f, 1.0f));// Green
objSection = DrawStar(manualObj3, 0.92f, -0.5f, 5, 0.25f, 0.11f);
objSection.SetCustomParameter(constantColor, new Vector4(0.6f, 1.0f, 0.0f, 1.0f));// Green

objSection = DrawStar(manualObj4, 0.3f, 0.97f, 5, 0.3f, 0.1f);
objSection.SetCustomParameter(constantColor, new Vector4(1.0f, 1.0f, 0.0f, 1.0f)); // Yellow
objSection = DrawStar(manualObj5, 0.94f, 0.3f, 5, 0.5f, 0.2f);
objSection.SetCustomParameter(constantColor, new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); // Red
objSection = DrawStar(manualObj6, -0.97f, -0.8f, 5, 0.6f, 0.2f);
objSection.SetCustomParameter(constantColor, new Vector4(0.0f, 0.0f, 1.0f, 1.0f)); // Blue

node1.AttachObject(manualObj1);
node1.AttachObject(manualObj2);
node1.AttachObject(manualObj3);

node2.AttachObject(manualObj4);
node2.AttachObject(manualObj5);
node2.AttachObject(manualObj6);
}


The bad new is that the version 0.2.0 of Mogre DOESN't support this functionality by default. Due to a problem in the building process, the ManualObject is not generated correctly.

@pjohnsen: Thanks a lot for your help with the building process.