Document directory
- 1.1 V-World lib
- 1.2 vwviewer
- 1.3 open source license
- 1.4 Third-Party Libraries
- 1.5 join the project
- 2.1 compile
- 2.2 run
- 3.1 create an application project
- 3.2 configure an application project
- 3.5 create scene nodes using scene map-related classes
- 3.6 ry
- 3.7 complete instance
By yurunsun@gmail.com
Sina Weibo @ sun yurun Sina Blog
Csdn blog
Date:
1. Project Overview 1.1 V-World lib
V-World Lib is a high-performance 3D graphics library implemented by opengl1.1. It is used to quickly develop interactive 3D graphics applications in Windows operating systems.
The main features are as follows:
- Mathematical libraries such as vectors, tuples, and Matrices
- Basic elements and model file elements
- Scenario diagram composed of geometric nodes, lighting nodes, camera nodes, and group nodes
- Encapsulation drawing and form
- Separation of interfaces and implementations for ease of use
- Reference count management memory
1.2 vwviewer
As a sample application, vwviewer uses v-world lib to implement a 3D model viewer that supports multiple formats.
1.3 open source license
All of the above items comply with the GNU Public License (lgpl): Allow Dynamic Links in commercial applications.
1.4 Third-Party Libraries
Use lib3ds to process 3DS files
Use GLM to process OBJ files
Wtl helps process Win32 APIs
1.5 join the project
Project home: https://code.google.com/p/v-world/
SVN: https://v-world.googlecode.com/svn/trunk/
Submit bugs or want to join please contact: yurunsun@gmail.com
2. Compile and run 2.1.
Install vs2010 (except for Express, because it does not contain templates such as ATL)
Go to the wtl project homepage or go to the checkout wtl Template Library: SVN: // svn.code.sf.net/p/wtl/code/
Open the wtl project directory of checkout and\wtl\trunk\wtl\include\
Copy all the header files under the directory to the Microsoft SDK header file directory created when installing vs2010, for example:
D:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\include\
Open with vs2010VirtualWorld.sln
, Compile
2.2 run
The target files compiled in debug and release modes are placed in\BinDebug\
And\BinRelease\
Directory. Virtualworld. dll is V-World Lib, and vwviewer.exe is the sample program developed using the V-World Library: 3D model viewer.
3. Use v-world lib to develop graphics software
The following uses vwviewer as an example to describe how to use v-world lib to develop interactive graphics software.
3.1 create an application project
V-World lib providesCWindow
Window classes of the base class can be independently displayed as frame-style Windows, and can also be easily embedded into windows generated by any framework such as MFC, wtl, ATL, Win32, and Qt as subwindows, therefore, the type of the application is very free. In vwviewer, we use the vs plug-in of wtl to automatically generate a frame-style main window with a menu bar.
3.2 configure an application project
Add header file
One of the features of v-world Lib is the separation from interfaces. Only one header file (plus the. INL file provides inline function implementation) and one library file are required. The header file defines the required interface classes. Except for some getter/setter functions that provide efficient inline implementation, all others use pure virtual functions as interfaces.
Go to the application project configuration page and choose configuration Properties> VC ++ directories> include directories.
Add
..\VirtualWorld\Include;
Add library files
We recommend that you use v-world as a dynamic link. During compilation, there are two methods to find the function address of the dynamic link library. One is to display and use the function address in the code.LoadLibrary
The other is the. Lib file generated by the link with the dynamic link library. (Note that the. lib here only exists to find the DLL address. Do not confuse it with the static link method .) We select the latter method:
Go to the application project configuration page and choose configuration Properties> VC ++ directories> library directories.
Add
..\VirtualWorld\BinDebug
For the release configuration, change
..\VirtualWorld\BinRelease;
Then
Choose application project configuration> Configuration Properties> linkder> Input
AddVirtualWorld.lib
Next open..\VirtualWorld\Include\VirtualWorld.h
File to view the available class libraries.
3.3 Use Factory
CFactory
Create an instance
namespace VirtualWorld { class VIRTUALWORLD_API CFactory : public CSingleton<CFactory> { public: IWindow32* CreateWindow32(); //... };}
Most classes defined in the header file need to use the factory class to create instances, which is a common mode for separating interfaces.
On the other hand, the existence of the factory class as a singleton is also a conventional model.
For example, to create an iwindow32 object:
IWindow32* pView = VirtualWorld::CFactory::GetInstance()->CreateWindow32();
3.4 use window class
IWindow32
Create window
Readers who are familiar with Win32 APIs will find thatIWindow32
Some Windows-style function interfaces are defined, because v-world Lib is not prepared for cross-platform.
Method:
CreateWin(...)
: In comparison with the standard Win32 APICreateWindow
The function has the same parameters.
GetHwnd()
: Get window handle
RedrawWin(...)
: In comparison with the standard Win32 APIRedrawWindow
The function has the same parameters.
PreTranslateMessage(...)
: MFC-style message preprocessing functions
Attribute:
RootSGNode
: Root Node of the scenario diagram (for more information)
ActiveCameraNode
: Activated cameras (coming soon)
GUIEventHandler
: Gui Event Callback interface (coming soon)
Specific applications:
Add iwindow32 as a member in the main window class generated by wtl:
VirtualWorld::IWindow32* m_pView;
In the main window class generated by wtlWM_CREATE
Response FunctionsOnCreate
Create a subwindow:
m_pView = pFac->CreateWindow32();m_hWndClient = m_pView->CreateWin(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);m_pView->SetGUIEventHandler(this);
Now we have successfully called the iwindow32 API in v-world to create a subwindow.
3.5 use the scenario diagram-related class to create the scenario node 3.5.1 concept of the scenario Diagram
InIWindow32
The interface mentions two functions for accessing the graph root node of the scenario. The following describes the related concepts of the scenario graph.
In terms of data structure, a scenario is a dag, called scene graph, or SG for short. The scenario is drawn to traverse each node of SG. Nodes are divided into group nodes and leaf nodes. The following pseudocode shows a possible and reasonable call order:
// Here is my own leafnode * myself = new leafnode; // There is a car on the left, a dog, leafnode * car = new leafnode; leafnode * dog = new leafnode; groupnode * leftside = new groupnode; leftside-> addchild (CAR); leftside-> addchild (DOG); // There is a playground and football leafnode * football = new leafnode in the distance; leafnode * grassland = new leafnode; groupnode * Faraway = new groupnode; faraway-> addchild (Football); faraway-> addchild (grassland ); // figure groupnode * root = new groupnode; root-> addchild (leftside); root-> addchild (faraway ); root-> addchild (myself );
3.5.2 node base class
ISceneBaseNode
This class is the base class for all scenario nodes.
Attribute:
- Name: node name
- Parent: parent node pointer
- Nodetype: Node Type
- Nodetypestring: node type of the string version
- Visibility: visible
- Localmatrix: transformation matrix in the Local Coordinate System
- Worldmatrix: transformation matrix in the world coordinate system
The local coordinate system is initially a 4*4 unit matrix. The transformation matrix under the world coordinate system is equivalent to the transformation matrix under the world coordinate system of the parent node, multiplied by the transformation matrix under the Local Coordinate System:
this->WorldMatrix = parent->WorldMatrix * this->LocalMatrix
Note that the node is stored in the map container provided by its parent node as the key. Therefore, all nodes must have names. Otherwise, they cannot be attached to the parent node.
Method:
Translate(const CVector3f& t);Rotate(float angle, const CVector3f& axis);Scale(const CVector3f& axis);
It indicates the translation, rotation, and scaling of the node in the local coordinate system. The actual effect is directly applied to the local coordinate transformation matrix of the current node. Example:
Initially, the node's local coordinate transformation matrix L = I is the unit matrix. when moving to the (1.0f, 2.0f, 3.0f) position, create the displacement matrix T:
1 0 0 0T = 0 1 0 0 0 0 1 0 1 2 3 1
In this case
L = L * T = I * T;
Perform the following scaling along the XYZ axis (2.0f, 5.0f, 0.5f), that is, 2 times the X axis, 5 times the Y axis, and 0.5 times the original Z axis, then create the scaling matrix R
2 0 0 0R = 0 5 0 0 0 0 0.5 0 0 0 0 1
In this case
L = L * R = I * T * R
3.5.3 group nodes
ISceneGroupNode
BesidesISceneBaseNode
In addition to the provided attributes and methods, the system is mainly responsible for managing subnodes:
typedef std::map<CString, ISceneBaseNode*> NodeTable;void AddChild(ISceneBaseNode* a_Child);ISceneBaseNode* GetChild(const CString& a_Name) const;const NodeTable& GetChildren() const;void RemoveChild(ISceneBaseNode* a_Child);void RemoveChild(const CString& a_Name);
Using map to manage subnodes is one of the classic modes.
3.5.4 metanode
ISceneGeometryNode
BesidesISceneBaseNode
In addition to the provided attributes and methodsGeometryObject
Attribute to attach an element to an element node.GeometryObject
Will be introduced later.
3.5.5 illumination nodes
ISceneLightNode
DivisionISceneBaseNode
In addition to the property method provided, the following lighting attributes are added:
ID;Ambient;Diffuse;Specular;Position;SpotDirection;SpotExponent;SpotCutoff;Attenuation;
These are classic lighting parameters. For more information, see the graphic tutorial.
3.5.6 camera nodes
ISceneCameraNode
The new attributes are as follows:
Fovy;ZNear;ZFar;Rect;
These are classic parameters for adjusting the angle of view, cropping the plane, and the size of the view.
Add method:
The new method in cameranode has some special features:
void LookAt(const CVector3f& a_Position, const CVector3f& a_FocusPoint, const CVector3f& a_UpVector);
This is the DivisionISceneBaseNode
In addition to the three affine transformations provided in, another function that can act on the transformation matrix, readers familiar with OpenGL will immediately find that this function is similar to the classic
gluLookAt(...);
HereLookAt
ModifiedLocalMatrix
To complete the coordinate system transformation.
3.5.7 Add the camera node to the root node
Readers who have played the game know that there are multiple perspectives in the game. For example, when the first person perspective is in a csgame, the camera obviously needs to move with the character node. In this case, it is reasonable to use the camera node and the metanode as the subnode. However, when the game goes down, CS allows you to use a free angle of view. In this case, you do not have to add the camera node to the scene graph, so that you can easily change the camera in the world coordinate system.
At any time, there can only be one activated camera. That's whyIWindow32
ProvidedActiveCamera
Attribute.
3.6 ry
In 3.5.4, we mentioned the usage of metadata nodes.GeometryObject
Attribute as a ry, in turn eachGeometryObject
Must be attachedISceneGeometryNode
Nodes appear in the scenario diagram.
3.6.1
IGeometryBaseObject
The base class of all ry graphics classes.
Attribute:
DrawMode
: Draw a graph by filling or contour
NormalMode
: Vertex normal or surface normal
GetBoundingBox
: Box
Material
: Materials
3.6.2 common images
Similar to databases such as Glu, glut, and qgl, the basic graph is provided here:
IGeometryCubeObject
: Cube
IGeometrySphereObject
: Sphere
IGeometryCylinderObject
: Cylinder
3.6.3 obtain images from model files
IGeometryModelObject
The new method is
bool LoadModel(const CString& a_FileName);
When you use the factory function to create this instance, different instances are created based on the file type (. OBJ,. 3DS,. Dae,. 3 dxml,..., etc. Call example:
CString modelType = CUtility::GetFileSuffix(a_FilePath);IGeometryModelObject* objModel = CFactory::GetInstance()->CreateGeometryModelObject(modelType);if (objModel != NULL) { bool hr = objModel->LoadModel(a_FilePath); if (hr == true) { //... }}
Currently, OBJ and 3DS files are supported.
3.7 complete instance
The following is the sample code for calling V-model in vwviewer. For the complete code, seeMainFrm.cpp
.
LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/){ CFactory* pFac = CFactory::GetInstance(); m_pView = pFac->CreateWindow32(); m_hWndClient = m_pView->CreateWin(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE); m_pView->SetGUIEventHandler(this); m_pCameraDlg = new CCameraDlg(); m_pCameraDlg->Create(m_hWnd); m_pNodetreeDlg = new CNodetreeDlg(); m_pNodetreeDlg->Create(m_hWnd); ISceneGroupNode* rootNode = pFac->CreateSceneGroupNode(); ISceneCameraNode* cameraNode = pFac->CreateSceneCameraNode(); ISceneGeometryNode* cubeNode = pFac->CreateSceneGeometryNode(); ISceneGeometryNode* sphereNode = pFac->CreateSceneGeometryNode(); ISceneGeometryNode* cylinderNode = pFac->CreateSceneGeometryNode(); ISceneLightNode* lightNode = pFac->CreateSceneLightNode(); IGeometryCubeObject* cubeObj = pFac->CreateGeometryBoxObject(); IGeometrySphereObject* sphereObj = pFac->CreateGeometrySphereObject(); IGeometryCylinderObject* cylinderObj = pFac->CreateGeometryCylinderObject(); IMaterial* material = pFac->CreateMaterial(); material->SetAmbient(CVector4f(0.000f, 0.50f, 0.000f, 1.0f)); material->SetDiffuse(CVector4f(0.000f, 0.300f, 0.000f, 1.0f)); material->SetSpecular(CVector4f(1.000f, 1.000f, 1.000f, 1.0f)); material->SetEmmision(CVector4f(0.000f, 0.000f, 0.000f, 1.0f)); material->SetShine(128.000f); cubeObj->SetMaterial(material); cubeObj->SetRadius(0.3f); cubeObj->SetDrawMode(IGeometryBaseObject::GEOMETRY_DRAW_SOLID); cubeNode->SetName(_T("Box1")); cubeNode->SetGeometryObject(cubeObj); cubeNode->Translate(CVector3f(1.0f, 0.0f, 0.0f)); rootNode->AddChild(cubeNode); sphereObj->SetMaterial(material); sphereObj->SetRadius(0.4f); sphereObj->SetDrawMode(IGeometryBaseObject::GEOMETRY_DRAW_SOLID); sphereObj->SetNormalMode(IGeometryBaseObject::GEOMETRY_NORMAL_VERTEX); sphereNode->SetName(_T("Sphere1")); sphereNode->SetGeometryObject(sphereObj); sphereNode->Translate(CVector3f(-1.0f, 0.0f, 0.0f)); rootNode->AddChild(sphereNode); cylinderObj->SetMaterial(material); cylinderObj->SetDrawMode(IGeometryBaseObject::GEOMETRY_DRAW_SOLID); cylinderObj->SetNormalMode(IGeometryBaseObject::GEOMETRY_NORMAL_VERTEX); cylinderObj->SetBaseRadius(0.3f); cylinderNode->SetName(_T("Cylinder1")); cylinderNode->SetGeometryObject(cylinderObj); cylinderNode->Translate(CVector3f(0.0f, 0.0f, -1.0f)); cylinderNode->Rotate(0.1f, CVector3f(1.0f, 0.0f, 0.0f)); rootNode->AddChild(cylinderNode); lightNode->SetName(_T("light0")); lightNode->SetAmbient(CVector4f(0.4f, 0.4f, 0.4f, 1.0f)); lightNode->SetPosition(CVector4f(-1.0f, -1.0f, 1.0f, 0.0f)); rootNode->AddChild(lightNode); cameraNode->SetName(_T("Camera")); cameraNode->SetFovy(30.0f); cameraNode->SetZNear(1.0f); cameraNode->SetZFar(1000.0f); cameraNode->Translate(CVector3f(0.0f, 0.0f, 5.0f)); rootNode->SetName(_T("Root")); m_pView->SetActiveCameraNode(cameraNode); m_pView->SetRootSGNode(rootNode); // register object for message filtering and idle updates CMessageLoop* pLoop = _Module.GetMessageLoop(); ATLASSERT(pLoop != NULL); pLoop->AddMessageFilter(this); pLoop->AddIdleHandler(this); return 0;}
4. Architecture Design of V-Model
The V-model is logically divided into four layers:
- Mathematics
- Graphics
- Node
- Window Type
Among them, the mathematics class includes cvector3, cvector4, and cmatrix, which contains a large number of mathematical operations;
Some of the graphics classes provide basic graphics and some are used to load model files. During rendering, the display list Technology in opengl1.1 is used to improve rendering efficiency;
The node logic clearly organizes the scenario and simplifies the world coordinate system, local coordinate system, and affine transformation that are prone to errors into a parent-child relationship;
The window class encapsulates windows Windows, organizes root nodes and cameras, and provides GUI Event Callback interfaces.
Generally, users can use V-model to quickly process 3D model files and organize scenarios for rendering. Interested readers can apply to join this project, expand the Supported file formats, and modify bugs; for vwviewer, you are also welcome to join us with creative ideas about this product.
- If this article is helpful to you, please go to the csdn blog to leave a message;
- Reprinted Please note: From yurun technology blog http://blog.csdn.net/sunyurun