Creating Textured Geometry using StateSets
TracNav
- About
- Screenshots
- News
- Developer Blog
- Mailing Lists
- Forum
Documentation
- Getting Started
- Platform Specifics
- Tutorials
- Examples
- User Guides
- Programming Guides
- Reference Guides
- LatestDevelopments
- Porting
- CMake
- CDash
- CPack
- FAQ
- Tips And Tricks
- Maths
- Knowledge Base
- Trac Usage Examples
- TracGuide Documentation
- Software Patents
- Software Patents Europe
- Downloads
- Community
- Links
(Wiki editing note: Add link to complete source code at bottom)
Goals
Add a texture to geometry defined by OpenGL drawing primitives introduced in tutorial Basic geometry.
Background
The previous tutorial introduced viewing scenes that include basic shapes created from OpenGL primitives. This section explains how to add textures to these shapes. To make the code easier to use, we'll put the pyramid code into a function that creates a new geode and returns a pointer to it. The following code is from tutorial Basic geometry.
osg::Geode* createPyramid()
{
osg::Geode* pyramidGeode = new osg::Geode();
osg::Geometry* pyramidGeometry = new osg::Geometry();
pyramidGeode->addDrawable(pyramidGeometry);
// Specify the vertices:
osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
pyramidVertices->push_back( osg::Vec3(0, 0, 0) ); // front left
pyramidVertices->push_back( osg::Vec3(2, 0, 0) ); // front right
pyramidVertices->push_back( osg::Vec3(2, 2, 0) ); // back right
pyramidVertices->push_back( osg::Vec3( 0,2, 0) ); // back left
pyramidVertices->push_back( osg::Vec3( 1, 1,2) ); // peak
// Associate this set of vertices with the geometry associated with the
// geode we added to the scene.
pyramidGeometry->setVertexArray( pyramidVertices );
// Create a QUAD primitive for the base by specifying the
// vertices from our vertex list that make up this QUAD:
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);
// Add this primitive to the geometry: pyramidGeometry->addPrimitiveSet(pyramidBase);
// code to create other faces goes here!
// (removed to save space, see tutorial two)
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
pyramidGeometry->setColorArray(colors);
pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
// Since the mapping from vertices to texture coordinates is 1:1,
// we don't need to use an index array to map vertices to texture
// coordinates. We can do it directly with the 'setTexCoordArray'
// method of the Geometry class.
// This method takes a variable that is an array of two dimensional
// vectors (osg::Vec2). This variable needs to have the same
// number of elements as our Geometry has vertices. Each array element
// defines the texture coordinate for the cooresponding vertex in the
// vertex array.
osg::Vec2Array* texcoords = new osg::Vec2Array(5);
(*texcoords)[0].set(0.00f,0.0f); // tex coord for vertex 0
(*texcoords)[1].set(0.25f,0.0f); // tex coord for vertex 1
(*texcoords)[2].set(0.50f,0.0f); // ""
(*texcoords)[3].set(0.75f,0.0f); // ""
(*texcoords)[4].set(0.50f,1.0f); // ""
pyramidGeometry->setTexCoordArray(0,texcoords);
return pyramidGeode;
}
Loading a Texture, Creating a State Set, assigning it to a Node
The method for rendering primitives is controlled using StateSets. This section of code demonstrates how to load a texture from file, create a StateSet in which this texture is enabled, and assign this StateSet to a node in the scene. The first section starts out the same as previous tutorials. Initialize a viewer and build a scene with a single pyramid.
int main()
{
// Declare a group to act as root node of a scene:
osg::Group* root = new osg::Group();
osg::Geode* pyramidGeode = createPyramid();
root->addChild(pyramidGeode);
Now for adding a texture. Here we'll declare a texture instance and set its data variance as 'DYNAMIC'. (If we don't declare the texture as dynamic, some of the osg's optimization routines could remove it.) The texture class encapsulates OpenGL texture modes (wrap, filiter, etc.) as well as an osg::Image. The code below shows how to read an osg::Image instance from a file and associate this image with a texture.
osg::Texture2D* KLN89FaceTexture = new osg::Texture2D;
// protect from being optimized away as static state:
KLN89FaceTexture->setDataVariance(osg::Object::DYNAMIC);
// load an image by reading a file:
osg::Image* klnFace = osgDB::readImageFile("KLN89FaceB.tga");
if (!klnFace)
{
std::cout << " couldn't find texture, quiting." << std::endl;
return -1;
}
// Assign the texture to the image we read from file:
KLN89FaceTexture->setImage(klnFace);
Textures can be associated with rendering StateSets. The next step is to create a StateSet, associate and enable our texture with this state set and assign the StateSet to our geometry.
// Create a new StateSet with default settings:
osg::StateSet* stateOne = new osg::StateSet();
// Assign texture unit 0 of our new StateSet to the texture
// we just created and enable the texture.
stateOne->setTextureAttributeAndModes
(0,KLN89FaceTexture,osg::StateAttribute::ON);
// Associate this state set with the Geode that contains
// the pyramid:
pyramidGeode->setStateSet(stateOne);
The last step is the simulation loop:
osgViewer::Viewer viewer; //The final step is to set up and enter a simulation loop. viewer.setSceneData( root ); return viewer.run(); }
Continue with tutorial Transforms and States
Attachments
-
Tutorial_03.rar
(2.5 kB) - added by umituzun84@…
9 years ago.
TexturedGeometry?
