X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=radiant%2Fpatch.h;h=9e1bb16d99f085cf74b131ab63c25898ed5e3fe2;hb=ff94c74142a8d5e10586145b3cc82af2fca62e43;hp=403c43bcc02ee7e920e1dabd1b85a530e90b586b;hpb=f15b9265ecdd46d8e5fc377e62a159b74073f532;p=xonotic%2Fnetradiant.git diff --git a/radiant/patch.h b/radiant/patch.h index 403c43bc..9e1bb16d 100644 --- a/radiant/patch.h +++ b/radiant/patch.h @@ -1,25 +1,25 @@ /* -Copyright (C) 2001-2006, William Joseph. -All Rights Reserved. + Copyright (C) 2001-2006, William Joseph. + All Rights Reserved. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant 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. + GtkRadiant 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. -GtkRadiant 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. + GtkRadiant 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 GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ -#if !defined(INCLUDED_PATCH_H) +#if !defined( INCLUDED_PATCH_H ) #define INCLUDED_PATCH_H /// \file @@ -66,8 +66,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA enum EPatchType { - ePatchTypeQuake3, - ePatchTypeDoom3, + ePatchTypeQuake3, + ePatchTypeDoom3, }; extern int g_PatchSubdivideThreshold; @@ -79,1846 +79,1658 @@ extern int g_PatchSubdivideThreshold; extern std::size_t MAX_PATCH_WIDTH; extern std::size_t MAX_PATCH_HEIGHT; -#define MAX_PATCH_ROWCTRL (((MAX_PATCH_WIDTH-1)-1)/2) -#define MAX_PATCH_COLCTRL (((MAX_PATCH_HEIGHT-1)-1)/2) +#define MAX_PATCH_ROWCTRL ( ( ( MAX_PATCH_WIDTH - 1 ) - 1 ) / 2 ) +#define MAX_PATCH_COLCTRL ( ( ( MAX_PATCH_HEIGHT - 1 ) - 1 ) / 2 ) enum EPatchCap { - eCapBevel, - eCapEndCap, - eCapIBevel, - eCapIEndCap, - eCapCylinder, + eCapBevel, + eCapEndCap, + eCapIBevel, + eCapIEndCap, + eCapCylinder, }; enum EPatchPrefab { - ePlane, - eBevel, - eEndCap, - eCylinder, - eDenseCylinder, - eVeryDenseCylinder, - eSqCylinder, - eCone, - eSphere, - eXactCylinder, - eXactSphere, - eXactCone, + ePlane, + eBevel, + eEndCap, + eCylinder, + eDenseCylinder, + eVeryDenseCylinder, + eSqCylinder, + eCone, + eSphere, + eXactCylinder, + eXactSphere, + eXactCone, }; enum EMatrixMajor { - ROW, COL, + ROW, COL, }; struct BezierCurve { - Vector3 crd; - Vector3 left; - Vector3 right; + Vector3 crd; + Vector3 left; + Vector3 right; }; -const std::size_t BEZIERCURVETREE_MAX_INDEX = std::size_t(1) << (std::numeric_limits::digits - 1); +const std::size_t BEZIERCURVETREE_MAX_INDEX = std::size_t( 1 ) << ( std::numeric_limits::digits - 1 ); struct BezierCurveTree { - std::size_t index; - BezierCurveTree* left; - BezierCurveTree* right; + std::size_t index; + BezierCurveTree* left; + BezierCurveTree* right; }; -inline bool BezierCurveTree_isLeaf(const BezierCurveTree* node) -{ - return node->left == 0 && node->right == 0; +inline bool BezierCurveTree_isLeaf( const BezierCurveTree* node ){ + return node->left == 0 && node->right == 0; } -void BezierCurveTree_Delete(BezierCurveTree *pCurve); +void BezierCurveTree_Delete( BezierCurveTree *pCurve ); -inline VertexPointer vertexpointer_arbitrarymeshvertex(const ArbitraryMeshVertex* array) -{ - return VertexPointer(VertexPointer::pointer(&array->vertex), sizeof(ArbitraryMeshVertex)); +inline VertexPointer vertexpointer_arbitrarymeshvertex( const ArbitraryMeshVertex* array ){ + return VertexPointer( VertexPointer::pointer( &array->vertex ), sizeof( ArbitraryMeshVertex ) ); } typedef PatchControl* PatchControlIter; typedef const PatchControl* PatchControlConstIter; -inline void copy_ctrl(PatchControlIter ctrl, PatchControlConstIter begin, PatchControlConstIter end) -{ - std::copy(begin, end, ctrl); +inline void copy_ctrl( PatchControlIter ctrl, PatchControlConstIter begin, PatchControlConstIter end ){ + std::copy( begin, end, ctrl ); } -const Colour4b colour_corner(0, 255, 0, 255); -const Colour4b colour_inside(255, 0, 255, 255); +const Colour4b colour_corner( 0, 255, 0, 255 ); +const Colour4b colour_inside( 255, 0, 255, 255 ); class Patch; class PatchFilter { public: - virtual bool filter(const Patch& patch) const = 0; +virtual bool filter( const Patch& patch ) const = 0; }; -bool patch_filtered(Patch& patch); -void add_patch_filter(PatchFilter& filter, int mask, bool invert = false); +bool patch_filtered( Patch& patch ); +void add_patch_filter( PatchFilter& filter, int mask, bool invert = false ); -void Patch_addTextureChangedCallback(const SignalHandler& handler); +void Patch_addTextureChangedCallback( const SignalHandler& handler ); void Patch_textureChanged(); -inline void BezierCurveTreeArray_deleteAll(Array& curveTrees) -{ - for(Array::iterator i = curveTrees.begin(); i != curveTrees.end(); ++i) - { - BezierCurveTree_Delete(*i); - } +inline void BezierCurveTreeArray_deleteAll( Array& curveTrees ){ + for ( Array::iterator i = curveTrees.begin(); i != curveTrees.end(); ++i ) + { + BezierCurveTree_Delete( *i ); + } } -inline void PatchControlArray_invert(Array& ctrl, std::size_t width, std::size_t height) -{ - Array tmp(width); - - PatchControlIter from = ctrl.data() + (width * (height - 1)); - PatchControlIter to = ctrl.data(); - for(std::size_t h = 0; h != ((height - 1) >> 1); ++h, to += width, from -= width) - { - copy_ctrl(tmp.data(), to, to + width); - copy_ctrl(to, from, from + width); - copy_ctrl(from, tmp.data(), tmp.data() + width); - } +inline void PatchControlArray_invert( Array& ctrl, std::size_t width, std::size_t height ){ + Array tmp( width ); + + PatchControlIter from = ctrl.data() + ( width * ( height - 1 ) ); + PatchControlIter to = ctrl.data(); + for ( std::size_t h = 0; h != ( ( height - 1 ) >> 1 ); ++h, to += width, from -= width ) + { + copy_ctrl( tmp.data(), to, to + width ); + copy_ctrl( to, from, from + width ); + copy_ctrl( from, tmp.data(), tmp.data() + width ); + } } class PatchTesselation { public: - PatchTesselation() - : m_numStrips(0), m_lenStrips(0), m_nArrayWidth(0), m_nArrayHeight(0) - { - } - Array m_vertices; - Array m_indices; - std::size_t m_numStrips; - std::size_t m_lenStrips; - - Array m_arrayWidth; - std::size_t m_nArrayWidth; - Array m_arrayHeight; - std::size_t m_nArrayHeight; - - Array m_curveTreeU; - Array m_curveTreeV; +PatchTesselation() + : m_numStrips( 0 ), m_lenStrips( 0 ), m_nArrayWidth( 0 ), m_nArrayHeight( 0 ){ +} +Array m_vertices; +Array m_indices; +std::size_t m_numStrips; +std::size_t m_lenStrips; + +Array m_arrayWidth; +std::size_t m_nArrayWidth; +Array m_arrayHeight; +std::size_t m_nArrayHeight; + +Array m_curveTreeU; +Array m_curveTreeV; }; class RenderablePatchWireframe : public OpenGLRenderable { - PatchTesselation& m_tess; +PatchTesselation& m_tess; public: - RenderablePatchWireframe(PatchTesselation& tess) : m_tess(tess) - { - } - void render(RenderStateFlags state) const - { - { +RenderablePatchWireframe( PatchTesselation& tess ) : m_tess( tess ){ +} +void render( RenderStateFlags state ) const { + { #if NV_DRIVER_BUG - glVertexPointer(3, GL_FLOAT, 0, 0); - glDrawArrays(GL_TRIANGLE_FAN, 0, 0); + glVertexPointer( 3, GL_FLOAT, 0, 0 ); + glDrawArrays( GL_TRIANGLE_FAN, 0, 0 ); #endif - std::size_t n = 0; - glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->vertex); - for(std::size_t i = 0; i <= m_tess.m_curveTreeV.size(); ++i) - { - glDrawArrays(GL_LINE_STRIP, GLint(n), GLsizei(m_tess.m_nArrayWidth)); - - if(i == m_tess.m_curveTreeV.size()) break; - - if(!BezierCurveTree_isLeaf(m_tess.m_curveTreeV[i])) - glDrawArrays(GL_LINE_STRIP, GLint(m_tess.m_curveTreeV[i]->index), GLsizei(m_tess.m_nArrayWidth)); - - n += (m_tess.m_arrayHeight[i]*m_tess.m_nArrayWidth); - - } - } - - { - const ArbitraryMeshVertex* p = m_tess.m_vertices.data(); - std::size_t n = m_tess.m_nArrayWidth * sizeof(ArbitraryMeshVertex); - for(std::size_t i = 0; i <= m_tess.m_curveTreeU.size(); ++i) - { - glVertexPointer(3, GL_FLOAT, GLsizei(n), &p->vertex); - glDrawArrays(GL_LINE_STRIP, 0, GLsizei(m_tess.m_nArrayHeight)); - - if(i == m_tess.m_curveTreeU.size()) break; - - if(!BezierCurveTree_isLeaf(m_tess.m_curveTreeU[i])) - { - glVertexPointer(3, GL_FLOAT, GLsizei(n), &(m_tess.m_vertices.data() + (m_tess.m_curveTreeU[i]->index))->vertex); - glDrawArrays(GL_LINE_STRIP, 0, GLsizei(m_tess.m_nArrayHeight)); - } - - p += m_tess.m_arrayWidth[i]; - } - } - } + std::size_t n = 0; + glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex ); + for ( std::size_t i = 0; i <= m_tess.m_curveTreeV.size(); ++i ) + { + glDrawArrays( GL_LINE_STRIP, GLint( n ), GLsizei( m_tess.m_nArrayWidth ) ); + + if ( i == m_tess.m_curveTreeV.size() ) { + break; + } + + if ( !BezierCurveTree_isLeaf( m_tess.m_curveTreeV[i] ) ) { + glDrawArrays( GL_LINE_STRIP, GLint( m_tess.m_curveTreeV[i]->index ), GLsizei( m_tess.m_nArrayWidth ) ); + } + + n += ( m_tess.m_arrayHeight[i] * m_tess.m_nArrayWidth ); + + } + } + + { + const ArbitraryMeshVertex* p = m_tess.m_vertices.data(); + std::size_t n = m_tess.m_nArrayWidth * sizeof( ArbitraryMeshVertex ); + for ( std::size_t i = 0; i <= m_tess.m_curveTreeU.size(); ++i ) + { + glVertexPointer( 3, GL_FLOAT, GLsizei( n ), &p->vertex ); + glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_tess.m_nArrayHeight ) ); + + if ( i == m_tess.m_curveTreeU.size() ) { + break; + } + + if ( !BezierCurveTree_isLeaf( m_tess.m_curveTreeU[i] ) ) { + glVertexPointer( 3, GL_FLOAT, GLsizei( n ), &( m_tess.m_vertices.data() + ( m_tess.m_curveTreeU[i]->index ) )->vertex ); + glDrawArrays( GL_LINE_STRIP, 0, GLsizei( m_tess.m_nArrayHeight ) ); + } + + p += m_tess.m_arrayWidth[i]; + } + } +} }; class RenderablePatchFixedWireframe : public OpenGLRenderable { - PatchTesselation& m_tess; +PatchTesselation& m_tess; public: - RenderablePatchFixedWireframe(PatchTesselation& tess) : m_tess(tess) - { - } - void render(RenderStateFlags state) const - { - glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->vertex); - const RenderIndex* strip_indices = m_tess.m_indices.data(); - for(std::size_t i = 0; ivertex ); + const RenderIndex* strip_indices = m_tess.m_indices.data(); + for ( std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips ) + { + glDrawElements( GL_QUAD_STRIP, GLsizei( m_tess.m_lenStrips ), RenderIndexTypeID, strip_indices ); + } +} }; class RenderablePatchSolid : public OpenGLRenderable { - PatchTesselation& m_tess; +PatchTesselation& m_tess; public: - RenderablePatchSolid(PatchTesselation& tess) : m_tess(tess) - { - } - void RenderNormals() const; - void render(RenderStateFlags state) const - { +RenderablePatchSolid( PatchTesselation& tess ) : m_tess( tess ){ +} +void RenderNormals() const; +void render( RenderStateFlags state ) const { #if 0 - if((state & RENDER_FILL) == 0) - { - RenderablePatchWireframe(m_tess).render(state); - } - else + if ( ( state & RENDER_FILL ) == 0 ) { + RenderablePatchWireframe( m_tess ).render( state ); + } + else #endif - { - if((state & RENDER_BUMP) != 0) - { - if(GlobalShaderCache().useShaderLanguage()) - { - glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->normal); - glVertexAttribPointerARB(c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->texcoord); - glVertexAttribPointerARB(c_attr_Tangent, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->tangent); - glVertexAttribPointerARB(c_attr_Binormal, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->bitangent); - } - else - { - glVertexAttribPointerARB(11, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->normal); - glVertexAttribPointerARB(8, 2, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->texcoord); - glVertexAttribPointerARB(9, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->tangent); - glVertexAttribPointerARB(10, 3, GL_FLOAT, 0, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->bitangent); - } - } - else - { - glNormalPointer(GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->normal); - glTexCoordPointer(2, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->texcoord); - } - glVertexPointer(3, GL_FLOAT, sizeof(ArbitraryMeshVertex), &m_tess.m_vertices.data()->vertex); - const RenderIndex* strip_indices = m_tess.m_indices.data(); - for(std::size_t i = 0; inormal ); + glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord ); + glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->tangent ); + glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->bitangent ); + } + else + { + glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->normal ); + glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord ); + glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->tangent ); + glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->bitangent ); + } + } + else + { + glNormalPointer( GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->normal ); + glTexCoordPointer( 2, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->texcoord ); + } + glVertexPointer( 3, GL_FLOAT, sizeof( ArbitraryMeshVertex ), &m_tess.m_vertices.data()->vertex ); + const RenderIndex* strip_indices = m_tess.m_indices.data(); + for ( std::size_t i = 0; i < m_tess.m_numStrips; i++, strip_indices += m_tess.m_lenStrips ) + { + glDrawElements( GL_QUAD_STRIP, GLsizei( m_tess.m_lenStrips ), RenderIndexTypeID, strip_indices ); + } + } + +#if defined( _DEBUG ) + RenderNormals(); #endif - } +} }; // parametric surface defined by quadratic bezier control curves class Patch : - public XMLImporter, - public XMLExporter, - public TransformNode, - public Bounded, - public Cullable, - public Snappable, - public Undoable, - public Filterable, - public Nameable + public XMLImporter, + public XMLExporter, + public TransformNode, + public Bounded, + public Cullable, + public Snappable, + public Undoable, + public Filterable, + public Nameable +{ +class xml_state_t +{ +public: +enum EState +{ + eDefault, + ePatch, + eMatrix, + eShader, +}; +xml_state_t( EState state ) + : m_state( state ) +{} +EState state() const { + return m_state; +} +const char* content() const { + return m_content.c_str(); +} +std::size_t write( const char* buffer, std::size_t length ){ + return m_content.write( buffer, length ); +} +private: +EState m_state; +StringOutputStream m_content; +}; + +std::vector m_xml_state; + +typedef Array PatchControlArray; + +class SavedState : public UndoMemento { - class xml_state_t - { - public: - enum EState - { - eDefault, - ePatch, - eMatrix, - eShader, - }; - xml_state_t(EState state) - : m_state(state) - {} - EState state() const - { - return m_state; - } - const char* content() const - { - return m_content.c_str(); - } - std::size_t write(const char* buffer, std::size_t length) - { - return m_content.write(buffer, length); - } - private: - EState m_state; - StringOutputStream m_content; - }; - - std::vector m_xml_state; - - typedef Array PatchControlArray; - - class SavedState : public UndoMemento - { - public: - SavedState( - std::size_t width, - std::size_t height, - const PatchControlArray& ctrl, - const char* shader, - bool patchDef3, - std::size_t subdivisions_x, - std::size_t subdivisions_y - ) : - m_width(width), - m_height(height), - m_shader(shader), - m_ctrl(ctrl), - m_patchDef3(patchDef3), - m_subdivisions_x(subdivisions_x), - m_subdivisions_y(subdivisions_y) - { - } - - void release() - { - delete this; - } - - std::size_t m_width, m_height; - CopiedString m_shader; - PatchControlArray m_ctrl; - bool m_patchDef3; - std::size_t m_subdivisions_x; - std::size_t m_subdivisions_y; - }; +public: +SavedState( + std::size_t width, + std::size_t height, + const PatchControlArray& ctrl, + const char* shader, + bool patchDef3, + std::size_t subdivisions_x, + std::size_t subdivisions_y + ) : + m_width( width ), + m_height( height ), + m_shader( shader ), + m_ctrl( ctrl ), + m_patchDef3( patchDef3 ), + m_subdivisions_x( subdivisions_x ), + m_subdivisions_y( subdivisions_y ){ +} + +void release(){ + delete this; +} + +std::size_t m_width, m_height; +std::string m_shader; +PatchControlArray m_ctrl; +bool m_patchDef3; +std::size_t m_subdivisions_x; +std::size_t m_subdivisions_y; +}; public: - class Observer - { - public: - virtual void allocate(std::size_t size) = 0; - }; +class Observer +{ +public: +virtual void allocate( std::size_t size ) = 0; +}; private: - typedef UniqueSet Observers; - Observers m_observers; +typedef UniqueSet Observers; +Observers m_observers; - scene::Node* m_node; +scene::Node* m_node; - AABB m_aabb_local; // local bbox +AABB m_aabb_local; // local bbox - CopiedString m_shader; - Shader* m_state; +std::string m_shader; +Shader* m_state; - std::size_t m_width; - std::size_t m_height; +std::size_t m_width; +std::size_t m_height; public: - bool m_patchDef3; - std::size_t m_subdivisions_x; - std::size_t m_subdivisions_y; +bool m_patchDef3; +std::size_t m_subdivisions_x; +std::size_t m_subdivisions_y; private: - - UndoObserver* m_undoable_observer; - MapFile* m_map; - // dynamically allocated array of control points, size is m_width*m_height - PatchControlArray m_ctrl; - PatchControlArray m_ctrlTransformed; +UndoObserver* m_undoable_observer; +MapFile* m_map; - PatchTesselation m_tess; - RenderablePatchSolid m_render_solid; - RenderablePatchWireframe m_render_wireframe; - RenderablePatchFixedWireframe m_render_wireframe_fixed; +// dynamically allocated array of control points, size is m_width*m_height +PatchControlArray m_ctrl; +PatchControlArray m_ctrlTransformed; - static Shader* m_state_ctrl; - static Shader* m_state_lattice; - VertexBuffer m_ctrl_vertices; - RenderableVertexBuffer m_render_ctrl; - IndexBuffer m_lattice_indices; - RenderableIndexBuffer m_render_lattice; +PatchTesselation m_tess; +RenderablePatchSolid m_render_solid; +RenderablePatchWireframe m_render_wireframe; +RenderablePatchFixedWireframe m_render_wireframe_fixed; - bool m_bOverlay; +static Shader* m_state_ctrl; +static Shader* m_state_lattice; +VertexBuffer m_ctrl_vertices; +RenderableVertexBuffer m_render_ctrl; +IndexBuffer m_lattice_indices; +RenderableIndexBuffer m_render_lattice; - bool m_transformChanged; - Callback m_evaluateTransform; - Callback m_boundsChanged; +bool m_bOverlay; - void construct() - { - m_bOverlay = false; - m_width = m_height = 0; +bool m_transformChanged; +Callback m_evaluateTransform; +Callback m_boundsChanged; - m_patchDef3 = false; - m_subdivisions_x = 0; - m_subdivisions_y = 0; +void construct(){ + m_bOverlay = false; + m_width = m_height = 0; - check_shader(); - captureShader(); + m_patchDef3 = false; + m_subdivisions_x = 0; + m_subdivisions_y = 0; - m_xml_state.push_back(xml_state_t::eDefault); - } + check_shader(); + captureShader(); + + m_xml_state.push_back( xml_state_t::eDefault ); +} public: - Callback m_lightsChanged; - - static int m_CycleCapIndex;// = 0; - static EPatchType m_type; - - STRING_CONSTANT(Name, "Patch"); - - Patch(scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged) : - m_node(&node), - m_shader(texdef_name_default()), - m_state(0), - m_undoable_observer(0), - m_map(0), - m_render_solid(m_tess), - m_render_wireframe(m_tess), - m_render_wireframe_fixed(m_tess), - m_render_ctrl(GL_POINTS, m_ctrl_vertices), - m_render_lattice(GL_LINES, m_lattice_indices, m_ctrl_vertices), - m_transformChanged(false), - m_evaluateTransform(evaluateTransform), - m_boundsChanged(boundsChanged) - { - construct(); - } - Patch(const Patch& other, scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged) : - m_node(&node), - m_shader(texdef_name_default()), - m_state(0), - m_undoable_observer(0), - m_map(0), - m_render_solid(m_tess), - m_render_wireframe(m_tess), - m_render_wireframe_fixed(m_tess), - m_render_ctrl(GL_POINTS, m_ctrl_vertices), - m_render_lattice(GL_LINES, m_lattice_indices, m_ctrl_vertices), - m_transformChanged(false), - m_evaluateTransform(evaluateTransform), - m_boundsChanged(boundsChanged) - { - construct(); - - m_patchDef3 = other.m_patchDef3; - m_subdivisions_x = other.m_subdivisions_x; - m_subdivisions_y = other.m_subdivisions_y; - setDims(other.m_width, other.m_height); - copy_ctrl(m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data()+(m_width*m_height)); - SetShader(other.m_shader.c_str()); - controlPointsChanged(); - } - - Patch(const Patch& other) : - XMLImporter(other), - XMLExporter(other), - TransformNode(other), - Bounded(other), - Cullable(other), - Snappable(), - Undoable(other), - Filterable(other), - Nameable(other), - m_state(0), - m_undoable_observer(0), - m_map(0), - m_render_solid(m_tess), - m_render_wireframe(m_tess), - m_render_wireframe_fixed(m_tess), - m_render_ctrl(GL_POINTS, m_ctrl_vertices), - m_render_lattice(GL_LINES, m_lattice_indices, m_ctrl_vertices), - m_transformChanged(false), - m_evaluateTransform(other.m_evaluateTransform), - m_boundsChanged(other.m_boundsChanged) - { - m_bOverlay = false; - - m_patchDef3 = other.m_patchDef3; - m_subdivisions_x = other.m_subdivisions_x; - m_subdivisions_y = other.m_subdivisions_y; - setDims(other.m_width, other.m_height); - copy_ctrl(m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data()+(m_width*m_height)); - SetShader(other.m_shader.c_str()); - controlPointsChanged(); - } - - ~Patch() - { - BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeU); - BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeV); - - releaseShader(); - - ASSERT_MESSAGE(m_observers.empty(), "Patch::~Patch: observers still attached"); - } - - InstanceCounter m_instanceCounter; - void instanceAttach(const scene::Path& path) - { - if(++m_instanceCounter.m_count == 1) - { - m_state->incrementUsed(); - m_map = path_find_mapfile(path.begin(), path.end()); - m_undoable_observer = GlobalUndoSystem().observer(this); - GlobalFilterSystem().registerFilterable(*this); - } - else - { - ASSERT_MESSAGE(path_find_mapfile(path.begin(), path.end()) == m_map, "node is instanced across more than one file"); - } - } - void instanceDetach(const scene::Path& path) - { - if(--m_instanceCounter.m_count == 0) - { - m_map = 0; - m_undoable_observer = 0; - GlobalUndoSystem().release(this); - GlobalFilterSystem().unregisterFilterable(*this); - m_state->decrementUsed(); - } - } - - const char* name() const - { - return "patch"; - } - void attach(const NameCallback& callback) - { - } - void detach(const NameCallback& callback) - { - } - - void attach(Observer* observer) - { - observer->allocate(m_width * m_height); - - m_observers.insert(observer); - } - void detach(Observer* observer) - { - m_observers.erase(observer); - } - - void updateFiltered() - { - if(m_node != 0) - { - if(patch_filtered(*this)) - { - m_node->enable(scene::Node::eFiltered); - } - else - { - m_node->disable(scene::Node::eFiltered); - } - } - } - - void onAllocate(std::size_t size) - { - for(Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) - { - (*i)->allocate(size); - } - } - - const Matrix4& localToParent() const - { - return g_matrix4_identity; - } - const AABB& localAABB() const - { - return m_aabb_local; - } - VolumeIntersectionValue intersectVolume(const VolumeTest& test, const Matrix4& localToWorld) const - { - return test.TestAABB(m_aabb_local, localToWorld); - } - void render_solid(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const - { - renderer.SetState(m_state, Renderer::eFullMaterials); - renderer.addRenderable(m_render_solid, localToWorld); - } - void render_wireframe(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const - { - renderer.SetState(m_state, Renderer::eFullMaterials); - if(m_patchDef3) - { - renderer.addRenderable(m_render_wireframe_fixed, localToWorld); - } - else - { - renderer.addRenderable(m_render_wireframe, localToWorld); - } - } - - void render_component(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const - { - renderer.SetState(m_state_lattice, Renderer::eWireframeOnly); - renderer.SetState(m_state_lattice, Renderer::eFullMaterials); - renderer.addRenderable(m_render_lattice, localToWorld); - - renderer.SetState(m_state_ctrl, Renderer::eWireframeOnly); - renderer.SetState(m_state_ctrl, Renderer::eFullMaterials); - renderer.addRenderable(m_render_ctrl, localToWorld); - } - void testSelect(Selector& selector, SelectionTest& test) - { - SelectionIntersection best; - IndexPointer::index_type* pIndex = m_tess.m_indices.data(); - for(std::size_t s=0; s TransformChangedCaller; - - void evaluateTransform() - { - if(m_transformChanged) - { - m_transformChanged = false; - revertTransform(); - m_evaluateTransform(); - } - } - - void revertTransform() - { - m_ctrlTransformed = m_ctrl; - } - void freezeTransform() - { - undoSave(); - evaluateTransform(); - ASSERT_MESSAGE(m_ctrlTransformed.size() == m_ctrl.size(), "Patch::freeze: size mismatch"); - std::copy(m_ctrlTransformed.begin(), m_ctrlTransformed.end(), m_ctrl.begin()); - } - - void controlPointsChanged() - { - transformChanged(); - evaluateTransform(); - UpdateCachedData(); - } - bool isValid() const; - - void snapto(float snap) - { - undoSave(); - - for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) - { - vector3_snap((*i).m_vertex, snap); - } - - controlPointsChanged(); - } - - - - - void RenderDebug(RenderStateFlags state) const; - void RenderNormals(RenderStateFlags state) const; - - void pushElement(const XMLElement& element) - { - switch(m_xml_state.back().state()) - { - case xml_state_t::eDefault: - ASSERT_MESSAGE(string_equal(element.name(), "patch"), "parse error"); - m_xml_state.push_back(xml_state_t::ePatch); - break; - case xml_state_t::ePatch: - if(string_equal(element.name(), "matrix")) - { - setDims(atoi(element.attribute("width")), atoi(element.attribute("height"))); - m_xml_state.push_back(xml_state_t::eMatrix); - } - else if(string_equal(element.name(), "shader")) - { - m_xml_state.push_back(xml_state_t::eShader); - } - break; - default: - ERROR_MESSAGE("parse error"); - } - - } - void popElement(const char* name) - { - switch(m_xml_state.back().state()) - { - case xml_state_t::eDefault: - ERROR_MESSAGE("parse error"); - break; - case xml_state_t::ePatch: - break; - case xml_state_t::eMatrix: - { - StringTokeniser content(m_xml_state.back().content()); - - for(PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i) - { - (*i).m_vertex[0] = string_read_float(content.getToken()); - (*i).m_vertex[1] = string_read_float(content.getToken()); - (*i).m_vertex[2] = string_read_float(content.getToken()); - (*i).m_texcoord[0] = string_read_float(content.getToken()); - (*i).m_texcoord[1] = string_read_float(content.getToken()); - } - controlPointsChanged(); - } - break; - case xml_state_t::eShader: - { - SetShader(m_xml_state.back().content()); - } - break; - default: - ERROR_MESSAGE("parse error"); - } - - ASSERT_MESSAGE(!m_xml_state.empty(), "popping empty stack"); - m_xml_state.pop_back(); - } - std::size_t write(const char* buffer, std::size_t length) - { - switch(m_xml_state.back().state()) - { - case xml_state_t::eDefault: - break; - case xml_state_t::ePatch: - break; - case xml_state_t::eMatrix: - case xml_state_t::eShader: - return m_xml_state.back().write(buffer, length); - break; - default: - ERROR_MESSAGE("parse error"); - } - return length; - } - - void exportXML(XMLImporter& importer) - { - StaticElement patchElement("patch"); - importer.pushElement(patchElement); - - { - const StaticElement element("shader"); - importer.pushElement(element); - importer.write(m_shader.c_str(), strlen(m_shader.c_str())); - importer.popElement(element.name()); - } - - { - char width[16], height[16]; - sprintf(width, "%u", Unsigned(m_width)); - sprintf(height, "%u", Unsigned(m_height)); - StaticElement element("matrix"); - element.insertAttribute("width", width); - element.insertAttribute("height", height); - - importer.pushElement(element); - { - for(PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i) - { - importer << (*i).m_vertex[0] - << ' ' << (*i).m_vertex[1] - << ' ' << (*i).m_vertex[2] - << ' ' << (*i).m_texcoord[0] - << ' ' << (*i).m_texcoord[1]; - } - } - importer.popElement(element.name()); - } - - importer.popElement(patchElement.name()); - } - - void UpdateCachedData(); - - const char *GetShader() const - { - return m_shader.c_str(); - } - void SetShader(const char* name) - { - ASSERT_NOTNULL(name); - - if(shader_equal(m_shader.c_str(), name)) - return; - - undoSave(); - - if(m_instanceCounter.m_count != 0) - { - m_state->decrementUsed(); - } - releaseShader(); - m_shader = name; - captureShader(); - if(m_instanceCounter.m_count != 0) - { - m_state->incrementUsed(); - } - - check_shader(); - Patch_textureChanged(); - } - int getShaderFlags() const - { - if(m_state != 0) - { - return m_state->getFlags(); - } - return 0; - } - - typedef PatchControl* iterator; - typedef const PatchControl* const_iterator; - - iterator begin() - { - return m_ctrl.data(); - } - const_iterator begin() const - { - return m_ctrl.data(); - } - iterator end() - { - return m_ctrl.data() + m_ctrl.size(); - } - const_iterator end() const - { - return m_ctrl.data() + m_ctrl.size(); - } - - PatchControlArray& getControlPoints() - { - return m_ctrl; - } - PatchControlArray& getControlPointsTransformed() - { - return m_ctrlTransformed; - } - - void setDims (std::size_t w, std::size_t h); - std::size_t getWidth() const - { - return m_width; - } - std::size_t getHeight() const - { - return m_height; - } - PatchControl& ctrlAt(std::size_t row, std::size_t col) - { - return m_ctrl[row*m_width+col]; - } - const PatchControl& ctrlAt(std::size_t row, std::size_t col) const - { - return m_ctrl[row*m_width+col]; - } - - void ConstructPrefab(const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width = 3, std::size_t height = 3); - void constructPlane(const AABB& aabb, int axis, std::size_t width, std::size_t height); - void InvertMatrix(); - void TransposeMatrix(); - void Redisperse(EMatrixMajor mt); - void Smooth(EMatrixMajor mt); - void InsertRemove(bool bInsert, bool bColumn, bool bFirst); - Patch* MakeCap(Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst); - void ConstructSeam(EPatchCap eType, Vector3* p, std::size_t width); - - void FlipTexture(int nAxis); - void TranslateTexture(float s, float t); - void ScaleTexture(float s, float t); - void RotateTexture(float angle); - void SetTextureRepeat(float s, float t); // call with s=1 t=1 for FIT - void CapTexture(); - void NaturalTexture(); - void ProjectTexture(int nAxis); - - void undoSave() - { - if(m_map != 0) - { - m_map->changed(); - } - if(m_undoable_observer != 0) - { - m_undoable_observer->save(this); - } - } - - UndoMemento* exportState() const - { - return new SavedState(m_width, m_height, m_ctrl, m_shader.c_str(), m_patchDef3, m_subdivisions_x, m_subdivisions_y); - } - void importState(const UndoMemento* state) - { - undoSave(); - - const SavedState& other = *(static_cast(state)); - - // begin duplicate of SavedState copy constructor, needs refactoring - - // copy construct - { - m_width = other.m_width; - m_height = other.m_height; - SetShader(other.m_shader.c_str()); - m_ctrl = other.m_ctrl; - onAllocate(m_ctrl.size()); - m_patchDef3 = other.m_patchDef3; - m_subdivisions_x = other.m_subdivisions_x; - m_subdivisions_y = other.m_subdivisions_y; - } - - // end duplicate code - - Patch_textureChanged(); - - controlPointsChanged(); - } - - static void constructStatic(EPatchType type) - { - Patch::m_type = type; - Patch::m_state_ctrl = GlobalShaderCache().capture("$POINT"); - Patch::m_state_lattice = GlobalShaderCache().capture("$LATTICE"); - } - - static void destroyStatic() - { - GlobalShaderCache().release("$LATTICE"); - GlobalShaderCache().release("$POINT"); - } +Callback m_lightsChanged; + +static int m_CycleCapIndex; // = 0; +static EPatchType m_type; + +STRING_CONSTANT( Name, "Patch" ); + +Patch( scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) : + m_node( &node ), + m_shader( texdef_name_default() ), + m_state( 0 ), + m_undoable_observer( 0 ), + m_map( 0 ), + m_render_solid( m_tess ), + m_render_wireframe( m_tess ), + m_render_wireframe_fixed( m_tess ), + m_render_ctrl( GL_POINTS, m_ctrl_vertices ), + m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ), + m_transformChanged( false ), + m_evaluateTransform( evaluateTransform ), + m_boundsChanged( boundsChanged ){ + construct(); +} +Patch( const Patch& other, scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) : + m_node( &node ), + m_shader( texdef_name_default() ), + m_state( 0 ), + m_undoable_observer( 0 ), + m_map( 0 ), + m_render_solid( m_tess ), + m_render_wireframe( m_tess ), + m_render_wireframe_fixed( m_tess ), + m_render_ctrl( GL_POINTS, m_ctrl_vertices ), + m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ), + m_transformChanged( false ), + m_evaluateTransform( evaluateTransform ), + m_boundsChanged( boundsChanged ){ + construct(); + + m_patchDef3 = other.m_patchDef3; + m_subdivisions_x = other.m_subdivisions_x; + m_subdivisions_y = other.m_subdivisions_y; + setDims( other.m_width, other.m_height ); + copy_ctrl( m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data() + ( m_width * m_height ) ); + SetShader( other.m_shader.c_str() ); + controlPointsChanged(); +} + +Patch( const Patch& other ) : + XMLImporter( other ), + XMLExporter( other ), + TransformNode( other ), + Bounded( other ), + Cullable( other ), + Snappable(), + Undoable( other ), + Filterable( other ), + Nameable( other ), + m_state( 0 ), + m_undoable_observer( 0 ), + m_map( 0 ), + m_render_solid( m_tess ), + m_render_wireframe( m_tess ), + m_render_wireframe_fixed( m_tess ), + m_render_ctrl( GL_POINTS, m_ctrl_vertices ), + m_render_lattice( GL_LINES, m_lattice_indices, m_ctrl_vertices ), + m_transformChanged( false ), + m_evaluateTransform( other.m_evaluateTransform ), + m_boundsChanged( other.m_boundsChanged ){ + m_bOverlay = false; + + m_patchDef3 = other.m_patchDef3; + m_subdivisions_x = other.m_subdivisions_x; + m_subdivisions_y = other.m_subdivisions_y; + setDims( other.m_width, other.m_height ); + copy_ctrl( m_ctrl.data(), other.m_ctrl.data(), other.m_ctrl.data() + ( m_width * m_height ) ); + SetShader( other.m_shader.c_str() ); + controlPointsChanged(); +} + +~Patch(){ + BezierCurveTreeArray_deleteAll( m_tess.m_curveTreeU ); + BezierCurveTreeArray_deleteAll( m_tess.m_curveTreeV ); + + releaseShader(); + + ASSERT_MESSAGE( m_observers.empty(), "Patch::~Patch: observers still attached" ); +} + +InstanceCounter m_instanceCounter; +void instanceAttach( const scene::Path& path ){ + if ( ++m_instanceCounter.m_count == 1 ) { + m_state->incrementUsed(); + m_map = path_find_mapfile( path.begin(), path.end() ); + m_undoable_observer = GlobalUndoSystem().observer( this ); + GlobalFilterSystem().registerFilterable( *this ); + } + else + { + ASSERT_MESSAGE( path_find_mapfile( path.begin(), path.end() ) == m_map, "node is instanced across more than one file" ); + } +} +void instanceDetach( const scene::Path& path ){ + if ( --m_instanceCounter.m_count == 0 ) { + m_map = 0; + m_undoable_observer = 0; + GlobalUndoSystem().release( this ); + GlobalFilterSystem().unregisterFilterable( *this ); + m_state->decrementUsed(); + } +} + +const char* name() const { + return "patch"; +} +void attach( const NameCallback& callback ){ +} +void detach( const NameCallback& callback ){ +} + +void attach( Observer* observer ){ + observer->allocate( m_width * m_height ); + + m_observers.insert( observer ); +} +void detach( Observer* observer ){ + m_observers.erase( observer ); +} + +void updateFiltered(){ + if ( m_node != 0 ) { + if ( patch_filtered( *this ) ) { + m_node->enable( scene::Node::eFiltered ); + } + else + { + m_node->disable( scene::Node::eFiltered ); + } + } +} + +void onAllocate( std::size_t size ){ + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->allocate( size ); + } +} + +const Matrix4& localToParent() const { + return g_matrix4_identity; +} +const AABB& localAABB() const { + return m_aabb_local; +} +VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { + return test.TestAABB( m_aabb_local, localToWorld ); +} +void render_solid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + renderer.SetState( m_state, Renderer::eFullMaterials ); + renderer.addRenderable( m_render_solid, localToWorld ); +} +void render_wireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + renderer.SetState( m_state, Renderer::eFullMaterials ); + if ( m_patchDef3 ) { + renderer.addRenderable( m_render_wireframe_fixed, localToWorld ); + } + else + { + renderer.addRenderable( m_render_wireframe, localToWorld ); + } +} + +void render_component( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + renderer.SetState( m_state_lattice, Renderer::eWireframeOnly ); + renderer.SetState( m_state_lattice, Renderer::eFullMaterials ); + renderer.addRenderable( m_render_lattice, localToWorld ); + + renderer.SetState( m_state_ctrl, Renderer::eWireframeOnly ); + renderer.SetState( m_state_ctrl, Renderer::eFullMaterials ); + renderer.addRenderable( m_render_ctrl, localToWorld ); +} +void testSelect( Selector& selector, SelectionTest& test ){ + SelectionIntersection best; + IndexPointer::index_type* pIndex = m_tess.m_indices.data(); + for ( std::size_t s = 0; s < m_tess.m_numStrips; s++ ) + { + test.TestQuadStrip( vertexpointer_arbitrarymeshvertex( m_tess.m_vertices.data() ), IndexPointer( pIndex, m_tess.m_lenStrips ), best ); + pIndex += m_tess.m_lenStrips; + } + if ( best.valid() ) { + selector.addIntersection( best ); + } +} +void transform( const Matrix4& matrix ){ + for ( PatchControlIter i = m_ctrlTransformed.data(); i != m_ctrlTransformed.data() + m_ctrlTransformed.size(); ++i ) + { + matrix4_transform_point( matrix, ( *i ).m_vertex ); + } + + if ( matrix4_handedness( matrix ) == MATRIX4_LEFTHANDED ) { + PatchControlArray_invert( m_ctrlTransformed, m_width, m_height ); + } + UpdateCachedData(); +} +void transformChanged(){ + m_transformChanged = true; + m_lightsChanged(); + SceneChangeNotify(); +} +typedef MemberCaller TransformChangedCaller; + +void evaluateTransform(){ + if ( m_transformChanged ) { + m_transformChanged = false; + revertTransform(); + m_evaluateTransform(); + } +} + +void revertTransform(){ + m_ctrlTransformed = m_ctrl; +} +void freezeTransform(){ + undoSave(); + evaluateTransform(); + ASSERT_MESSAGE( m_ctrlTransformed.size() == m_ctrl.size(), "Patch::freeze: size mismatch" ); + std::copy( m_ctrlTransformed.begin(), m_ctrlTransformed.end(), m_ctrl.begin() ); +} + +void controlPointsChanged(){ + transformChanged(); + evaluateTransform(); + UpdateCachedData(); +} +bool isValid() const; + +void snapto( float snap ){ + undoSave(); + + for ( PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i ) + { + vector3_snap( ( *i ).m_vertex, snap ); + } + + controlPointsChanged(); +} + + + + +void RenderDebug( RenderStateFlags state ) const; +void RenderNormals( RenderStateFlags state ) const; + +void pushElement( const XMLElement& element ){ + switch ( m_xml_state.back().state() ) + { + case xml_state_t::eDefault: + ASSERT_MESSAGE( string_equal( element.name(), "patch" ), "parse error" ); + m_xml_state.push_back( xml_state_t::ePatch ); + break; + case xml_state_t::ePatch: + if ( string_equal( element.name(), "matrix" ) ) { + setDims( atoi( element.attribute( "width" ) ), atoi( element.attribute( "height" ) ) ); + m_xml_state.push_back( xml_state_t::eMatrix ); + } + else if ( string_equal( element.name(), "shader" ) ) { + m_xml_state.push_back( xml_state_t::eShader ); + } + break; + default: + ERROR_MESSAGE( "parse error" ); + } + +} +void popElement( const char* name ){ + switch ( m_xml_state.back().state() ) + { + case xml_state_t::eDefault: + ERROR_MESSAGE( "parse error" ); + break; + case xml_state_t::ePatch: + break; + case xml_state_t::eMatrix: + { + StringTokeniser content( m_xml_state.back().content() ); + + for ( PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i ) + { + ( *i ).m_vertex[0] = string_read_float( content.getToken() ); + ( *i ).m_vertex[1] = string_read_float( content.getToken() ); + ( *i ).m_vertex[2] = string_read_float( content.getToken() ); + ( *i ).m_texcoord[0] = string_read_float( content.getToken() ); + ( *i ).m_texcoord[1] = string_read_float( content.getToken() ); + } + controlPointsChanged(); + } + break; + case xml_state_t::eShader: + { + SetShader( m_xml_state.back().content() ); + } + break; + default: + ERROR_MESSAGE( "parse error" ); + } + + ASSERT_MESSAGE( !m_xml_state.empty(), "popping empty stack" ); + m_xml_state.pop_back(); +} +std::size_t write( const char* buffer, std::size_t length ){ + switch ( m_xml_state.back().state() ) + { + case xml_state_t::eDefault: + break; + case xml_state_t::ePatch: + break; + case xml_state_t::eMatrix: + case xml_state_t::eShader: + return m_xml_state.back().write( buffer, length ); + break; + default: + ERROR_MESSAGE( "parse error" ); + } + return length; +} + +void exportXML( XMLImporter& importer ){ + StaticElement patchElement( "patch" ); + importer.pushElement( patchElement ); + + { + const StaticElement element( "shader" ); + importer.pushElement( element ); + importer.write( m_shader.c_str(), strlen( m_shader.c_str() ) ); + importer.popElement( element.name() ); + } + + { + char width[16], height[16]; + sprintf( width, "%u", Unsigned( m_width ) ); + sprintf( height, "%u", Unsigned( m_height ) ); + StaticElement element( "matrix" ); + element.insertAttribute( "width", width ); + element.insertAttribute( "height", height ); + + importer.pushElement( element ); + { + for ( PatchControlIter i = m_ctrl.data(), end = m_ctrl.data() + m_ctrl.size(); i != end; ++i ) + { + importer << ( *i ).m_vertex[0] + << ' ' << ( *i ).m_vertex[1] + << ' ' << ( *i ).m_vertex[2] + << ' ' << ( *i ).m_texcoord[0] + << ' ' << ( *i ).m_texcoord[1]; + } + } + importer.popElement( element.name() ); + } + + importer.popElement( patchElement.name() ); +} + +void UpdateCachedData(); + +const char *GetShader() const { + return m_shader.c_str(); +} +void SetShader( const char* name ){ + ASSERT_NOTNULL( name ); + + if ( shader_equal( m_shader.c_str(), name ) ) { + return; + } + + undoSave(); + + if ( m_instanceCounter.m_count != 0 ) { + m_state->decrementUsed(); + } + releaseShader(); + m_shader = name; + captureShader(); + if ( m_instanceCounter.m_count != 0 ) { + m_state->incrementUsed(); + } + + check_shader(); + Patch_textureChanged(); +} +int getShaderFlags() const { + if ( m_state != 0 ) { + return m_state->getFlags(); + } + return 0; +} + +typedef PatchControlArray::iterator iterator; +typedef PatchControlArray::const_iterator const_iterator; + +iterator begin(){ + return m_ctrl.begin(); +} +const_iterator begin() const { + return m_ctrl.begin(); +} +iterator end(){ + return m_ctrl.end(); +} +const_iterator end() const { + return m_ctrl.end(); +} + +PatchControlArray& getControlPoints(){ + return m_ctrl; +} +PatchControlArray& getControlPointsTransformed(){ + return m_ctrlTransformed; +} + +void setDims( std::size_t w, std::size_t h ); +std::size_t getWidth() const { + return m_width; +} +std::size_t getHeight() const { + return m_height; +} +PatchControl& ctrlAt( std::size_t row, std::size_t col ){ + return m_ctrl[row * m_width + col]; +} +const PatchControl& ctrlAt( std::size_t row, std::size_t col ) const { + return m_ctrl[row * m_width + col]; +} + +void ConstructPrefab( const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width = 3, std::size_t height = 3 ); +void constructPlane( const AABB& aabb, int axis, std::size_t width, std::size_t height ); +void InvertMatrix(); +void TransposeMatrix(); +void Redisperse( EMatrixMajor mt ); +void Smooth( EMatrixMajor mt ); +void InsertRemove( bool bInsert, bool bColumn, bool bFirst ); +Patch* MakeCap( Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst ); +void ConstructSeam( EPatchCap eType, Vector3* p, std::size_t width ); + +void FlipTexture( int nAxis ); +void TranslateTexture( float s, float t ); +void ScaleTexture( float s, float t ); +void RotateTexture( float angle ); +void SetTextureRepeat( float s, float t ); // call with s=1 t=1 for FIT +void CapTexture(); +void NaturalTexture(); +void ProjectTexture( int nAxis ); + +void undoSave(){ + if ( m_map != 0 ) { + m_map->changed(); + } + if ( m_undoable_observer != 0 ) { + m_undoable_observer->save( this ); + } +} + +UndoMemento* exportState() const { + return new SavedState( m_width, m_height, m_ctrl, m_shader.c_str(), m_patchDef3, m_subdivisions_x, m_subdivisions_y ); +} +void importState( const UndoMemento* state ){ + undoSave(); + + const SavedState& other = *( static_cast( state ) ); + + // begin duplicate of SavedState copy constructor, needs refactoring + + // copy construct + { + m_width = other.m_width; + m_height = other.m_height; + SetShader( other.m_shader.c_str() ); + m_ctrl = other.m_ctrl; + onAllocate( m_ctrl.size() ); + m_patchDef3 = other.m_patchDef3; + m_subdivisions_x = other.m_subdivisions_x; + m_subdivisions_y = other.m_subdivisions_y; + } + + // end duplicate code + + Patch_textureChanged(); + + controlPointsChanged(); +} + +static void constructStatic( EPatchType type ){ + Patch::m_type = type; + Patch::m_state_ctrl = GlobalShaderCache().capture( "$POINT" ); + Patch::m_state_lattice = GlobalShaderCache().capture( "$LATTICE" ); +} + +static void destroyStatic(){ + GlobalShaderCache().release( "$LATTICE" ); + GlobalShaderCache().release( "$POINT" ); +} private: - void captureShader() - { - m_state = GlobalShaderCache().capture(m_shader.c_str()); - } - - void releaseShader() - { - GlobalShaderCache().release(m_shader.c_str()); - } - - void check_shader() - { - if(!shader_valid(GetShader())) - { - globalErrorStream() << "patch has invalid texture name: '" << GetShader() << "'\n"; - } - } - - void InsertPoints(EMatrixMajor mt, bool bFirst); - void RemovePoints(EMatrixMajor mt, bool bFirst); - - void AccumulateBBox(); - - void TesselateSubMatrixFixed(ArbitraryMeshVertex* vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl* subMatrix[3][3]); - - // uses binary trees representing bezier curves to recursively tesselate a bezier sub-patch - void TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY, - std::size_t offStartX, std::size_t offStartY, - std::size_t offEndX, std::size_t offEndY, - std::size_t nFlagsX, std::size_t nFlagsY, - Vector3& left, Vector3& mid, Vector3& right, - Vector2& texLeft, Vector2& texMid, Vector2& texRight, - bool bTranspose ); - - // tesselates the entire surface - void BuildTesselationCurves(EMatrixMajor major); - void accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1); - void BuildVertexArray(); +void captureShader(){ + m_state = GlobalShaderCache().capture( m_shader.c_str() ); +} + +void releaseShader(){ + GlobalShaderCache().release( m_shader.c_str() ); +} + +void check_shader(){ + if ( !shader_valid( GetShader() ) ) { + globalErrorStream() << "patch has invalid texture name: '" << GetShader() << "'\n"; + } +} + +void InsertPoints( EMatrixMajor mt, bool bFirst ); +void RemovePoints( EMatrixMajor mt, bool bFirst ); + +void AccumulateBBox(); + +void TesselateSubMatrixFixed( ArbitraryMeshVertex * vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl * subMatrix[3][3] ); + +// uses binary trees representing bezier curves to recursively tesselate a bezier sub-patch +void TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY, + std::size_t offStartX, std::size_t offStartY, + std::size_t offEndX, std::size_t offEndY, + std::size_t nFlagsX, std::size_t nFlagsY, + Vector3& left, Vector3& mid, Vector3& right, + Vector2& texLeft, Vector2& texMid, Vector2& texRight, + bool bTranspose ); + +// tesselates the entire surface +void BuildTesselationCurves( EMatrixMajor major ); +void accumulateVertexTangentSpace( std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1 ); +void BuildVertexArray(); }; -inline bool Patch_importHeader(Patch& patch, Tokeniser& tokeniser) -{ - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "{")); - return true; +inline bool Patch_importHeader( Patch& patch, Tokeniser& tokeniser ){ + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) ); + return true; } -inline bool Patch_importShader(Patch& patch, Tokeniser& tokeniser) -{ - // parse shader name - tokeniser.nextLine(); - const char* texture = tokeniser.getToken(); - if(texture == 0) - { - Tokeniser_unexpectedError(tokeniser, texture, "#texture-name"); - return false; - } - if(string_equal(texture, "NULL")) - { - patch.SetShader(texdef_name_default()); - } - else - { - StringOutputStream shader(string_length(GlobalTexturePrefix_get()) + string_length(texture)); - shader << GlobalTexturePrefix_get() << texture; - patch.SetShader(shader.c_str()); - } - return true; -} - -inline bool PatchDoom3_importShader(Patch& patch, Tokeniser& tokeniser) -{ - // parse shader name - tokeniser.nextLine(); - const char *shader = tokeniser.getToken(); - if(shader == 0) - { - Tokeniser_unexpectedError(tokeniser, shader, "#shader-name"); - return false; - } - if(string_equal(shader, "_emptyname")) - { - shader = texdef_name_default(); - } - patch.SetShader(shader); - return true; -} - -inline bool Patch_importParams(Patch& patch, Tokeniser& tokeniser) -{ - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); +inline bool Patch_importShader( Patch& patch, Tokeniser& tokeniser ){ + // parse shader name + tokeniser.nextLine(); + const char* texture = tokeniser.getToken(); + if ( texture == 0 ) { + Tokeniser_unexpectedError( tokeniser, texture, "#texture-name" ); + return false; + } + if ( string_equal( texture, "NULL" ) ) { + patch.SetShader( texdef_name_default() ); + } + else + { + StringOutputStream shader( string_length( GlobalTexturePrefix_get() ) + string_length( texture ) ); + shader << GlobalTexturePrefix_get() << texture; + patch.SetShader( shader.c_str() ); + } + return true; +} + +inline bool PatchDoom3_importShader( Patch& patch, Tokeniser& tokeniser ){ + // parse shader name + tokeniser.nextLine(); + const char *shader = tokeniser.getToken(); + if ( shader == 0 ) { + Tokeniser_unexpectedError( tokeniser, shader, "#shader-name" ); + return false; + } + if ( string_equal( shader, "_emptyname" ) ) { + shader = texdef_name_default(); + } + patch.SetShader( shader ); + return true; +} + +inline bool Patch_importParams( Patch& patch, Tokeniser& tokeniser ){ + tokeniser.nextLine(); + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); - // parse matrix dimensions - { - std::size_t c, r; - RETURN_FALSE_IF_FAIL(Tokeniser_getSize(tokeniser, c)); - RETURN_FALSE_IF_FAIL(Tokeniser_getSize(tokeniser, r)); + // parse matrix dimensions + { + std::size_t c, r; + RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, c ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, r ) ); - patch.setDims(c, r); - } + patch.setDims( c, r ); + } - if(patch.m_patchDef3) - { - RETURN_FALSE_IF_FAIL(Tokeniser_getSize(tokeniser, patch.m_subdivisions_x)); - RETURN_FALSE_IF_FAIL(Tokeniser_getSize(tokeniser, patch.m_subdivisions_y)); - } + if ( patch.m_patchDef3 ) { + RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, patch.m_subdivisions_x ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_getSize( tokeniser, patch.m_subdivisions_y ) ); + } - // ignore contents/flags/value - int tmp; - RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, tmp)); - RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, tmp)); - RETURN_FALSE_IF_FAIL(Tokeniser_getInteger(tokeniser, tmp)); + // ignore contents/flags/value + int tmp; + RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, tmp ) ); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); - return true; + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); + return true; } -inline bool Patch_importMatrix(Patch& patch, Tokeniser& tokeniser) -{ - // parse matrix - tokeniser.nextLine(); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); - { - for(std::size_t c=0; cm_vertex, best); - if(best.valid()) - { - Selector_add(selector, m_selectable, best); - } - } - void snapto(float snap) - { - vector3_snap(m_ctrl->m_vertex, snap); - } +PatchControl* m_ctrl; +ObservedSelectable m_selectable; + +PatchControlInstance( PatchControl* ctrl, const SelectionChangeCallback& observer ) + : m_ctrl( ctrl ), m_selectable( observer ){ +} + +void testSelect( Selector& selector, SelectionTest& test ){ + SelectionIntersection best; + test.TestPoint( m_ctrl->m_vertex, best ); + if ( best.valid() ) { + Selector_add( selector, m_selectable, best ); + } +} +void snapto( float snap ){ + vector3_snap( m_ctrl->m_vertex, snap ); +} }; class PatchInstance : -public Patch::Observer, -public scene::Instance, -public Selectable, -public Renderable, -public SelectionTestable, -public ComponentSelectionTestable, -public ComponentEditable, -public ComponentSnappable, -public PlaneSelectable, -public LightCullable + public Patch::Observer, + public scene::Instance, + public Selectable, + public Renderable, + public SelectionTestable, + public ComponentSelectionTestable, + public ComponentEditable, + public ComponentSnappable, + public PlaneSelectable, + public LightCullable +{ +class TypeCasts { - class TypeCasts - { - InstanceTypeCastTable m_casts; - public: - TypeCasts() - { - InstanceStaticCast::install(m_casts); - InstanceContainedCast::install(m_casts); - InstanceContainedCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceIdentityCast::install(m_casts); - InstanceContainedCast::install(m_casts); - } - InstanceTypeCastTable& get() - { - return m_casts; - } - }; - - - Patch& m_patch; - typedef std::vector PatchControlInstances; - PatchControlInstances m_ctrl_instances; - - ObservedSelectable m_selectable; - - DragPlanes m_dragPlanes; - - mutable RenderablePointVector m_render_selected; - mutable AABB m_aabb_component; - - static Shader* m_state_selpoint; - - const LightList* m_lightList; - - TransformModifier m_transform; +InstanceTypeCastTable m_casts; public: +TypeCasts(){ + InstanceStaticCast::install( m_casts ); + InstanceContainedCast::install( m_casts ); + InstanceContainedCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceIdentityCast::install( m_casts ); + InstanceContainedCast::install( m_casts ); +} +InstanceTypeCastTable& get(){ + return m_casts; +} +}; + + +Patch& m_patch; +typedef std::vector PatchControlInstances; +PatchControlInstances m_ctrl_instances; + +ObservedSelectable m_selectable; + +DragPlanes m_dragPlanes; + +mutable RenderablePointVector m_render_selected; +mutable AABB m_aabb_component; + +static Shader* m_state_selpoint; + +const LightList* m_lightList; + +TransformModifier m_transform; +public: + +typedef LazyStatic StaticTypeCasts; + +void lightsChanged(){ + m_lightList->lightsChanged(); +} +typedef MemberCaller LightsChangedCaller; + +STRING_CONSTANT( Name, "PatchInstance" ); + +PatchInstance( const scene::Path& path, scene::Instance* parent, Patch& patch ) : + Instance( path, parent, this, StaticTypeCasts::instance().get() ), + m_patch( patch ), + m_selectable( SelectedChangedCaller( *this ) ), + m_dragPlanes( SelectedChangedComponentCaller( *this ) ), + m_render_selected( GL_POINTS ), + m_transform( Patch::TransformChangedCaller( m_patch ), ApplyTransformCaller( *this ) ){ + m_patch.instanceAttach( Instance::path() ); + m_patch.attach( this ); + + m_lightList = &GlobalShaderCache().attach( *this ); + m_patch.m_lightsChanged = LightsChangedCaller( *this ); + + Instance::setTransformChangedCallback( LightsChangedCaller( *this ) ); +} +~PatchInstance(){ + Instance::setTransformChangedCallback( Callback() ); + + m_patch.m_lightsChanged = Callback(); + GlobalShaderCache().detach( *this ); + + m_patch.detach( this ); + m_patch.instanceDetach( Instance::path() ); +} + +void selectedChanged( const Selectable& selectable ){ + GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable ); + GlobalSelectionSystem().onSelectedChanged( *this, selectable ); + + Instance::selectedChanged(); +} +typedef MemberCaller1 SelectedChangedCaller; + +void selectedChangedComponent( const Selectable& selectable ){ + GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable ); + GlobalSelectionSystem().onComponentSelection( *this, selectable ); +} +typedef MemberCaller1 SelectedChangedComponentCaller; + +Patch& getPatch(){ + return m_patch; +} +Bounded& get( NullType){ + return m_patch; +} +Cullable& get( NullType){ + return m_patch; +} +Transformable& get( NullType){ + return m_transform; +} + +static void constructStatic(){ + m_state_selpoint = GlobalShaderCache().capture( "$SELPOINT" ); +} + +static void destroyStatic(){ + GlobalShaderCache().release( "$SELPOINT" ); +} - typedef LazyStatic StaticTypeCasts; - - void lightsChanged() - { - m_lightList->lightsChanged(); - } - typedef MemberCaller LightsChangedCaller; - - STRING_CONSTANT(Name, "PatchInstance"); - - PatchInstance(const scene::Path& path, scene::Instance* parent, Patch& patch) : - Instance(path, parent, this, StaticTypeCasts::instance().get()), - m_patch(patch), - m_selectable(SelectedChangedCaller(*this)), - m_dragPlanes(SelectedChangedComponentCaller(*this)), - m_render_selected(GL_POINTS), - m_transform(Patch::TransformChangedCaller(m_patch), ApplyTransformCaller(*this)) - { - m_patch.instanceAttach(Instance::path()); - m_patch.attach(this); - - m_lightList = &GlobalShaderCache().attach(*this); - m_patch.m_lightsChanged = LightsChangedCaller(*this); - - Instance::setTransformChangedCallback(LightsChangedCaller(*this)); - } - ~PatchInstance() - { - Instance::setTransformChangedCallback(Callback()); - - m_patch.m_lightsChanged = Callback(); - GlobalShaderCache().detach(*this); - - m_patch.detach(this); - m_patch.instanceDetach(Instance::path()); - } - - void selectedChanged(const Selectable& selectable) - { - GlobalSelectionSystem().getObserver(SelectionSystem::ePrimitive)(selectable); - GlobalSelectionSystem().onSelectedChanged(*this, selectable); - - Instance::selectedChanged(); - } - typedef MemberCaller1 SelectedChangedCaller; - - void selectedChangedComponent(const Selectable& selectable) - { - GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable); - GlobalSelectionSystem().onComponentSelection(*this, selectable); - } - typedef MemberCaller1 SelectedChangedComponentCaller; - - Patch& getPatch() - { - return m_patch; - } - Bounded& get(NullType) - { - return m_patch; - } - Cullable& get(NullType) - { - return m_patch; - } - Transformable& get(NullType) - { - return m_transform; - } - - static void constructStatic() - { - m_state_selpoint = GlobalShaderCache().capture("$SELPOINT"); - } - - static void destroyStatic() - { - GlobalShaderCache().release("$SELPOINT"); - } - - - void allocate(std::size_t size) - { - m_ctrl_instances.clear(); - m_ctrl_instances.reserve(size); - for(Patch::iterator i = m_patch.begin(); i != m_patch.end(); ++i) - { - m_ctrl_instances.push_back(PatchControlInstance(&(*i), SelectedChangedComponentCaller(*this))); - } - } - - void setSelected(bool select) - { - m_selectable.setSelected(select); - } - bool isSelected() const - { - return m_selectable.isSelected(); - } - - - void update_selected() const - { - m_render_selected.clear(); - Patch::iterator ctrl = m_patch.getControlPointsTransformed().begin(); - for(PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl) - { - if((*i).m_selectable.isSelected()) - { - const Colour4b colour_selected(0, 0, 255, 255); - m_render_selected.push_back(PointVertex(reinterpret_cast((*ctrl).m_vertex), colour_selected)); - } - } - } + +void allocate( std::size_t size ){ + m_ctrl_instances.clear(); + m_ctrl_instances.reserve( size ); + for ( Patch::iterator i = m_patch.begin(); i != m_patch.end(); ++i ) + { + m_ctrl_instances.push_back( PatchControlInstance( &( *i ), SelectedChangedComponentCaller( *this ) ) ); + } +} + +void setSelected( bool select ){ + m_selectable.setSelected( select ); +} +bool isSelected() const { + return m_selectable.isSelected(); +} + + +void update_selected() const { + m_render_selected.clear(); + Patch::iterator ctrl = m_patch.getControlPointsTransformed().begin(); + for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl ) + { + if ( ( *i ).m_selectable.isSelected() ) { + const Colour4b colour_selected( 0, 0, 255, 255 ); + m_render_selected.push_back( PointVertex( reinterpret_cast( ( *ctrl ).m_vertex ), colour_selected ) ); + } + } +} #if 0 - void render(Renderer& renderer, const VolumeTest& volume) const - { - if(GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && m_selectable.isSelected()) - { - renderer.Highlight(Renderer::eFace, false); - - m_patch.render(renderer, volume, localToWorld()); - - if(GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex) - { - renderer.Highlight(Renderer::ePrimitive, false); - - m_patch.render_component(renderer, volume, localToWorld()); - - renderComponentsSelected(renderer, volume); - } - } - else - m_patch.render(renderer, volume, localToWorld()); - } +void render( Renderer& renderer, const VolumeTest& volume ) const { + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && m_selectable.isSelected() ) { + renderer.Highlight( Renderer::eFace, false ); + + m_patch.render( renderer, volume, localToWorld() ); + + if ( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex ) { + renderer.Highlight( Renderer::ePrimitive, false ); + + m_patch.render_component( renderer, volume, localToWorld() ); + + renderComponentsSelected( renderer, volume ); + } + } + else{ + m_patch.render( renderer, volume, localToWorld() ); + } +} #endif - void renderSolid(Renderer& renderer, const VolumeTest& volume) const - { - m_patch.evaluateTransform(); - renderer.setLights(*m_lightList); - m_patch.render_solid(renderer, volume, localToWorld()); - - renderComponentsSelected(renderer, volume); - } - - void renderWireframe(Renderer& renderer, const VolumeTest& volume) const - { - m_patch.evaluateTransform(); - m_patch.render_wireframe(renderer, volume, localToWorld()); - - renderComponentsSelected(renderer, volume); - } - - void renderComponentsSelected(Renderer& renderer, const VolumeTest& volume) const - { - m_patch.evaluateTransform(); - update_selected(); - if(!m_render_selected.empty()) - { - renderer.Highlight(Renderer::ePrimitive, false); - renderer.SetState(m_state_selpoint, Renderer::eWireframeOnly); - renderer.SetState(m_state_selpoint, Renderer::eFullMaterials); - renderer.addRenderable(m_render_selected, localToWorld()); - } - } - void renderComponents(Renderer& renderer, const VolumeTest& volume) const - { - m_patch.evaluateTransform(); - if(GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex) - { - m_patch.render_component(renderer, volume, localToWorld()); - } - } - - void testSelect(Selector& selector, SelectionTest& test) - { - test.BeginMesh(localToWorld(), true); - m_patch.testSelect(selector, test); - } - - void selectCtrl(bool select) - { - for(PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) - { - (*i).m_selectable.setSelected(select); - } - } - bool isSelectedComponents() const - { - for(PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) - { - if((*i).m_selectable.isSelected()) - { - return true; - } - } - return false; - } - void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) - { - if(mode == SelectionSystem::eVertex) - { - selectCtrl(select); - } - else if(mode == SelectionSystem::eFace) - { - m_dragPlanes.setSelected(select); - } - } - const AABB& getSelectedComponentsBounds() const - { - m_aabb_component = AABB(); - - for(PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) - { - if((*i).m_selectable.isSelected()) - { - aabb_extend_by_point_safe(m_aabb_component, (*i).m_ctrl->m_vertex); - } - } - - return m_aabb_component; - } - - void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) - { - test.BeginMesh(localToWorld()); - - switch(mode) - { - case SelectionSystem::eVertex: - { - for(PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) - { - (*i).testSelect(selector, test); - } - } - break; - default: - break; - } - } - - bool selectedVertices() - { - for(PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) - { - if((*i).m_selectable.isSelected()) - { - return true; - } - } - return false; - } - - void transformComponents(const Matrix4& matrix) - { - if(selectedVertices()) - { - PatchControlIter ctrl = m_patch.getControlPointsTransformed().begin(); - for(PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl) - { - if((*i).m_selectable.isSelected()) - { - matrix4_transform_point(matrix, (*ctrl).m_vertex); - } - } - m_patch.UpdateCachedData(); - } - - if(m_dragPlanes.isSelected()) // this should only be true when the transform is a pure translation. - { - m_patch.transform(m_dragPlanes.evaluateTransform(vector4_to_vector3(matrix.t()))); - } - } - - - void selectPlanes(Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback) - { - test.BeginMesh(localToWorld()); - - m_dragPlanes.selectPlanes(m_patch.localAABB(), selector, test, selectedPlaneCallback); - } - void selectReversedPlanes(Selector& selector, const SelectedPlanes& selectedPlanes) - { - m_dragPlanes.selectReversedPlanes(m_patch.localAABB(), selector, selectedPlanes); - } - - - void snapComponents(float snap) - { - if(selectedVertices()) - { - m_patch.undoSave(); - for(PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i) - { - if((*i).m_selectable.isSelected()) - { - (*i).snapto(snap); - } - } - m_patch.controlPointsChanged(); - } - } - - void evaluateTransform() - { - Matrix4 matrix(m_transform.calculateTransform()); - - if(m_transform.getType() == TRANSFORM_PRIMITIVE) - { - m_patch.transform(matrix); - } - else - { - transformComponents(matrix); - } - } - void applyTransform() - { - m_patch.revertTransform(); - evaluateTransform(); - m_patch.freezeTransform(); - } - typedef MemberCaller ApplyTransformCaller; - - - bool testLight(const RendererLight& light) const - { - return light.testAABB(worldAABB()); - } +void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { + m_patch.evaluateTransform(); + renderer.setLights( *m_lightList ); + m_patch.render_solid( renderer, volume, localToWorld() ); + + renderComponentsSelected( renderer, volume ); +} + +void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { + m_patch.evaluateTransform(); + m_patch.render_wireframe( renderer, volume, localToWorld() ); + + renderComponentsSelected( renderer, volume ); +} + +void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume ) const { + m_patch.evaluateTransform(); + update_selected(); + if ( !m_render_selected.empty() ) { + renderer.Highlight( Renderer::ePrimitive, false ); + renderer.SetState( m_state_selpoint, Renderer::eWireframeOnly ); + renderer.SetState( m_state_selpoint, Renderer::eFullMaterials ); + renderer.addRenderable( m_render_selected, localToWorld() ); + } +} +void renderComponents( Renderer& renderer, const VolumeTest& volume ) const { + m_patch.evaluateTransform(); + if ( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex ) { + m_patch.render_component( renderer, volume, localToWorld() ); + } +} + +void testSelect( Selector& selector, SelectionTest& test ){ + test.BeginMesh( localToWorld(), true ); + m_patch.testSelect( selector, test ); +} + +void selectCtrl( bool select ){ + for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) + { + ( *i ).m_selectable.setSelected( select ); + } +} +bool isSelectedComponents() const { + for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) + { + if ( ( *i ).m_selectable.isSelected() ) { + return true; + } + } + return false; +} +void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ){ + if ( mode == SelectionSystem::eVertex ) { + selectCtrl( select ); + } + else if ( mode == SelectionSystem::eFace ) { + m_dragPlanes.setSelected( select ); + } +} +const AABB& getSelectedComponentsBounds() const { + m_aabb_component = AABB(); + + for ( PatchControlInstances::const_iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) + { + if ( ( *i ).m_selectable.isSelected() ) { + aabb_extend_by_point_safe( m_aabb_component, ( *i ).m_ctrl->m_vertex ); + } + } + + return m_aabb_component; +} + +void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){ + test.BeginMesh( localToWorld() ); + + switch ( mode ) + { + case SelectionSystem::eVertex: + { + for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) + { + ( *i ).testSelect( selector, test ); + } + } + break; + default: + break; + } +} + +bool selectedVertices(){ + for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) + { + if ( ( *i ).m_selectable.isSelected() ) { + return true; + } + } + return false; +} + +void transformComponents( const Matrix4& matrix ){ + if ( selectedVertices() ) { + PatchControlIter ctrl = m_patch.getControlPointsTransformed().data(); + for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl ) + { + if ( ( *i ).m_selectable.isSelected() ) { + matrix4_transform_point( matrix, ( *ctrl ).m_vertex ); + } + } + m_patch.UpdateCachedData(); + } + + if ( m_dragPlanes.isSelected() ) { // this should only be true when the transform is a pure translation. + m_patch.transform( m_dragPlanes.evaluateTransform( vector4_to_vector3( matrix.t() ) ) ); + } +} + + +void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){ + test.BeginMesh( localToWorld() ); + + m_dragPlanes.selectPlanes( m_patch.localAABB(), selector, test, selectedPlaneCallback ); +} +void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ){ + m_dragPlanes.selectReversedPlanes( m_patch.localAABB(), selector, selectedPlanes ); +} + + +void snapComponents( float snap ){ + if ( selectedVertices() ) { + m_patch.undoSave(); + for ( PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i ) + { + if ( ( *i ).m_selectable.isSelected() ) { + ( *i ).snapto( snap ); + } + } + m_patch.controlPointsChanged(); + } +} + +void evaluateTransform(){ + Matrix4 matrix( m_transform.calculateTransform() ); + + if ( m_transform.getType() == TRANSFORM_PRIMITIVE ) { + m_patch.transform( matrix ); + } + else + { + transformComponents( matrix ); + } +} +void applyTransform(){ + m_patch.revertTransform(); + evaluateTransform(); + m_patch.freezeTransform(); +} +typedef MemberCaller ApplyTransformCaller; + + +bool testLight( const RendererLight& light ) const { + return light.testAABB( worldAABB() ); +} }; template class PatchNode : - public scene::Node::Symbiot, - public scene::Instantiable, - public scene::Cloneable + public scene::Node::Symbiot, + public scene::Instantiable, + public scene::Cloneable { - typedef PatchNode Self; - - class TypeCasts - { - InstanceTypeCastTable m_casts; - public: - TypeCasts() - { - NodeStaticCast::install(m_casts); - NodeStaticCast::install(m_casts); - NodeContainedCast::install(m_casts); - NodeContainedCast::install(m_casts); - NodeContainedCast::install(m_casts); - NodeContainedCast::install(m_casts); - NodeContainedCast::install(m_casts); - NodeContainedCast::install(m_casts); - NodeContainedCast::install(m_casts); - NodeContainedCast::install(m_casts); - } - InstanceTypeCastTable& get() - { - return m_casts; - } - }; - - - scene::Node m_node; - InstanceSet m_instances; - Patch m_patch; - TokenImporter m_importMap; - TokenExporter m_exportMap; +typedef PatchNode Self; +class TypeCasts +{ +InstanceTypeCastTable m_casts; public: +TypeCasts(){ + NodeStaticCast::install( m_casts ); + NodeStaticCast::install( m_casts ); + NodeContainedCast::install( m_casts ); + NodeContainedCast::install( m_casts ); + NodeContainedCast::install( m_casts ); + NodeContainedCast::install( m_casts ); + NodeContainedCast::install( m_casts ); + NodeContainedCast::install( m_casts ); + NodeContainedCast::install( m_casts ); + NodeContainedCast::install( m_casts ); +} +InstanceTypeCastTable& get(){ + return m_casts; +} +}; + + +scene::Node m_node; +InstanceSet m_instances; +Patch m_patch; +TokenImporter m_importMap; +TokenExporter m_exportMap; + +public: + +typedef LazyStatic StaticTypeCasts; - typedef LazyStatic StaticTypeCasts; - - Snappable& get(NullType) - { - return m_patch; - } - TransformNode& get(NullType) - { - return m_patch; - } - Patch& get(NullType) - { - return m_patch; - } - XMLImporter& get(NullType) - { - return m_patch; - } - XMLExporter& get(NullType) - { - return m_patch; - } - MapImporter& get(NullType) - { - return m_importMap; - } - MapExporter& get(NullType) - { - return m_exportMap; - } - Nameable& get(NullType) - { - return m_patch; - } - - PatchNode(bool patchDef3 = false) : - m_node(this, this, StaticTypeCasts::instance().get()), - m_patch(m_node, InstanceSetEvaluateTransform::Caller(m_instances), InstanceSet::BoundsChangedCaller(m_instances)), - m_importMap(m_patch), - m_exportMap(m_patch) - { - m_patch.m_patchDef3 = patchDef3; - } - PatchNode(const PatchNode& other) : - scene::Node::Symbiot(other), - scene::Instantiable(other), - scene::Cloneable(other), - m_node(this, this, StaticTypeCasts::instance().get()), - m_patch(other.m_patch, m_node, InstanceSetEvaluateTransform::Caller(m_instances), InstanceSet::BoundsChangedCaller(m_instances)), - m_importMap(m_patch), - m_exportMap(m_patch) - { - } - void release() - { - delete this; - } - scene::Node& node() - { - return m_node; - } - Patch& get() - { - return m_patch; - } - const Patch& get() const - { - return m_patch; - } - - scene::Node& clone() const - { - return (new PatchNode(*this))->node(); - } - - scene::Instance* create(const scene::Path& path, scene::Instance* parent) - { - return new PatchInstance(path, parent, m_patch); - } - void forEachInstance(const scene::Instantiable::Visitor& visitor) - { - m_instances.forEachInstance(visitor); - } - void insert(scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance) - { - m_instances.insert(observer, path, instance); - } - scene::Instance* erase(scene::Instantiable::Observer* observer, const scene::Path& path) - { - return m_instances.erase(observer, path); - } +Snappable& get( NullType){ + return m_patch; +} +TransformNode& get( NullType){ + return m_patch; +} +Patch& get( NullType){ + return m_patch; +} +XMLImporter& get( NullType){ + return m_patch; +} +XMLExporter& get( NullType){ + return m_patch; +} +MapImporter& get( NullType){ + return m_importMap; +} +MapExporter& get( NullType){ + return m_exportMap; +} +Nameable& get( NullType){ + return m_patch; +} + +PatchNode( bool patchDef3 = false ) : + m_node( this, this, StaticTypeCasts::instance().get() ), + m_patch( m_node, InstanceSetEvaluateTransform::Caller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ) ), + m_importMap( m_patch ), + m_exportMap( m_patch ){ + m_patch.m_patchDef3 = patchDef3; +} +PatchNode( const PatchNode& other ) : + scene::Node::Symbiot( other ), + scene::Instantiable( other ), + scene::Cloneable( other ), + m_node( this, this, StaticTypeCasts::instance().get() ), + m_patch( other.m_patch, m_node, InstanceSetEvaluateTransform::Caller( m_instances ), InstanceSet::BoundsChangedCaller( m_instances ) ), + m_importMap( m_patch ), + m_exportMap( m_patch ){ +} +void release(){ + delete this; +} +scene::Node& node(){ + return m_node; +} +Patch& get(){ + return m_patch; +} +const Patch& get() const { + return m_patch; +} + +scene::Node& clone() const { + return ( new PatchNode( *this ) )->node(); +} + +scene::Instance* create( const scene::Path& path, scene::Instance* parent ){ + return new PatchInstance( path, parent, m_patch ); +} +void forEachInstance( const scene::Instantiable::Visitor& visitor ){ + m_instances.forEachInstance( visitor ); +} +void insert( scene::Instantiable::Observer* observer, const scene::Path& path, scene::Instance* instance ){ + m_instances.insert( observer, path, instance ); +} +scene::Instance* erase( scene::Instantiable::Observer* observer, const scene::Path& path ){ + return m_instances.erase( observer, path ); +} }; @@ -1926,149 +1738,124 @@ public: typedef PatchNode PatchNodeQuake3; typedef PatchNode PatchNodeDoom3; -inline Patch* Node_getPatch(scene::Node& node) -{ - return NodeTypeCast::cast(node); +inline Patch* Node_getPatch( scene::Node& node ){ + return NodeTypeCast::cast( node ); } -inline PatchInstance* Instance_getPatch(scene::Instance& instance) -{ - return InstanceTypeCast::cast(instance); +inline PatchInstance* Instance_getPatch( scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } template class PatchSelectedVisitor : public SelectionSystem::Visitor { - const Functor& m_functor; +const Functor& m_functor; public: - PatchSelectedVisitor(const Functor& functor) : m_functor(functor) - { - } - void visit(scene::Instance& instance) const - { - PatchInstance* patch = Instance_getPatch(instance); - if(patch != 0) - { - m_functor(*patch); - } - } +PatchSelectedVisitor( const Functor& functor ) : m_functor( functor ){ +} +void visit( scene::Instance& instance ) const { + PatchInstance* patch = Instance_getPatch( instance ); + if ( patch != 0 ) { + m_functor( *patch ); + } +} }; template -inline void Scene_forEachSelectedPatch(const Functor& functor) -{ - GlobalSelectionSystem().foreachSelected(PatchSelectedVisitor(functor)); +inline void Scene_forEachSelectedPatch( const Functor& functor ){ + GlobalSelectionSystem().foreachSelected( PatchSelectedVisitor( functor ) ); } template class PatchVisibleSelectedVisitor : public SelectionSystem::Visitor { - const Functor& m_functor; +const Functor& m_functor; public: - PatchVisibleSelectedVisitor(const Functor& functor) : m_functor(functor) - { - } - void visit(scene::Instance& instance) const - { - PatchInstance* patch = Instance_getPatch(instance); - if(patch != 0 - && instance.path().top().get().visible()) - { - m_functor(*patch); - } - } +PatchVisibleSelectedVisitor( const Functor& functor ) : m_functor( functor ){ +} +void visit( scene::Instance& instance ) const { + PatchInstance* patch = Instance_getPatch( instance ); + if ( patch != 0 + && instance.path().top().get().visible() ) { + m_functor( *patch ); + } +} }; template -inline void Scene_forEachVisibleSelectedPatchInstance(const Functor& functor) -{ - GlobalSelectionSystem().foreachSelected(PatchVisibleSelectedVisitor(functor)); +inline void Scene_forEachVisibleSelectedPatchInstance( const Functor& functor ){ + GlobalSelectionSystem().foreachSelected( PatchVisibleSelectedVisitor( functor ) ); } template class PatchForEachWalker : public scene::Graph::Walker { - const Functor& m_functor; +const Functor& m_functor; public: - PatchForEachWalker(const Functor& functor) : m_functor(functor) - { - } - bool pre(const scene::Path& path, scene::Instance& instance) const - { - if(path.top().get().visible()) - { - Patch* patch = Node_getPatch(path.top()); - if(patch != 0) - { - m_functor(*patch); - } - } - return true; - } +PatchForEachWalker( const Functor& functor ) : m_functor( functor ){ +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Patch* patch = Node_getPatch( path.top() ); + if ( patch != 0 ) { + m_functor( *patch ); + } + } + return true; +} }; template -inline void Scene_forEachVisiblePatch(const Functor& functor) -{ - GlobalSceneGraph().traverse(PatchForEachWalker(functor)); +inline void Scene_forEachVisiblePatch( const Functor& functor ){ + GlobalSceneGraph().traverse( PatchForEachWalker( functor ) ); } template class PatchForEachSelectedWalker : public scene::Graph::Walker { - const Functor& m_functor; +const Functor& m_functor; public: - PatchForEachSelectedWalker(const Functor& functor) : m_functor(functor) - { - } - bool pre(const scene::Path& path, scene::Instance& instance) const - { - if(path.top().get().visible()) - { - Patch* patch = Node_getPatch(path.top()); - if(patch != 0 - && Instance_getSelectable(instance)->isSelected()) - { - m_functor(*patch); - } - } - return true; - } +PatchForEachSelectedWalker( const Functor& functor ) : m_functor( functor ){ +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Patch* patch = Node_getPatch( path.top() ); + if ( patch != 0 + && Instance_getSelectable( instance )->isSelected() ) { + m_functor( *patch ); + } + } + return true; +} }; template -inline void Scene_forEachVisibleSelectedPatch(const Functor& functor) -{ - GlobalSceneGraph().traverse(PatchForEachSelectedWalker(functor)); +inline void Scene_forEachVisibleSelectedPatch( const Functor& functor ){ + GlobalSceneGraph().traverse( PatchForEachSelectedWalker( functor ) ); } template class PatchForEachInstanceWalker : public scene::Graph::Walker { - const Functor& m_functor; +const Functor& m_functor; public: - PatchForEachInstanceWalker(const Functor& functor) : m_functor(functor) - { - } - bool pre(const scene::Path& path, scene::Instance& instance) const - { - if(path.top().get().visible()) - { - PatchInstance* patch = Instance_getPatch(instance); - if(patch != 0) - { - m_functor(*patch); - } - } - return true; - } +PatchForEachInstanceWalker( const Functor& functor ) : m_functor( functor ){ +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + PatchInstance* patch = Instance_getPatch( instance ); + if ( patch != 0 ) { + m_functor( *patch ); + } + } + return true; +} }; template -inline void Scene_forEachVisiblePatchInstance(const Functor& functor) -{ - GlobalSceneGraph().traverse(PatchForEachInstanceWalker(functor)); +inline void Scene_forEachVisiblePatchInstance( const Functor& functor ){ + GlobalSceneGraph().traverse( PatchForEachInstanceWalker( functor ) ); } #endif