*** empty log message ***
This commit is contained in:
parent
bce184e87c
commit
eb4ee3afad
@ -128,6 +128,7 @@ EXAMPLE_DIRS = \
|
||||
osgautotransform\
|
||||
osgbillboard\
|
||||
osgbluemarble\
|
||||
osgdem\
|
||||
osgcallback\
|
||||
osgcameragroup\
|
||||
osgclip\
|
||||
|
282
doc/stereo.html
282
doc/stereo.html
@ -1,306 +1,228 @@
|
||||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.4.3-20mdk i686) [Netscape]">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=iso-8859-1">
|
||||
<meta name="GENERATOR"
|
||||
content="Mozilla/4.77 [en] (X11; U; Linux 2.4.3-20mdk i686) [Netscape]">
|
||||
<title>Native stereo support</title>
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
|
||||
<img SRC="images/OpenSceneGraphBanner_Distribution.jpg">
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ee" vlink="#551a8b"
|
||||
alink="#ff0000">
|
||||
<img src="images/OpenSceneGraphBanner_Distribution.jpg">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="index.html">Index</a></td>
|
||||
|
||||
<td><a href="introduction.html">Introduction</a></td>
|
||||
|
||||
<td><a href="contents.html">Contents</a></td>
|
||||
|
||||
<td><a href="install.html">Install</a></td>
|
||||
|
||||
<td><a href="dependencies.html">Dependencies</a></td>
|
||||
|
||||
<td><a href="examples.html">examples</a></td>
|
||||
|
||||
<td><a href="data.html">Data</a></td>
|
||||
|
||||
<td><a href="osgviewer.html">Viewer</a></td>
|
||||
|
||||
<td><a href="stereo.html">Stereo</a></td>
|
||||
|
||||
<td><a href="plan.html">Plan</a></td>
|
||||
|
||||
<td><a href="documentation.html">Reference Guides</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>
|
||||
<u>Native Support for Stereo</u></h2>
|
||||
The OSG has support for anaglyphic stereo (i.e. red/green or red/cyan glasses),
|
||||
quad buffered stereo (i.e. active stereo using shutter glasses, or passive
|
||||
stereo using polarized projectors & glasses) and horizontal and vertical
|
||||
split window stereo implementations. Almost all OSG applications have the
|
||||
potential for stereo support simply by setting the relevant environmental
|
||||
variables, or via command line arguments. Little or no code changes will
|
||||
be required, the support is handled transparently inside osgUtil::SceneView's
|
||||
handling of rendering. It is a simple as:
|
||||
<br><b> osgviewer --stereo cow.osg</b>
|
||||
<p>If the user is planning to use head tracked stereo, or a cave then it
|
||||
is currently recommend to set it up via a VR toolkit such as VRjuggler,
|
||||
in this case refer to the VR toolkits handling of stereo, and keep all
|
||||
the OSG's stereo specific environment variables (below) set to OFF, or
|
||||
set the values to off within own your own applications.
|
||||
<br>
|
||||
<h2> <u>Native Support for Stereo</u></h2>
|
||||
The OSG has support for anaglyphic stereo (i.e. red/green or red/cyan
|
||||
glasses), quad buffered stereo (i.e. active stereo using shutter
|
||||
glasses, or passive stereo using polarized projectors & glasses)
|
||||
and horizontal and vertical split window stereo implementations. Almost
|
||||
all OSG applications have the potential for stereo support simply by
|
||||
setting the relevant environmental variables, or via command line
|
||||
arguments. Little or no code changes will be required, the support is
|
||||
handled transparently inside osgUtil::SceneView's handling of
|
||||
rendering. It is a simple as: <br>
|
||||
<b> osgviewer --stereo cow.osg</b>
|
||||
<p>If the user is planning to use head tracked stereo, or a cave then
|
||||
it is currently recommend to set it up via a VR toolkit such as
|
||||
VRjuggler, in this case refer to the VR toolkits handling of stereo,
|
||||
and keep all the OSG's stereo specific environment variables (below)
|
||||
set to OFF, or set the values to off within own your own applications. <br>
|
||||
</p>
|
||||
<hr>
|
||||
<h3>
|
||||
The environmental variables of interest:</h3>
|
||||
|
||||
<h3> The environmental variables of interest:</h3>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>OSG_STEREO</b></td>
|
||||
|
||||
<td><b>ON</b></td>
|
||||
|
||||
<td>Turn stereo on </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>OFF</b></td>
|
||||
|
||||
<td>Turn stereo off (default). </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>OSG_STEREO_MODE</b></td>
|
||||
|
||||
<td><b>ANAGLYPHIC</b></td>
|
||||
|
||||
<td>Use anaglyphic stereo when in stereo (default). </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>QUAD_BUFFER</b></td>
|
||||
|
||||
<td>Use quad buffered stereo when in stereo. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>HORIZONTAL_SPLIT</b></td>
|
||||
|
||||
<td>Use horizontal split stereo mode when in stereo </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>VERTICAL_SPLIT</b></td>
|
||||
|
||||
<td>Use vertical split stereo mode when in stereo </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>OSG_SCREEN_DISTANCE</b></td>
|
||||
|
||||
<td><b>0.50</b></td>
|
||||
|
||||
<td>Set the distance the viewer is from screen in metres (default shown) </td>
|
||||
<td>Set the distance the viewer is from screen in metres (default
|
||||
shown) </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>OSG_SCREEN_HEIGHT</b></td>
|
||||
|
||||
<td><b>0.26</b></td>
|
||||
|
||||
<td>Set the height if image on the screen in metres (default shown) </td>
|
||||
<td>Set the height if image on the screen in metres (default
|
||||
shown) </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>OSG_EYE_SEPARATION</b></td>
|
||||
|
||||
<td><b>0.06</b></td>
|
||||
|
||||
<td>Set the eye separation - interoccular distance (default shown.) </td>
|
||||
<td>Set the eye separation - interoccular distance (default
|
||||
shown.) </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION</b></td>
|
||||
|
||||
<td><b>42</b></td>
|
||||
|
||||
<td>Set the number of pixels between the left and right viewports (default
|
||||
shown).</td>
|
||||
<td>Set the number of pixels between the left and right viewports
|
||||
(default shown).</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING</b></td>
|
||||
|
||||
<td><b>LEFT_EYE_LEFT_VIEWPORT</b></td>
|
||||
|
||||
<td>Set the left eye to render to left viewport, right eye to right viewport
|
||||
(default). </td>
|
||||
<td>Set the left eye to render to left viewport, right eye to
|
||||
right viewport (default). </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>LEFT_EYE_RIGHT_VIEWPORT</b></td>
|
||||
|
||||
<td>Set the left eye to render to right viewport, right eye to left viewport. </td>
|
||||
<td>Set the left eye to render to right viewport, right eye to
|
||||
left viewport. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>OSG_SPLIT_STEREO_VERTICAL_SEPARATION</b></td>
|
||||
|
||||
<td><b>42</b></td>
|
||||
|
||||
<td>Set the number of pixels between the top and bottom viewports (default
|
||||
shown).</td>
|
||||
<td>Set the number of pixels between the top and bottom viewports
|
||||
(default shown).</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING</b></td>
|
||||
|
||||
<td><b>LEFT_EYE_TOP_VIEWPORT</b></td>
|
||||
|
||||
<td>Set the left eye to render to top viewport, right eye to bottom viewport
|
||||
(default). </td>
|
||||
<td>Set the left eye to render to top viewport, right eye to
|
||||
bottom viewport (default). </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>LEFT_EYE_BOTTOM_VIEWPORT</b></td>
|
||||
|
||||
<td>Set the left eye to render to bottom viewport, right eye to top viewport. </td>
|
||||
<td>Set the left eye to render to bottom viewport, right eye to
|
||||
top viewport. </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
<h3>
|
||||
Command line arguments can be used to override these settings:</h3>
|
||||
|
||||
<h3> Command line arguments can be used to override these settings:</h3>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>-stereo</b></td>
|
||||
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td>Switch on stereo. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><b>-stereo</b></td>
|
||||
|
||||
<td><b>ON</b></td>
|
||||
|
||||
<td>Switch on stereo. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>OFF</b></td>
|
||||
|
||||
<td>Switch off stereo. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>ANAGLYPHIC</b></td>
|
||||
|
||||
<td>Switch on ANAGLYPHIC stereo. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>QUAD_BUFFER</b></td>
|
||||
|
||||
<td>Switch on QUAD_BUFFER stereo. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>VERTICAL_SPLIT</b></td>
|
||||
|
||||
<td>Switch on VERTICAL_SPLIT stereo. </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td></td>
|
||||
|
||||
<td><br>
|
||||
</td>
|
||||
<td><b>HORIZONTAL_SPLIT</b></td>
|
||||
|
||||
<td>Switch on VERTICAL_SPLIT stereo. </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
<h3>
|
||||
Examples:</h3>
|
||||
To invoke stereo from the comandline:
|
||||
<br><b> osgviewer -stereo cow.osg</b>
|
||||
<p>To invoke quad buffered stereo from the commandline:
|
||||
<br><b> osgviewer -stereo QUAD_BUFFER cow.osg</b>
|
||||
<p>To force all apps to start up in quad buffered stereo (if system supports
|
||||
it)
|
||||
<br><b> export OSG_STEREO=ON</b>
|
||||
<br><b> export OSG_STEREO_MODE=QUAD_BUFFER</b>
|
||||
<br><b> osgviewer cow.osg</b>
|
||||
<h3> Examples:</h3>
|
||||
To invoke stereo from the comandline: <br>
|
||||
<b> osgviewer -stereo cow.osg</b>
|
||||
<p>To invoke quad buffered stereo from the commandline: <br>
|
||||
<b> osgviewer -stereo QUAD_BUFFER cow.osg</b> </p>
|
||||
<p>To force all apps to start up in quad buffered stereo (if system
|
||||
supports it) <br>
|
||||
<b> export OSG_STEREO=ON</b> <br>
|
||||
<b> export OSG_STEREO_MODE=QUAD_BUFFER</b> <br>
|
||||
<b> osgviewer cow.osg</b> </p>
|
||||
<p>To set quad buffered stereo to the default, but use the commandline
|
||||
to switch stereo on:
|
||||
<br><b> export OSG_STEREO=OFF</b>
|
||||
<br><b> export OSG_STEREO_MODE=QUAD_BUFFER</b>
|
||||
<br><b> osgviewer -stereo cow.osg</b>
|
||||
<p>
|
||||
to switch stereo on: <br>
|
||||
<b> export OSG_STEREO=OFF</b> <br>
|
||||
<b> export OSG_STEREO_MODE=QUAD_BUFFER</b> <br>
|
||||
<b> osgviewer -stereo cow.osg</b> </p>
|
||||
<p> </p>
|
||||
<hr>
|
||||
<h3>
|
||||
Size matters:</h3>
|
||||
<h3> Size matters:</h3>
|
||||
For appropriate depth perception the stereo code creates separate left
|
||||
and eye views, both the frustum and modelview are shifted to account for
|
||||
the separate eye views. To achieve the right amount of adjustment
|
||||
the OSG requires the users eye separation, the distance from the eyes to
|
||||
the screen and the height of the screen. The OSG will use the defaults
|
||||
of 0.05m,0.5m and 0.26m respectively which are assumed to be reasonable
|
||||
defaults for most users workstation configurations, note the OSG_SCREEN_HEIGHT
|
||||
is the image height rather than total size of your monitor/display surface.
|
||||
For the best stereo effects please measure these values and set them up
|
||||
via the environmental variables. Once set the views you get should
|
||||
give improved depth perception. A good way of measuring how well
|
||||
you are configured for your display is to fly away from objects (using
|
||||
the FlightManipulator for instance, but not the TrackballManipulator, see
|
||||
the screen and the height of the screen. The OSG will use the
|
||||
defaults of 0.05m,0.5m and 0.26m respectively which are assumed to be
|
||||
reasonable defaults for most users workstation configurations, note the
|
||||
OSG_SCREEN_HEIGHT is the image height rather than total size of your
|
||||
monitor/display surface. For the best stereo effects please
|
||||
measure these values and set them up via the environmental
|
||||
variables. Once set the views you get should give improved depth
|
||||
perception. A good way of measuring how well you are configured
|
||||
for your display is to fly away from objects (using the
|
||||
FlightManipulator for instance, but not the TrackballManipulator, see
|
||||
below) so that they go of toward infinity. As they move away the offset
|
||||
between the two images should tend towards your eye separation, if you
|
||||
achieve this then the object will be perceived as at infinity.
|
||||
achieve this then the object will be perceived as at infinity. <br>
|
||||
<br>
|
||||
<hr>
|
||||
<h3>
|
||||
Camera Manipulator Modes:</h3>
|
||||
There are three osgUtil::CameraManipulator's which come with osgUtil, which
|
||||
operate as a Trackball, Drive and Flight modes of interaction (see osgviewer.html
|
||||
for how to invoke them in the scene graph viewer). The osgUtil::Trackball
|
||||
Manipulator automatically scales the fusion distance to that which will
|
||||
fusion on center point of rotation - this will appear at the middle of
|
||||
the monitor at the monitors depth. Whereas, the osgUtil::DriveManipualtor,
|
||||
osgUtil::FlightManipulator scale the fusion distance to the distance the
|
||||
viewer is from the screen, the results in a perception that the virtual
|
||||
world is scaled to physical world, this is clearly better for simulators
|
||||
and alike. You can control the fusion of the image in these two modes via
|
||||
the osg::Camera::setFusionDistanceMode(FusionDistanceMode mode) where mode
|
||||
can be osg::Camera::PROPORTIONAL_TO_LOOK_DISTANCE (used by Trackball) or
|
||||
osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE (used by Drive and Flight),
|
||||
and osg::Camera::setFusionDistanceRatio(float). See include/osg/Camera
|
||||
for further details, and the camera manipulators for implementation details.
|
||||
The fusion distance ratio defaults to 1.0 but can be biased to move objects
|
||||
out or into screen, they will also appear to get smaller and larger respectively.
|
||||
The camera manipulators allow the user to alter this value at runtime via
|
||||
the '+' and '-' keys.
|
||||
</body>
|
||||
</html>
|
||||
|
@ -69,10 +69,14 @@ osg::Node* createTile(const std::string& filename, bool leftHemisphere, double x
|
||||
options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW;
|
||||
options->_destinationPixelWindow.set(0,0,256,256);
|
||||
|
||||
osgDB::ImageOptions::TexCoordRange* texCoordRange = 0;
|
||||
|
||||
osgDB::Registry::instance()->setOptions(options.get());
|
||||
osg::Image* image = osgDB::readImageFile(filename.c_str());
|
||||
if (image)
|
||||
{
|
||||
texCoordRange = dynamic_cast<osgDB::ImageOptions::TexCoordRange*>(image->getUserData());
|
||||
|
||||
osg::Texture2D* texture = new osg::Texture2D;
|
||||
texture->setImage(image);
|
||||
texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP);
|
||||
@ -82,6 +86,9 @@ osg::Node* createTile(const std::string& filename, bool leftHemisphere, double x
|
||||
texture->setMaxAnisotropy(8);
|
||||
stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
|
||||
|
||||
bool useCompressedTextures = true;
|
||||
if (useCompressedTextures)
|
||||
{
|
||||
texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT3_COMPRESSION);
|
||||
|
||||
osg::ref_ptr<osg::State> state = new osg::State;
|
||||
@ -90,8 +97,7 @@ osg::Node* createTile(const std::string& filename, bool leftHemisphere, double x
|
||||
image->readImageFromCurrentTexture();
|
||||
|
||||
texture->setInternalFormatMode(osg::Texture::USE_IMAGE_DATA_FORMAT);
|
||||
|
||||
std::cout<<"glGetError()=="<<glGetError()<<std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -114,9 +120,24 @@ osg::Node* createTile(const std::string& filename, bool leftHemisphere, double x
|
||||
color[0].set(255,255,255,255);
|
||||
|
||||
|
||||
|
||||
osg::Vec2 tex_orig(0.0f,0.0f);
|
||||
|
||||
float rowTexDelta = 1.0f/(float)(numRows-1);
|
||||
float columnTexDelta = 1.0f/(float)(numColumns-1);
|
||||
|
||||
if (texCoordRange)
|
||||
{
|
||||
tex_orig.set(texCoordRange->_x,texCoordRange->_y);
|
||||
rowTexDelta = texCoordRange->_h/(float)(numRows-1);
|
||||
columnTexDelta = texCoordRange->_w/(float)(numColumns-1);
|
||||
|
||||
std::cout<<"setting tex values to use texCoordRange"<<std::endl;
|
||||
std::cout<<" tex_orig="<<tex_orig<<std::endl;
|
||||
std::cout<<" rowTexDelta"<<rowTexDelta<<std::endl;
|
||||
std::cout<<" columnTexDelta"<<columnTexDelta<<std::endl;
|
||||
}
|
||||
|
||||
double orig_latitude = osg::PI*x;
|
||||
double delta_latitude = osg::PI*w/(double)(numColumns-1);
|
||||
|
||||
@ -124,7 +145,7 @@ osg::Node* createTile(const std::string& filename, bool leftHemisphere, double x
|
||||
double orig_longitude = osg::PI*y;
|
||||
double delta_longitude = osg::PI*h/(double)(numRows-1);
|
||||
|
||||
osg::Vec2 tex(0.0f,0.0f);
|
||||
osg::Vec2 tex(tex_orig);
|
||||
int vi=0;
|
||||
double longitude = orig_longitude;
|
||||
osg::Vec3 normal;
|
||||
@ -132,7 +153,7 @@ osg::Node* createTile(const std::string& filename, bool leftHemisphere, double x
|
||||
{
|
||||
double latitude = orig_latitude;
|
||||
|
||||
tex.x() = 0.0f;
|
||||
tex.x() = tex_orig.x();
|
||||
for(c=0;c<numColumns;++c)
|
||||
{
|
||||
double sin_longitude = sin(longitude);
|
||||
@ -302,7 +323,9 @@ bool createWorld(const std::string& left_hemisphere, const std::string& right_he
|
||||
// create the world
|
||||
|
||||
|
||||
std::string base = osgDB::getFilePath(baseName)+'/'+osgDB::getStrippedName(baseName);
|
||||
std::string path = osgDB::getFilePath(baseName);
|
||||
std::string base = path.empty()?osgDB::getStrippedName(baseName):
|
||||
path +'/'+ osgDB::getStrippedName(baseName);
|
||||
std::string extension = '.'+osgDB::getLowerCaseFileExtension(baseName);
|
||||
|
||||
std::cout << "baseName = "<<baseName<<std::endl;
|
||||
@ -337,8 +360,19 @@ int main( int argc, char **argv )
|
||||
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
|
||||
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-i <filename>","Specify the input file to process");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-o <outputfile>","Specify the output master file to generate");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-l <numOfLevels>","Specify the number of PagedLOD levels to generate");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
std::string inputFile;
|
||||
while (arguments.read("-i",inputFile)) {}
|
||||
|
||||
std::string basename("output.ive");
|
||||
while (arguments.read("-o",basename)) {}
|
||||
|
||||
float numLevels;
|
||||
while (arguments.read("-l",numLevels)) {}
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
@ -365,7 +399,6 @@ int main( int argc, char **argv )
|
||||
|
||||
std::string left_hemisphere("land_shallow_topo_west.tif");
|
||||
std::string right_hemisphere("land_shallow_topo_east.tif");
|
||||
std::string basename("BlueMarble/bluemarble.ive");
|
||||
|
||||
// create a graphics context to allow us to use OpenGL to compress textures.
|
||||
GraphicsContext gfx;
|
||||
|
18
examples/osgdem/GNUmakefile
Normal file
18
examples/osgdem/GNUmakefile
Normal file
@ -0,0 +1,18 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgdem.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgFX -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
GNUmakefile.inst=GNUmakefile
|
||||
|
||||
EXEC = osgdem
|
||||
|
||||
INC += $(X_INC)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
13
examples/osgdem/GNUmakefile.inst
Normal file
13
examples/osgdem/GNUmakefile.inst
Normal file
@ -0,0 +1,13 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgdem.cpp\
|
||||
|
||||
LIBS += -losgProducer -lProducer -losgDB -losgText -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
EXEC = osgdem
|
||||
|
||||
INC += $(X_INC)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
883
examples/osgdem/osgdem.cpp
Normal file
883
examples/osgdem/osgdem.cpp
Normal file
@ -0,0 +1,883 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
|
||||
*
|
||||
* This application is open source and may be redistributed and/or modified
|
||||
* freely and without restriction, both in commericial and non commericial applications,
|
||||
* as long as this copyright notice is maintained.
|
||||
*
|
||||
* This application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/State>
|
||||
#include <osg/ShapeDrawable>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/WriteFile>
|
||||
#include <osgDB/ImageOptions>
|
||||
#include <osgDB/FileNameUtils>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
#include <osgUtil/TriStripVisitor>
|
||||
#include <osgUtil/SmoothingVisitor>
|
||||
#include <osgUtil/TangentSpaceGenerator>
|
||||
|
||||
#include <osgFX/BumpMapping>
|
||||
|
||||
#include <osgProducer/Viewer>
|
||||
|
||||
|
||||
float VERTICAL_SIZE = 0.0005;
|
||||
|
||||
class GraphicsContext {
|
||||
public:
|
||||
GraphicsContext()
|
||||
{
|
||||
rs = new Producer::RenderSurface;
|
||||
rs->setWindowRectangle(0,0,1,1);
|
||||
rs->useBorder(false);
|
||||
rs->useConfigEventThread(false);
|
||||
rs->realize();
|
||||
std::cout<<"Realized window"<<std::endl;
|
||||
}
|
||||
|
||||
virtual ~GraphicsContext()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Producer::ref_ptr<Producer::RenderSurface> rs;
|
||||
};
|
||||
|
||||
osg::Image* createNormalMap(osg::HeightField* grid)
|
||||
{
|
||||
osg::Image* image = new osg::Image;
|
||||
image->allocateImage(grid->getNumColumns(),grid->getNumRows(),1,GL_RGB,GL_BYTE);
|
||||
|
||||
char* ptr = (char*) image->data();
|
||||
for(unsigned int r=0;r<grid->getNumRows();++r)
|
||||
{
|
||||
for(unsigned int c=0;c<grid->getNumColumns();++c)
|
||||
{
|
||||
osg::Vec3 normal = grid->getNormal(c,r);
|
||||
(*ptr++) = (char)((normal.x()+1.0)*0.5*255);
|
||||
(*ptr++) = (char)((normal.y()+1.0)*0.5*255);
|
||||
(*ptr++) = (char)((normal.z()+1.0)*0.5*255);
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
|
||||
}
|
||||
|
||||
|
||||
template< typename T>
|
||||
osg::HeightField* _createHeightField(osg::Image* image, float zScale)
|
||||
{
|
||||
unsigned char* ptr = image->data();
|
||||
unsigned int rowSizeInBytes = image->getRowSizeInBytes();
|
||||
unsigned int pixelSizeInBits = image->getPixelSizeInBits();
|
||||
unsigned int pixelSizeInBytes = pixelSizeInBits/8;
|
||||
|
||||
unsigned int numColumns = image->s();
|
||||
unsigned int numRows = image->t();
|
||||
|
||||
osg::HeightField* grid = new osg::HeightField;
|
||||
grid->allocateGrid(numColumns,numRows);
|
||||
|
||||
for(unsigned int r=0;r<numRows;++r)
|
||||
{
|
||||
unsigned char* ptr_in_row = ptr;
|
||||
for(unsigned int c=0;c<numColumns;++c)
|
||||
{
|
||||
grid->setHeight(c,r,zScale*(float)(*((T*)ptr_in_row)));
|
||||
ptr_in_row += pixelSizeInBytes;
|
||||
}
|
||||
ptr += rowSizeInBytes;
|
||||
}
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
osg::HeightField* createHeightField(osg::Image* image, const osg::Vec3& origin, const osg::Vec3& size)
|
||||
{
|
||||
osg::HeightField* grid = new osg::HeightField;
|
||||
switch(image->getDataType())
|
||||
{
|
||||
case(GL_UNSIGNED_BYTE): grid = _createHeightField<unsigned char>(image,size.z()); break;
|
||||
case(GL_BYTE): grid = _createHeightField<char>(image,size.z()); break;
|
||||
case(GL_UNSIGNED_SHORT): grid = _createHeightField<unsigned short>(image,size.z()); break;
|
||||
case(GL_SHORT): grid = _createHeightField<short>(image,size.z()); break;
|
||||
case(GL_UNSIGNED_INT): grid = _createHeightField<unsigned int>(image,size.z()); break;
|
||||
case(GL_INT): grid = _createHeightField<int>(image,size.z()); break;
|
||||
case(GL_FLOAT): grid = _createHeightField<float>(image,size.z()); break;
|
||||
}
|
||||
grid->setOrigin(origin);
|
||||
grid->setXInterval(size.x()/(float)(image->s()-1));
|
||||
grid->setYInterval(size.y()/(float)(image->s()-1));
|
||||
|
||||
return grid;
|
||||
|
||||
}
|
||||
|
||||
osg::Node* createTile(osg::HeightField* grid,
|
||||
unsigned int columnBegin, unsigned int columnEnd,
|
||||
unsigned int rowBegin, unsigned int rowEnd,
|
||||
float xTexCoordBegin, float xTexCoordEnd,
|
||||
float yTexCoordBegin, float yTexCoordEnd,
|
||||
unsigned int targetNumPolygonsPerTile)
|
||||
{
|
||||
|
||||
|
||||
int numPolys = (columnEnd-columnBegin)*(rowEnd-rowBegin)*2;
|
||||
int numColumns, numRows;
|
||||
bool oneToOneMapping = numPolys<=targetNumPolygonsPerTile;
|
||||
if (oneToOneMapping)
|
||||
{
|
||||
numColumns = (columnEnd-columnBegin)+1;
|
||||
numRows = (rowEnd-rowBegin)+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
numColumns = (int)sqrtf((float)targetNumPolygonsPerTile/2.0) + 1;
|
||||
numRows = targetNumPolygonsPerTile/(2*(numColumns)-1) + 1;
|
||||
}
|
||||
|
||||
bool createSkirt = true;
|
||||
|
||||
|
||||
int numVerticesInBody = numColumns*numRows;
|
||||
int numVerticesInSkirt = createSkirt ? numColumns*2 + numRows*2 - 4 : 0;
|
||||
int numVertices = numVerticesInBody+numVerticesInSkirt;
|
||||
|
||||
osg::Vec3 skirtVector(0.0f,0.0f,-0.003f);
|
||||
|
||||
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array& v = *(new osg::Vec3Array(numVertices));
|
||||
osg::Vec2Array& t = *(new osg::Vec2Array(numVertices));
|
||||
osg::UByte4Array& color = *(new osg::UByte4Array(1));
|
||||
|
||||
color[0].set(255,255,255,255);
|
||||
|
||||
|
||||
int vi=0;
|
||||
int r,c;
|
||||
if (!oneToOneMapping)
|
||||
{
|
||||
for(r=0;r<numRows;++r)
|
||||
{
|
||||
unsigned int row = rowBegin + (unsigned int)((float)(rowEnd-rowBegin) * ((float)r/(float)(numRows-1)));
|
||||
for(c=0;c<numColumns;++c)
|
||||
{
|
||||
unsigned int col = columnBegin + (unsigned int)((float)(columnEnd-columnBegin) * ((float)c/(float)(numColumns-1)));
|
||||
v[vi] = grid->getOrigin()+osg::Vec3(grid->getXInterval()*(float)col,
|
||||
grid->getYInterval()*(float)row,
|
||||
grid->getHeight(col,row));
|
||||
t[vi].x() = xTexCoordBegin + (xTexCoordEnd-xTexCoordBegin)*(float)(col-columnBegin)/(float)(columnEnd-columnBegin);
|
||||
t[vi].y() = yTexCoordBegin + (yTexCoordEnd-yTexCoordBegin)*(float)(row-rowBegin)/(float)(rowEnd-rowBegin);
|
||||
|
||||
++vi;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(r=rowBegin;r<=rowEnd;++r)
|
||||
{
|
||||
for(c=columnBegin;c<=columnEnd;++c)
|
||||
{
|
||||
v[vi] = grid->getOrigin()+osg::Vec3(grid->getXInterval()*c,
|
||||
grid->getYInterval()*r,
|
||||
grid->getHeight(c,r));
|
||||
t[vi].x() = xTexCoordBegin + (xTexCoordEnd-xTexCoordBegin)*(float)(c-columnBegin)/(float)(columnEnd-columnBegin);
|
||||
t[vi].y() = yTexCoordBegin + (yTexCoordEnd-yTexCoordBegin)*(float)(r-rowBegin)/(float)(rowEnd-rowBegin);
|
||||
|
||||
++vi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
geometry->setVertexArray(&v);
|
||||
geometry->setColorArray(&color);
|
||||
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
geometry->setTexCoordArray(0,&t);
|
||||
geometry->setTexCoordArray(1,&t);
|
||||
|
||||
bool pickOutDiagonals = true;
|
||||
if (pickOutDiagonals)
|
||||
{
|
||||
osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_TRIANGLES,2*3*(numColumns-1)*(numRows-1)));
|
||||
geometry->addPrimitiveSet(&drawElements);
|
||||
int ei=0;
|
||||
for(r=0;r<numRows-1;++r)
|
||||
{
|
||||
for(c=0;c<numColumns-1;++c)
|
||||
{
|
||||
unsigned short i00 = (r)*numColumns+c;
|
||||
unsigned short i10 = (r)*numColumns+c+1;
|
||||
unsigned short i01 = (r+1)*numColumns+c;
|
||||
unsigned short i11 = (r+1)*numColumns+c+1;
|
||||
|
||||
float diff_00_11 = fabsf(v[i00].z()-v[i11].z());
|
||||
float diff_01_10 = fabsf(v[i01].z()-v[i10].z());
|
||||
if (diff_00_11<diff_01_10)
|
||||
{
|
||||
// diagonal between 00 and 11
|
||||
drawElements[ei++] = i00;
|
||||
drawElements[ei++] = i10;
|
||||
drawElements[ei++] = i11;
|
||||
|
||||
drawElements[ei++] = i00;
|
||||
drawElements[ei++] = i11;
|
||||
drawElements[ei++] = i01;
|
||||
}
|
||||
else
|
||||
{
|
||||
// diagonal between 01 and 10
|
||||
drawElements[ei++] = i01;
|
||||
drawElements[ei++] = i00;
|
||||
drawElements[ei++] = i10;
|
||||
|
||||
drawElements[ei++] = i01;
|
||||
drawElements[ei++] = i10;
|
||||
drawElements[ei++] = i11;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(r=0;r<numRows-1;++r)
|
||||
{
|
||||
osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,2*numColumns));
|
||||
geometry->addPrimitiveSet(&drawElements);
|
||||
int ei=0;
|
||||
for(c=0;c<numColumns;++c)
|
||||
{
|
||||
drawElements[ei++] = (r+1)*numColumns+c;
|
||||
drawElements[ei++] = (r)*numColumns+c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numVerticesInSkirt>0)
|
||||
{
|
||||
osg::DrawElementsUShort& skirtDrawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,2*numVerticesInSkirt+2));
|
||||
geometry->addPrimitiveSet(&skirtDrawElements);
|
||||
int ei=0;
|
||||
int firstSkirtVertexIndex = vi;
|
||||
// create bottom skirt vertices
|
||||
r=0;
|
||||
for(c=0;c<numColumns-1;++c)
|
||||
{
|
||||
skirtDrawElements[ei++] = (r)*numColumns+c;
|
||||
skirtDrawElements[ei++] = vi;
|
||||
v[vi] = v[(r)*numColumns+c]+skirtVector;
|
||||
t[vi++] = t[(r)*numColumns+c];
|
||||
}
|
||||
// create right skirt vertices
|
||||
c=numColumns-1;
|
||||
for(r=0;r<numRows-1;++r)
|
||||
{
|
||||
skirtDrawElements[ei++] = (r)*numColumns+c;
|
||||
skirtDrawElements[ei++] = vi;
|
||||
v[vi] = v[(r)*numColumns+c]+skirtVector;
|
||||
t[vi++] = t[(r)*numColumns+c];
|
||||
}
|
||||
// create top skirt vertices
|
||||
r=numRows-1;
|
||||
for(c=numColumns-1;c>0;--c)
|
||||
{
|
||||
skirtDrawElements[ei++] = (r)*numColumns+c;
|
||||
skirtDrawElements[ei++] = vi;
|
||||
v[vi] = v[(r)*numColumns+c]+skirtVector;
|
||||
t[vi++] = t[(r)*numColumns+c];
|
||||
}
|
||||
// create left skirt vertices
|
||||
c=0;
|
||||
for(r=numRows-1;r>0;--r)
|
||||
{
|
||||
skirtDrawElements[ei++] = (r)*numColumns+c;
|
||||
skirtDrawElements[ei++] = vi;
|
||||
v[vi] = v[(r)*numColumns+c]+skirtVector;
|
||||
t[vi++] = t[(r)*numColumns+c];
|
||||
}
|
||||
skirtDrawElements[ei++] = 0;
|
||||
skirtDrawElements[ei++] = firstSkirtVertexIndex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
osgUtil::TriStripVisitor tsv;
|
||||
tsv.stripify(*geometry);
|
||||
//
|
||||
// osgUtil::SmoothingVisitor sv;
|
||||
// sv.smooth(*geometry);
|
||||
|
||||
osg::Vec4Array& tsgTangentArray = *(new osg::Vec4Array(1));
|
||||
osg::Vec4Array& tsgBinormalArray = *(new osg::Vec4Array(1));
|
||||
osg::Vec4Array& tsgNormalArray = *(new osg::Vec4Array(1));
|
||||
tsgTangentArray[0].set(1.0f,0.0f,0.0f,0.0f);
|
||||
tsgBinormalArray[0].set(0.0f,1.0f,0.0f,0.0f);
|
||||
tsgNormalArray[0].set(0.0f,0.0f,1.0f,0.0f);
|
||||
geometry->setVertexAttribData(6, osg::Geometry::ArrayData(&tsgTangentArray, osg::Geometry::BIND_OVERALL,GL_FALSE));
|
||||
geometry->setVertexAttribData(7, osg::Geometry::ArrayData(&tsgBinormalArray, osg::Geometry::BIND_OVERALL,GL_FALSE));
|
||||
geometry->setVertexAttribData(15, osg::Geometry::ArrayData(&tsgNormalArray, osg::Geometry::BIND_OVERALL,GL_FALSE));
|
||||
|
||||
//geometry->setUseVertexBufferObjects(true);
|
||||
|
||||
geometry->setUseDisplayList(false);
|
||||
geometry->setUseVertexBufferObjects(false);
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(geometry);
|
||||
|
||||
return geode;
|
||||
|
||||
}
|
||||
|
||||
|
||||
osg::Node* createQuadTree(osg::HeightField* grid,
|
||||
unsigned int columnBegin, unsigned int columnEnd,
|
||||
unsigned int rowBegin, unsigned int rowEnd,
|
||||
float xTexCoordBegin, float xTexCoordEnd,
|
||||
float yTexCoordBegin, float yTexCoordEnd,
|
||||
unsigned int targetNumPolygonsPerTile)
|
||||
{
|
||||
unsigned int numPolys = (columnEnd-columnBegin)*(rowEnd-rowBegin)*2;
|
||||
|
||||
|
||||
std::cout << "createQuadTree "<<columnBegin<<","<<columnEnd<<std::endl;
|
||||
|
||||
osg::Node* tile = createTile(grid,
|
||||
columnBegin, columnEnd,
|
||||
rowBegin, rowEnd,
|
||||
xTexCoordBegin, xTexCoordEnd,
|
||||
yTexCoordBegin, yTexCoordEnd,
|
||||
targetNumPolygonsPerTile);
|
||||
|
||||
if (numPolys<=targetNumPolygonsPerTile)
|
||||
{
|
||||
return tile;
|
||||
}
|
||||
else
|
||||
{
|
||||
float cut_off_distance = tile->getBound().radius()*4.0f;
|
||||
float max_visible_distance = 1e7;
|
||||
|
||||
unsigned int columnCenter = (columnBegin + columnEnd)/2;
|
||||
unsigned int rowCenter = (rowBegin + rowEnd)/2;
|
||||
float xTexCoordCenter = xTexCoordBegin+
|
||||
(xTexCoordEnd-xTexCoordBegin)*((float)(columnCenter-columnBegin)/(float)(columnEnd-columnBegin));
|
||||
float yTexCoordCenter = yTexCoordBegin+
|
||||
(yTexCoordEnd-yTexCoordBegin)*((float)(rowCenter-rowBegin)/(float)(rowEnd-rowBegin));
|
||||
|
||||
osg::Group* group = new osg::Group;
|
||||
group->addChild(createQuadTree(grid,
|
||||
columnBegin, columnCenter,
|
||||
rowBegin, rowCenter,
|
||||
xTexCoordBegin, xTexCoordCenter,
|
||||
yTexCoordBegin, yTexCoordCenter,
|
||||
targetNumPolygonsPerTile));
|
||||
|
||||
group->addChild(createQuadTree(grid,
|
||||
columnCenter, columnEnd,
|
||||
rowBegin, rowCenter,
|
||||
xTexCoordCenter, xTexCoordEnd,
|
||||
yTexCoordBegin, yTexCoordCenter,
|
||||
targetNumPolygonsPerTile));
|
||||
|
||||
group->addChild(createQuadTree(grid,
|
||||
columnCenter, columnEnd,
|
||||
rowCenter, rowEnd,
|
||||
xTexCoordCenter, xTexCoordEnd,
|
||||
yTexCoordCenter, yTexCoordEnd,
|
||||
targetNumPolygonsPerTile));
|
||||
|
||||
group->addChild(createQuadTree(grid,
|
||||
columnBegin, columnCenter,
|
||||
rowCenter, rowEnd,
|
||||
xTexCoordBegin, xTexCoordCenter,
|
||||
yTexCoordCenter, yTexCoordEnd,
|
||||
targetNumPolygonsPerTile));
|
||||
|
||||
osg::LOD* lod = new osg::LOD;
|
||||
lod->addChild(tile,cut_off_distance,max_visible_distance);
|
||||
lod->addChild(group,0.0f,cut_off_distance);
|
||||
|
||||
return lod;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template< typename T>
|
||||
void populate_z(osg::Image* image, const osg::Vec3& zAxis,osg::Vec3Array& v)
|
||||
{
|
||||
unsigned char* ptr = image->data();
|
||||
unsigned int rowSizeInBytes = image->getRowSizeInBytes();
|
||||
unsigned int pixelSizeInBits = image->getPixelSizeInBits();
|
||||
unsigned int pixelSizeInBytes = pixelSizeInBits/8;
|
||||
|
||||
unsigned int numColumns = image->s();
|
||||
unsigned int numRows = image->t();
|
||||
for(unsigned int r=0,vi=0;r<numRows;++r)
|
||||
{
|
||||
unsigned char* ptr_in_row = ptr;
|
||||
for(unsigned int c=0;c<numColumns;++c)
|
||||
{
|
||||
v[vi++] += zAxis * (float)(*((T*)ptr_in_row));
|
||||
ptr_in_row += pixelSizeInBytes;
|
||||
}
|
||||
ptr += rowSizeInBytes;
|
||||
}
|
||||
}
|
||||
|
||||
osg::Node* computeGeometry(osg::Image* image, const osg::Vec3& origin, const osg::Vec3& xAxis, const osg::Vec3& yAxis, const osg::Vec3& zAxis)
|
||||
{
|
||||
if (!image) return 0;
|
||||
|
||||
osgDB::ImageOptions::TexCoordRange* texCoordRange = dynamic_cast<osgDB::ImageOptions::TexCoordRange*>(image->getUserData());
|
||||
|
||||
unsigned int numColumns = image->s();
|
||||
unsigned int numRows = image->t();
|
||||
unsigned int r;
|
||||
unsigned int c;
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
|
||||
bool useGeometry = true;
|
||||
if (useGeometry)
|
||||
{
|
||||
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array& v = *(new osg::Vec3Array(numColumns*numRows));
|
||||
//osg::Vec3Array& n = *(new osg::Vec3Array(numColumns*numRows));
|
||||
osg::Vec2Array& t = *(new osg::Vec2Array(numColumns*numRows));
|
||||
osg::UByte4Array& color = *(new osg::UByte4Array(1));
|
||||
|
||||
color[0].set(255,255,255,255);
|
||||
|
||||
|
||||
#if 0
|
||||
osg::Vec2 tex_orig(0.0f,0.0f);
|
||||
|
||||
float rowTexDelta = 1.0f/(float)(numRows-1);
|
||||
float columnTexDelta = 1.0f/(float)(numColumns-1);
|
||||
#else
|
||||
|
||||
osg::Vec2 tex_orig(origin.x(),origin.y());
|
||||
|
||||
float columnTexDelta = xAxis.length()/(float)(numColumns-1);
|
||||
float rowTexDelta = yAxis.length()/(float)(numRows-1);
|
||||
#endif
|
||||
|
||||
if (texCoordRange)
|
||||
{
|
||||
// tex_orig.set(texCoordRange->_x,texCoordRange->_y);
|
||||
// rowTexDelta = texCoordRange->_h/(float)(numRows-1);
|
||||
// columnTexDelta = texCoordRange->_w/(float)(numColumns-1);
|
||||
|
||||
std::cout<<"setting tex values to use texCoordRange"<<std::endl;
|
||||
std::cout<<" tex_orig="<<tex_orig<<std::endl;
|
||||
std::cout<<" rowTexDelta"<<rowTexDelta<<std::endl;
|
||||
std::cout<<" columnTexDelta"<<columnTexDelta<<std::endl;
|
||||
}
|
||||
|
||||
osg::Vec2 tex(tex_orig);
|
||||
int vi=0;
|
||||
osg::Vec3 normal(0.0f,0.0f,1.0f);
|
||||
osg::Vec3 pos = origin;
|
||||
osg::Vec3 delta_x = xAxis/(double)(numColumns-1);
|
||||
osg::Vec3 delta_y = yAxis/(double)(numRows-1);
|
||||
for(r=0;r<numRows;++r)
|
||||
{
|
||||
tex.x() = tex_orig.x();
|
||||
osg::Vec3 pos_in_row = pos;
|
||||
for(c=0;c<numColumns;++c)
|
||||
{
|
||||
v[vi] = pos_in_row; // + zAxis * (sin(pos_in_row.x()*osg::PI*2)*cos(pos_in_row.y()*osg::PI*2));
|
||||
//n[vi] = normal;
|
||||
t[vi].set(tex.x(),tex.y());
|
||||
|
||||
pos_in_row +=delta_x;
|
||||
tex.x()+=columnTexDelta;
|
||||
++vi;
|
||||
}
|
||||
pos += delta_y;
|
||||
tex.y() += rowTexDelta;
|
||||
}
|
||||
|
||||
switch(image->getDataType())
|
||||
{
|
||||
case(GL_UNSIGNED_BYTE): populate_z<unsigned char>(image,zAxis,v); break;
|
||||
case(GL_BYTE): populate_z<char>(image,zAxis,v); break;
|
||||
case(GL_UNSIGNED_SHORT): populate_z<unsigned short>(image,zAxis,v); break;
|
||||
case(GL_SHORT): populate_z<short>(image,zAxis,v); break;
|
||||
case(GL_UNSIGNED_INT): populate_z<unsigned int>(image,zAxis,v); break;
|
||||
case(GL_INT): populate_z<int>(image,zAxis,v); break;
|
||||
case(GL_FLOAT): populate_z<float>(image,zAxis,v); break;
|
||||
}
|
||||
|
||||
geometry->setVertexArray(&v);
|
||||
//geometry->setNormalArray(&n);
|
||||
//geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
geometry->setColorArray(&color);
|
||||
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
geometry->setTexCoordArray(0,&t);
|
||||
geometry->setTexCoordArray(1,&t);
|
||||
|
||||
|
||||
for(r=0;r<numRows-1;++r)
|
||||
{
|
||||
osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,2*numColumns));
|
||||
geometry->addPrimitiveSet(&drawElements);
|
||||
int ei=0;
|
||||
for(c=0;c<numColumns;++c)
|
||||
{
|
||||
drawElements[ei++] = (r+1)*numColumns+c;
|
||||
drawElements[ei++] = (r)*numColumns+c;
|
||||
}
|
||||
}
|
||||
|
||||
osgUtil::TriStripVisitor tsv;
|
||||
tsv.stripify(*geometry);
|
||||
//
|
||||
// osgUtil::SmoothingVisitor sv;
|
||||
// sv.smooth(*geometry);
|
||||
|
||||
osg::Vec4Array& tsgTangentArray = *(new osg::Vec4Array(1));
|
||||
osg::Vec4Array& tsgBinormalArray = *(new osg::Vec4Array(1));
|
||||
osg::Vec4Array& tsgNormalArray = *(new osg::Vec4Array(1));
|
||||
tsgTangentArray[0].set(1.0f,0.0f,0.0f,0.0f);
|
||||
tsgBinormalArray[0].set(0.0f,1.0f,0.0f,0.0f);
|
||||
tsgNormalArray[0].set(0.0f,0.0f,1.0f,0.0f);
|
||||
geometry->setVertexAttribData(6, osg::Geometry::ArrayData(&tsgTangentArray, osg::Geometry::BIND_OVERALL,GL_FALSE));
|
||||
geometry->setVertexAttribData(7, osg::Geometry::ArrayData(&tsgBinormalArray, osg::Geometry::BIND_OVERALL,GL_FALSE));
|
||||
geometry->setVertexAttribData(15, osg::Geometry::ArrayData(&tsgNormalArray, osg::Geometry::BIND_OVERALL,GL_FALSE));
|
||||
|
||||
//geometry->setUseVertexBufferObjects(true);
|
||||
|
||||
geometry->setUseDisplayList(false);
|
||||
geometry->setUseVertexBufferObjects(false);
|
||||
|
||||
geode->addDrawable(geometry);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
osg::HeightField* grid = createHeightField(image,origin,osg::Vec3(xAxis.length(),yAxis.length(),zAxis.length()));
|
||||
|
||||
geode->addDrawable(new osg::ShapeDrawable(grid));
|
||||
}
|
||||
|
||||
return geode;
|
||||
}
|
||||
|
||||
osg::Node* computeGeometry(osg::Image* image, const osg::Vec3& origin, const osg::Vec3& size)
|
||||
{
|
||||
return computeGeometry(image,origin,osg::Vec3(size.x(),0.0f,0.0f),osg::Vec3(0.0f,size.y(),0.0f),osg::Vec3(0.0f,0.0f,size.z()));
|
||||
}
|
||||
|
||||
osg::Node* createTile(const std::string& filename, double x, double y, double w,double h)
|
||||
{
|
||||
|
||||
osg::ref_ptr<osgDB::ImageOptions> options = new osgDB::ImageOptions;
|
||||
options->_sourceImageWindowMode = osgDB::ImageOptions::RATIO_WINDOW;
|
||||
options->_sourceRatioWindow.set(x,1-(y+h),w,h);
|
||||
|
||||
options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW;
|
||||
options->_destinationPixelWindow.set(0,0,20,20);
|
||||
|
||||
osgDB::Registry::instance()->setOptions(options.get());
|
||||
osg::Image* image = osgDB::readImageFile(filename.c_str());
|
||||
if (image)
|
||||
{
|
||||
|
||||
return computeGeometry(image,osg::Vec3(x,y,0.0),osg::Vec3(w,h,VERTICAL_SIZE));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
osg::Node* createTileAndRecurse(const std::string& filename, const std::string& basename, const std::string& extension, unsigned int noTilesX, unsigned int noTilesY, double x, double y, double w,double h, unsigned int numLevelsLeft)
|
||||
{
|
||||
|
||||
osg::Group* group = new osg::Group;
|
||||
|
||||
double dx = w / (double) noTilesX;
|
||||
double dy = h / (double) noTilesY;
|
||||
|
||||
|
||||
if (numLevelsLeft>0)
|
||||
{
|
||||
|
||||
float cut_off_distance = 4.0f*dy;
|
||||
float max_visible_distance = 1e7;
|
||||
|
||||
// create current layer, and write to disk.
|
||||
unsigned int numTiles = 0;
|
||||
double lx = x;
|
||||
for(unsigned i=0;i<noTilesX;++i,lx+=dx)
|
||||
{
|
||||
double ly = y;
|
||||
for(unsigned j=0;j<noTilesY;++j,ly+=dy)
|
||||
{
|
||||
// create name for tile.
|
||||
char char_num = 'A'+numTiles;
|
||||
std::string lbasename = basename+"_"+char_num;
|
||||
|
||||
// create the subtiles and write out to disk.
|
||||
{
|
||||
osg::ref_ptr<osg::Node> node = createTileAndRecurse(filename,lbasename,extension,2,2,lx,ly,dx,dy,numLevelsLeft-1);
|
||||
osgDB::writeNodeFile(*node, lbasename+extension);
|
||||
}
|
||||
|
||||
// create PagedLOD for tile.
|
||||
osg::PagedLOD* pagedlod = new osg::PagedLOD;
|
||||
osg::Node* tile = createTile(filename,lx,ly,dx,dy);
|
||||
pagedlod->addChild(tile, cut_off_distance,max_visible_distance);
|
||||
pagedlod->setRange(1,0.0f,cut_off_distance);
|
||||
pagedlod->setFileName(1,lbasename+extension);
|
||||
pagedlod->setCenter(tile->getBound().center());
|
||||
|
||||
group->addChild(pagedlod);
|
||||
|
||||
// increment number of tiles.
|
||||
++numTiles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
double lx = x;
|
||||
for(unsigned i=0;i<noTilesX;++i,lx+=dx)
|
||||
{
|
||||
double ly = y;
|
||||
for(unsigned j=0;j<noTilesY;++j,ly+=dy)
|
||||
{
|
||||
group->addChild(createTile(filename,lx,ly,dx,dy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return group;
|
||||
|
||||
}
|
||||
|
||||
bool createWorld(const std::string& inputFile, const std::string& baseName, unsigned int numLevels)
|
||||
{
|
||||
|
||||
osgDB::ReaderWriter* readerWriter = osgDB::Registry::instance()->getReaderWriterForExtension("gdal");
|
||||
if (!readerWriter)
|
||||
{
|
||||
std::cout<<"Error: GDAL plugin not available, cannot preceed with database creation"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
osg::Timer timer;
|
||||
osg::Timer_t start_tick = timer.tick();
|
||||
|
||||
// create the world
|
||||
|
||||
|
||||
std::string path = osgDB::getFilePath(baseName);
|
||||
std::string base = path.empty()?osgDB::getStrippedName(baseName):
|
||||
path +'/'+ osgDB::getStrippedName(baseName);
|
||||
std::string extension = '.'+osgDB::getLowerCaseFileExtension(baseName);
|
||||
|
||||
std::cout << "baseName = "<<baseName<<std::endl;
|
||||
std::cout << "base = "<<base<<std::endl;
|
||||
std::cout << "extension = "<<extension<<std::endl;
|
||||
|
||||
|
||||
|
||||
|
||||
bool doBumpMapping = true;
|
||||
|
||||
int bumpMapSize = 512;
|
||||
|
||||
if (doBumpMapping)
|
||||
{
|
||||
|
||||
osg::ref_ptr<osg::Node> scene;
|
||||
|
||||
// = createTileAndRecurse(inputFile, base, /*extension*/".ive", 2,2, 0.0, 0.0, 1.0, 1.0, numLevels);
|
||||
|
||||
// generate normal map
|
||||
osg::Image* normalMap = 0;
|
||||
{
|
||||
osg::ref_ptr<osgDB::ImageOptions> options = new osgDB::ImageOptions;
|
||||
options->_sourceImageWindowMode = osgDB::ImageOptions::RATIO_WINDOW;
|
||||
options->_sourceRatioWindow.set(0,0,1,1);
|
||||
|
||||
options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW;
|
||||
options->_destinationPixelWindow.set(0,0,512,512);
|
||||
|
||||
osgDB::Registry::instance()->setOptions(options.get());
|
||||
osg::Image* image = osgDB::readImageFile(inputFile.c_str());
|
||||
if (image)
|
||||
{
|
||||
osg::HeightField* grid = createHeightField(image,osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(1.0,1.0,VERTICAL_SIZE));
|
||||
normalMap = createNormalMap(grid);
|
||||
normalMap->setFileName("normalmap.rgb");
|
||||
osgDB::writeImageFile(*normalMap,"normalmap.rgb");
|
||||
|
||||
|
||||
scene = createQuadTree(grid,
|
||||
0, grid->getNumColumns()-1,
|
||||
0, grid->getNumRows()-1,
|
||||
0.0f, 1.0f,
|
||||
0.0f, 1.0f,
|
||||
2000);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// generate diffuse map
|
||||
osg::Image* diffuseMap = 0;
|
||||
// {
|
||||
// osg::ref_ptr<osgDB::ImageOptions> options = new osgDB::ImageOptions;
|
||||
// options->_sourceImageWindowMode = osgDB::ImageOptions::RATIO_WINDOW;
|
||||
// options->_sourceRatioWindow.set(0,0,1,1);
|
||||
//
|
||||
// options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW;
|
||||
// options->_destinationPixelWindow.set(0,0,2048,2048);
|
||||
//
|
||||
// osgDB::Registry::instance()->setOptions(options.get());
|
||||
// diffuseMap = osgDB::readImageFile(inputFile.c_str());
|
||||
// if (diffuseMap)
|
||||
// {
|
||||
// diffuseMap->setFileName("diffuse.rgb");
|
||||
// osgDB::writeImageFile(*diffuseMap,"diffuse.rgb");
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
diffuseMap = osgDB::readImageFile("LlanoTex.jpg");
|
||||
|
||||
|
||||
osg::Texture2D* diffuseMapTexture = new osg::Texture2D(diffuseMap);
|
||||
osg::Texture2D* normalMapTexture = new osg::Texture2D(normalMap);
|
||||
|
||||
// create osgFX::BumpingMapping
|
||||
osg::ref_ptr<osgFX::BumpMapping> bumpMap = new osgFX::BumpMapping;
|
||||
bumpMap->setLightNumber(0);
|
||||
bumpMap->setNormalMapTextureUnit(0);
|
||||
bumpMap->setDiffuseTextureUnit(1);
|
||||
bumpMap->setOverrideDiffuseTexture(diffuseMapTexture);
|
||||
bumpMap->setOverrideNormalMapTexture(normalMapTexture);
|
||||
|
||||
bumpMap->addChild(scene.get());
|
||||
|
||||
#ifdef USE_PREPARE
|
||||
bumpMap->prepareChildren();
|
||||
#endif
|
||||
|
||||
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||
|
||||
|
||||
group->addChild(bumpMap.get());
|
||||
|
||||
osg::StateSet* stateset = group->getOrCreateStateSet();
|
||||
stateset->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
|
||||
|
||||
osgDB::writeNodeFile(*group, baseName);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||
group->addChild(createTileAndRecurse(inputFile, base, extension, 2,2, 0.0, 0.0, 1.0, 1.0, numLevels));
|
||||
|
||||
osg::StateSet* stateset = group->getOrCreateStateSet();
|
||||
stateset->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
|
||||
|
||||
osgDB::writeNodeFile(*group, baseName);
|
||||
|
||||
}
|
||||
|
||||
osg::Timer_t end_tick = timer.tick();
|
||||
std::cout << "Time to create world "<<timer.delta_s(start_tick,end_tick)<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
osg::ArgumentParser arguments(&argc,argv);
|
||||
|
||||
// set up the usage document, in case we need to print out how to use this program.
|
||||
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
|
||||
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models.");
|
||||
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-i <filename>","Specify the input file to process");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-o <outputfile>","Specify the output master file to generate");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-l <numOfLevels>","Specify the number of PagedLOD levels to generate");
|
||||
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
|
||||
|
||||
std::string inputFile;
|
||||
while (arguments.read("-i",inputFile)) {}
|
||||
|
||||
std::string basename("output.ive");
|
||||
while (arguments.read("-o",basename)) {}
|
||||
|
||||
float numLevels;
|
||||
while (arguments.read("-l",numLevels)) {}
|
||||
|
||||
while (arguments.read("-v",VERTICAL_SIZE)) {}
|
||||
|
||||
// if user request help write it out to cout.
|
||||
if (arguments.read("-h") || arguments.read("--help"))
|
||||
{
|
||||
arguments.getApplicationUsage()->write(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// any option left unread are converted into errors to write out later.
|
||||
arguments.reportRemainingOptionsAsUnrecognized();
|
||||
|
||||
// report any errors if they have occured when parsing the program aguments.
|
||||
if (arguments.errors())
|
||||
{
|
||||
arguments.writeErrorMessages(std::cout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// if (arguments.argc()<=1)
|
||||
// {
|
||||
// arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// create a graphics context to allow us to use OpenGL to compress textures.
|
||||
GraphicsContext gfx;
|
||||
|
||||
createWorld(inputFile,basename,(unsigned int)numLevels);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ osg::Geode* ForestTechniqueManager::createTerrain(const osg::Vec3& origin, const
|
||||
if (createGrid)
|
||||
{
|
||||
|
||||
osg::Grid* grid = new osg::Grid;
|
||||
osg::HeightField* grid = new osg::HeightField;
|
||||
grid->allocateGrid(numColumns,numRows);
|
||||
grid->setOrigin(origin);
|
||||
grid->setXInterval(size.x()/(float)(numColumns-1));
|
||||
|
@ -68,7 +68,7 @@ osg::Node* createBase(const osg::Vec3& center,float radius)
|
||||
geode->setStateSet( stateset );
|
||||
|
||||
|
||||
osg::Grid* grid = new osg::Grid;
|
||||
osg::HeightField* grid = new osg::HeightField;
|
||||
grid->allocateGrid(38,39);
|
||||
grid->setOrigin(center+osg::Vec3(-radius,-radius,0.0f));
|
||||
grid->setXInterval(radius*2.0f/(float)(38-1));
|
||||
|
@ -42,7 +42,7 @@ osg::Geode* createShapes()
|
||||
geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(4.0f,0.0f,0.0f),radius,height),hints));
|
||||
geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(6.0f,0.0f,0.0f),radius,height),hints));
|
||||
|
||||
osg::Grid* grid = new osg::Grid;
|
||||
osg::HeightField* grid = new osg::HeightField;
|
||||
grid->allocateGrid(38,39);
|
||||
grid->setXInterval(0.28f);
|
||||
grid->setYInterval(0.28f);
|
||||
|
@ -418,21 +418,25 @@ class SG_EXPORT HeightField : public Shape
|
||||
{
|
||||
public:
|
||||
|
||||
HeightField() {}
|
||||
|
||||
HeightField(const HeightField& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
|
||||
Shape(mesh,copyop),
|
||||
HeightField():
|
||||
_columns(0),
|
||||
_rows(0),
|
||||
_origin(0.0f,0.0f,0.0f),
|
||||
_dx(1.0f),
|
||||
_dy(1.0f) {}
|
||||
|
||||
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const HeightField*>(obj)!=NULL; }
|
||||
virtual const char* libraryName() const { return "osg"; }
|
||||
virtual const char* className() const { return "HeightField"; }
|
||||
virtual void accept(osg::ShapeVisitor& sv) { sv.apply(*this); }
|
||||
virtual void accept(osg::ConstShapeVisitor& csv) const { csv.apply(*this); }
|
||||
HeightField(const HeightField& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
|
||||
Shape(mesh,copyop),
|
||||
_columns(mesh._columns),
|
||||
_rows(mesh._rows),
|
||||
_origin(mesh._origin),
|
||||
_dx(mesh._dx),
|
||||
_dy(mesh._dy),
|
||||
_heights(mesh._heights) {}
|
||||
|
||||
META_Shape(osg, HeightField)
|
||||
|
||||
void allocateGrid(unsigned int numColumns,unsigned int numRows);
|
||||
|
||||
inline unsigned int getNumColumns() const { return _columns; }
|
||||
inline unsigned int getNumRows() const { return _rows; }
|
||||
@ -446,9 +450,23 @@ class SG_EXPORT HeightField : public Shape
|
||||
inline void setYInterval(float dy) { _dy = dy; }
|
||||
inline float getYInterval() const { return _dy; }
|
||||
|
||||
virtual float getHeight(unsigned int c,unsigned int r) const = 0;
|
||||
|
||||
virtual Vec3 getNormal(unsigned int c,unsigned int r) const;
|
||||
inline void setHeight(unsigned int c,unsigned int r,float value)
|
||||
{
|
||||
_heights[c+r*_columns] = value;
|
||||
}
|
||||
|
||||
inline float& getHeight(unsigned int c,unsigned int r)
|
||||
{
|
||||
return _heights[c+r*_columns];
|
||||
}
|
||||
|
||||
inline float getHeight(unsigned int c,unsigned int r) const
|
||||
{
|
||||
return _heights[c+r*_columns];
|
||||
}
|
||||
|
||||
Vec3 getNormal(unsigned int c,unsigned int r) const;
|
||||
|
||||
inline void setRotation(const Quat& quat) { _rotation = quat; }
|
||||
inline const Quat& getRotation() const { return _rotation; }
|
||||
@ -467,39 +485,11 @@ class SG_EXPORT HeightField : public Shape
|
||||
|
||||
Quat _rotation;
|
||||
|
||||
};
|
||||
|
||||
class SG_EXPORT Grid : public HeightField
|
||||
{
|
||||
public:
|
||||
|
||||
Grid();
|
||||
|
||||
Grid(const Grid& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Shape(osg,Grid);
|
||||
|
||||
void allocateGrid(unsigned int numColumns,unsigned int numRows);
|
||||
|
||||
void setHeight(unsigned int c,unsigned int r,float value)
|
||||
{
|
||||
_heights[c+r*_columns] = value;
|
||||
}
|
||||
|
||||
virtual float getHeight(unsigned int c,unsigned int r) const
|
||||
{
|
||||
return _heights[c+r*_columns];
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
~Grid();
|
||||
|
||||
typedef std::vector<float> HeightList;
|
||||
HeightList _heights;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CompositeShape : public Shape
|
||||
{
|
||||
public:
|
||||
|
@ -86,14 +86,33 @@ class OSGDB_EXPORT ImageOptions : public osgDB::ReaderWriter::Options
|
||||
CUBIC
|
||||
};
|
||||
|
||||
/** Used as UserData attached to generated osg::Image's*/
|
||||
struct TexCoordRange : public osg::Referenced
|
||||
{
|
||||
TexCoordRange():
|
||||
_x(0.0),
|
||||
_y(0.0),
|
||||
_w(1.0),
|
||||
_h(1.0) {}
|
||||
|
||||
void set(double x,double y, double w, double h)
|
||||
{
|
||||
_x = x;
|
||||
_y = y;
|
||||
_w = w;
|
||||
_h = h;
|
||||
}
|
||||
|
||||
double _x,_y,_w,_h;
|
||||
};
|
||||
|
||||
|
||||
// source
|
||||
ImageSamplingMode _sourceImageSamplingMode;
|
||||
ImageWindowMode _sourceImageWindowMode;
|
||||
RatioWindow _sourceRatioWindow;
|
||||
PixelWindow _sourcePixelWindow;
|
||||
|
||||
|
||||
|
||||
// destination
|
||||
osg::ref_ptr<osg::Image> _destinationImage;
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
namespace osgGA{
|
||||
|
||||
//
|
||||
// The AnimationPathManipulator is a Camera Manipulator that reads an
|
||||
// The AnimationPathManipulator is a Matrix Manipulator that reads an
|
||||
// animation path from a file and plays it back. The file is expected
|
||||
// to be ascii and a succession of lines with 8 floating point values
|
||||
// per line. The succession of values are:
|
||||
|
@ -15,6 +15,16 @@
|
||||
|
||||
using namespace osg;
|
||||
|
||||
void HeightField::allocateGrid(unsigned int numColumns,unsigned int numRows)
|
||||
{
|
||||
if (_columns!=numColumns || _rows!=numRows)
|
||||
{
|
||||
_heights.resize(numColumns*numRows);
|
||||
}
|
||||
_columns=numColumns;
|
||||
_rows=numRows;
|
||||
}
|
||||
|
||||
Vec3 HeightField::getNormal(unsigned int c,unsigned int r) const
|
||||
{
|
||||
// four point normal generation.
|
||||
@ -53,27 +63,4 @@ Vec3 HeightField::getNormal(unsigned int c,unsigned int r) const
|
||||
return normal;
|
||||
}
|
||||
|
||||
Grid::Grid()
|
||||
{
|
||||
}
|
||||
|
||||
Grid::Grid(const Grid& mesh,const CopyOp& copyop):
|
||||
HeightField(mesh,copyop)
|
||||
{
|
||||
_heights = mesh._heights;
|
||||
}
|
||||
|
||||
Grid::~Grid()
|
||||
{
|
||||
}
|
||||
|
||||
void Grid::allocateGrid(unsigned int numColumns,unsigned int numRows)
|
||||
{
|
||||
if (_columns!=numColumns || _rows!=numRows)
|
||||
{
|
||||
_heights.resize(numColumns*numRows);
|
||||
}
|
||||
_columns=numColumns;
|
||||
_rows=numRows;
|
||||
}
|
||||
|
||||
|
@ -42,18 +42,35 @@ class ReaderWriterGDAL : public osgDB::ReaderWriter
|
||||
int destHeight = osg::minimum(dataHeight,1024);
|
||||
|
||||
|
||||
osgDB::ImageOptions::TexCoordRange* texCoordRange = 0;
|
||||
|
||||
const osgDB::ImageOptions* imageOptions = dynamic_cast<const osgDB::ImageOptions*>(options);
|
||||
if (imageOptions)
|
||||
{
|
||||
std::cout<<"Got ImageOptions"<<std::endl;
|
||||
|
||||
int margin = 0;
|
||||
switch(imageOptions->_sourceImageWindowMode)
|
||||
{
|
||||
case(osgDB::ImageOptions::RATIO_WINDOW):
|
||||
windowX = osg::maximum((int)(floor((double)dataWidth * imageOptions->_sourceRatioWindow.windowX)),0);
|
||||
windowY = osg::maximum((int)(floor((double)dataHeight * imageOptions->_sourceRatioWindow.windowY)),0);
|
||||
windowWidth = osg::minimum((int)(ceil((double)dataWidth * (imageOptions->_sourceRatioWindow.windowX + imageOptions->_sourceRatioWindow.windowWidth))),dataWidth)-windowX;
|
||||
windowHeight = osg::minimum((int)(ceil((double)dataHeight * (imageOptions->_sourceRatioWindow.windowY + imageOptions->_sourceRatioWindow.windowHeight))),dataHeight)-windowY;
|
||||
{
|
||||
double desiredX = (double)dataWidth * imageOptions->_sourceRatioWindow.windowX;
|
||||
double desiredY = (double)dataHeight * imageOptions->_sourceRatioWindow.windowY;
|
||||
double desiredWidth = (double)dataWidth * imageOptions->_sourceRatioWindow.windowWidth;
|
||||
double desiredHeight = (double)dataHeight * imageOptions->_sourceRatioWindow.windowHeight;
|
||||
|
||||
windowX = osg::maximum((int)(floor(desiredX))-margin,0);
|
||||
windowY = osg::maximum((int)(floor(desiredY))-margin,0);
|
||||
windowWidth = osg::minimum((int)(ceil(desiredX + desiredWidth))+margin,dataWidth)-windowX;
|
||||
windowHeight = osg::minimum((int)(ceil(desiredY + desiredHeight))+margin,dataHeight)-windowY;
|
||||
|
||||
texCoordRange = new osgDB::ImageOptions::TexCoordRange;
|
||||
texCoordRange->set((desiredX-(double)windowX)/(double)windowWidth,
|
||||
((double)(windowY+windowHeight) -(desiredY+desiredHeight))/(double)windowHeight,
|
||||
(desiredWidth)/(double)windowWidth,
|
||||
(desiredHeight)/(double)windowHeight);
|
||||
std::cout<<"tex coord range "<<texCoordRange->_x<<" "<<texCoordRange->_y<<" "<<texCoordRange->_w<<" "<<texCoordRange->_h<<std::endl;
|
||||
}
|
||||
break;
|
||||
case(osgDB::ImageOptions::PIXEL_WINDOW):
|
||||
windowX = imageOptions->_sourcePixelWindow.windowX;
|
||||
@ -145,6 +162,7 @@ class ReaderWriterGDAL : public osgDB::ReaderWriter
|
||||
else if (band->GetColorInterpretation()==GCI_GreenBand) bandGreen = band;
|
||||
else if (band->GetColorInterpretation()==GCI_BlueBand) bandBlue = band;
|
||||
else if (band->GetColorInterpretation()==GCI_AlphaBand) bandAlpha = band;
|
||||
else bandGray = band;
|
||||
|
||||
// int gotMin,gotMax;
|
||||
// double minmax[2];
|
||||
@ -282,6 +300,8 @@ class ReaderWriterGDAL : public osgDB::ReaderWriter
|
||||
(unsigned char *)imageData,
|
||||
osg::Image::USE_NEW_DELETE);
|
||||
|
||||
if (texCoordRange) image->setUserData(texCoordRange);
|
||||
|
||||
image->flipVertical();
|
||||
|
||||
return image;
|
||||
|
@ -73,6 +73,21 @@ bool Drawable_readLocalData(Object& obj, Input& fr)
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("useVertexBufferObjects"))
|
||||
{
|
||||
if (fr[1].matchWord("TRUE"))
|
||||
{
|
||||
drawable.setUseVertexBufferObjects(true);
|
||||
fr+=2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
else if (fr[1].matchWord("FALSE"))
|
||||
{
|
||||
drawable.setUseVertexBufferObjects(false);
|
||||
fr+=2;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
@ -103,6 +118,9 @@ bool Drawable_writeLocalData(const Object& obj, Output& fw)
|
||||
if (drawable.getUseDisplayList()) fw << "TRUE" << std::endl;
|
||||
else fw << "FALSE" << std::endl;
|
||||
|
||||
fw.indent()<<"useVertexBufferObjects ";
|
||||
if (drawable.getUseVertexBufferObjects()) fw << "TRUE" << std::endl;
|
||||
else fw << "FALSE" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -305,14 +305,25 @@ bool HeightField_writeLocalData(const Object& obj, Output& fw);
|
||||
//register the read and write functions with the osgDB::Registry.
|
||||
RegisterDotOsgWrapperProxy g_HeightFieldFuncProxy
|
||||
(
|
||||
0,
|
||||
new osg::HeightField,
|
||||
"HeightField",
|
||||
"Object HieghtField",
|
||||
"Object HeightField",
|
||||
&HeightField_readLocalData,
|
||||
&HeightField_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
//register the read and write functions with the osgDB::Registry.
|
||||
RegisterDotOsgWrapperProxy g_GridFuncProxy
|
||||
(
|
||||
new osg::HeightField,
|
||||
"Grid",
|
||||
"Object HeightField",
|
||||
0,
|
||||
0,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
bool HeightField_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
@ -359,49 +370,12 @@ bool HeightField_readLocalData(Object& obj, Input& fr)
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool HeightField_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
const HeightField& heightfield = static_cast<const HeightField&>(obj);
|
||||
|
||||
fw.indent()<<"Origin "<<heightfield.getOrigin()<<std::endl;
|
||||
fw.indent()<<"XInterval "<<heightfield.getXInterval()<<std::endl;
|
||||
fw.indent()<<"YInterval "<<heightfield.getYInterval()<<std::endl;
|
||||
fw.indent()<<"Rotation "<<heightfield.getRotation()<<std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// forward declare functions to use later.
|
||||
bool Grid_readLocalData(Object& obj, Input& fr);
|
||||
bool Grid_writeLocalData(const Object& obj, Output& fw);
|
||||
|
||||
//register the read and write functions with the osgDB::Registry.
|
||||
RegisterDotOsgWrapperProxy g_GridFuncProxy
|
||||
(
|
||||
new osg::Grid,
|
||||
"Grid",
|
||||
"Object HeightField Grid",
|
||||
&Grid_readLocalData,
|
||||
&Grid_writeLocalData,
|
||||
DotOsgWrapper::READ_AND_WRITE
|
||||
);
|
||||
|
||||
bool Grid_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
bool iteratorAdvanced = false;
|
||||
|
||||
Grid& grid = static_cast<Grid&>(obj);
|
||||
|
||||
if (fr.matchSequence("NumColumnsAndRows %i %i"))
|
||||
{
|
||||
int numcolumns,numrows;
|
||||
fr[1].getInt(numcolumns);
|
||||
fr[2].getInt(numrows);
|
||||
grid.allocateGrid(numcolumns,numrows);
|
||||
heightfield.allocateGrid(numcolumns,numrows);
|
||||
fr+=3;
|
||||
iteratorAdvanced = true;
|
||||
}
|
||||
@ -421,9 +395,9 @@ bool Grid_readLocalData(Object& obj, Input& fr)
|
||||
{
|
||||
if (fr.readSequence(height))
|
||||
{
|
||||
grid.setHeight(column,row,height);
|
||||
heightfield.setHeight(column,row,height);
|
||||
++column;
|
||||
if (column>=grid.getNumColumns())
|
||||
if (column>=heightfield.getNumColumns())
|
||||
{
|
||||
column = 0;
|
||||
++row;
|
||||
@ -440,25 +414,29 @@ bool Grid_readLocalData(Object& obj, Input& fr)
|
||||
|
||||
}
|
||||
|
||||
|
||||
return iteratorAdvanced;
|
||||
}
|
||||
|
||||
bool Grid_writeLocalData(const Object& obj, Output& fw)
|
||||
bool HeightField_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
const Grid& grid = static_cast<const Grid&>(obj);
|
||||
const HeightField& heightfield = static_cast<const HeightField&>(obj);
|
||||
|
||||
fw.indent()<<"NumColumnsAndRows "<<grid.getNumColumns()<<" "<<grid.getNumRows()<<std::endl;
|
||||
fw.indent()<<"Origin "<<heightfield.getOrigin()<<std::endl;
|
||||
fw.indent()<<"XInterval "<<heightfield.getXInterval()<<std::endl;
|
||||
fw.indent()<<"YInterval "<<heightfield.getYInterval()<<std::endl;
|
||||
fw.indent()<<"Rotation "<<heightfield.getRotation()<<std::endl;
|
||||
|
||||
fw.indent()<<"NumColumnsAndRows "<<heightfield.getNumColumns()<<" "<<heightfield.getNumRows()<<std::endl;
|
||||
|
||||
fw.indent()<<"Heights"<<std::endl;
|
||||
|
||||
ParameterOutput po(fw);
|
||||
po.begin();
|
||||
for(unsigned int row=0;row<grid.getNumRows();++row)
|
||||
for(unsigned int row=0;row<heightfield.getNumRows();++row)
|
||||
{
|
||||
for(unsigned int column=0;column<grid.getNumColumns();++column)
|
||||
for(unsigned int column=0;column<heightfield.getNumColumns();++column)
|
||||
{
|
||||
po.write(grid.getHeight(column,row));
|
||||
po.write(heightfield.getHeight(column,row));
|
||||
}
|
||||
po.newLine();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user