Monday, November 23, 2020

Creating Ocean Animation with osgOcean - OpenSceneGraph

 I am curious to try on how to implement the ocean by using OpenSceneGraph and the result is amazing. I was using osgOcean to impelment it and you can download here.
osgOcean is powerfull open source and you can use to release of the rendering code that was used to generate the above and below water effects.

osgOcean requires a Fast Fourier Transform library library and It can work well with either FFTW  or FFTSS.   

To implement ocean with OpenSceneGraph, you need some dependencies consist of
- OpenSceneGraph -- you can download here
- osgOcean --- you can download here
- FFTW --- you can download here
- FFTSS --- you can download here

osgOcean features:

  • FFT ocean simulation model and rendering
  • Foam caps
  • Refraction/Reflection Passes
  • God Rays
  • Surface glare
  • Underwater depth of field
  • Underwater/above water fogging
  • Simulated light absorption and scattering
  • Silt effects
  • Screen distortion effects
  • Choice of FFT library linkage


Screenshot and Videos  



see the ocean looks very nice



you can see the waves and foam with osgOcean



added ship in the ocean


Friday, March 24, 2017

Using OSG Node to Load 3D Object Model



It is very easy to load 3D object model in OpenSceneGraph. Let starts to write  some code and build it. What we need, just included headers, <osgDB/ReadFile> and <osgViewer/Viewer> then add root variable that provides the runtime access to the 3D model and assign to it to the setSceneData() method.

This code was implemented in OpenSuse 42.2, Netbean C++, OpenSceneGraph-3.0.1
If you don't have a 3D object model, you can download here

Please copy paste the code to your main.cpp file

#include <cstdlib>
#include <iostream>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/ShapeDrawable>

using namespace std;

int main(int argc, char** argv) {
    osg::ref_ptr<osg::Node> model1 = osgDB::readNodeFile("/home/addies/osg/data/cessna.osg" );
    osg::ref_ptr<osg::Group> root = new osg::Group;
    root->addChild( model1.get() );

    osgViewer::Viewer viewer;
    viewer.setSceneData( root.get() );

    return viewer.run();
}


If you are successfully, then you will get result as below.




In this example, I just introduce two new OSG classes osg::ref_ptr<> and osg::Node. The osg::Node class represents the basic element of a scene graph. The variable root stands for the root node of the 3D model, which is used as the scene data to be visualized.

Meanwhile, an instance of the osg::ref_ptr<> class template is created to manage the node object. It is a smart pointer that provide efficient memory management.

Thank you

Hope you enjoy it




Other Topics:


Thursday, March 23, 2017

Rendering 3D Simulator with OpenSceneGraph



Real-time rendering is in quite demand in computer science today, and OpenSceneGraph, being one of the best 3D graphics toolkits, is being used widely in the fields of virtual reality, scientific visualization, visual simulation, modeling, games, mobile applications, and so on. Although you can use the powerful OpenSceneGraph, which is based on the low-level OpenGL API, to implement applications that simulate different environments in the 3D world, developing picture-perfect applications is easier said than done.

Here is an example of OpenSceneGraph rendering implementation that I have made in crane simulator. The 3D model object was created by using 3ds max and export the object model into ive format by using osg exporter. 





Physics calculation was implemented with NVidia Physx. This physics server will send all coordinate objects through UDP network then OSG will do rendering process as following physics information.





Here is a video example for my own experiment to demonstrate the power of OpenSceneGraph.


 

I hope that you can grasp the idea on how to implement OpenSceneGraph rendering.

Thank you





Other Topics:




Sunday, March 19, 2017

Rendering Basic Shapes


OpenSceneGraph provide an osg::ShapeDrawable class to render basic geometry shapes quickly with plain parameters. An osg::ShapeDrawable instance always includes an osg::Shape object to indicate the specified geometry's type and properties.

The most frequently used basic shapes defined in OSG are osg::Box, osg::Capsule, osg::Cone,  osg::Cylinder, and osg::Sphere. Their appearances can be well defined by passing parameters directly to constructors.

It is easy to create simple objects by using an osg::Shape subclass. We will take three typical shapes as examples: a box with different width, height, and depth values, a sphere with a radius value, and a cone with a radius and a height.

Please open your best IDE, If you need guidance on how to set the OSG environment, for CodeBlock instruction can be found here and for Visual Studio can be found here and for Netbean can be found here.

Please create new project and copy paste this code.

This tutorial was implemented on OpenSuse 42.2, OpenSceneGraph-3.0.1, Netbean C++.

#include <osg/ShapeDrawable>
#include <osg/Geode>
#include <osgViewer/Viewer>

using namespace std;

int main(int argc, char** argv) {

    osg::ref_ptr<osg::ShapeDrawable> shape1 = new osg::ShapeDrawable;
    shape1->setShape( new osg::Box(osg::Vec3(-3.0f, 0.0f, 0.0f), 2.0f, 2.0f, 1.0f) );
  
    osg::ref_ptr<osg::ShapeDrawable> shape2 = new osg::ShapeDrawable;
    shape2->setShape( new osg::Sphere(osg::Vec3(3.0f, 0.0f, 0.0f), 1.0f) );
    shape2->setColor( osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) );
  
    osg::ref_ptr<osg::ShapeDrawable> shape3 = new osg::ShapeDrawable;
    shape3->setShape( new osg::Cone(osg::Vec3(0.0f, 0.0f, 0.0f), 1.0f, 1.0f) );
    shape3->setColor( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) );
  
    osg::ref_ptr<osg::Geode> root = new osg::Geode;
    root->addDrawable( shape1.get() );
    root->addDrawable( shape2.get() );
    root->addDrawable( shape3.get() );
  
    osgViewer::Viewer viewer;
    viewer.setSceneData( root.get() );
  
    return viewer.run();
}

Finally, if you are successful then you will get something like this





Other Topics:




Saturday, March 18, 2017

How to run OpenSceneGraph with Netbean IDE 8.2 C++



This tutorial was implemented with OpenSuse 42.2, Netbean IDE 8.2 C++, OpenSceneGraph-3.0.1

Before start this tutorial,  you need to compile the OSG source or install the binaries.
If you want to know on how to compile it, you can follow this guidance
          for Linux OpenSuse 42.2 compile with CodeBlocks
          for Windows 10 compile with Visual Studio 2010

Let's start

Please open your Netbean IDE for C++ and create New Project (Ctrl+Shift+N)
Select Categories: C/C++ and Projects: C/C++ Application then click Next.
Enter your Project Name: HelloWorld then click Finish.

Please copy paste this code into your main.cpp file

#include <cstdlib>
#include <iostream>
#include <osgViewer/Viewer>
#include <osg/ShapeDrawable>

using namespace std;

int main(int argc, char** argv) {

    osgViewer::Viewer viewer;
    osg::ref_ptr<osg::Group> root (new osg::Group);
    osg::ref_ptr<osg::Geode> myshapegeode (new osg::Geode);

    osg::ref_ptr<osg::Capsule> myCapsule (new osg::Capsule(osg::Vec3f(),1,2));
    osg::ref_ptr<osg::ShapeDrawable> capsuledrawable (new
                   osg::ShapeDrawable(myCapsule.get()));
    myshapegeode->addDrawable(capsuledrawable.get());
    root->addChild(myshapegeode.get());
    viewer.setSceneData( root.get() );
    return (viewer.run());
}


Next step, we need to configure the project properties by right click the project and select properties.

Under Categories: C++ compiler, please add Include Directories: ../../osg/osgBuild/include
 in my case, I have built in /home/osg/osgBuild/include then click Apply. Please refer to picture as below:


Under Categories: Linker, please add
        Additional Library Directories: ../../osg/osgBuild/lib In my case, I have built in /home/osg/osgBuild/lib

        Libraries: Open Threads, osg, osgDB, osgGA, osgUtil, osgViewer then click OK --> click OK

Result as shown as picture below




Then run project by pressing F6 and if you are successfully, you will get capsule picture shown as below



That's all and Hope you enjoy this tutorial. Thank you.




Other Topics:



Thursday, March 16, 2017

How to build OpenSceneGraph with Visual Studio 2010



This building process was implemented in Windows 10, Visual Studio 2010, CMake 3.5.2, OpenSceneGraph-3.0.1


Step 1. Preparation


Building the OSG requires CMake, due to the extensive use of CMake directives in the Makefiles. I used CMake-GUI to make easy setting up OSG option. You may download cmake from https://cmake.org

Next preparation, download the OSG source from OpenSceneGraph website. In this project, I used version OpenSceneGraph-3.0.1


Extract the OpenSceneGraph source into the correct folder for example
      C:\osg\OpenSceneGraph-3.0.1

Create new folder osgBuild
      C:\osg\osgBuild



Step 2. Configure and Generate OSG

Please open your CMake-GUI





put "Where is the source code" with path C:\osg\OpenSceneGraph-3.0.1 and next put "Where to build the binaries" with path C:\osg\osgBuild then click button Configure, cmake will ask you to select "Specify the generator for this project". Please select Visual Studio 10 2010 then click finish.

 
 CMake will report with Configuring Done and click Generate. CMake will generate all configured file in your build folder C:\osg\osgBuild.



Step 3. Compile OSG with Visual Studio 2010

Please open your Visual Studio 2010 and open ALL_BUILD.vcxproj project from your build folder C:\osg\osgBuild and Build (or press  F7).





Finally, let test the binaries










Step 4. Hello World OSG with Visual Studio 2010

Please create new project by clicking File --> New --> Project --> Win32 Console Application and just put in your project name as HelloWorld. Copy code as below into your main.cpp file

/**
   Hello World to display capsule geometry
*/
#include "stdafx.h"
#include <iostream>
#include <osgViewer/Viewer>
#include <osg/ShapeDrawable>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    osgViewer::Viewer viewer;
    osg::ref_ptr<osg::Group> root (new osg::Group);
    osg::ref_ptr<osg::Geode> myshapegeode (new osg::Geode);

    osg::ref_ptr<osg::Capsule> myCapsule (new osg::Capsule(osg::Vec3f(),1,2));
    osg::ref_ptr<osg::ShapeDrawable> capsuledrawable (new
             osg::ShapeDrawable(myCapsule.get()));
    myshapegeode->addDrawable(capsuledrawable.get());
  
    root->addChild(myshapegeode.get());
    viewer.setSceneData( root.get() );
  
    return (viewer.run());
}


Before compiling, let set the environment variables by right click on project and select properties.

In C/C++ properties, at Additional Include Directories puts C:\osg\osgBuild\include as shown as picture below



In Linker --> General properties, at Additional Library Directories puts C:\osg\osgBuild\lib as shown as picture below




In Linker --> Input properties, at Additional Dipendencies puts OpenThreadsd.lib;osgd.lib;osgDBd.lib;osgGAd.lib;osgUtild.lib;osgViewerd.lib; as shown as picture below


then click OK and Build your code by pressing F7. Then copy OSG DLL file from C:\osg\osgBuild\bin into your project folder, in my case at C:\Users\addiestar.silaban\Documents\Visual Studio 2010\Projects\osgHello\Debug  please refer to picture below




Finally run the code by pressing F5 and if you are successfully, you will get result like picture as below





Thank you





Other Topics:



 

Tuesday, March 14, 2017

Building Geometry Model



The osg::Geode class corresponds to the leaf node of scene graph. It has no child nodes, but always contains geometry information for rendering. Its name Geode is short for geometry node.

The geometry data to be drawn are stored in a set of osg::Drawable objects managed by osg::Geode . The non-instantiatable osg::Drawable class is defined as a pure virtual class. It has several subclasses for rendering models, images, and texts to the OpenGL pipeline. These renderable elements are collectively called drawables.

Please open your CodeBlocks and create new project. Copy paste code below into your main.cpp file to implement basic geometry then build (you can download the code here ). If you are confuse on how to set OpenSceneGraph environment, please refer to this guidance for OSG CodeBlock or OSG Netbean C++ or OSG Visual Studio 2010.


#include <osg/Node>
#include <osg/Group>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osgDB/ReadFile> 
#include <osgViewer/Viewer>
#include <osg/PositionAttitudeTransform>
#include <osgGA/TrackballManipulator>
int main()
{
    osgViewer::Viewer viewer;
    osg::Group* root = new osg::Group();
    osg::Geode* pyramidGeode = new osg::Geode();
    osg::Geometry* pyramidGeometry = new osg::Geometry();

    //Associate the pyramid geometry with the pyramid geode
    //   Add the pyramid geode to the root node of the scene graph.

    pyramidGeode->addDrawable(pyramidGeometry);
    root->addChild(pyramidGeode);

    //Declare an array of vertices. Each vertex will be represented by
    //a triple -- an instances of the vec3 class. An instance of
    //osg::Vec3Array can be used to store these triples. Since
    //osg::Vec3Array is derived from the STL vector class, we can use the
    //push_back method to add array elements. Push back adds elements to
    //the end of the vector, thus the index of first element entered is
    //zero, the second entries index is 1, etc.
    //Using a right-handed coordinate system with 'z' up, array
    //elements zero..four below represent the 5 points required to create
    //a simple pyramid.

    osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
    pyramidVertices->push_back( osg::Vec3( 0, 0, 0) ); // front left
    pyramidVertices->push_back( osg::Vec3(10, 0, 0) ); // front right
    pyramidVertices->push_back( osg::Vec3(10,10, 0) ); // back right
    pyramidVertices->push_back( osg::Vec3( 0,10, 0) ); // back left
    pyramidVertices->push_back( osg::Vec3( 5, 5,10) ); // peak

    //Associate this set of vertices with the geometry associated with the
    //geode we added to the scene.

    pyramidGeometry->setVertexArray( pyramidVertices );

    //Next, create a primitive set and add it to the pyramid geometry.
    //Use the first four points of the pyramid to define the base using an
    //instance of the DrawElementsUint class. Again this class is derived
    //from the STL vector, so the push_back method will add elements in
    //sequential order. To ensure proper backface cullling, vertices
    //should be specified in counterclockwise order. The arguments for the
    //constructor are the enumerated type for the primitive
    //(same as the OpenGL primitive enumerated types), and the index in
    //the vertex array to start from.

    osg::DrawElementsUInt* pyramidBase =
        new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidBase->push_back(3);
    pyramidBase->push_back(2);
    pyramidBase->push_back(1);
    pyramidBase->push_back(0);
    pyramidGeometry->addPrimitiveSet(pyramidBase);

    //Repeat the same for each of the four sides. Again, vertices are
    //specified in counter-clockwise order.

    osg::DrawElementsUInt* pyramidFaceOne =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceOne->push_back(0);
    pyramidFaceOne->push_back(1);
    pyramidFaceOne->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceOne);

    osg::DrawElementsUInt* pyramidFaceTwo =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceTwo->push_back(1);
    pyramidFaceTwo->push_back(2);
    pyramidFaceTwo->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceTwo);

    osg::DrawElementsUInt* pyramidFaceThree =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceThree->push_back(2);
    pyramidFaceThree->push_back(3);
    pyramidFaceThree->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceThree);

    osg::DrawElementsUInt* pyramidFaceFour =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceFour->push_back(3);
    pyramidFaceFour->push_back(0);
    pyramidFaceFour->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceFour);

    //Declare and load an array of Vec4 elements to store colors.

    osg::Vec4Array* colors = new osg::Vec4Array;
    colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //index 0 red
    colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) ); //index 1 green
    colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) ); //index 2 blue
    colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 3 white
    colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //index 4 red

    //The next step is to associate the array of colors with the geometry,
    //assign the color indices created above to the geometry and set the
    //binding mode to _PER_VERTEX.

    pyramidGeometry->setColorArray(colors);
    pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

    //Now that we have created a geometry node and added it to the scene
    //we can reuse this geometry. For example, if we wanted to put a
    //second pyramid 15 units to the right of the first one, we could add
    //this geode as the child of a transform node in our scene graph.

    // Declare and initialize a transform node.
    osg::PositionAttitudeTransform* pyramidTwoXForm =
        new osg::PositionAttitudeTransform();

    // Use the 'addChild' method of the osg::Group class to
    // add the transform as a child of the root node and the
    // pyramid node as a child of the transform.

    root->addChild(pyramidTwoXForm);
    pyramidTwoXForm->addChild(pyramidGeode);

    // Declare and initialize a Vec3 instance to change the
    // position of the model in the scene

    osg::Vec3 pyramidTwoPosition(15,0,0);
    pyramidTwoXForm->setPosition( pyramidTwoPosition );

    // switch off lighting as we haven't assigned any normals.
    root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

    //The final step is to set up and enter a simulation loop.

    viewer.setSceneData( root );
    //viewer.run();

    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
    viewer.realize();

    while( !viewer.done() )
    {
        viewer.frame();
    }

    return 0;
}


Result