Coloring A Scene Node
Coloring A Scene Node
I am working on a program that turns the nearest node to the camera to be yellow. I have created nodes around the scene using addSphereSceneNode. Currently, it is displaying many black nodes across the scene.
Now what I want to do is turn the nearest node to be yellow. Working in an unlit environment, I was told earlier that I would have to edit the vertex colors. I am having trouble finding out how to edit the vertex colors for a single node. It says I need to access the mesh but I am confused on how to retrieve the mesh from the node.
It seems like a simple problem that I can't seem to understand. Please help me out.
Now what I want to do is turn the nearest node to be yellow. Working in an unlit environment, I was told earlier that I would have to edit the vertex colors. I am having trouble finding out how to edit the vertex colors for a single node. It says I need to access the mesh but I am confused on how to retrieve the mesh from the node.
It seems like a simple problem that I can't seem to understand. Please help me out.
I have changed from using addSphereSceneNode to just creating 2 spherical meshes, a black one and a yellow one. I then used addAnimatedMeshSceneNode to add the nodes to the scene, loading up the black mesh.
Now when I have the node ID, I am able to retrieve the node, but I am still unable to retrieve the mesh from the node. I am assuming I can cast it as an IMeshSceneNode, but I am having trouble doing that.
My code is below:
ONE MORE THING:
When I create the yellow mesh, how do I edit the vertex colors so that it will be a yellow sphere. I am using an unlit environment.
Please help me out, thanks.
Now when I have the node ID, I am able to retrieve the node, but I am still unable to retrieve the mesh from the node. I am assuming I can cast it as an IMeshSceneNode, but I am having trouble doing that.
My code is below:
Code: Select all
scene::IMeshSceneNode* meshnode = smgr->getSceneNodeFromId(someID);
When I create the yellow mesh, how do I edit the vertex colors so that it will be a yellow sphere. I am using an unlit environment.
Please help me out, thanks.
Yes, it is a relatively simple problem, but if all of the nodes you want to apply this to are the same, I'm going to suggest you do it a bit differently. Anyways, on to your question.
If you have a pointer to an ISceneNode, you can ask it for its actual type. If you find out that you have a mesh scene node, you can safely cast the ISceneNode pointer to IMeshSceneNode. Once you have a pointer to the derived class, you can access the functions of the derived class, one of which gives you access to the underlying IMesh. Now that you have a pointer to an IMesh object, there is just a little work to do. The IMesh contains a series of IMeshBuffer objects. For each of the IMeshBuffer objects, you need to change the vertex color for each of the vertices. This part is a bit tricky because you have to access the vertex data correctly.
You can actually use the IMeshManipulator functions like setVertexColors() or apply() to modify the mesh vertices. This makes things much simpler.
If all of your nodes are the same, I suggest that you create a copy of the original mesh and modify the vertex colors once. Then when you want to highlight one of your nodes, you just swap the mesh used by that scene node...
Then, you create your nodes...
You keep track of the selected node...
Also, if you have a bunch of black nodes it is likely because you have lighting enabled, and you don't have any lights. If you want to not use lighting, you need to disable lighting on every node in the scene. i.e., you need to call node->setMaterialFlag(video::EMF_LIGHTING, false) for each node.
Travis
If you have a pointer to an ISceneNode, you can ask it for its actual type. If you find out that you have a mesh scene node, you can safely cast the ISceneNode pointer to IMeshSceneNode. Once you have a pointer to the derived class, you can access the functions of the derived class, one of which gives you access to the underlying IMesh. Now that you have a pointer to an IMesh object, there is just a little work to do. The IMesh contains a series of IMeshBuffer objects. For each of the IMeshBuffer objects, you need to change the vertex color for each of the vertices. This part is a bit tricky because you have to access the vertex data correctly.
You can actually use the IMeshManipulator functions like setVertexColors() or apply() to modify the mesh vertices. This makes things much simpler.
If all of your nodes are the same, I suggest that you create a copy of the original mesh and modify the vertex colors once. Then when you want to highlight one of your nodes, you just swap the mesh used by that scene node...
Code: Select all
// at program startup
scene::IMeshManipulator* manip = smgr->getMeshManipulator ();
scene::IGeometryCreator* geom = smgr->getGeometryCreator ();
// create two sphere meshes...
scene::IMesh* meshes [2];
meshes [0] = geom->createSphereMesh (...);
meshes [1] = manip->createMeshCopy (meshes [0]);
// modify the vertex color of the second mesh
manip->setVertexColors(meshes [1], video::SColor(255, 128, 128, 0));
// you could also use one of the manipulators instead
// manip->apply(scene::SVertex...Manipulator(...), meshes [1]);
Code: Select all
smgr->addMeshScneNode(meshes [0], 0, pos, rot, scl);
Code: Select all
// this part is probably outside your main loop or is your event receiver
// member data
scene::IMeshSceneNode* prev_selected = 0;
// this part is probably inside your main loop or in your event receiver
// event processing logic.
// your code should be able to get the selected node and make sure it
// is of the correct type.
scene::IMeshSceneNode* next_selected = //...
if (prev_selected != next_selected)
{
// restore the mesh for the previously selected node
if (prev_selected)
prev_selected->setMesh (meshes [0]);
// set the newly selected node to use the modified mesh
if (next_selected)
next_selected->setMesh (meshes [1]);
// cache pointer to selected node
prev_selected = next_selected;
}
Travis
This code is not correct. The function getSceneNodeFromId() returns an ISceneNode*, and the compiler can't convert from ISceneNode* to IMeshSceneNode* unless you ask nicely.so1odo1o wrote:Code: Select all
scene::IMeshSceneNode* meshnode = smgr->getSceneNodeFromId(someID);
Code: Select all
scene::ISceneNode* node = smgr->getSceneNodeFromId(someID);
if (node && node->getType() == scene::ESNT_MESH)
{
scene::IMeshSceneNode* mesh_node = (scene::IMeshSceneNode*)node;
// do other stuff here...
}
For some reason, the nodes are staying black.
Here is my code so far:
Main loop :
I then tried adding meshes[1] after it hadbeen manipulated instead of meshes[0] above, but the nodes still appear as black.
Here is my code so far:
Code: Select all
// Add nodes to graph
scene::IMeshManipulator* manip = smgr->getMeshManipulator();
scene::IMesh* meshes[2];
meshes[0] = smgr->getGeometryCreator()->createSphereMesh(1.0, 16U, 16U);
meshes[1] = manip->createMeshCopy(meshes[0]);
manip->setVertexColors(meshes[1], video::SColor(255, 128, 128, 0));
for(int i = 0; i < num; i++)
{
GraphNode gn = nodes.at(i);
smgr->addMeshSceneNode(meshes[0], 0, gn._id, core::vector3df(gn._x,gn._y,gn._z));
}
Code: Select all
while(device->run())
{
if (device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(255,200,200,200));
// Set material
video::SMaterial m;
m.Lighting = false;
driver->setMaterial(m);
// Set world transform
core::matrix4 identity;
driver->setTransform(video::ETS_WORLD, identity);
...
for(int i = 0; i < ids.size(); i++)
{
// Draw lines
driver->draw3DLine(
smgr->getSceneNodeFromId(ids[i].id1)->getAbsolutePosition(),
smgr->getSceneNodeFromId(ids[i].id2)->getAbsolutePosition(),
video::SColor(255,0,0,0));
}
// Find nearest node here
core::vector3df camPos = smgr->getActiveCamera()->getAbsolutePosition();
int oldID = nodes[0]._id;
int newID = oldID;
float smallestDist = camPos.getDistanceFrom(
smgr->getSceneNodeFromId(nodes[0]._id)->getAbsolutePosition());
for(int i = 0; i < num; i++)
{
float dist = camPos.getDistanceFrom(
smgr->getSceneNodeFromId(nodes[i]._id)->getAbsolutePosition());
if(dist <= smallestDist)
{
smallestDist = dist;
newID = nodes[i]._id;
scene::IMeshSceneNode* old_node = (scene::IMeshSceneNode*) smgr->getSceneNodeFromId(oldID);
scene::IMeshSceneNode* new_node = (scene::IMeshSceneNode*) smgr->getSceneNodeFromId(newID);
old_node->setMesh(meshes[0]);
new_node->setMesh(meshes[1]);
I'm pretty sure you didn't read this...
You have three choices...vitek wrote: Also, if you have a bunch of black nodes it is likely because you have lighting enabled, and you don't have any lights. If you want to not use lighting, you need to disable lighting on every node in the scene. i.e., you need to call node->setMaterialFlag(video::EMF_LIGHTING, false) for each node.
- Disable lighting for every node in the scene (or just the ones you want) by calling node->setMaterialFlag(video::EMF_LIGHTING, false).
- Leave lighting enabled and turn on some ambient light with smgr->setAmbientLight(video::SColorf(.2f, .2f, .2f)).
- Leave lighting enabled and create a dynamic light with smgr->addLightSceneNode().
Sorry, I forgot to update my other post, but I did disable the lighting for each node right after:
Right now, random nodes are currently turning white. (No sign of yellow). Does it matter if I had done this later during beginScene and endScene:
Code: Select all
// Add nodes to graph
scene::IMeshManipulator* manip = smgr->getMeshManipulator();
scene::IMesh* meshes[2];
meshes[0] = smgr->getGeometryCreator()->createSphereMesh(1.0, 16U, 16U);
meshes[1] = manip->createMeshCopy(meshes[0]);
manip->setVertexColors(meshes[1], video::SColor(255, 128, 128, 0));
for(int i = 0; i < num; i++)
{
GraphNode gn = nodes.at(i);
scene::IMeshSceneNode* node =
smgr->addMeshSceneNode(meshes[0], 0, gn._id, core::vector3df(gn._x,gn._y,gn._z));
if(node)
{
node->setMaterialFlag(video::EMF_LIGHTING, false);
}
}
Code: Select all
core::matrix4 identity;
driver->setTransform(video::ETS_WORLD, identity);