Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
506b9130a8 | ||
|
|
5d1b70a7f2 | ||
|
|
eff3df57d9 | ||
|
|
2931f3380f |
+21
-15
@@ -6,6 +6,9 @@ include (CheckCXXCompilerFlag)
|
|||||||
|
|
||||||
project(SimGear)
|
project(SimGear)
|
||||||
|
|
||||||
|
# using 10.7 because boost requires libc++ and 10.6 doesn't include it
|
||||||
|
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
|
||||||
|
|
||||||
# read 'version' file into a variable (stripping any newlines or spaces)
|
# read 'version' file into a variable (stripping any newlines or spaces)
|
||||||
file(READ version versionFile)
|
file(READ version versionFile)
|
||||||
string(STRIP ${versionFile} SIMGEAR_VERSION)
|
string(STRIP ${versionFile} SIMGEAR_VERSION)
|
||||||
@@ -34,7 +37,7 @@ SET(CPACK_INSTALL_CMAKE_PROJECTS ${CMAKE_CURRENT_BINARY_DIR};SimGear;ALL;/)
|
|||||||
|
|
||||||
# split version string into components, note CMAKE_MATCH_0 is the entire regexp match
|
# split version string into components, note CMAKE_MATCH_0 is the entire regexp match
|
||||||
string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" CPACK_PACKAGE_VERSION ${SIMGEAR_VERSION} )
|
string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" CPACK_PACKAGE_VERSION ${SIMGEAR_VERSION} )
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
|
set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
|
set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
|
set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
|
||||||
|
|
||||||
@@ -175,12 +178,12 @@ if(SIMGEAR_HEADLESS)
|
|||||||
else()
|
else()
|
||||||
message(STATUS "SimGear mode: NORMAL")
|
message(STATUS "SimGear mode: NORMAL")
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
|
|
||||||
if (ENABLE_SOUND)
|
if (ENABLE_SOUND)
|
||||||
find_package(OpenAL REQUIRED)
|
find_package(OpenAL REQUIRED)
|
||||||
message(STATUS "Sound support: ENABLED")
|
message(STATUS "Sound support: ENABLED")
|
||||||
endif(ENABLE_SOUND)
|
endif(ENABLE_SOUND)
|
||||||
|
|
||||||
find_package(OpenSceneGraph 3.2.0 REQUIRED osgText osgSim osgDB osgParticle osgGA osgViewer osgUtil)
|
find_package(OpenSceneGraph 3.2.0 REQUIRED osgText osgSim osgDB osgParticle osgGA osgViewer osgUtil)
|
||||||
endif(SIMGEAR_HEADLESS)
|
endif(SIMGEAR_HEADLESS)
|
||||||
|
|
||||||
@@ -197,8 +200,8 @@ else()
|
|||||||
# XML_STATIC is important to avoid sg_expat_external.h
|
# XML_STATIC is important to avoid sg_expat_external.h
|
||||||
# declaring symbols as declspec(import)
|
# declaring symbols as declspec(import)
|
||||||
add_definitions(-DHAVE_EXPAT_CONFIG_H -DXML_STATIC)
|
add_definitions(-DHAVE_EXPAT_CONFIG_H -DXML_STATIC)
|
||||||
set(EXPAT_INCLUDE_DIRS
|
set(EXPAT_INCLUDE_DIRS
|
||||||
${PROJECT_SOURCE_DIR}/3rdparty/expat
|
${PROJECT_SOURCE_DIR}/3rdparty/expat
|
||||||
${PROJECT_BINARY_DIR}/3rdparty/expat)
|
${PROJECT_BINARY_DIR}/3rdparty/expat)
|
||||||
endif(SYSTEM_EXPAT)
|
endif(SYSTEM_EXPAT)
|
||||||
|
|
||||||
@@ -275,12 +278,12 @@ SET(CMAKE_MINSIZEREL_POSTFIX "" CACHE STRING "add a postfix, usually empty on wi
|
|||||||
|
|
||||||
# isnan might not be real symbol, so can't check using function_exists
|
# isnan might not be real symbol, so can't check using function_exists
|
||||||
check_cxx_source_compiles(
|
check_cxx_source_compiles(
|
||||||
"#include <cmath>
|
"#include <cmath>
|
||||||
int main() { return isnan(0.0);} "
|
int main() { return isnan(0.0);} "
|
||||||
HAVE_ISNAN)
|
HAVE_ISNAN)
|
||||||
|
|
||||||
check_cxx_source_compiles(
|
check_cxx_source_compiles(
|
||||||
"#include <cmath>
|
"#include <cmath>
|
||||||
int main() { return std::isnan(0.0);} "
|
int main() { return std::isnan(0.0);} "
|
||||||
HAVE_STD_ISNAN)
|
HAVE_STD_ISNAN)
|
||||||
|
|
||||||
@@ -299,6 +302,9 @@ endif(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set(WARNING_FLAGS_CXX "-Wall -Wno-overloaded-virtual")
|
set(WARNING_FLAGS_CXX "-Wall -Wno-overloaded-virtual")
|
||||||
set(WARNING_FLAGS_C "-Wall")
|
set(WARNING_FLAGS_C "-Wall")
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
@@ -320,16 +326,16 @@ if(WIN32)
|
|||||||
# foreach(warning 4244 4251 4267 4275 4290 4786 4305 4996)
|
# foreach(warning 4244 4251 4267 4275 4290 4786 4305 4996)
|
||||||
# SET(WARNING_FLAGS "${WARNING_FLAGS} /wd${warning}")
|
# SET(WARNING_FLAGS "${WARNING_FLAGS} /wd${warning}")
|
||||||
# endforeach(warning)
|
# endforeach(warning)
|
||||||
|
|
||||||
set(MSVC_FLAGS "-DWIN32 -DNOMINMAX -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D__CRT_NONSTDC_NO_WARNINGS /wd4996 /wd4250 -Dstrdup=_strdup")
|
set(MSVC_FLAGS "-DWIN32 -DNOMINMAX -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D__CRT_NONSTDC_NO_WARNINGS /wd4996 /wd4250 -Dstrdup=_strdup")
|
||||||
if (${MSVC_VERSION} GREATER 1599)
|
if (${MSVC_VERSION} GREATER 1599)
|
||||||
set( MSVC_LD_FLAGS "/FORCE:MULTIPLE" )
|
set( MSVC_LD_FLAGS "/FORCE:MULTIPLE" )
|
||||||
endif (${MSVC_VERSION} GREATER 1599)
|
endif (${MSVC_VERSION} GREATER 1599)
|
||||||
endif(MSVC)
|
endif(MSVC)
|
||||||
|
|
||||||
# assumed on Windows
|
# assumed on Windows
|
||||||
set(HAVE_GETLOCALTIME 1)
|
set(HAVE_GETLOCALTIME 1)
|
||||||
|
|
||||||
set( WINSOCK_LIBRARY "ws2_32.lib" )
|
set( WINSOCK_LIBRARY "ws2_32.lib" )
|
||||||
set( RT_LIBRARY "winmm" )
|
set( RT_LIBRARY "winmm" )
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
@@ -338,15 +344,15 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS_C} ${MSVC_FLAGS}")
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS_CXX} ${MSVC_FLAGS} ${BOOST_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS_CXX} ${MSVC_FLAGS} ${BOOST_CXX_FLAGS}")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}")
|
||||||
|
|
||||||
# use BEFORE to ensure local directories are used first,
|
# use BEFORE to ensure local directories are used first,
|
||||||
# ahead of system-installed libs
|
# ahead of system-installed libs
|
||||||
include_directories(BEFORE ${PROJECT_SOURCE_DIR})
|
include_directories(BEFORE ${PROJECT_SOURCE_DIR})
|
||||||
include_directories(BEFORE ${PROJECT_SOURCE_DIR}/simgear/canvas/ShivaVG/include)
|
include_directories(BEFORE ${PROJECT_SOURCE_DIR}/simgear/canvas/ShivaVG/include)
|
||||||
include_directories(BEFORE ${PROJECT_BINARY_DIR}/simgear)
|
include_directories(BEFORE ${PROJECT_BINARY_DIR}/simgear)
|
||||||
|
|
||||||
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}
|
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}
|
||||||
${Boost_INCLUDE_DIRS}
|
${Boost_INCLUDE_DIRS}
|
||||||
${ZLIB_INCLUDE_DIR}
|
${ZLIB_INCLUDE_DIR}
|
||||||
${OPENAL_INCLUDE_DIR}
|
${OPENAL_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -399,5 +405,5 @@ CONFIGURE_FILE(
|
|||||||
IMMEDIATE @ONLY)
|
IMMEDIATE @ONLY)
|
||||||
ADD_CUSTOM_TARGET(uninstall
|
ADD_CUSTOM_TARGET(uninstall
|
||||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,12 @@ SGPath appleSpecialFolder(int dirType, int domainMask, const SGPath& def)
|
|||||||
{
|
{
|
||||||
CocoaAutoreleasePool ap;
|
CocoaAutoreleasePool ap;
|
||||||
NSFileManager* fm = [NSFileManager defaultManager];
|
NSFileManager* fm = [NSFileManager defaultManager];
|
||||||
NSURL* pathUrl = [fm URLForDirectory:dirType
|
NSSearchPathDirectory d = static_cast<NSSearchPathDirectory>(dirType);
|
||||||
inDomain:domainMask
|
NSURL* pathUrl = [fm URLForDirectory:d
|
||||||
appropriateForURL:Nil
|
inDomain:domainMask
|
||||||
create:YES
|
appropriateForURL:Nil
|
||||||
error:nil];
|
create:YES
|
||||||
|
error:nil];
|
||||||
if (!pathUrl) {
|
if (!pathUrl) {
|
||||||
return def;;
|
return def;;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <boost/iterator/iterator_adaptor.hpp>
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
|
|
||||||
#include "Effect.hxx"
|
#include "Effect.hxx"
|
||||||
|
#include "mat.hxx"
|
||||||
|
|
||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
@@ -69,6 +70,8 @@ class EffectGeode : public osg::Geode
|
|||||||
META_Node(simgear,EffectGeode);
|
META_Node(simgear,EffectGeode);
|
||||||
Effect* getEffect() const { return _effect.get(); }
|
Effect* getEffect() const { return _effect.get(); }
|
||||||
void setEffect(Effect* effect);
|
void setEffect(Effect* effect);
|
||||||
|
SGMaterial* getMaterial() const { return _material; }
|
||||||
|
void setMaterial(SGMaterial* mat) { _material = mat; }
|
||||||
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
||||||
virtual void releaseGLObjects(osg::State* = 0) const;
|
virtual void releaseGLObjects(osg::State* = 0) const;
|
||||||
|
|
||||||
@@ -83,6 +86,7 @@ class EffectGeode : public osg::Geode
|
|||||||
void runGenerators(osg::Geometry *geometry);
|
void runGenerators(osg::Geometry *geometry);
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<Effect> _effect;
|
osg::ref_ptr<Effect> _effect;
|
||||||
|
SGMaterial* _material;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ Effect* SGMaterial::get_effect(int i)
|
|||||||
return _status[i].effect.get();
|
return _status[i].effect.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect* SGMaterial::get_effect(const SGTexturedTriangleBin& triangleBin)
|
Effect* SGMaterial::get_one_effect(int texIndex)
|
||||||
{
|
{
|
||||||
SGGuard<SGMutex> g(_lock);
|
SGGuard<SGMutex> g(_lock);
|
||||||
if (_status.empty()) {
|
if (_status.empty()) {
|
||||||
@@ -449,7 +449,7 @@ Effect* SGMaterial::get_effect(const SGTexturedTriangleBin& triangleBin)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = triangleBin.getTextureIndex() % _status.size();
|
int i = texIndex % _status.size();
|
||||||
return get_effect(i);
|
return get_effect(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,7 +460,7 @@ Effect* SGMaterial::get_effect()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
osg::Texture2D* SGMaterial::get_object_mask(const SGTexturedTriangleBin& triangleBin)
|
osg::Texture2D* SGMaterial::get_one_object_mask(int texIndex)
|
||||||
{
|
{
|
||||||
if (_status.empty()) {
|
if (_status.empty()) {
|
||||||
SG_LOG( SG_GENERAL, SG_WARN, "No mask available.");
|
SG_LOG( SG_GENERAL, SG_WARN, "No mask available.");
|
||||||
@@ -469,7 +469,7 @@ osg::Texture2D* SGMaterial::get_object_mask(const SGTexturedTriangleBin& triangl
|
|||||||
|
|
||||||
// Note that the object mask is closely linked to the texture/effect
|
// Note that the object mask is closely linked to the texture/effect
|
||||||
// so we index based on the texture index,
|
// so we index based on the texture index,
|
||||||
unsigned int i = triangleBin.getTextureIndex() % _status.size();
|
unsigned int i = texIndex % _status.size();
|
||||||
if (i < _masks.size()) {
|
if (i < _masks.size()) {
|
||||||
return _masks[i].get();
|
return _masks[i].get();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -119,13 +119,13 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get the textured state.
|
* Get the textured state.
|
||||||
*/
|
*/
|
||||||
simgear::Effect* get_effect(const SGTexturedTriangleBin& triangleBin);
|
simgear::Effect* get_one_effect(int texIndex);
|
||||||
simgear::Effect* get_effect();
|
simgear::Effect* get_effect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the textured state.
|
* Get the textured state.
|
||||||
*/
|
*/
|
||||||
osg::Texture2D* get_object_mask(const SGTexturedTriangleBin& triangleBin);
|
osg::Texture2D* get_one_object_mask(int texIndex);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,9 +8,12 @@ set(HEADERS
|
|||||||
SGDirectionalLightBin.hxx
|
SGDirectionalLightBin.hxx
|
||||||
SGLightBin.hxx
|
SGLightBin.hxx
|
||||||
SGModelBin.hxx
|
SGModelBin.hxx
|
||||||
|
SGNodeTriangles.hxx
|
||||||
SGOceanTile.hxx
|
SGOceanTile.hxx
|
||||||
SGReaderWriterBTG.hxx
|
SGReaderWriterBTG.hxx
|
||||||
SGTexturedTriangleBin.hxx
|
SGTexturedTriangleBin.hxx
|
||||||
|
SGTileDetailsCallback.hxx
|
||||||
|
SGTileGeometryBin.hxx
|
||||||
SGTriangleBin.hxx
|
SGTriangleBin.hxx
|
||||||
SGVasiDrawable.hxx
|
SGVasiDrawable.hxx
|
||||||
SGVertexArrayBin.hxx
|
SGVertexArrayBin.hxx
|
||||||
|
|||||||
@@ -0,0 +1,482 @@
|
|||||||
|
// future API - just run through once to convert from OSG to SG
|
||||||
|
// then we can use these triangle lists for random
|
||||||
|
// trees/lights/buildings/objects
|
||||||
|
struct SGTexturedTriangle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<SGVec3f> vertices;
|
||||||
|
std::vector<SGVec2f> texcoords;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SGBorderContour
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SGVec3d start;
|
||||||
|
SGVec3d end;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SGTriangleInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SGTriangleInfo( const SGVec3d& center ) {
|
||||||
|
gbs_center = center;
|
||||||
|
mt_init(&seed, 123);
|
||||||
|
}
|
||||||
|
|
||||||
|
// API used to build the Info by the visitor
|
||||||
|
void addGeometry( osg::Geometry* g ) {
|
||||||
|
geometries.push_back(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMaterial( SGMaterial* m ) {
|
||||||
|
mat = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGMaterial* getMaterial( void ) const {
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// API used to get a specific texture or effect from a material. Materials can have
|
||||||
|
// multiple textures - use the floor of the x coordinate of the first vertes to select it.
|
||||||
|
// This will be constant, and give the same result each time to select one effect/texture per drawable.
|
||||||
|
int getTextureIndex( void ) const {
|
||||||
|
int texInfo = 0;
|
||||||
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
|
if ( vertices ) {
|
||||||
|
const osg::Vec3 *v0 = &vertices->operator[](0);
|
||||||
|
texInfo = floor(v0->x());
|
||||||
|
}
|
||||||
|
return texInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// new API - TODO
|
||||||
|
void getTriangles( std::vector<SGTexturedTriangle>& tris )
|
||||||
|
{
|
||||||
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
|
const osg::Vec2Array* texcoords = dynamic_cast<osg::Vec2Array*>(geometries[0]->getTexCoordArray(0));
|
||||||
|
|
||||||
|
int numPrimitiveSets = geometries[0]->getNumPrimitiveSets();
|
||||||
|
if ( numPrimitiveSets > 0 ) {
|
||||||
|
const osg::PrimitiveSet* ps = geometries[0]->getPrimitiveSet(0);
|
||||||
|
unsigned int numIndices = ps->getNumIndices();
|
||||||
|
|
||||||
|
for ( unsigned int i=2; i<numIndices; i+= 3 ) {
|
||||||
|
SGTexturedTriangle tri;
|
||||||
|
|
||||||
|
tri.vertices.push_back( toSG(vertices->operator[](ps->index(i-2))) );
|
||||||
|
tri.vertices.push_back( toSG(vertices->operator[](ps->index(i-1))) );
|
||||||
|
tri.vertices.push_back( toSG(vertices->operator[](ps->index(i-0))) );
|
||||||
|
|
||||||
|
tri.texcoords.push_back( toSG(texcoords->operator[](ps->index(i-2))) );
|
||||||
|
tri.texcoords.push_back( toSG(texcoords->operator[](ps->index(i-1))) );
|
||||||
|
tri.texcoords.push_back( toSG(texcoords->operator[](ps->index(i-0))) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getBorderContours( std::vector<SGBorderContour>& border )
|
||||||
|
{
|
||||||
|
// each structure contains a list of target indexes and a count
|
||||||
|
int numPrimitiveSets = geometries[0]->getNumPrimitiveSets();
|
||||||
|
if ( numPrimitiveSets > 0 ) {
|
||||||
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
|
|
||||||
|
const osg::PrimitiveSet* ps = geometries[0]->getPrimitiveSet(0);
|
||||||
|
unsigned int numTriangles = ps->getNumIndices()/3;
|
||||||
|
|
||||||
|
// use a map for fast lookup map the segment as a 64 bit int
|
||||||
|
std::map<uint64_t, int> segCounter;
|
||||||
|
uint32_t idx1, idx2;
|
||||||
|
uint64_t key;
|
||||||
|
|
||||||
|
for ( unsigned int i=0; i<numTriangles; i+= 3 ) {
|
||||||
|
// first seg
|
||||||
|
if ( ps->index(i+0) < ps->index(i+1) ) {
|
||||||
|
idx1 = ps->index(i+0);
|
||||||
|
idx2 = ps->index(i+1);
|
||||||
|
} else {
|
||||||
|
idx1 = ps->index(i+1);
|
||||||
|
idx2 = ps->index(i+0);
|
||||||
|
}
|
||||||
|
|
||||||
|
key=( (uint64_t)idx1<<32) | (uint64_t)idx2;
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "key " << std::hex << key << std::dec << " count is " << segCounter[key] );
|
||||||
|
segCounter[key]++;
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "after increment key " << std::hex << key << std::dec << " count is " << segCounter[key] );
|
||||||
|
|
||||||
|
// second seg
|
||||||
|
if ( ps->index(i+1) < ps->index(i+2) ) {
|
||||||
|
idx1 = ps->index(i+1);
|
||||||
|
idx2 = ps->index(i+2);
|
||||||
|
} else {
|
||||||
|
idx1 = ps->index(i+2);
|
||||||
|
idx2 = ps->index(i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
key=( (uint64_t)idx1<<32) | (uint64_t)idx2;
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "key " << std::hex << key << std::dec << " count is " << segCounter[key] );
|
||||||
|
segCounter[key]++;
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "after increment key " << std::hex << key << std::dec << " count is " << segCounter[key] );
|
||||||
|
|
||||||
|
// third seg
|
||||||
|
if ( ps->index(i+2) < ps->index(i+0) ) {
|
||||||
|
idx1 = ps->index(i+2);
|
||||||
|
idx2 = ps->index(i+0);
|
||||||
|
} else {
|
||||||
|
idx1 = ps->index(i+0);
|
||||||
|
idx2 = ps->index(i+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
key=( (uint64_t)idx1<<32) | (uint64_t)idx2;
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "key " << std::hex << key << std::dec << " count is " << segCounter[key] );
|
||||||
|
segCounter[key]++;
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "after increment key " << std::hex << key << std::dec << " count is " << segCounter[key] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// return all segments with count = 1 ( border )
|
||||||
|
std::map<uint64_t, int>::iterator segIt = segCounter.begin();
|
||||||
|
while ( segIt != segCounter.end() ) {
|
||||||
|
if ( segIt->second == 1 ) {
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "key " << std::hex << segIt->first << std::dec << " count is " << segIt->second );
|
||||||
|
|
||||||
|
unsigned int iStart = segIt->first >> 32;
|
||||||
|
unsigned int iEnd = segIt->first & 0x00000000FFFFFFFF;
|
||||||
|
|
||||||
|
SGBorderContour bc;
|
||||||
|
|
||||||
|
bc.start = toVec3d(toSG(vertices->operator[](iStart)));
|
||||||
|
bc.end = toVec3d(toSG(vertices->operator[](iEnd)));
|
||||||
|
border.push_back( bc );
|
||||||
|
}
|
||||||
|
segIt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// debug out - requires GDAL
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
SGGeod geodPos = SGGeod::fromCart(gbs_center);
|
||||||
|
SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180);
|
||||||
|
|
||||||
|
for ( unsigned int i=0; i<border.size(); i++ ){
|
||||||
|
// de-rotate and translate : todo - create a paralell vertex list so we just do this
|
||||||
|
// once per vertex, not for every triangle's use of the vertex
|
||||||
|
SGVec3d sgVStart = hlOr.backTransform( border[i].start) + gbs_center;
|
||||||
|
SGVec3d sgVEnd = hlOr.backTransform( border[i].end) + gbs_center;
|
||||||
|
|
||||||
|
// convert from cartesian to Geodetic, and save as a list of Geods for output
|
||||||
|
SGGeod gStart = SGGeod::fromCart(sgVStart);
|
||||||
|
SGGeod gEnd = SGGeod::fromCart(sgVEnd);
|
||||||
|
|
||||||
|
SGShapefile::FromSegment( gStart, gEnd, true, "./borders", mat->get_names()[0], "border" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Random buildings API - get num triangles, then get a triangle at index
|
||||||
|
unsigned int getNumTriangles( void ) const {
|
||||||
|
unsigned int num_triangles = 0;
|
||||||
|
|
||||||
|
if ( !geometries.empty() ) {
|
||||||
|
int numPrimitiveSets = geometries[0]->getNumPrimitiveSets();
|
||||||
|
if ( numPrimitiveSets > 0 ) {
|
||||||
|
const osg::PrimitiveSet* ps = geometries[0]->getPrimitiveSet(0);
|
||||||
|
unsigned int numIndices = ps->getNumIndices();
|
||||||
|
num_triangles = numIndices/3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_triangles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getTriangle(unsigned int i, std::vector<SGVec3f>& triVerts, std::vector<SGVec2f>& triTCs) const {
|
||||||
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
|
const osg::Vec2Array* texcoords = dynamic_cast<osg::Vec2Array*>(geometries[0]->getTexCoordArray(0));
|
||||||
|
|
||||||
|
if ( !geometries.empty() ) {
|
||||||
|
int numPrimitiveSets = geometries[0]->getNumPrimitiveSets();
|
||||||
|
if ( numPrimitiveSets > 0 ) {
|
||||||
|
const osg::PrimitiveSet* ps = geometries[0]->getPrimitiveSet(0);
|
||||||
|
int idxStart = i*3;
|
||||||
|
|
||||||
|
triVerts.push_back( toSG(vertices->operator[](ps->index(idxStart+0))) );
|
||||||
|
triVerts.push_back( toSG(vertices->operator[](ps->index(idxStart+1))) );
|
||||||
|
triVerts.push_back( toSG(vertices->operator[](ps->index(idxStart+2))) );
|
||||||
|
|
||||||
|
triTCs.push_back( toSG(texcoords->operator[](ps->index(idxStart+0))) );
|
||||||
|
triTCs.push_back( toSG(texcoords->operator[](ps->index(idxStart+1))) );
|
||||||
|
triTCs.push_back( toSG(texcoords->operator[](ps->index(idxStart+2))) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// random lights and trees - just get a list of points on where to add the light / tree
|
||||||
|
// TODO move this out - and handle in the random light / tree code
|
||||||
|
// just use generic triangle API.
|
||||||
|
void addRandomSurfacePoints(float coverage, float offset,
|
||||||
|
osg::Texture2D* object_mask,
|
||||||
|
std::vector<SGVec3f>& points)
|
||||||
|
{
|
||||||
|
if ( !geometries.empty() ) {
|
||||||
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
|
const osg::Vec2Array* texcoords = dynamic_cast<osg::Vec2Array*>(geometries[0]->getTexCoordArray(0));
|
||||||
|
|
||||||
|
int numPrimitiveSets = geometries[0]->getNumPrimitiveSets();
|
||||||
|
if ( numPrimitiveSets > 0 ) {
|
||||||
|
const osg::PrimitiveSet* ps = geometries[0]->getPrimitiveSet(0);
|
||||||
|
unsigned int numIndices = ps->getNumIndices();
|
||||||
|
|
||||||
|
for ( unsigned int i=2; i<numIndices; i+= 3 ) {
|
||||||
|
SGVec3f v0 = toSG(vertices->operator[](ps->index(i-2)));
|
||||||
|
SGVec3f v1 = toSG(vertices->operator[](ps->index(i-1)));
|
||||||
|
SGVec3f v2 = toSG(vertices->operator[](ps->index(i-0)));
|
||||||
|
|
||||||
|
SGVec2f t0 = toSG(texcoords->operator[](ps->index(i-2)));
|
||||||
|
SGVec2f t1 = toSG(texcoords->operator[](ps->index(i-1)));
|
||||||
|
SGVec2f t2 = toSG(texcoords->operator[](ps->index(i-0)));
|
||||||
|
|
||||||
|
SGVec3f normal = cross(v1 - v0, v2 - v0);
|
||||||
|
|
||||||
|
// Compute the area
|
||||||
|
float area = 0.5f*length(normal);
|
||||||
|
if (area <= SGLimitsf::min())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// For partial units of area, use a zombie door method to
|
||||||
|
// create the proper random chance of a light being created
|
||||||
|
// for this triangle
|
||||||
|
float unit = area + mt_rand(&seed)*coverage;
|
||||||
|
|
||||||
|
SGVec3f offsetVector = offset*normalize(normal);
|
||||||
|
// generate a light point for each unit of area
|
||||||
|
|
||||||
|
while ( coverage < unit ) {
|
||||||
|
float a = mt_rand(&seed);
|
||||||
|
float b = mt_rand(&seed);
|
||||||
|
|
||||||
|
if ( a + b > 1 ) {
|
||||||
|
a = 1 - a;
|
||||||
|
b = 1 - b;
|
||||||
|
}
|
||||||
|
float c = 1 - a - b;
|
||||||
|
SGVec3f randomPoint = offsetVector + a*v0 + b*v1 + c*v2;
|
||||||
|
|
||||||
|
if (object_mask != NULL) {
|
||||||
|
SGVec2f texCoord = a*t0 + b*t1 + c*t2;
|
||||||
|
|
||||||
|
// Check this random point against the object mask
|
||||||
|
// red channel.
|
||||||
|
osg::Image* img = object_mask->getImage();
|
||||||
|
unsigned int x = (int) (img->s() * texCoord.x()) % img->s();
|
||||||
|
unsigned int y = (int) (img->t() * texCoord.y()) % img->t();
|
||||||
|
|
||||||
|
if (mt_rand(&seed) < img->getColor(x, y).r()) {
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No object mask, so simply place the object
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
}
|
||||||
|
unit -= coverage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addRandomTreePoints(float wood_coverage,
|
||||||
|
osg::Texture2D* object_mask,
|
||||||
|
float vegetation_density,
|
||||||
|
float cos_max_density_angle,
|
||||||
|
float cos_zero_density_angle,
|
||||||
|
std::vector<SGVec3f>& points)
|
||||||
|
{
|
||||||
|
if ( !geometries.empty() ) {
|
||||||
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
|
const osg::Vec2Array* texcoords = dynamic_cast<osg::Vec2Array*>(geometries[0]->getTexCoordArray(0));
|
||||||
|
|
||||||
|
int numPrimitiveSets = geometries[0]->getNumPrimitiveSets();
|
||||||
|
if ( numPrimitiveSets > 0 ) {
|
||||||
|
const osg::PrimitiveSet* ps = geometries[0]->getPrimitiveSet(0);
|
||||||
|
unsigned int numIndices = ps->getNumIndices();
|
||||||
|
|
||||||
|
for ( unsigned int i=2; i<numIndices; i+= 3 ) {
|
||||||
|
SGVec3f v0 = toSG(vertices->operator[](ps->index(i-2)));
|
||||||
|
SGVec3f v1 = toSG(vertices->operator[](ps->index(i-1)));
|
||||||
|
SGVec3f v2 = toSG(vertices->operator[](ps->index(i-0)));
|
||||||
|
|
||||||
|
SGVec2f t0 = toSG(texcoords->operator[](ps->index(i-2)));
|
||||||
|
SGVec2f t1 = toSG(texcoords->operator[](ps->index(i-1)));
|
||||||
|
SGVec2f t2 = toSG(texcoords->operator[](ps->index(i-0)));
|
||||||
|
|
||||||
|
SGVec3f normal = cross(v1 - v0, v2 - v0);
|
||||||
|
|
||||||
|
// Ensure the slope isn't too steep by checking the
|
||||||
|
// cos of the angle between the slope normal and the
|
||||||
|
// vertical (conveniently the z-component of the normalized
|
||||||
|
// normal) and values passed in.
|
||||||
|
float alpha = normalize(normal).z();
|
||||||
|
float slope_density = 1.0;
|
||||||
|
|
||||||
|
if (alpha < cos_zero_density_angle)
|
||||||
|
continue; // Too steep for any vegetation
|
||||||
|
|
||||||
|
if (alpha < cos_max_density_angle) {
|
||||||
|
slope_density =
|
||||||
|
(alpha - cos_zero_density_angle) / (cos_max_density_angle - cos_zero_density_angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the area
|
||||||
|
float area = 0.5f*length(normal);
|
||||||
|
if (area <= SGLimitsf::min())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Determine the number of trees, taking into account vegetation
|
||||||
|
// density (which is linear) and the slope density factor.
|
||||||
|
// Use a zombie door method to create the proper random chance
|
||||||
|
// of a tree being created for partial values.
|
||||||
|
int woodcount = (int) (vegetation_density * vegetation_density *
|
||||||
|
slope_density *
|
||||||
|
area / wood_coverage + mt_rand(&seed));
|
||||||
|
|
||||||
|
for (int j = 0; j < woodcount; j++) {
|
||||||
|
float a = mt_rand(&seed);
|
||||||
|
float b = mt_rand(&seed);
|
||||||
|
|
||||||
|
if ( a + b > 1.0f ) {
|
||||||
|
a = 1.0f - a;
|
||||||
|
b = 1.0f - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
float c = 1.0f - a - b;
|
||||||
|
|
||||||
|
SGVec3f randomPoint = a*v0 + b*v1 + c*v2;
|
||||||
|
|
||||||
|
if (object_mask != NULL) {
|
||||||
|
SGVec2f texCoord = a*t0 + b*t1 + c*t2;
|
||||||
|
|
||||||
|
// Check this random point against the object mask
|
||||||
|
// green (for trees) channel.
|
||||||
|
osg::Image* img = object_mask->getImage();
|
||||||
|
unsigned int x = (int) (img->s() * texCoord.x()) % img->s();
|
||||||
|
unsigned int y = (int) (img->t() * texCoord.y()) % img->t();
|
||||||
|
|
||||||
|
if (mt_rand(&seed) < img->getColor(x, y).g()) {
|
||||||
|
// The red channel contains the rotation for this object
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
points.push_back(randomPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// debug : this will save the tile as a shapefile that can be viewed in QGIS.
|
||||||
|
// NOTE: this is really slow....
|
||||||
|
// remember - we need to de-rotate the tile, then translate back to gbs_center.
|
||||||
|
void dumpBorder() {
|
||||||
|
//dump the first triangle only of the first geometry, for now...
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "effect geode has " << geometries.size() << " geometries" );
|
||||||
|
|
||||||
|
const osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometries[0]->getVertexArray());
|
||||||
|
if ( vertices ) {
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, " geometry has " << vertices->getNumElements() << " vertices" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !geometries.empty() ) {
|
||||||
|
int numPrimitiveSets = geometries[0]->getNumPrimitiveSets();
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, " geometry has " << numPrimitiveSets << " primitive sets" );
|
||||||
|
|
||||||
|
if ( numPrimitiveSets > 0 ) {
|
||||||
|
const osg::PrimitiveSet* ps = geometries[0]->getPrimitiveSet(0);
|
||||||
|
unsigned int numIndices = ps->getNumIndices();
|
||||||
|
|
||||||
|
// create the same quat we used to rotate here
|
||||||
|
// - use backTransform to go back to original node location
|
||||||
|
SGGeod geodPos = SGGeod::fromCart(gbs_center);
|
||||||
|
SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180);
|
||||||
|
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, " primitive set has has " << numIndices << " indices" );
|
||||||
|
for ( unsigned int i=2; i<numIndices; i+= 3 ) {
|
||||||
|
if ( numIndices >= 3 ) {
|
||||||
|
unsigned int v0i = ps->index(i-2);
|
||||||
|
unsigned int v1i = ps->index(i-1);
|
||||||
|
unsigned int v2i = ps->index(i-0);
|
||||||
|
|
||||||
|
const osg::Vec3 *v0 = &vertices->operator[](v0i);
|
||||||
|
const osg::Vec3 *v1 = &vertices->operator[](v1i);
|
||||||
|
const osg::Vec3 *v2 = &vertices->operator[](v2i);
|
||||||
|
|
||||||
|
// de-rotate and translate : todo - create a paralell vertex list so we just do this
|
||||||
|
// once per vertex, not for every triangle's use of the vertex
|
||||||
|
SGVec3d vec0 = hlOr.backTransform( toVec3d(toSG(*v0))) + gbs_center;
|
||||||
|
SGVec3d vec1 = hlOr.backTransform( toVec3d(toSG(*v1))) + gbs_center;
|
||||||
|
SGVec3d vec2 = hlOr.backTransform( toVec3d(toSG(*v2))) + gbs_center;
|
||||||
|
|
||||||
|
// convert from cartesian to Geodetic, and save as a list of Geods for output
|
||||||
|
std::vector<SGGeod> triangle;
|
||||||
|
triangle.push_back( SGGeod::fromCart(vec0) );
|
||||||
|
triangle.push_back( SGGeod::fromCart(vec1) );
|
||||||
|
triangle.push_back( SGGeod::fromCart(vec2) );
|
||||||
|
|
||||||
|
SGShapefile::FromGeodList( triangle, true, "./triangles", mat->get_names()[0], "tri" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
mt seed;
|
||||||
|
SGMaterial* mat;
|
||||||
|
SGVec3d gbs_center;
|
||||||
|
std::vector<osg::Geometry*> geometries;
|
||||||
|
std::vector<int> polygon_border; // TODO
|
||||||
|
};
|
||||||
|
|
||||||
|
// This visitor will generate an SGTriangleInfo.
|
||||||
|
// currently, it looks like it could save multiple lists, which could be the case
|
||||||
|
// if multiple osg::geods are found with osg::Geometry.
|
||||||
|
// But right now, we store a single PrimitiveSet under a single EffectGeod.
|
||||||
|
// so the traversal should only find a single EffectGeod - building a single SGTriangleInfo
|
||||||
|
class GetNodeTriangles : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GetNodeTriangles(const SGVec3d& c, std::vector<SGTriangleInfo>* nt) : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ), center(c), nodeTris(nt) {}
|
||||||
|
|
||||||
|
// This method gets called for every node in the scene
|
||||||
|
// graph. Check each node to see if it has user
|
||||||
|
// out target. If so, save the node's address.
|
||||||
|
virtual void apply( osg::Node& node )
|
||||||
|
{
|
||||||
|
EffectGeode* eg = dynamic_cast<EffectGeode*>(&node);
|
||||||
|
if ( eg ) {
|
||||||
|
// get the material from the user info
|
||||||
|
SGTriangleInfo triInfo( center );
|
||||||
|
triInfo.setMaterial( eg->getMaterial() );
|
||||||
|
|
||||||
|
// let's find the drawables for this node
|
||||||
|
int numDrawables = eg->getNumDrawables();
|
||||||
|
for ( int i=0; i<numDrawables; i++ ) {
|
||||||
|
triInfo.addGeometry( eg->getDrawable(i)->asGeometry() );
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeTris->push_back( triInfo );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep traversing the rest of the scene graph.
|
||||||
|
traverse( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SGVec3d center;
|
||||||
|
std::vector<SGTriangleInfo>* nodeTris;
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,304 @@
|
|||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <simgear_config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "obj.hxx"
|
||||||
|
|
||||||
|
#include <simgear/scene/material/EffectGeode.hxx>
|
||||||
|
#include <simgear/scene/material/matlib.hxx>
|
||||||
|
#include <simgear/scene/material/mat.hxx>
|
||||||
|
|
||||||
|
#include "SGTexturedTriangleBin.hxx"
|
||||||
|
|
||||||
|
using namespace simgear;
|
||||||
|
|
||||||
|
typedef std::map<std::string,SGTexturedTriangleBin> SGMaterialTriangleMap;
|
||||||
|
|
||||||
|
// Class handling the initial BTG loading : should probably be in its own file
|
||||||
|
// it is very closely coupled with SGTexturedTriangleBin.hxx
|
||||||
|
// it was used to load fans, strips, and triangles.
|
||||||
|
// WS2.0 no longer uses fans or strips, but people still use ws1.0, so we need
|
||||||
|
// to keep this functionality.
|
||||||
|
class SGTileGeometryBin : public osg::Referenced {
|
||||||
|
public:
|
||||||
|
SGMaterialTriangleMap materialTriangleMap;
|
||||||
|
|
||||||
|
SGTileGeometryBin() {}
|
||||||
|
|
||||||
|
static SGVec2f
|
||||||
|
getTexCoord(const std::vector<SGVec2f>& texCoords, const int_list& tc,
|
||||||
|
const SGVec2f& tcScale, unsigned i)
|
||||||
|
{
|
||||||
|
if (tc.empty())
|
||||||
|
return tcScale;
|
||||||
|
else if (tc.size() == 1)
|
||||||
|
return mult(texCoords[tc[0]], tcScale);
|
||||||
|
else
|
||||||
|
return mult(texCoords[tc[i]], tcScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
SGVec2f getTexCoordScale(const std::string& name, SGMaterialCache* matcache)
|
||||||
|
{
|
||||||
|
if (!matcache)
|
||||||
|
return SGVec2f(1, 1);
|
||||||
|
SGMaterial* material = matcache->find(name);
|
||||||
|
if (!material)
|
||||||
|
return SGVec2f(1, 1);
|
||||||
|
|
||||||
|
return material->get_tex_coord_scale();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addTriangleGeometry(SGTexturedTriangleBin& triangles,
|
||||||
|
const SGBinObject& obj, unsigned grp,
|
||||||
|
const SGVec2f& tc0Scale,
|
||||||
|
const SGVec2f& tc1Scale)
|
||||||
|
{
|
||||||
|
const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
|
||||||
|
const std::vector<SGVec3f>& normals(obj.get_normals());
|
||||||
|
const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
|
||||||
|
const int_list& tris_v(obj.get_tris_v()[grp]);
|
||||||
|
const int_list& tris_n(obj.get_tris_n()[grp]);
|
||||||
|
const tci_list& tris_tc(obj.get_tris_tcs()[grp]);
|
||||||
|
bool num_norms_is_num_verts = true;
|
||||||
|
|
||||||
|
if (tris_v.size() != tris_n.size()) {
|
||||||
|
// If the normal indices do not match, they should be inmplicitly
|
||||||
|
// the same than the vertex indices.
|
||||||
|
num_norms_is_num_verts = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !tris_tc[1].empty() ) {
|
||||||
|
triangles.hasSecondaryTexCoord(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 2; i < tris_v.size(); i += 3) {
|
||||||
|
SGVertNormTex v0;
|
||||||
|
v0.SetVertex( toVec3f(vertices[tris_v[i-2]]) );
|
||||||
|
v0.SetNormal( num_norms_is_num_verts ? normals[tris_n[i-2]] :
|
||||||
|
normals[tris_v[i-2]] );
|
||||||
|
v0.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i-2) );
|
||||||
|
if (!tris_tc[1].empty()) {
|
||||||
|
v0.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i-2) );
|
||||||
|
}
|
||||||
|
SGVertNormTex v1;
|
||||||
|
v1.SetVertex( toVec3f(vertices[tris_v[i-1]]) );
|
||||||
|
v1.SetNormal( num_norms_is_num_verts ? normals[tris_n[i-1]] :
|
||||||
|
normals[tris_v[i-1]] );
|
||||||
|
v1.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i-1) );
|
||||||
|
if (!tris_tc[1].empty()) {
|
||||||
|
v1.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i-1) );
|
||||||
|
}
|
||||||
|
SGVertNormTex v2;
|
||||||
|
v2.SetVertex( toVec3f(vertices[tris_v[i]]) );
|
||||||
|
v2.SetNormal( num_norms_is_num_verts ? normals[tris_n[i]] :
|
||||||
|
normals[tris_v[i]] );
|
||||||
|
v2.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i) );
|
||||||
|
if (!tris_tc[1].empty()) {
|
||||||
|
v2.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i) );
|
||||||
|
}
|
||||||
|
|
||||||
|
triangles.insert(v0, v1, v2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addStripGeometry(SGTexturedTriangleBin& triangles,
|
||||||
|
const SGBinObject& obj, unsigned grp,
|
||||||
|
const SGVec2f& tc0Scale,
|
||||||
|
const SGVec2f& tc1Scale)
|
||||||
|
{
|
||||||
|
const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
|
||||||
|
const std::vector<SGVec3f>& normals(obj.get_normals());
|
||||||
|
const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
|
||||||
|
const int_list& strips_v(obj.get_strips_v()[grp]);
|
||||||
|
const int_list& strips_n(obj.get_strips_n()[grp]);
|
||||||
|
const tci_list& strips_tc(obj.get_strips_tcs()[grp]);
|
||||||
|
bool num_norms_is_num_verts = true;
|
||||||
|
|
||||||
|
if (strips_v.size() != strips_n.size()) {
|
||||||
|
// If the normal indices do not match, they should be inmplicitly
|
||||||
|
// the same than the vertex indices.
|
||||||
|
num_norms_is_num_verts = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !strips_tc[1].empty() ) {
|
||||||
|
triangles.hasSecondaryTexCoord(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 2; i < strips_v.size(); ++i) {
|
||||||
|
SGVertNormTex v0;
|
||||||
|
v0.SetVertex( toVec3f(vertices[strips_v[i-2]]) );
|
||||||
|
v0.SetNormal( num_norms_is_num_verts ? normals[strips_n[i-2]] :
|
||||||
|
normals[strips_v[i-2]] );
|
||||||
|
v0.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[0], tc0Scale, i-2) );
|
||||||
|
if (!strips_tc[1].empty()) {
|
||||||
|
v0.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i-2) );
|
||||||
|
}
|
||||||
|
SGVertNormTex v1;
|
||||||
|
v1.SetVertex( toVec3f(vertices[strips_v[i-1]]) );
|
||||||
|
v1.SetNormal( num_norms_is_num_verts ? normals[strips_n[i-1]] :
|
||||||
|
normals[strips_v[i-1]] );
|
||||||
|
v1.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[1], tc0Scale, i-1) );
|
||||||
|
if (!strips_tc[1].empty()) {
|
||||||
|
v1.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i-1) );
|
||||||
|
}
|
||||||
|
SGVertNormTex v2;
|
||||||
|
v2.SetVertex( toVec3f(vertices[strips_v[i]]) );
|
||||||
|
v2.SetNormal( num_norms_is_num_verts ? normals[strips_n[i]] :
|
||||||
|
normals[strips_v[i]] );
|
||||||
|
v2.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[0], tc0Scale, i) );
|
||||||
|
if (!strips_tc[1].empty()) {
|
||||||
|
v2.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i) );
|
||||||
|
}
|
||||||
|
if (i%2)
|
||||||
|
triangles.insert(v1, v0, v2);
|
||||||
|
else
|
||||||
|
triangles.insert(v0, v1, v2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
addFanGeometry(SGTexturedTriangleBin& triangles,
|
||||||
|
const SGBinObject& obj, unsigned grp,
|
||||||
|
const SGVec2f& tc0Scale,
|
||||||
|
const SGVec2f& tc1Scale)
|
||||||
|
{
|
||||||
|
const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
|
||||||
|
const std::vector<SGVec3f>& normals(obj.get_normals());
|
||||||
|
const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
|
||||||
|
const int_list& fans_v(obj.get_fans_v()[grp]);
|
||||||
|
const int_list& fans_n(obj.get_fans_n()[grp]);
|
||||||
|
const tci_list& fans_tc(obj.get_fans_tcs()[grp]);
|
||||||
|
bool num_norms_is_num_verts = true;
|
||||||
|
|
||||||
|
if (fans_v.size() != fans_n.size()) {
|
||||||
|
// If the normal indices do not match, they should be inmplicitly
|
||||||
|
// the same than the vertex indices.
|
||||||
|
num_norms_is_num_verts = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !fans_tc[1].empty() ) {
|
||||||
|
triangles.hasSecondaryTexCoord(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SGVertNormTex v0;
|
||||||
|
v0.SetVertex( toVec3f(vertices[fans_v[0]]) );
|
||||||
|
v0.SetNormal( num_norms_is_num_verts ? normals[fans_n[0]] :
|
||||||
|
normals[fans_v[0]] );
|
||||||
|
v0.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, 0) );
|
||||||
|
if (!fans_tc[1].empty()) {
|
||||||
|
v0.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, 0) );
|
||||||
|
}
|
||||||
|
SGVertNormTex v1;
|
||||||
|
v1.SetVertex( toVec3f(vertices[fans_v[1]]) );
|
||||||
|
v1.SetNormal( num_norms_is_num_verts ? normals[fans_n[1]] :
|
||||||
|
normals[fans_v[1]] );
|
||||||
|
v1.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, 1) );
|
||||||
|
if (!fans_tc[1].empty()) {
|
||||||
|
v1.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, 1) );
|
||||||
|
}
|
||||||
|
for (unsigned i = 2; i < fans_v.size(); ++i) {
|
||||||
|
SGVertNormTex v2;
|
||||||
|
v2.SetVertex( toVec3f(vertices[fans_v[i]]) );
|
||||||
|
v2.SetNormal( num_norms_is_num_verts ? normals[fans_n[i]] :
|
||||||
|
normals[fans_v[i]] );
|
||||||
|
v2.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, i) );
|
||||||
|
if (!fans_tc[1].empty()) {
|
||||||
|
v2.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, i) );
|
||||||
|
}
|
||||||
|
triangles.insert(v0, v1, v2);
|
||||||
|
v1 = v2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
insertSurfaceGeometry(const SGBinObject& obj, SGMaterialCache* matcache)
|
||||||
|
{
|
||||||
|
if (obj.get_tris_n().size() < obj.get_tris_v().size() ||
|
||||||
|
obj.get_tris_tcs().size() < obj.get_tris_v().size()) {
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT,
|
||||||
|
"Group list sizes for triangles do not match!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned grp = 0; grp < obj.get_tris_v().size(); ++grp) {
|
||||||
|
std::string materialName = obj.get_tri_materials()[grp];
|
||||||
|
SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
|
||||||
|
SGVec2f tc1Scale(1.0, 1.0);
|
||||||
|
addTriangleGeometry(materialTriangleMap[materialName],
|
||||||
|
obj, grp, tc0Scale, tc1Scale );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.get_strips_n().size() < obj.get_strips_v().size() ||
|
||||||
|
obj.get_strips_tcs().size() < obj.get_strips_v().size()) {
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT,
|
||||||
|
"Group list sizes for strips do not match!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (unsigned grp = 0; grp < obj.get_strips_v().size(); ++grp) {
|
||||||
|
std::string materialName = obj.get_strip_materials()[grp];
|
||||||
|
SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
|
||||||
|
SGVec2f tc1Scale(1.0, 1.0);
|
||||||
|
addStripGeometry(materialTriangleMap[materialName],
|
||||||
|
obj, grp, tc0Scale, tc1Scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.get_fans_n().size() < obj.get_fans_v().size() ||
|
||||||
|
obj.get_fans_tcs().size() < obj.get_fans_v().size()) {
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT,
|
||||||
|
"Group list sizes for fans do not match!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (unsigned grp = 0; grp < obj.get_fans_v().size(); ++grp) {
|
||||||
|
std::string materialName = obj.get_fan_materials()[grp];
|
||||||
|
SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
|
||||||
|
SGVec2f tc1Scale(1.0, 1.0);
|
||||||
|
addFanGeometry(materialTriangleMap[materialName],
|
||||||
|
obj, grp, tc0Scale, tc1Scale );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Node* getSurfaceGeometry(SGMaterialCache* matcache, bool useVBOs) const
|
||||||
|
{
|
||||||
|
if (materialTriangleMap.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
EffectGeode* eg = NULL;
|
||||||
|
osg::Group* group = (materialTriangleMap.size() > 1 ? new osg::Group : NULL);
|
||||||
|
if (group) {
|
||||||
|
group->setName("surfaceGeometryGroup");
|
||||||
|
}
|
||||||
|
|
||||||
|
//osg::Geode* geode = new osg::Geode;
|
||||||
|
SGMaterialTriangleMap::const_iterator i;
|
||||||
|
for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
|
||||||
|
osg::Geometry* geometry = i->second.buildGeometry(useVBOs);
|
||||||
|
SGMaterial *mat = NULL;
|
||||||
|
if (matcache) {
|
||||||
|
mat = matcache->find(i->first);
|
||||||
|
}
|
||||||
|
eg = new EffectGeode;
|
||||||
|
eg->setName("EffectGeode");
|
||||||
|
if (mat) {
|
||||||
|
eg->setMaterial(mat);
|
||||||
|
eg->setEffect(mat->get_one_effect(i->second.getTextureIndex()));
|
||||||
|
} else {
|
||||||
|
eg->setMaterial(NULL);
|
||||||
|
}
|
||||||
|
eg->addDrawable(geometry);
|
||||||
|
eg->runGenerators(geometry); // Generate extra data needed by effect
|
||||||
|
if (group) {
|
||||||
|
group->addChild(eg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group) {
|
||||||
|
return group;
|
||||||
|
} else {
|
||||||
|
return eg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
+37
-1323
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,9 @@ using namespace osg;
|
|||||||
|
|
||||||
void UpdateOnceCallback::operator()(Node* node, NodeVisitor* nv)
|
void UpdateOnceCallback::operator()(Node* node, NodeVisitor* nv)
|
||||||
{
|
{
|
||||||
|
ref_ptr<UpdateOnceCallback> prevent_premature_deletion=this;
|
||||||
|
// workaround for crash bug in OSG 3.2.1
|
||||||
|
// https://bugs.debian.org/765855
|
||||||
doUpdate(node, nv);
|
doUpdate(node, nv);
|
||||||
node->removeUpdateCallback(this);
|
node->removeUpdateCallback(this);
|
||||||
// The callback could be deleted now.
|
// The callback could be deleted now.
|
||||||
|
|||||||
Reference in New Issue
Block a user