SoTexture2( C++ | Java | .NET ) ,SoExtTexture2( C++ | Java | .NET ) ,SoTexture3( C++ | Java | .NET ) , and SoTextureCubeMap( C++ | Java | .NET )nodes define the image(s) for the texture map and specify how the texture wraps around the object and which texture model to use.
The textureQuality field of the SoComplexity( C++ | Java | .NET ) node controls the quality of filtering used to apply the texture. A value of 0.0 disables texturing completely, and a value of 1.0 specifies to use the highest quality of texturing. The default value for this field is 0.5.
wrapS (SoSFEnum) | Specifies how the image wraps in the s (horizontal) direction. Possible values are as follows: REPEAT: repeat the image to fill the shape (default). CLAMP: repeat the last row of pixels. CLAMP_TO_BORDER: clamps texture coordinate to a range coinciding with the centers of the border texels of a texture map at each mipmap level. CLAMP_TO_EDGE: clamps texture coordinate to a range coinciding with the centers of the edge texels of a texture map at each mipmap level. MIRRORED_REPEAT: repeats the image, alternating the original and a mirrored copy of the image. |
model (SoSFEnum) | Specifies the texture model to use. Possible values are as follows: MODULATE: multiplies the shaded color times the texture color (the default). DECAL: replaces the shaded color with the texture color. BLEND: blends the shaded color and the specified blend color (see the blendColor field). REPLACE: the texture color replaces the surface color. ADD: add incoming fragment and texture source colors. COMBINE: use the next SoTextureCombiner( C++ | Java | .NET ) node to combine different textures. |
blendColor (SoSFColor) | Specifies the color to blend when using the BLEND texture model. |
magFilter (SoSFEnum) | Specifies the OpenGL filtering method for magnification. Possible values are as follow: AUTO: Open Inventor automatically selects the filtering method depending on SoComplexity::textureQuality. NEAREST: the texel nearest to the center of the pixel is used. LINEAR: a weighted linear average of the 2x2 array of texels that lie nearest the center of the pixel is used. |
minFilter (SoSFEnum) | Specifies the OpenGL filtering method for minification. Possible values are the values for magFilter (AUTO, NEAREST, or LINEAR) or the following: NEAREST_MIPMAP_NEAREST: chooses the nearest texel value from the nearest mipmap level. LINEAR_MIPMAP_NEAREST: LINEAR within the nearest mipmap level. NEAREST_MIPMAP_LINEAR: selects the nearest texels in each of the two nearest mipmap levels and then interpolates linearly between these two values. LINEAR_MIPMAP_LINEAR: uses linear interpolation to compute the value in each of the two nearest mipmap levels and then interpolates linearly between these two values. |
enableCompressedTexture (SoSFBool) | Enables storage of textures on the graphics board in compressed format. |
enableBorder (SoSFBool) | Enables borders for textures. This means that the border is already in the texture. |
borderColor (SoSFVec4f) | Specifies border color used for border texture filtering. This value is only used if enableBorder is FALSE. |
maxAnisotropy (SoSFFloat) | Specifies, on a per-texture object basis, the maximum degree of anisotropy to account for in texture filtering. |
internalFormat (SoSFEnum) | Internal format for texture storage. If not available on the graphics device, AUTO_INTERNAL_FORMAT is used. Default is AUTO_INTERNAL_FORMAT. |
useAutoMipmap (SoSFBool) | Requests mipmaps be generated by the graphics hardware. If FALSE or not supported, then mipmaps are generated by Open Inventor. FALSE by default. |
The COMBINE model takes RGB and Alpha from up to three sources and combines them together to give the color of a texel (see Figure 7.7, “ Texture Combine”.).
In the figure above, Source n RGB/Alpha can be:
Fragment color
Texture color fetched and filtered from texture unit I
Result of the previous texture combine
Constant color
The following table shows the SoTexture2( C++ | Java | .NET ) fields:
filename (SoSFString) | Specifies the name of the file to use as a texture map. See your release documentation for information on the file formats supported on your system. (You use this field or the image field.) If the filename field is set, the image is read and the image field is set to the pixels in that file. If the image field is set, the filename field is set to an empty string. This behavior assures that there is no ambiguity about which field is used for the texture. |
image (SoSFImage) | Specifies the color and number of pixels in the texture map. |
wrapT (SoSFEnum) | Specifies how the image wraps in the t (vertical) direction. Possible values are the same as for wrapS in the section called “Fields common to SoTexture nodes”. |
renderToTextureProperty (SoSFNode) | Specifies an SoRenderToTextureProperty( C++ | Java | .NET )node containing a scene graph that will be rendered to create the texture image. If field is set, then the filename and image fields are ignored. |
In addition to the fields shown above, SoTexture2( C++ | Java | .NET ) also has all of the fields inherited from SoTexture( C++ | Java | .NET ).
This node is similar to SoTexture2( C++ | Java | .NET ), but differs in the following significant ways:
It has no image field. Data is sent directly to OpenGL
It doesn’t load the texture image into system memory until the node is traversed. Depending on the scene graph, this may significantly reduce the use of system memory, e.g., if the scene has many LODs containing textures. On the other hand, when the scene graph is first traversed there may be a small delay while the textures are being loaded.
It has additional features:
support for OpenGL paletted textures for reducing the use of texture memory.
maximum system memory quota allowed for managing the textures.
the ability to:
delegate the texture loading to a thread.
trigger the loading manually.
get the loading status.
use a callback at the start and finish of loading.
use a callback at the finish of unloading.
The following table shows the SoExtTexture2( C++ | Java | .NET ) fields:
filename (SoSFString) | Specifies the name of the file containing the texture image. |
wrapT (SoSFEnum) | Specifies how the image wraps in the t (vertical) direction. Possible values are the same as for wrapS in the section called “Fields common to SoTexture nodes”. |
loadingStatus (SoSFBool) | Tells if the texture has been loaded or not (not necessarily displayed). |
syncMode (SoSFEnum) | Specifies the synchronous/asynchronous mode. |
loadingMode (SoSFEnum) | Specifies the loading mode. |
loadingThread-Priority (SoSFInt32) | Specifies the priority of the texture loading thread when activated (syncMode = ASYNCHRONOUS). |
In addition to the fields shown above, SoExtTexture2( C++ | Java | .NET ) also has all of the fields inherited from SoTexture( C++ | Java | .NET ).
Example 7.2. Asynchronous loading of a texture
|
|
This example shows four textured cubes. The lower left one is being textured asynchronously. The scene is rotating and is not blocked by loading the texture image.
// This function is called 10 times/second static void rotationCallback(void *data, SoSensor*) { // Rotates the scene SoRotation *rot = (SoRotation*) data; SbRotation currentRotation = rot->rotation.getValue(); currentRotation = SbRotation(SbVec3f(0.0f, 0.0f, 1.0f), (float)(M_PI/90.0f)) * currentRotation; rot->rotation.setValue(currentRotation); } // Called when starting the loading of texture1 void startTex1Load(void *userData, SoExtTexture2 *tex) { printf("Started loading the texture 1...\n"); } // Called when finishing the loading of texture1 void finishTex1Load(void *userData, SoExtTexture2 *tex) { printf("... Finished loading the texture 1.\n"); } int main(int argc, char **argv) { // Initialize Inventor and Xt Widget appWindow = SoXt::init(argv[0]); if (appWindow == NULL) exit(1); SoSeparator *root = new SoSeparator; root->ref(); SoRotation *rot = new SoRotation; SoTimerSensor *rotatingSensor = new SoTimerSensor(rotationCallback, rot); rotatingSensor->setInterval(0.1f); // scheduled once per 1/10th of second rotatingSensor->schedule(); root->addChild(rot); // Cube 1 SoTranslation *tr1 = new SoTranslation(); root->addChild(tr1); tr1->translation.setValue(-1.25, -1.25, 0.); SoExtTexture2 *texture1 = new SoExtTexture2; texture1->loadingMode.setValue(SoExtTexture2::MANUAL); texture1->loadingThreadPriority.setValue(-1); texture1->filename = "test1.jpg"; texture1->addOnLoadStartCB((SoExtTexture2::SoExtTexture2CB*)startTex1Load, texture1); texture1->addOnLoadFinishCB((SoExtTexture2::SoExtTexture2CB *finishTex1Load, texture1); root->addChild(texture1); root->addChild(new SoCube); // Cube 2 SoTranslation *tr2 = new SoTranslation(); root->addChild(tr2); tr2->translation.setValue(2.5, 0., 0.); SoExtTexture2 *texture2 = new SoExtTexture2; texture2->filename = "test2.jpg"; root->addChild(texture2); root->addChild(new SoCube); // Cube 3 SoTranslation *tr3 = new SoTranslation(); root->addChild(tr3); tr3->translation.setValue(0., 2.5, 0.); SoExtTexture2 *texture3 = new SoExtTexture2; texture3->filename = "test3.jpg"; root->addChild(texture3); root->addChild(new SoCube); // Cube 4 SoSeparator *sep4 = new SoSeparator; SoTranslation *tr4 = new SoTranslation(); root->addChild(tr4); tr4->translation.setValue(-2.5, 0., 0.); SoExtTexture2 *texture4 = new SoExtTexture2; texture4->filename = "test4.jpg"; root->addChild(texture4); root->addChild(new SoCube); // Initialize the viewer SoXtExaminerViewer *viewer = new SoXtExaminerViewer(appWindow); viewer->setSceneGraph(root); viewer->setTitle("ExtTexture2 Viewer"); viewer->setSize(SbVec2s(300, 300)); // In Inventor 2.1, if the machine does not have hardware texture // mapping, we must override the default drawStyle to display textures. viewer->setDrawStyle(SoXtViewer::STILL, SoXtViewer::VIEW_AS_IS); viewer->show(); // Launch the loading automatically texture1->loadingMode.setValue(SoExtTexture2::AUTO); texture1->syncMode.setValue(SoExtTexture2::ASYNCHRONOUS); texture1->loadTexture(); SoXt::show(appWindow); SoXt::mainLoop(); return 0; }
SoRotation rot; // This function is called 10 times/second void rotationCallback(SoSensor s) { // Rotates the scene SbRotation currentRotation = rot.rotation.GetValue(); currentRotation *= new SbRotation( new SbVec3f(0.0f, 0.0f, 1.0f), (float)(Math.PI/90.0f)); rot.rotation.SetValue(currentRotation); } // Called when starting the loading of texture1 void startTex1Load(SoExtTexture2 tex) { Console.WriteLine("Started loading the texture 1...\n"); } // Called when finishing the loading of texture1 void finishTex1Load(SoExtTexture2 tex) { Console.WriteLine("... Finished loading the texture 1.\n"); } private void CreateSample() { SoSeparator root = new SoSeparator(); rot = new SoRotation(); SoTimerSensor rotatingSensor = new SoTimerSensor(); rotatingSensor.Action = new SoSensor.SensorCB(rotationCallback); SbTime interval = new SbTime(); interval.SetValue(0.3); rotatingSensor.SetInterval(interval); rotatingSensor.Schedule(); root.AddChild(rot); // Cube 1 SoTranslation tr1 = new SoTranslation(); root.AddChild(tr1); tr1.translation.SetValue(-1.25f, -1.25f, 0f); SoExtTexture2 texture1 = new SoExtTexture2(); texture1.loadingMode.SetValue((int)SoExtTexture2.Loadings.MANUAL); texture1.loadingThreadPriority.SetValue(-1); texture1.filename.SetValue("$OIVNETHOME/src/Inventor/examples/data/Textures/test1.jpg"); texture1.LoadStart += new SoExtTexture2.Texture2CB(startTex1Load); texture1.LoadFinish += new SoExtTexture2.Texture2CB(finishTex1Load); root.AddChild(texture1); root.AddChild(new SoCube()); // Cube 2 SoTranslation tr2 = new SoTranslation(); root.AddChild(tr2); tr2.translation.SetValue(2.5f, 0f, 0f); SoExtTexture2 texture2 = new SoExtTexture2(); texture2.filename.SetValue("$OIVNETHOME/src/Inventor/examples/data/Textures/test2.jpg"); root.AddChild(texture2); root.AddChild(new SoCube()); // Cube 3 SoTranslation tr3 = new SoTranslation(); root.AddChild(tr3); tr3.translation.SetValue(0f, 2.5f, 0f); SoExtTexture2 texture3 = new SoExtTexture2(); texture3.filename.SetValue("$OIVNETHOME/src/Inventor/examples/data/Textures/test3.jpg"); root.AddChild(texture3); root.AddChild(new SoCube()); // Cube 4 SoSeparator sep4 = new SoSeparator(); SoTranslation tr4 = new SoTranslation(); root.AddChild(tr4); tr4.translation.SetValue(-2.5f, 0f, 0f); SoExtTexture2 texture4 = new SoExtTexture2(); texture4.filename.SetValue("$OIVNETHOME/src/Inventor/examples/data/Textures/test4.jpg"); root.AddChild(texture4); root.AddChild(new SoCube()); // Initialize the viewer SoWinExaminerViewer viewer = new SoWinExaminerViewer(this, "", true, SoWinFullViewer.BuildFlags.BUILD_ALL, SoWinViewer.Types.BROWSER); viewer.SetSceneGraph(root); viewer.SetTitle("ExtTexture2 Viewer"); viewer.SetSize(new SbVec2s(350, 350)); // In Inventor 2.1f, if the machine does not have hardware texture // mapping, we must override the default drawStyle to display textures. viewer.SetDrawStyle(SoWinViewer.DrawTypes.STILL, SoWinViewer.DrawStyles.VIEW_AS_IS); viewer.Show(); // Launch the loading automatically texture1.loadingMode.SetValue((int)SoExtTexture2.Filters.AUTO); texture1.LoadTexture(); }
The SoIndexedTexture2( C++ | Java | .NET )property node defines a color index texture map and parameters for that map. This map applies to the current texture unit (see the section called “ SoTextureUnit”) and is used to apply texture to subsequent shapes as they are rendered.
The image data is stored in an SoSFArray2D( C++ | Java | .NET ) . This array can contain different types of data: UNSIGNED_BYTE, UNSIGNED_SHORT, UNSIGNED_INT32, SIGNED_BYTE, SIGNED_SHORT, SIGNED_INT32, FLOAT.
Each data value coming from the SoSFArray2D( C++ | Java | .NET ) is used as an index into the color map defined by the current SoColorMap( C++ | Java | .NET )node.
The minValue and maxValue fields allow you to specify the mapping from the data to the color map. For example, if minValue is set to 10000 and maxValue to 38000, all values less than or equal to 1000 will be mapped to the entry 0 of the color map and all values greater than or equal to 38000 to the last entry. Figure 7.8, “ SoIndexedTexture2 mapping data range to color map” below illustrates the process of mapping and shows how it can be used to map only the used data range to the color map.
The following table shows the SoIndexedTexture2( C++ | Java | .NET ) fields:
minValue (SoSFFloat) maxValue (SoSFFloat) | Specifies the range of values which is mapped onto the color map (see SoColorMap( C++ | Java | .NET )). When minValue and maxValue are equal to 0 (the default), the entire range of the data type is mapped onto the color map, except in the case of float data. For example, for a color map of size N:
All values less than or equal to minValue will be mapped to the first entry of the color map. Similarly, all values greater than or equal to maxValue will be mapped to the last entry of the color map. |
imageIndex (SoSFArray2D) | This field contains the in-memory representation of the indexed texture image. Each value of this array is a color index. |
rescaleTexCoord (SoSFBool) | This field controls the way an image with non-power-of-two dimension is handled:.
|
wrapT (SoSFEnum) | Specifies how the image wraps in the t (vertical) direction. Possible values are the same as for wrapS in the section called “Fields common to SoTexture nodes”. |
In addition to the fields shown above, SoIndexedTexture2( C++ | Java | .NET ) also has all of the fields inherited from SoTexture( C++ | Java | .NET ).
The following example program: $OIVHOME/src/Inventor/examples/Features/IndexedTexture/IndexedTexture.cxx
(screenshot shown below) illustrates the use of SoIndexedTexture2( C++ | Java | .NET ) and SoColorMap( C++ | Java | .NET ).
SoTexture3( C++ | Java | .NET ) has the following fields:
filenames (SoMFString) | Specifies the list of file names containing texture images. See your release documentation for information on the file formats supported on your system. (You use this field or the images file.) If the filenames field is set, the image files are read and the images field is set to the pixels in those files. If the images field is set, the filenames field is set to an empty string. This behavior assures that there is no ambiguity about which field is used for the texture. All files must contain images of the same type (same width and height, as well as same number of components). See also notes at the end of the section called “SoTextureCubeMap ”. |
images (SoSFImage3) | Specifies the color and number of pixels in the texture map. |
wrapT (SoSFEnum) | Specifies how the image wraps in the t (vertical), and r (depth) directions. Possible values are the same as for wrapS in the section called “Fields common to SoTexture nodes”. |
In addition to the fields shown above, SoTexture3( C++ | Java | .NET ) also has all of the fields inherited from SoTexture( C++ | Java | .NET ).
SoTextureCubeMap( C++ | Java | .NET ) has the following fields:
filenames (SoMFString) | Specifies the six file names containing texture images. See your release documentation for information on the file formats supported on your system. (You use this field or the image XXX fields (below).) If the filenames field is set, the images are read and the image fields are set to the pixels in those files. If the image fields (imagePosX, etc…) are set, the corresponding names in the filenames field are set to an empty string. All files must contain images of the same type (same width and height, as well as same number of components). See also notes at the end of this section. |
imagePosX (SoSFImage) | Specifies the color and number of pixels in the texture map. |
wrapT (SoSFEnum) | Specifies how the image wraps in the t (vertical), and r (depth) directions. Possible values are the same as for wrapS in the section called “Fields common to SoTexture nodes”. |
renderToTextureProperty (SoSFNode) | Specifies an SoRenderToTextureProperty( C++ | Java | .NET )node containing a scene graph that will be rendered to create the texture image. If a value is specified for this field, the image fields and the filenames fields are ignored. |
In addition to the fields shown above, SoTextureCubeMap( C++ | Java | .NET ) also has all of the fields inherited from SoTexture( C++ | Java | .NET ).
You can specify the quality of the texture you are going to use. This feature is exposed in the textureQuality field of the SoComplexity( C++ | Java | .NET )node. A value of 0.0 disables texturing, and a value of 1.0 specifies to use the highest quality texturing. The default value for this field is 0.5.
SoTexture3( C++ | Java | .NET ) and SoTextureCubeMap( C++ | Java | .NET ): When loading several image files, be sure that all of them have the same width and height as well as the same number of components. If the images do not have the same number of components, the first image read will determine the number of components that will be used. Different images will then be reformatted according to that number of components. Similarly, the first image read will determine the width and height for all images. If an image has a different size, it will be reformatted (but not rescaled) to fit the common size. For SoTexture3( C++ | Java | .NET ), the depth of the texture is determined by the number of images specified, even if one or several image files cannot be read. Pixels for unread files are set to black. This ensures that texture coordinates will remain valid even if some files are not read. |
SoTexture3( C++ | Java | .NET ) and SoTextureCubeMap( C++ | Java | .NET ): The size of a 2D image or a 3D image (i.e., the set of 2D images that constitute the pixels for the 3D texture)) must be a power of 2 in all dimensions. This is an OpenGL requirement. Therefore, if any of the dimensions are not a power of 2, the texture is enlarged (it is never shrunk) to fit the power-of-2 requirement. For a 3D texture, unlike 2D textures where a resized texture is actually rescaled, the 3D image is not rescaled. Therefore, pixels that are added to the 3D images will not contain any color information from the original 3D image and are black. You should be aware of this when setting texture coordinates. If your 3D image is not correctly dimensioned, you may want to consider either applying a ratio to your coordinates or adding an SoTexture3Transform( C++ | Java | .NET )(see next section) node with the field scaleFactor set to compensate. |
If you want to translate, rotate, or scale a texture, you need to insert a texture transform node into the scene graph before the shape node. The texture transform nodes are:
These nodes actually transform the texture coordinates. You can concatenate transforms by inserting two or more texture transform nodes. If you are using multiple textures, note that this transformation is applied to the texture coordinates of the current texture unit (SoTextureUnit( C++ | Java | .NET ) ). This allows you to change the size and position of the textures on objects.
The fields of the SoTexture2Transform( C++ | Java | .NET )node are as follows:
translation (SoSFVec2f) | Specifies a translation of the object’s texture coordinates. |
rotation (SoSFFloat) | Specifies a rotation of the object’s texture coordinates. |
scaleFactor (SoSFVec2f) | Specifies how to scale the texture on the object. The object’s s and t coordinates are multiplied by the scale factor. If the scale factor is bigger than 1, the texture appears smaller on the object and vice versa. |
center (SoSFVec2f) | Specifies the center of the rotation and scale transformations. The default is (0.0, 0.0), the front lower left corner of the texture. |
The fields of the SoTexture3Transform( C++ | Java | .NET )node are as follows:
translation (SoSFVec3f) | Specifies a translation of the object’s texture coordinates. |
rotation (SoSFRotation) | Specifies a rotation of the object’s texture coordinates. |
scaleFactor (SoSFVec3f) | Specifies how to scale the texture on the object. The object’s s, t, and r coordinates are multiplied by the scale factor. If the scale factor is bigger than 1, the texture appears smaller on the object and vice versa. |
center (SoSFVec3f) | Specifies the center of the rotation and scale transformations. The default is (0.0, 0.0, 0.0), the front lower left corner of the texture. |
In the following example, the default texture coordinates are, counter-clockwise from the lower left vertex: (0,0), (1,0), (1,1), and (0,1). In the left image, the actual (i.e., transformed) texture coordinates are: (0,0), (0.5,0), (0.5,0.5), and (0,0.5). In the right image, the actual texture coordinates are: (0,0), (2,0), (2,2), and (0,2).