From: ehofman Date: Sun, 26 Jun 2005 17:16:45 +0000 (+0000) Subject: Harald JOHNSEN: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=f62ff0ad66383ad0416a60337827098f48522664;p=simgear.git Harald JOHNSEN: Changes ======= New volumetric shadows for FlightGear. There is now two new checkboxes in the rendering dialog to enable/disable shadows for the user aircraft and for static scenery objects (ie those defined in the .stg files). AI and random objects are not handled for the moment. known bugs ========== - ghost objects --- diff --git a/simgear/environment/visual_enviro.hxx b/simgear/environment/visual_enviro.hxx index e3740b6c..946c169c 100644 --- a/simgear/environment/visual_enviro.hxx +++ b/simgear/environment/visual_enviro.hxx @@ -24,7 +24,9 @@ #include #include STL_STRING +#include +SG_USING_STD(vector); SG_USING_STD(string); class SGLightning; @@ -217,6 +219,8 @@ public: void getFOV( float &w, float &h ); list_of_SGWxRadarEcho *get_radar_echo(void); + + sgMat4 *get_transform(void) { return &transform; } }; extern SGEnviro sgEnviro; diff --git a/simgear/scene/model/Makefile.am b/simgear/scene/model/Makefile.am index e12c5829..d05744c1 100644 --- a/simgear/scene/model/Makefile.am +++ b/simgear/scene/model/Makefile.am @@ -12,7 +12,8 @@ include_HEADERS = \ modellib.hxx \ personality.hxx \ placement.hxx \ - placementtrans.hxx + placementtrans.hxx \ + shadowvolume.hxx libsgmodel_a_SOURCES = \ animation.cxx \ @@ -22,6 +23,7 @@ libsgmodel_a_SOURCES = \ modellib.cxx \ personality.cxx \ placement.cxx \ - placementtrans.cxx + placementtrans.cxx \ + shadowvolume.cxx INCLUDES = -I$(top_srcdir) diff --git a/simgear/scene/model/shadowvolume.cxx b/simgear/scene/model/shadowvolume.cxx new file mode 100644 index 00000000..de106bcd --- /dev/null +++ b/simgear/scene/model/shadowvolume.cxx @@ -0,0 +1,900 @@ +// Shadow volume class +// +// Written by Harald JOHNSEN, started June 2005. +// +// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program 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. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// +// + +#include +#include +#include +#include +#include SG_GLU_H + +#include "shadowvolume.hxx" + +/* + geometry and edge list + - traverse object graph until leaf to get geometry + - what about transform and selection ? + - use sub objects rather then objects + - get local transform and selection + - range anim : ssgRangeSelector ( min, max ) => ssgSelector ( true/false ) + => selection [0..n], kids [0..n] + - select/timed anim : ssgSelector ( true/false ) + => isSelected( nkid ) + - spin/rotate/trans/scale/... : ssgTransform ( matrix ) + => getNetTransform + - on new object : + - for one object branch + - for each leaf + - save geometry + - save address in cache + - when rendering object + - for each leaf + - getNetTransform + object global rotation (ac) => transform for light position + - go up in tree and check isSelected( self ) + - generate connectivity each time the geometry change + => using local light so connectivity never changes + - generate active edge list when : + - light moves + - subpart moves (animation code) + - ac rotate + => cache rotation matrix and generate edge list only if something change + => even if it changes, no need to do that every frame + + - static objects have static edge list if light does not move + + shadowing a scene + - render full scene as normal + - render occluder in stencil buffer with their shadow volumes + - apply stencil to framebuffer (darkens shadowed parts) + +*/ + +// TODO +// - shadow for objects +// * aircraft +// * tile objects (from .stg) +// - ai objects +// - random objects => tie shadow geometry to lib objects and reuse them +// - zfail if camera inside shadow +// - queue geometry work if lot of objects +// * add a render property on/off (for aircraft, for scene objects, for ai) +// * add a render property in rendering dialog +// * filter : halo, light, shadow, disc, disk, flame, (exhaust), noshadow +// BUG +// - ghost objects ? +// - no shadow : check static 737/747 +// why has the ggb an alpha animation = 0.01 ? + +static int statSilhouette=0; +static int statGeom=0; +static int statObj=0; + +static SGShadowVolume *states; + + +SGShadowVolume::ShadowCaster::ShadowCaster( int _num_tri, ssgBranch * _geometry_leaf ) : + geometry_leaf ( _geometry_leaf ), + scenery_object ( 0 ), + first_select ( 0 ), + frameNumber ( 0 ), + numTriangles ( 0 ), + indices ( 0 ), + vertices ( 0 ), + planeEquations ( 0 ), + isFacingLight ( 0 ), + neighbourIndices ( 0 ), + isSilhouetteEdge ( 0 ) +{ + int num_tri = _num_tri; + numTriangles = num_tri; + indices = new int[num_tri * 3]; + vertices = new sgVec3[num_tri * 3]; + planeEquations = new sgVec4[num_tri]; + neighbourIndices = new int[num_tri * 3]; + isSilhouetteEdge = new bool[num_tri * 3]; + isFacingLight = new bool[num_tri]; + sgSetVec3(last_lightpos, 0.0, 0.0, 0.0); + statGeom ++; + + ssgBranch *branch = (ssgBranch *) _geometry_leaf; + while( branch && branch->getNumParents() > 0 ) { + if( !first_select && branch->isA(ssgTypeSelector())) { + first_select = branch; + break; + } + branch = branch->getParent(0); + } +} + +void SGShadowVolume::ShadowCaster::addLeaf( int & tri_idx, ssgLeaf *geometry_leaf ) { + int num_tri = geometry_leaf->getNumTriangles(); + for(int i = 0; i < num_tri ; i ++ ) { + short v1, v2, v3; + sgVec3 a, b, c; + geometry_leaf->getTriangle( i, &v1, &v2, &v3 ); + sgCopyVec3(a, geometry_leaf->getVertex(v1)); + sgCopyVec3(b, geometry_leaf->getVertex(v2)); + sgCopyVec3(c, geometry_leaf->getVertex(v3)); + addTri( tri_idx++, a, b, c); + } +} + +SGShadowVolume::ShadowCaster::~ShadowCaster() { + delete [] indices ; + delete [] vertices ; + delete [] planeEquations ; + delete [] isFacingLight ; + delete [] neighbourIndices ; + delete [] isSilhouetteEdge ; +} + + +void SGShadowVolume::ShadowCaster::addTri(int p, sgVec3 a, sgVec3 b, sgVec3 c) { + sgVec4 tri_plane; + assert( p >= 0 && p < numTriangles ); + + sgMakePlane ( tri_plane, a, b, c ); + sgCopyVec4(planeEquations[p], tri_plane); + sgCopyVec3(vertices[p*3], a); + sgCopyVec3(vertices[p*3+1], b); + sgCopyVec3(vertices[p*3+2], c); + indices[p*3] = p*3; + indices[p*3+1] = p*3+1; + indices[p*3+2] = p*3+2; +} + +bool SGShadowVolume::ShadowCaster::sameVertex(int edge1, int edge2) { +// const float epsilon = 0.01; // 1cm +// const float epsilon = 0.0; // 1cm +//return false; + if( edge1 == edge2) + return true; + sgVec3 delta_v; + sgSubVec3( delta_v, vertices[edge1], vertices[edge2]); + if( delta_v[SG_X] != 0.0) return false; + if( delta_v[SG_Y] != 0.0) return false; + if( delta_v[SG_Z] != 0.0) return false; + return true; +} + + +//Calculate neighbour faces for each edge +// caution, this is O(n2) +void SGShadowVolume::ShadowCaster::SetConnectivity(void) +{ + int edgeCount = 0; + + //set the neighbour indices to be -1 + for(int ii=0; ii 0.0 ) + isFacingLight[i]=true; + else + isFacingLight[i]=false; + } + + //loop through faces + + for(int t=0; t < numTriangles; t++) { + int v = t * 3; + //if this face is not facing the light, not a silhouette edge + if(!isFacingLight[t]) + { + isSilhouetteEdge[v+0]=false; + isSilhouetteEdge[v+1]=false; + isSilhouetteEdge[v+2]=false; + continue; + } + //loop through edges + for(int i = v ; i < v+3 ; i++) { + //this face is facing the light + //if the neighbouring face is not facing the light, or there is no neighbouring face, + //then this is a silhouette edge + if(neighbourIndices[i]==-1 || !isFacingLight[neighbourIndices[i]]) + isSilhouetteEdge[i]=true; + else + isSilhouetteEdge[i]=false; + } + } +} + +// TODO: everyhting here is constant, store the vertex in a cache buffer and call drawelements +void SGShadowVolume::ShadowCaster::DrawInfiniteShadowVolume(sgVec3 lightPosition, bool drawCaps) +{ + glColor4f(1.0, 1.0, 0.0, 0.5); + //TODO: no need for a quad here +// glBegin(GL_QUADS); + glBegin(GL_TRIANGLES); + { + for(int i=0; iisA(ssgTypeTransform()) ) { + sgMat4 transform; + if( first ) { + ((ssgTransform *) branch)->getTransform( xform ); + first = false; + } else { + ((ssgTransform *) branch)->getTransform(transform); + sgPostMultMat4 ( xform, transform ) ; + } + } + branch = branch->getParent( 0 ); + } + if( first ) + sgMakeIdentMat4 ( xform ) ; +} + +// check the value of