⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graph

📁 计算机图形学~想必是很多人需要的~在此共享一下
💻
字号:
A Simple Scene GraphAlthough there are a few standard scene graph APIs available,including VRML and JAVA 3D, none have yet become dominant.Rather than discuss one of these, we shall opt instead tocontruct our own simple scene graph API. It will include the basics shared by more complex scene graph APIs and will be easy to extend. First, we start withthe public interface that a user can use to define ascene graph and display it. Then we consider a possibleimplementation using the left-child right-sibling data structure of section~8.6. Our design will employ two bases classes: a node class thatwe will use to contruct all our objects including geometricobjects, camera objects, material objects, and light sourceobjects. These nodes will form a tree that is our scenegraph.  We shall also need a simple mechanism that willallow us to view the scene graph with OpenGL. We use anothersimple class for this operation: the GLViewer class.\subsection{The Node Class}Our fundamental node has the public interface://Node.h class Node{ public:  Node();  virtual ~Node();  virtual void Render();  void AddChild(Node *);  friend class GLViewer;};We have both a constructor and destructor for creating and deletingnodes, which will enable us to work with dynamic graphs. We candefine a hiearchy by having a single method for addinga child to a node. However, as we shall see when wediscuss implementation, the order in which we add childrenwill affect the display of the scene graph.As we will have many types of nodes (geometry, camera,materials, lights) each node must have its own render method which will execute when the node is encounteredas part of the traversal process. We can invoke the renderingprocess from the viewer. The viewer will also let take careof the standard OpenGL interfac with the window system by using GLUT. Here is the public part of the viewerclass GLViewer{ public:  GLViewer();  ~GLViewer();  void CreateWin(char *Name, int Width, int Height);  //set buffer, backcolor  void SetValue(Enum PName, Enum Type);  void Init(int argc, char **argv);  void Show(Node *N);};We will be able to have multiple viewers so that we can, forexample, display two different views using two different camerasin two OpenGL windows. We could also use different OpenGL windowsto view different parts of the same scene graph by passingin different nodes to the Show method.Both the viewer and node classes will have many parameters that are used to specify attributes, such as color, line style and materialproperties, and rendering options, such double buffering andhidden-surface removal. We take an approach similar to OpenGL and GLUT by specifiying symbolic constants as an enumeratedtype:enum Enum{  PERSPECTIVE, ORTHO, POSITION, AIMAT, UPDIRECTION, ASPECT,   NEAR, FAR, YANGLE, BLACK, WHITE, RED, GREEN, YELLOW, BLUE,   MAGENTA, CYAN, GREY, WIDTH, HEIGHT,DEPTH,  AMBIENT, DIFFUSE, SPECULAR, SPOT_DIRECTION, DROPOFFRATE,   CUTOFFANGLE, EMISSION, SHININESS, TRANSLATION, ROTATION, SCALE,   BUFFER, SINGLE, DOUBLE, RADIUS, STYLE, POINTSIZE, LINEWIDTH,   FILLED, LINE, POINT, BACKCOLOR};\subsection{The Nodes}We have five major subclasses of our Node: geometry nodes,light nodes, camera nodes, attribute nodes, and transformationnodes. From the OpenGL perspective, there are two types ofoperations: those that generate primitives and those thatchange state. However, from the perspective of a scenegraph both types of functionality are allowed within anode.\subsubsection{Geometry Nodes}Our scene graph allows for the basic types of line and polygons, and the more complex objects, including cubes, cylinders, triangles, and spheres. Geometry nodeshave many properties in common, including color attributes, material properties, and instance matrices that canbe applied to them. These properties can be set by a userprogram and we have included set methods for them in a separate class//Geometry.hclass Geometry: public Node{ public:  Geometry();  ~Geometry();  void SetColor(Enum);  void SetColor(float, float, float);  void SetColorv(float *);  void SetColor(Color *);  void SetMaterial(Enum, float, float, float, float);  void SetMaterialv(Enum, float *);  void SetMaterial(Enum, float);  void SetMaterial(Material *);  void SetTransform(Enum, float *, int);  void SetTransform(Enum, float, float, float, int);  void SetTransform(Enum, float, float, float, float, int);  void SetTransform(Transformation *);  void SetStyle(Enum, Enum);  void SetStyle(Enum, float);  void SetStyle(DrawStyle *);  virtual void Render();}Now we can look at some the geometry nodes. Thesimplest is a line segment which allows us to setthe end points either directly or by a pointer toan array of two vertices. Note that in our simplesystem, we have included only three-dimensionalvertices. It is a simple exercise to add two-dimensionalvertices. Also, note that we could use a singlefunction \mono{SetVertices} for all  cases as C++permits overloading of functions.//Line.hclass Line: public Geometry{ public:  Line(){};  void SetVertices(float *, float *);  void SetVerticesv(float v[][3]);  void Render();};//Sphere.hclass Sphere: public Geometry{ public:  Sphere(){};  Sphere(float R);  void SetValue(Enum Pname, float v);  void Render();};\subsection{An Example}Before discussing the implementation, let's consider asimple example, the robot figure again//Scene.cc#include "Scene.h"#define BaseRadius 0.2#define Radius 0.08#define BaseLen 1#define UpLen 0.6#define LowLen 0.6#define EyeRadius 0.04#define ChairLegLen 0.55intmain(int argc, char **argv){  float v[][3]={{-0.3,-0.2,0.0},{0.3, -0.2, 0.0},		{0.3, 0.2, 0.0},{-0.3, 0.2, 0.0} };  //Light nodes  Light *Light1=new Light;  Light *Light2=new Light;  TurnOff *Off1=new TurnOff(Light1);  TurnOff *Off2=new TurnOff(Light2);  //Setting Light Values :  Light1->SetValue(POSITION, -2, -3, 1.5, 1);  Light1->SetValue(SPOT_DIRECTION, 2, 3, -1.5);  Light1->SetValue(CUTOFFANGLE, 40.0);  Light1->TurnOn();  Light2->SetValue(POSITION, 5, 5, 5, 0);  Light2->SetValue(SPECULAR, 1.0, 1.0, 1.0, 1.0);  Light2->SetValue(DIFFUSE, 1.0, 1.0, 1.0, 1.0);  Light2->TurnOn();  //Nodes for Camera:  Camera *Camera1=new Camera(PERSPECTIVE);  Camera1->SetValue(POSITION, 2.2, 0.9, 3);  Camera1->SetValue(AIMAT, 0, 0, 0);  Camera1->SetValue(UPDIRECTION, 0, 1, 0);  Camera1->SetValue(ASPECT, 1);  Camera1->SetValue(NEAR, 1);  Camera1->SetValue(FAR, 20);  Camera1->SetValue(YANGLE, 50);    //Nodes for Robot:  Material *RobotMat=new Material;  Material *EyeMat=new Material;  Cylinder *Base=new Cylinder;  Sphere *Head=new Sphere;  Sphere *EyeL=new Sphere;  Sphere *EyeR=new Sphere;  Cylinder *UpperArmL=new Cylinder;  Cylinder *UpperArmR=new Cylinder;  Cylinder *LowerArmL=new Cylinder;  Cylinder *LowerArmR=new Cylinder;  Cylinder *UpperLegL=new Cylinder;  Cylinder *UpperLegR=new Cylinder;  Cylinder *LowerLegL=new Cylinder;  Cylinder *LowerLegR=new Cylinder;  Polygon *Paper=new Polygon;  Transformation *EyeLTrans=new Transformation;  Transformation *EyeRTrans=new Transformation;  Transformation *HeadTrans=new Transformation;  Transformation *UpArmLTrans=new Transformation;  Transformation *UpArmRTrans=new Transformation;  Transformation *LowArmTrans=new Transformation;  Transformation *UpLegLTrans=new Transformation;  Transformation *UpLegRTrans=new Transformation;  Transformation *LowLegTrans=new Transformation;  Transformation *BaseTrans=new Transformation;  //Robot Value:  RobotMat->SetValue(DIFFUSE, 0.0, 0.0, 1.0, 1.0);  RobotMat->SetValue(AMBIENT, 0.0, 0.0, 1.0, 1.0);  RobotMat->SetValue(SPECULAR, 1.0, 1.0, 1.0, 1.0);  RobotMat->SetValue(SHININESS, 100.0);  EyeMat->SetValue(DIFFUSE, 1.0, 1.0, 1.0, 1.0);  EyeMat->SetValue(AMBIENT, 1.0, 1.0, 1.0, 1.0);  EyeMat->SetValue(SPECULAR, 1.0, 1.0, 1.0, 1.0);  EyeMat->SetValue(SHININESS, 100.0);  Base->SetValue(HEIGHT, BaseLen);  Base->SetValue(RADIUS, BaseRadius);  Head->SetValue(RADIUS, BaseRadius);  EyeL->SetValue(RADIUS, EyeRadius);  EyeR->SetValue(RADIUS, EyeRadius);  UpperArmL->SetValue(HEIGHT, UpLen);  UpperArmL->SetValue(RADIUS, Radius);  LowerArmL->SetValue(HEIGHT, LowLen);  LowerArmL->SetValue(RADIUS, Radius);  UpperArmR->SetValue(HEIGHT, UpLen);  UpperArmR->SetValue(RADIUS, Radius);  LowerArmR->SetValue(HEIGHT, LowLen);  LowerArmR->SetValue(RADIUS, Radius);  UpperLegL->SetValue(HEIGHT, UpLen);  UpperLegL->SetValue(RADIUS, Radius);  LowerLegL->SetValue(HEIGHT, LowLen);  LowerLegL->SetValue(RADIUS, Radius);  UpperLegR->SetValue(HEIGHT, UpLen);  UpperLegR->SetValue(RADIUS, Radius);  LowerLegR->SetValue(HEIGHT, LowLen);  LowerLegR->SetValue(RADIUS, Radius);  Paper->SetVerticesv(v, 4);  Paper->SetMaterial(EyeMat);  EyeLTrans->SetValue(TRANSLATION, BaseRadius-EyeRadius/2, 0, 0, 0);  EyeLTrans->SetValue(ROTATION, 30, 0, 0, 1, 1);  EyeRTrans->SetValue(TRANSLATION, BaseRadius-EyeRadius/2, 0, 0, 0);  EyeRTrans->SetValue(ROTATION, -30, 0, 0, 1, 1);  HeadTrans->SetValue(TRANSLATION, 0, 0, BaseLen+BaseRadius+BaseRadius/3, 0);  UpArmLTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);  UpArmLTrans->SetValue(ROTATION, -45, 0, 1, 0, 1);  UpArmLTrans->SetValue(TRANSLATION, 0, BaseRadius+Radius, BaseLen, 2);  UpArmRTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);  UpArmRTrans->SetValue(ROTATION, -45, 0, 1, 0, 1);  UpArmRTrans->SetValue(TRANSLATION, 0, -(BaseRadius+Radius), BaseLen, 2);  LowArmTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);  LowArmTrans->SetValue(ROTATION, -45, 0, 1, 0, 1);  UpLegLTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);  UpLegLTrans->SetValue(ROTATION, -90, 0, 1, 0, 1);  UpLegLTrans->SetValue(TRANSLATION, 0, BaseRadius+Radius, 0, 2);  UpLegRTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);  UpLegRTrans->SetValue(ROTATION, -100, 0, 1, 0, 1);  UpLegRTrans->SetValue(TRANSLATION, 0, -(BaseRadius+Radius), 0, 2);  LowLegTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);  LowLegTrans->SetValue(ROTATION, 95, 0, 1, 0, 1);  BaseTrans->SetValue(ROTATION, -90, 1, 0, 0, 0);  BaseTrans->SetValue(ROTATION, -10, 0, 0, 1, 1);  Head->SetTransform(HeadTrans);  EyeL->SetTransform(EyeLTrans);  EyeR->SetTransform(EyeRTrans);  EyeR->SetMaterial(EyeMat);  EyeL->SetMaterial(EyeMat);  UpperArmL->SetTransform(UpArmLTrans);  LowerArmL->SetTransform(LowArmTrans);  UpperArmR->SetTransform(UpArmRTrans);  LowerArmR->SetTransform(LowArmTrans);  UpperLegL->SetTransform(UpLegLTrans);  LowerLegL->SetTransform(LowLegTrans);  UpperLegR->SetTransform(UpLegRTrans);  LowerLegR->SetTransform(LowLegTrans);  Base->SetTransform(BaseTrans);  Paper->SetTransform(ROTATION, 20, 0, 1, 0, 0);  Paper->SetTransform(TRANSLATION, 0.05, -0.15, -0.2, 1);  //Set Relationship in Robot:  RobotMat->AddChild(Light1);  Light1->AddChild(Base);  Base->AddChild(Off1);  Off1->AddChild(Light2);  Light2->AddChild(Head);  Head->AddChild(Off2);  Head->AddChild(EyeL);  Head->AddChild(EyeR);  Base->AddChild(UpperArmL);  UpperArmL->AddChild(LowerArmL);  Base->AddChild(UpperArmR);  UpperArmR->AddChild(LowerArmR);  Base->AddChild(UpperLegL);  UpperLegL->AddChild(LowerLegL);  Base->AddChild(UpperLegR);  UpperLegR->AddChild(LowerLegR);  LowerArmR->AddChild(Paper);  //Nodes for Chair:  Cube *Seat=new Cube(0.7, 0.06, 0.7);  Line *Leg1=new Line;  Line *Leg2=new Line;  Line *Leg3=new Line;  Line *Leg4=new Line;  DrawStyle *LegStyle=new DrawStyle;  Color *ChairColor=new Color;    //Chair Value:  float v1[][3]={{-0.3, 0, 0.3},{-0.35, -1*ChairLegLen, 0.3}};  float v2[][3]={{0.3, 0, 0.3},{0.35, -1*ChairLegLen, 0.3}};  float v3[][3]={{0.3, 0, -0.3},{0.35, -1*ChairLegLen, -0.3}};  float v4[][3]={{-0.3, 0, -0.3},{-0.35, -1*ChairLegLen, -0.3}};  ChairColor->SetValue(RED);  Seat->SetTransform(TRANSLATION, 0, -0.15, 0, 0);  LegStyle->SetValue(LINEWIDTH, 7);  Leg1->SetStyle(LegStyle);  Leg1->SetVerticesv(v1);  Leg2->SetStyle(LegStyle);  Leg2->SetVerticesv(v2);  Leg3->SetStyle(LegStyle);  Leg3->SetVerticesv(v3);  Leg4->SetStyle(LegStyle);  Leg4->SetVerticesv(v4);  Seat->AddChild(Leg1);  Seat->AddChild(Leg2);  Seat->AddChild(Leg3);  Seat->AddChild(Leg4);  ChairColor->AddChild(Seat);  //Transformation Nodes for both Robot and Chair:  Transformation *Trans1=new Transformation;   Trans1->SetValue(TRANSLATION, -0.5, 0, 0, 2);  Trans1->AddChild(ChairColor);  Trans1->AddChild(RobotMat);  //Root Node:  Node *Root=new Node;  Root->AddChild(Trans1);  Root->AddChild(Camera1);    //Viewer:  GLViewer *MyViewer=new GLViewer;  MyViewer->Init(argc, argv);  MyViewer->SetValue(BACKCOLOR, GREY);  MyViewer->SetValue(BUFFER, DOUBLE);  MyViewer->CreateWin("Working Hard", 500, 500);  GLViewer *MyViewer2=new GLViewer;    MyViewer2->Init(argc, argv);  MyViewer2->SetValue(BACKCOLOR, MAGENTA);  MyViewer2->CreateWin("Working Hard2", 200, 200);  MyViewer2->SetValue(BUFFER, DOUBLE);  MyViewer->Show(Root);  MyViewer2->Show(Root);  return 0;}\subsection{Implementing a Node}Within the private part of the node is its implementation as a left-sibling right-childtree. We have also included a traversal method which is similar to the onewe used for our robot but could be someother standard traversalThere is a protected member, \mono{KeepMatrix}which can be used to push the present modelviewor projection matrix on the stack. This boolean variableenables us to choose whether or not to pass the presentmatrix state onto a child and avoids the need fora separator node. Here is a basic traversalvoid Node::Traverse(){  if(!KeepMatrix)    glPushMatrix();   Render();  if(LeftChild!=NULL)    LeftChild->Traverse();  if(!KeepMatrix)    glPopMatrix();  if(RightSibling!=NULL)    RightSibling->Traverse();}Note that the use of the left-sibling right-child structureimplies that children and siblings will be encountered ina predetermined order as the tree is traversed. We can open a new window through the \mono{Create Window}method and start the rendering of the scene by passinga node to the \mono{Show}method.voidGLViewer::Show(Node *N){  GLInit();  Root[ViewerIndex]=N;  if(ViewerIndex==(ViewerNum-1))    glutMainLoop();}voidGLViewer::Display0(){  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  Root[0]->Traverse();  if(BufType[0]==GLUT_DOUBLE)    glutSwapBuffers();  glFlush();}voidGLViewer::Display1(){  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  Root[1]->Traverse();  if(BufType[1]==GLUT_DOUBLE)    glutSwapBuffers();  glFlush();}voidGLViewer::Display2(){  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  Root[2]->Traverse();  if(BufType[2]==GLUT_DOUBLE)    glutSwapBuffers();  glFlush();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -