Started by Jun 07 2012 08:44 PM

,
6 replies to this topic

Posted 07 June 2012 - 08:44 PM

I need some advice on a certain number of things: 1) Creating a scene graph (I know the theory behind it, it basically has to do with each node having it's own matrix then if the object has a child or is a child of another object you multiple the matrices together to get the new one. Just not totally sure on how to go about doing that, Also, I was wondering if anyone could give me the theory behind mouse look, like something that will work for anything given some work. I don't really know the steps to take to get mouse look to work but it should be language independent.

So, what ever you guys give me, i'll take.

So, what ever you guys give me, i'll take.

Posted 08 June 2012 - 02:41 PM

Your questions are a little vague, but I'll try...

Doing what? Representing the nodes or performing the multiplication?

To represent the graph in C or C++ you might use pointers in the node structure to refer to any children. In many other languages (Java, Python, C#, ...) nullable references will do the same thing. Or you can create a pool of node objects and use indices in to the pool rather than pointers to represent child links.

If your question is about the multiplication, are you wondering about the mechanics of traversing the graph, or the nuts and bolts of matrix multiplication itself?

Given those angles you can construct two rotation matrices, one for each axis and multiply them to get the resulting transformation. The order in which you perform the multiplication is significant, but other than that and some trivial optimizations, that's about all there is to it.

I need some advice on a certain number of things: 1) Creating a scene graph (I know the theory behind it, it basically has to do with each node having it's own matrix then if the object has a child or is a child of another object you multiple the matrices together to get the new one. Just not totally sure on how to go about doing that,

Doing what? Representing the nodes or performing the multiplication?

To represent the graph in C or C++ you might use pointers in the node structure to refer to any children. In many other languages (Java, Python, C#, ...) nullable references will do the same thing. Or you can create a pool of node objects and use indices in to the pool rather than pointers to represent child links.

If your question is about the multiplication, are you wondering about the mechanics of traversing the graph, or the nuts and bolts of matrix multiplication itself?

There's not a lot of theory there. You maintain two angles, yaw and pitch. Moving the mouse updates these angles. Typically you'll want to clamp pitch to (-pi/2, pi/2), unless you want to allow somersaults.Also, I was wondering if anyone could give me the theory behind mouse look,

Given those angles you can construct two rotation matrices, one for each axis and multiply them to get the resulting transformation. The order in which you perform the multiplication is significant, but other than that and some trivial optimizations, that's about all there is to it.

Posted 09 June 2012 - 08:27 AM

Ok, i'll try to explain this as best as I can. first code:

.h

.cpp

now as you can see from this i sorta do add the matrices together (well, not really.) As im not sure if i got to do something like this:

so yea, that's something i need help with, most of those are place holders anyways especially the one where i add the ID3DXMesh interface.

.h

#ifndef INODE_H #define INODE_H #include <string> #include <d3dx9.h> #include "Container.h" #include <vector> #include "IrrException.h" #include "IrrRenderList.h" #include "IrrRenderSystem.h" #include "IrrMatrix4.h" #include "IrrVector3.h" #include "..//IrrD3D9Renderer/IrrD3D9Utility.h" namespace IrrGraphics { // Class to create a scene node. this is the base class for other nodes. class INode { protected: INode* child; INode* parent; IrrMatrix4 parentMat; IrrMatrix4 childMat; IrrVector3 childPos; IrrVector3 parentPos; IrrVector3 parentScale; IrrVector3 childScale; std::vector<INode*> Children; std::vector<ID3DXMesh*> meshes; std::string m_nodeName; public: INode(std::string nodeName); // node constructor (node's name) INode(); // default constructor. INode* getParentNode() const; // returns the parent node of this node. int getNumChildren() const; // returns the number of children this node has. INode* getChild(std::string childName) const; // returns the child with the given name. INode* getChild(int index) const; // returns the child with the given index. void setPosition(float xpos, float ypos, float zpos); // sets the node's position. IrrVector3 getPosition() const; // returns the position vector of the node. void setScale(float xscale, float yscale, float zscale); // sets the scale of the node. IrrVector3 getScale() const; // get scale of node. void addChild(INode* otherChild); // adds a child. void attachMesh(ID3DXMesh* mesh); // adds mesh to the node. // add a child to this node. void updateNode(); // updates the node. protected: bool isNodeAttached(INode* child); // checks if a node is connected to this one. // if not, it just void setParent(INode* p); }; } #endif

.cpp

#include "INode.h" namespace IrrGraphics { INode::INode(std::string nodeName) { this->m_nodeName = nodeName; this->child = NULL; this->parent = NULL; this->childMat.identity(); this->childPos.Set(0,0,0); this->childScale.Set(1,1,1); } void INode::attachMesh(ID3DXMesh* mesh) { meshes.push_back(mesh); } void INode::addChild(INode* otherChild) { Children.push_back(otherChild); setParent(this); } bool INode::isNodeAttached(INode* child) { if(child != NULL) { if(parent->child == child) { return true; } else { parent = parent->child; } } else { throw IrrException("Node not attach"); } } void INode::setParent(INode* p) { parent = p; } void INode::updateNode() { parentMat.identity(); D3DXMATRIX world; D3DXMatrixTranslation(&world,parentPos.getX(), parentPos.getY(), parentPos.getZ()); //D3DXMatrixScaling(&world,1,1,1); parentMat = IrrD3D9Util::D3DMatrixToIrrMatrix(world); IrrRenderList::getSingletonPtr()->getRenderSystem()->_setWorldMatrix(parentMat); for(int x = 0; x < meshes.size(); x++) { ID3DXMesh* mesh = meshes[x]; mesh->DrawSubset(0); } } INode::INode() { m_nodeName = "_untittled# "; child = NULL; parent = NULL; childMat.identity(); childPos.Set(0,0,0); childScale.Set(1,1,1); } void INode::setPosition(float xpos, float ypos, float zpos) { parentPos.Set(xpos,ypos,zpos); parentMat.setTranslation(parentPos.getX(),parentPos.getY(),parentPos.getZ()); } IrrVector3 INode::getPosition() const { return childPos; } INode* INode::getChild(std::string childName) const { for(int x = 0; x < Children.size(); x++) { INode* c = Children[x]; if(c->m_nodeName == childName) { return c; } } } }

now as you can see from this i sorta do add the matrices together (well, not really.) As im not sure if i got to do something like this:

if(parent->child != null) { childmat * parentMat; } else { childmat = NULL; }

so yea, that's something i need help with, most of those are place holders anyways especially the one where i add the ID3DXMesh interface.

Posted 09 June 2012 - 10:04 AM

Let's simmer this down to the essentials:

The exact way in which you represent a position relative to the parent node doesn't matter, but I've used a single matrix here. As you walk the graph, you concatenate the transforms as you go.

Does this make sense? Note that I didn't modify the data in any of the nodes in order to render it. There's simply no need.

It's quite common for scene graph nodes to contain modifiers too. You'd concatenate those in an entirely analogous way. As a crude example, if a valley is foggy, a tree in the valley should also be foggy, and so should its branches, etc.

class renderer { public: // ... void draw(const mat4x4 &item2world, const renderable &item); // ... }; struct scene_node; typedef boost::shared_ptr<scene_node> scene_node_ptr; struct scene_node { renderable instance; // data to render mat4x4 local2parent; std::vector<scene_node_ptr> children; // child nodes }; // Assumes no cycles in scene graph. void render_traversal(const scene_node &node, renderer &rend, const mat4x4 &parent2camera) { mat4x4 node2camera = parent2camera * node.local2parent; // order of operands depends on how you do matrix multiplication rend.draw(node2camera, node.instance); BOOST_FOREACH(const scene_node_ptr &child, node.children) { render_traversal(*child, rend, node2camera); } } // To render the entire graph, assuming it only has a single root node: void render_scene(const camera &cam, renderer &rend, const scene_node &root) { mat4x4 base = cam.world_to_camera(); render_traversal(root, rend, base); }

The exact way in which you represent a position relative to the parent node doesn't matter, but I've used a single matrix here. As you walk the graph, you concatenate the transforms as you go.

Does this make sense? Note that I didn't modify the data in any of the nodes in order to render it. There's simply no need.

It's quite common for scene graph nodes to contain modifiers too. You'd concatenate those in an entirely analogous way. As a crude example, if a valley is foggy, a tree in the valley should also be foggy, and so should its branches, etc.

**Edited by edd, 09 June 2012 - 10:07 AM.**