123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "T3D/convexShape.h"
- #include "math/mathIO.h"
- #include "math/mathUtils.h"
- #include "scene/sceneRenderState.h"
- #include "console/consoleTypes.h"
- #include "core/stream/bitStream.h"
- #include "materials/materialManager.h"
- #include "lighting/lightQuery.h"
- #include "renderInstance/renderPassManager.h"
- #include "gfx/gfxTransformSaver.h"
- #include "gfx/primBuilder.h"
- #include "gfx/gfxDrawUtil.h"
- #include "core/bitVector.h"
- #include "materials/materialFeatureTypes.h"
- #include "materials/baseMatInstance.h"
- #include "collision/optimizedPolyList.h"
- #include "T3D/physics/physicsPlugin.h"
- #include "T3D/physics/physicsBody.h"
- #include "T3D/physics/physicsCollision.h"
- #include "console/engineAPI.h"
- #include "core/strings/stringUnit.h"
- IMPLEMENT_CO_NETOBJECT_V1( ConvexShape );
- ConsoleDocClass( ConvexShape,
- "@brief A renderable, collidable convex shape defined by a collection of surface planes.\n\n"
-
- "%ConvexShape is intended to be used as a temporary asset for quickly "
- "blocking out a scene or filling in approximate shapes to be later replaced "
- "with final assets. This is most easily done by using the WorldEditor's "
- "Sketch Tool.\n\n"
-
- "@ingroup enviroMisc"
- );
- Point3F ConvexShapeCollisionConvex::support( const VectorF &vec ) const
- {
- const Vector< Point3F > &pointList = pShape->mGeometry.points;
- if ( pointList.empty() )
- return pShape->getObjBox().getCenter();
-
- // This doesn't deal with the case that the farthest plane along vec is also
- // perpendicular to it, but in that case maybe it doesn't matter which point we return
- // anyway.
- F32 bestDot = mDot( pointList[0], vec );
- const Point3F *bestP = &pointList[0];
- for ( S32 i = 1; i < pointList.size(); i++ )
- {
- F32 newD = mDot( pointList[i], vec );
- if ( newD > bestDot )
- {
- bestDot = newD;
- bestP = &pointList[i];
- }
- }
- return *bestP;
- }
- void ConvexShapeCollisionConvex::getFeatures( const MatrixF &mat, const VectorF &n, ConvexFeature *cf )
- {
- if ( pShape->mGeometry.points.empty() )
- {
- cf->material = 0;
- cf->mObject = NULL;
- return;
- }
- cf->material = 0;
- cf->mObject = mObject;
- // Simple implementation... Add all Points, Edges and Faces.
- // Points...
- S32 firstVert = cf->mVertexList.size();
-
- const Vector< Point3F > &pointList = pShape->mGeometry.points;
- const U32 pointListCount = pointList.size();
- cf->mVertexList.increment( pointListCount );
- for ( S32 i = 0; i < pointListCount; i++ )
- mat.mulP( pointList[i], &(cf->mVertexList[ firstVert + i ]) );
-
- // Edges and Triangles for each face...
- const Vector< ConvexShape::Face > &faceList = pShape->mGeometry.faces;
- for ( S32 i = 0; i < faceList.size(); i++ )
- {
- // Add this Face's Edges.
- const Vector< ConvexShape::Edge > &edgeList = faceList[i].edges;
- const U32 edgeCount = edgeList.size();
- const S32 firstEdge = cf->mEdgeList.size();
- cf->mEdgeList.increment( edgeCount );
- for ( S32 j = 0; j < edgeCount; j++ )
- {
- cf->mEdgeList[ firstEdge + j ].vertex[0] = faceList[i].points[ edgeList[j].p0 ];
- cf->mEdgeList[ firstEdge + j ].vertex[1] = faceList[i].points[ edgeList[j].p1 ];
- }
- // Add this face's Triangles.
- // Note that ConvexFeature calls triangles 'faces' but a ConvexShape 'Face' is not
- // necessarily a single triangle.
-
- const Vector< ConvexShape::Triangle > &triangleList = faceList[i].triangles;
- const U32 triangleCount = triangleList.size();
- S32 firstTriangle = cf->mFaceList.size();
- cf->mFaceList.increment( triangleCount );
- for ( S32 j = 0; j < triangleCount; j++ )
- {
- ConvexFeature::Face &cft = cf->mFaceList[ firstTriangle + j ];
- cft.normal = faceList[i].normal;
- cft.vertex[0] = triangleList[j].p0;
- cft.vertex[1] = triangleList[j].p1;
- cft.vertex[2] = triangleList[j].p2;
- }
- }
- }
- void ConvexShapeCollisionConvex::getPolyList( AbstractPolyList* list )
- {
- SphereF sphere( Point3F::Zero, 0.0f );
-
- pShape->buildPolyList( PLC_Collision, list, Box3F::Invalid, sphere );
- }
- GFXImplementVertexFormat( ConvexVert )
- {
- addElement( "POSITION", GFXDeclType_Float3 );
- addElement( "COLOR", GFXDeclType_Color );
- addElement( "NORMAL", GFXDeclType_Float3 );
- addElement( "TANGENT", GFXDeclType_Float3 );
- addElement( "TEXCOORD", GFXDeclType_Float2, 0 );
- };
- static const U32 sgConvexFaceColorCount = 16;
- static const ColorI sgConvexFaceColors[ sgConvexFaceColorCount ] =
- {
- ColorI( 239, 131, 201 ),
- ColorI( 124, 255, 69 ),
- ColorI( 255, 65, 77 ),
- ColorI( 33, 118, 235 ),
- ColorI( 114, 227, 110 ),
- ColorI( 197, 50, 237 ),
- ColorI( 236, 255, 255 ),
- ColorI( 139, 225, 192 ),
- ColorI( 215, 9, 65 ),
- ColorI( 249, 114, 93 ),
- ColorI( 255, 255, 90 ),
- ColorI( 93, 104, 97 ),
- ColorI( 255, 214, 192 ),
- ColorI( 122, 44, 198 ),
- ColorI( 137, 141, 194 ),
- ColorI( 164, 114, 43 )
- };
- bool ConvexShape::smRenderEdges = false;
- bool ConvexShape::protectedSetSurface( void *object, const char *index, const char *data )
- {
- ConvexShape *shape = static_cast< ConvexShape* >( object );
- QuatF quat;
- Point3F pos;
- //MatrixF mat;
- U32 matID;
- Point2F offset;
- Point2F scale;
- F32 rot = 0;
- bool horz = true, vert = true;
- /*
- dSscanf( data, "%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g",
- &mat[0], &mat[1], &mat[2], &mat[3],
- &mat[4], &mat[5], &mat[6], &mat[7],
- &mat[8], &mat[9], &mat[10], &mat[11],
- &mat[12], &mat[13], &mat[14], &mat[15] );
- */
- String t = data;
- dSscanf( data, "%g %g %g %g %g %g %g %i %g %g %g %g %f", &quat.x, &quat.y, &quat.z, &quat.w, &pos.x, &pos.y, &pos.z,
- &matID, &offset.x, &offset.y, &scale.x, &scale.y, &rot);
- MatrixF surface;
- quat.setMatrix( &surface );
- surface.setPosition( pos );
- shape->mSurfaces.push_back( surface );
- surfaceUV surfUV;
- if (StringUnit::getUnitCount(data, " ") > 7)
- {
- surfUV.matID = matID;
- surfUV.offset = offset;
- surfUV.scale = scale;
- surfUV.zRot = rot;
- surfUV.horzFlip = horz;
- surfUV.vertFlip = vert;
- }
- else
- {
- surfUV.matID = 0;
- surfUV.offset = Point2F(0,0);
- surfUV.scale = Point2F(1, 1);
- surfUV.zRot = 0;
- surfUV.horzFlip = false;
- surfUV.vertFlip = false;
- }
- shape->mSurfaceUVs.push_back(surfUV);
- return false;
- }
- bool ConvexShape::protectedSetSurfaceTexture(void *object, const char *index, const char *data)
- {
- ConvexShape *shape = static_cast< ConvexShape* >(object);
- surfaceMaterial surface;
- surface._setMaterial(StringTable->insert(data));
- shape->mSurfaceTextures.push_back(surface);
- return false;
- }
- ConvexShape::ConvexShape()
- :
- mMaterialInst( NULL ),
- //mVertCount( 0 ),
- //mPrimCount( 0 ),
- mPhysicsRep( NULL ),
- mNormalLength( 0.3f )
- {
- mNetFlags.set( Ghostable | ScopeAlways );
-
- mTypeMask |= StaticObjectType |
- StaticShapeObjectType;
- mConvexList = new Convex;
- mSurfaceBuffers.clear();
- mSurfaceUVs.clear();
- mSurfaceTextures.clear();
- INIT_ASSET(Material);
- }
- ConvexShape::~ConvexShape()
- {
- if ( mMaterialInst )
- SAFE_DELETE( mMaterialInst );
- for(U32 i=0; i<mSurfaceTextures.size(); i++)
- {
- if (mSurfaceTextures[i].materialInst)
- SAFE_DELETE(mSurfaceTextures[i].materialInst);
- }
- delete mConvexList;
- mConvexList = NULL;
- }
- void ConvexShape::initPersistFields()
- {
- docsURL;
- addGroup( "Rendering" );
- INITPERSISTFIELD_MATERIALASSET(Material, ConvexShape, "Default material used to render the ConvexShape surface.");
- endGroup( "Rendering" );
- addGroup( "Internal" );
- addProtectedField( "surface", TypeRealString, 0, &protectedSetSurface, &defaultProtectedGetFn,
- "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors );
- addProtectedField( "surfaceTexture", TypeRealString, 0, &protectedSetSurfaceTexture, &defaultProtectedGetFn,
- "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors );
- endGroup( "Internal" );
- Parent::initPersistFields();
- }
- void ConvexShape::inspectPostApply()
- {
- Parent::inspectPostApply();
- _updateGeometry( true );
- setMaskBits( UpdateMask );
- }
- bool ConvexShape::onAdd()
- {
- if ( !Parent::onAdd() )
- return false;
-
- //mObjBox.set( -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f );
- //resetWorldBox();
- // Face Order:
- // Top, Bottom, Front, Back, Left, Right
- // X Axis
- static const Point3F cubeTangents[6] =
- {
- Point3F( 1, 0, 0 ),
- Point3F(-1, 0, 0 ),
- Point3F( 1, 0, 0 ),
- Point3F(-1, 0, 0 ),
- Point3F( 0, 1, 0 ),
- Point3F( 0, -1, 0 )
- };
- // Y Axis
- static const Point3F cubeBinormals[6] =
- {
- Point3F( 0, 1, 0 ),
- Point3F( 0, 1, 0 ),
- Point3F( 0, 0, -1 ),
- Point3F( 0, 0, -1 ),
- Point3F( 0, 0, -1 ),
- Point3F( 0, 0, -1 )
- };
- // Z Axis
- static const Point3F cubeNormals[6] =
- {
- Point3F( 0, 0, 1),
- Point3F( 0, 0, -1),
- Point3F( 0, 1, 0),
- Point3F( 0, -1, 0),
- Point3F(-1, 0, 0),
- Point3F( 1, 0, 0),
- };
- if ( mSurfaces.empty() )
- {
- for ( S32 i = 0; i < 6; i++ )
- {
- mSurfaces.increment();
- MatrixF &surf = mSurfaces.last();
- surf.identity();
-
- surf.setColumn( 0, cubeTangents[i] );
- surf.setColumn( 1, cubeBinormals[i] );
- surf.setColumn( 2, cubeNormals[i] );
- surf.setPosition( cubeNormals[i] * 0.5f );
- mSurfaceUVs.increment();
- mSurfaceUVs[i].offset = Point2F(0, 0);
- mSurfaceUVs[i].scale = Point2F(1, 1);
- mSurfaceUVs[i].zRot = 0;
- mSurfaceUVs[i].horzFlip = false;
- mSurfaceUVs[i].vertFlip = false;
- mSurfaceUVs[i].matID = 0;
- }
- }
- if ( isClientObject() )
- _updateMaterial();
-
- _updateGeometry( true );
- addToScene();
- PlaneF p = PlaneF(Point3F(0, 0, 0), Point3F(0, 0, 1));
- Point3F a = Point3F(0, 0, 1);
- Point3F b = Point3F(1, 0, -1);
- Point3F c = Point3F(-1, 0, -1);
- Vector<Point3F> points;
- points.push_back(a);
- points.push_back(b);
- points.push_back(c);
- Point3F vertices[64];
- p.clipPolygon(points.address(), points.size(), vertices);
- return true;
- }
- void ConvexShape::onRemove()
- {
- removeFromScene();
- mConvexList->nukeList();
- SAFE_DELETE( mPhysicsRep );
- Parent::onRemove();
- }
- void ConvexShape::writeFields( Stream &stream, U32 tabStop )
- {
- Parent::writeFields( stream, tabStop );
- // Now write all planes.
- stream.write(2, "\r\n");
- S32 count = mSurfaces.size();
- if ( count > smMaxSurfaces )
- {
- Con::errorf( "ConvexShape has too many surfaces to save! Truncated value %d to maximum value of %d", count, smMaxSurfaces );
- count = smMaxSurfaces;
- }
- for (U32 i = 0; i < mSurfaceTextures.size(); i++)
- {
- stream.writeTabs(tabStop);
- char buffer[1024];
- dMemset(buffer, 0, 1024);
- dSprintf(buffer, 1024, "surfaceTexture = \"%s\";", mSurfaceTextures[i].getMaterial());
- stream.writeLine((const U8*)buffer);
- }
- for ( U32 i = 0; i < count; i++ )
- {
- const MatrixF &mat = mSurfaces[i];
- QuatF quat( mat );
- Point3F pos( mat.getPosition() );
- stream.writeTabs(tabStop);
- char buffer[1024];
- dMemset( buffer, 0, 1024 );
-
- dSprintf( buffer, 1024, "surface = \"%g %g %g %g %g %g %g %i %g %g %g %g %g %i %i\";",
- quat.x, quat.y, quat.z, quat.w, pos.x, pos.y, pos.z, mSurfaceUVs[i].matID,
- mSurfaceUVs[i].offset.x, mSurfaceUVs[i].offset.y, mSurfaceUVs[i].scale.x,
- mSurfaceUVs[i].scale.y, mSurfaceUVs[i].zRot, mSurfaceUVs[i].horzFlip, mSurfaceUVs[i].vertFlip);
- stream.writeLine( (const U8*)buffer );
- }
- }
- bool ConvexShape::writeField( StringTableEntry fieldname, const char *value )
- {
- if ( fieldname == StringTable->insert("surface") )
- return false;
- if ( fieldname == StringTable->insert("surfaceTexture") )
- return false;
- return Parent::writeField( fieldname, value );
- }
- void ConvexShape::onScaleChanged()
- {
- if ( isProperlyAdded() )
- _updateCollision();
- }
- void ConvexShape::setTransform( const MatrixF &mat )
- {
- Parent::setTransform( mat );
- if ( mPhysicsRep )
- mPhysicsRep->setTransform( mat );
-
- setMaskBits( TransformMask );
- }
- U32 ConvexShape::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
- {
- U32 retMask = Parent::packUpdate( conn, mask, stream );
-
- if ( stream->writeFlag( mask & TransformMask ) )
- {
- mathWrite(*stream, getTransform());
- mathWrite(*stream, getScale());
- }
- if ( stream->writeFlag( mask & UpdateMask ) )
- {
- PACK_ASSET(conn, Material);
-
- U32 surfCount = mSurfaces.size();
- stream->writeInt( surfCount, 32 );
- for ( S32 i = 0; i < surfCount; i++ )
- {
- QuatF quat( mSurfaces[i] );
- Point3F pos( mSurfaces[i].getPosition() );
- mathWrite( *stream, quat );
- mathWrite( *stream, pos );
- mathWrite(*stream, mSurfaceUVs[i].offset);
- mathWrite(*stream, mSurfaceUVs[i].scale);
- stream->writeFlag(mSurfaceUVs[i].horzFlip);
- stream->writeFlag(mSurfaceUVs[i].vertFlip);
- stream->writeInt(mSurfaceUVs[i].matID, 16);
- }
- const U32 surfaceTex = mSurfaceTextures.size();
- stream->writeInt( surfaceTex, 32 );
- //next check for any texture coord or scale mods
- for(U32 i=0; i < surfaceTex; i++)
- {
- if (stream->writeFlag(mSurfaceTextures[i].mMaterialAsset.notNull()))
- {
- NetStringHandle assetIdStr = mSurfaceTextures[i].mMaterialAsset.getAssetId();
- conn->packNetStringHandleU(stream, assetIdStr);
- }
- else
- stream->writeString(mSurfaceTextures[i].mMaterialName);
- }
- }
- return retMask;
- }
- void ConvexShape::unpackUpdate( NetConnection *conn, BitStream *stream )
- {
- Parent::unpackUpdate( conn, stream );
- if ( stream->readFlag() ) // TransformMask
- {
- mathRead(*stream, &mObjToWorld);
- mathRead(*stream, &mObjScale);
- setTransform( mObjToWorld );
- setScale( mObjScale );
- }
- if ( stream->readFlag() ) // UpdateMask
- {
- UNPACK_ASSET(conn, Material);
- mSurfaces.clear();
- mSurfaceUVs.clear();
- const U32 surfCount = stream->readInt( 32 );
- for ( S32 i = 0; i < surfCount; i++ )
- {
- mSurfaces.increment();
- MatrixF &mat = mSurfaces.last();
- QuatF quat;
- Point3F pos;
- mathRead( *stream, &quat );
- mathRead( *stream, &pos );
- quat.setMatrix( &mat );
- mat.setPosition( pos );
- mSurfaceUVs.increment();
- mathRead(*stream, &mSurfaceUVs[i].offset);
- mathRead(*stream, &mSurfaceUVs[i].scale);
- mSurfaceUVs[i].horzFlip = stream->readFlag();
- mSurfaceUVs[i].vertFlip = stream->readFlag();
- mSurfaceUVs[i].matID = stream->readInt(16);
- }
- //now fetch our text coord mods to store into the geometry data
- mSurfaceTextures.clear();
- const U32 surfaceTex = stream->readInt( 32 );
- //next check for any texture coord or scale mods
- for(U32 i=0; i < surfaceTex; i++)
- {
- mSurfaceTextures.increment();
- if (stream->readFlag())
- {
- mSurfaceTextures[i].mMaterialAssetId = StringTable->insert(conn->unpackNetStringHandleU(stream).getString());
- mSurfaceTextures[i]._setMaterial(mSurfaceTextures[i].mMaterialAssetId);
- }
- else
- mSurfaceTextures[i].mMaterialName = stream->readSTString();
- }
- if (isProperlyAdded())
- _updateMaterial();
- if ( isProperlyAdded() )
- _updateGeometry( true );
- }
- }
- void ConvexShape::prepRenderImage( SceneRenderState *state )
- {
- /*
- if ( state->isDiffusePass() )
- {
- ObjectRenderInst *ri2 = state->getRenderPass()->allocInst<ObjectRenderInst>();
- ri2->renderDelegate.bind( this, &ConvexShape::_renderDebug );
- ri2->type = RenderPassManager::RIT_Editor;
- state->getRenderPass()->addInst( ri2 );
- }
- */
- for (U32 i = 0; i < mSurfaceBuffers.size(); i++)
- {
- if (mSurfaceBuffers[i].mPrimitiveBuffer.isNull())
- continue;
- // If we don't have a material instance after the override then
- // we can skip rendering all together.
- BaseMatInstance *matInst;
- if (i == 0)
- {
- matInst = state->getOverrideMaterial(mMaterialInst ? mMaterialInst : MATMGR->getWarningMatInstance());
- }
- else
- {
- matInst = state->getOverrideMaterial(mSurfaceTextures[i - 1].materialInst ? mSurfaceTextures[i - 1].materialInst : MATMGR->getWarningMatInstance());
- }
- if (!matInst)
- continue;
- // Get a handy pointer to our RenderPassmanager
- RenderPassManager *renderPass = state->getRenderPass();
- // Allocate an MeshRenderInst so that we can submit it to the RenderPassManager
- MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
- // Set our RenderInst as a standard mesh render
- ri->type = RenderPassManager::RIT_Mesh;
- // Calculate our sorting point
- if (state)
- {
- // Calculate our sort point manually.
- const Box3F& rBox = getRenderWorldBox();
- ri->sortDistSq = rBox.getSqDistanceToPoint(state->getCameraPosition());
- }
- else
- ri->sortDistSq = 0.0f;
- // Set up our transforms
- MatrixF objectToWorld = getRenderTransform();
- objectToWorld.scale(getScale());
- ri->objectToWorld = renderPass->allocUniqueXform(objectToWorld);
- ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
- ri->projection = renderPass->allocSharedXform(RenderPassManager::Projection);
- // If we need lights then set them up.
- if (matInst->isForwardLit())
- {
- LightQuery query;
- query.init(getWorldSphere());
- query.getLights(ri->lights, 8);
- }
- // Make sure we have an up-to-date backbuffer in case
- // our Material would like to make use of it
- // NOTICE: SFXBB is removed and refraction is disabled!
- //ri->backBuffTex = GFX->getSfxBackBuffer();
- // Set our Material
- ri->matInst = matInst;
- if (matInst->getMaterial()->isTranslucent() && (!(matInst->getMaterial()->isAlphatest() && state->isShadowPass())))
- {
- ri->translucentSort = true;
- ri->type = RenderPassManager::RIT_Translucent;
- }
- // Set up our vertex buffer and primitive buffer
- ri->vertBuff = &mSurfaceBuffers[i].mVertexBuffer;
- ri->primBuff = &mSurfaceBuffers[i].mPrimitiveBuffer;
- ri->prim = renderPass->allocPrim();
- ri->prim->type = GFXTriangleList;
- ri->prim->minIndex = 0;
- ri->prim->startIndex = 0;
- ri->prim->numPrimitives = mSurfaceBuffers[i].mPrimCount;
- ri->prim->startVertex = 0;
- ri->prim->numVertices = mSurfaceBuffers[i].mVertCount;
- // We sort by the material then vertex buffer.
- ri->defaultKey = matInst->getStateHint();
- ri->defaultKey2 = (U32)(uintptr_t)ri->vertBuff; // Not 64bit safe!
- // Submit our RenderInst to the RenderPassManager
- state->getRenderPass()->addInst(ri);
- }
- }
- void ConvexShape::buildConvex( const Box3F &box, Convex *convex )
- {
- if ( mGeometry.faces.empty() )
- return;
- mConvexList->collectGarbage();
- Box3F realBox = box;
- mWorldToObj.mul( realBox );
- realBox.minExtents.convolveInverse( mObjScale );
- realBox.maxExtents.convolveInverse( mObjScale );
- if ( realBox.isOverlapped( getObjBox() ) == false )
- return;
- // See if this convex exists in the working set already...
- Convex *cc = 0;
- CollisionWorkingList &wl = convex->getWorkingList();
- for ( CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext )
- {
- if ( itr->mConvex->getType() == ConvexShapeCollisionConvexType )
- {
- ConvexShapeCollisionConvex *pConvex = static_cast<ConvexShapeCollisionConvex*>(itr->mConvex);
- if ( pConvex->pShape == this )
- {
- cc = itr->mConvex;
- return;
- }
- }
- }
- // Set up the convex...
- ConvexShapeCollisionConvex *cp = new ConvexShapeCollisionConvex();
- mConvexList->registerObject( cp );
- convex->addToWorkingList( cp );
- cp->mObject = this;
- cp->pShape = this;
- }
- bool ConvexShape::buildPolyList( PolyListContext context, AbstractPolyList *plist, const Box3F &box, const SphereF &sphere )
- {
- if ( mGeometry.points.empty() )
- return false;
- // If we're exporting deal with that first.
- if ( context == PLC_Export )
- {
- AssertFatal( dynamic_cast<OptimizedPolyList*>( plist ), "ConvexShape::buildPolyList - Bad polylist for export!" );
- _export( (OptimizedPolyList*)plist, box, sphere );
- return true;
- }
- plist->setTransform( &mObjToWorld, mObjScale );
- plist->setObject( this );
- // Add points...
- const Vector< Point3F > pointList = mGeometry.points;
- S32 base = plist->addPoint( pointList[0] );
- for ( S32 i = 1; i < pointList.size(); i++ )
- plist->addPoint( pointList[i] );
- // Add Surfaces...
- const Vector< ConvexShape::Face > faceList = mGeometry.faces;
- if(context == PLC_Navigation)
- {
- for(S32 i = 0; i < faceList.size(); i++)
- {
- const ConvexShape::Face &face = faceList[i];
- S32 s = face.triangles.size();
- for(S32 j = 0; j < s; j++)
- {
- plist->begin(0, s*i + j);
- plist->plane(PlaneF(face.centroid, face.normal));
- plist->vertex(base + face.points[face.triangles[j].p0]);
- plist->vertex(base + face.points[face.triangles[j].p1]);
- plist->vertex(base + face.points[face.triangles[j].p2]);
- plist->end();
- }
- }
- return true;
- }
- for ( S32 i = 0; i < faceList.size(); i++ )
- {
- const ConvexShape::Face &face = faceList[i];
- plist->begin( 0, i );
- plist->plane( PlaneF( face.centroid, face.normal ) );
- for ( S32 j = 0; j < face.triangles.size(); j++ )
- {
- plist->vertex( base + face.points[ face.triangles[j].p0 ] );
- plist->vertex( base + face.points[ face.triangles[j].p1 ] );
- plist->vertex( base + face.points[ face.triangles[j].p2 ] );
- }
- plist->end();
- }
- return true;
- }
- bool ConvexShape::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &)
- {
- if (mGeometry.points.empty())
- return false;
- //Get the collision mesh geometry
- {
- ColladaUtils::ExportData::colMesh* colMesh;
- exportData->colMeshes.increment();
- colMesh = &exportData->colMeshes.last();
- colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
- colMesh->mesh.setObject(this);
- //Just get the visible
- buildPolyList(PLC_Export, &colMesh->mesh, getWorldBox(), getWorldSphere());
- colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size());
- }
- //Next, process the geometry and materials.
- //Convex shapes only have the one 'level', so we'll just rely on the export post-process to back-fill
- if (isServerObject() && getClientObject())
- {
- exportData->meshData.increment();
- //Prep a meshData for this shape in particular
- ColladaUtils::ExportData::meshLODData* meshData = &exportData->meshData.last();
- //Fill out the info we'll need later to actually append our mesh data for the detail levels during the processing phase
- meshData->shapeInst = nullptr;
- meshData->originatingObject = this;
- meshData->meshTransform = mObjToWorld;
- meshData->scale = mObjScale;
- meshData->meshDetailLevels.increment();
- ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last();
- //Make sure we denote the size this detail level has
- curDetail->size = getNextPow2(getObjBox().len());
- }
- return true;
- }
- void ConvexShape::_export( OptimizedPolyList *plist, const Box3F &box, const SphereF &sphere )
- {
- BaseMatInstance *matInst = mMaterialInst;
- if ( isServerObject() && getClientObject() )
- matInst = dynamic_cast<ConvexShape*>(getClientObject())->mMaterialInst;
-
- MatrixF saveMat;
- Point3F saveScale;
- plist->getTransform( &saveMat, &saveScale );
- plist->setTransform( &mObjToWorld, mObjScale );
- plist->setObject( this );
- const Vector< ConvexShape::Face > faceList = mGeometry.faces;
- const Vector< Point3F > &pointList = mGeometry.points;
- for ( S32 i = 0; i < faceList.size(); i++ )
- {
- const ConvexShape::Face &face = faceList[i];
- plist->begin( matInst, i, OptimizedPolyList::TriangleList );
- plist->plane( PlaneF( face.centroid, face.normal ) );
- for ( S32 j = 0; j < face.triangles.size(); j++ )
- {
- for ( S32 k = 0; k < 3; k++ )
- {
- U32 vertId = face.triangles[j][k];
- plist->vertex( pointList[ face.points[ vertId ] ], face.normal, face.texcoords[ vertId ] );
- }
- }
- plist->end();
- }
- plist->setTransform( &saveMat, saveScale );
- }
- bool ConvexShape::castRay( const Point3F &start, const Point3F &end, RayInfo *info )
- {
- if ( mPlanes.empty() )
- return false;
- const Vector< PlaneF > &planeList = mPlanes;
- const U32 planeCount = planeList.size();
- F32 t;
- F32 tmin = F32_MAX;
- S32 hitFace = -1;
- Point3F hitPnt, pnt;
- VectorF rayDir( end - start );
- rayDir.normalizeSafe();
- for ( S32 i = 0; i < planeCount; i++ )
- {
- // Don't hit the back-side of planes.
- if ( mDot( rayDir, planeList[i] ) >= 0.0f )
- continue;
- t = planeList[i].intersect( start, end );
- if ( t >= 0.0f && t <= 1.0f && t < tmin )
- {
- pnt.interpolate( start, end, t );
- S32 j = 0;
- for ( ; j < planeCount; j++ )
- {
- if ( i == j )
- continue;
- F32 dist = planeList[j].distToPlane( pnt );
- if ( dist > 1.0e-004f )
- break;
- }
- if ( j == planeCount )
- {
- tmin = t;
- hitFace = i;
- }
- }
- }
- if ( hitFace == -1 )
- return false;
- info->face = hitFace;
- info->material = mMaterialInst;
- info->normal = planeList[ hitFace ];
- info->object = this;
- info->t = tmin;
- //mObjToWorld.mulV( info->normal );
- return true;
- }
- bool ConvexShape::collideBox( const Point3F &start, const Point3F &end, RayInfo *info )
- {
- return Parent::collideBox( start, end, info );
- }
- void ConvexShape::updateBounds( bool recenter )
- {
- if ( mGeometry.points.size() == 0 )
- return;
- Vector<Point3F> &pointListOS = mGeometry.points;
- U32 pointCount = pointListOS.size();
- Point3F volumnCenter( 0,0,0 );
- F32 areaSum = 0.0f;
- F32 faceCount = mGeometry.faces.size();
- for ( S32 i = 0; i < faceCount; i++ )
- {
- volumnCenter += mGeometry.faces[i].centroid * mGeometry.faces[i].area;
- areaSum += mGeometry.faces[i].area;
- }
- if ( areaSum == 0.0f )
- return;
- volumnCenter /= areaSum;
-
- mObjBox.minExtents = mObjBox.maxExtents = Point3F::Zero;
- mObjBox.setCenter( volumnCenter );
- for ( S32 i = 0; i < pointCount; i++ )
- mObjBox.extend( pointListOS[i] );
- resetWorldBox();
- }
- void ConvexShape::recenter()
- {
- if ( mGeometry.points.size() == 0 )
- return;
-
- Point3F volCenterOS( 0,0,0 );
- F32 areaSum = 0.0f;
- F32 faceCount = mGeometry.faces.size();
- for ( S32 i = 0; i < faceCount; i++ )
- {
- volCenterOS += mGeometry.faces[i].centroid * mGeometry.faces[i].area;
- areaSum += mGeometry.faces[i].area;
- }
- volCenterOS /= areaSum;
- for ( S32 i = 0; i < mSurfaces.size(); i++ )
- mSurfaces[i].setPosition( mSurfaces[i].getPosition() - volCenterOS );
-
- Point3F volCenterWS;
- MatrixF objToWorld( mObjToWorld );
- objToWorld.scale( mObjScale );
- objToWorld.mulP( volCenterOS, &volCenterWS );
- setPosition( volCenterWS );
- _updateGeometry(true);
- }
- MatrixF ConvexShape::getSurfaceWorldMat( S32 surfId, bool scaled ) const
- {
- if ( surfId < 0 || surfId >= mSurfaces.size() )
- return MatrixF::Identity;
- MatrixF objToWorld( mObjToWorld );
- if ( scaled )
- objToWorld.scale( mObjScale );
- MatrixF surfMat;
- surfMat.mul( objToWorld, mSurfaces[surfId] );
- return surfMat;
- }
- // Used in cullEmptyPlanes.
- S32 QSORT_CALLBACK sortDescendingU32( const void *a, const void *b )
- {
- U32 *aa = (U32*)(a);
- U32 *bb = (U32*)(b);
- return (S32)(*bb) - (S32)(*aa);
- }
- void ConvexShape::cullEmptyPlanes( Vector< U32 > *removedPlanes )
- {
- //if ( mPlanes.size() == mGeometry.faces.size() )
- // return;
- removedPlanes->clear();
- const U32 startPlaneCount = mPlanes.size();
- const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
- const U32 faceCount = faceList.size();
- S32 *used = new S32[ startPlaneCount ];
- for ( S32 i = 0; i < startPlaneCount; i++ )
- used[i] = i;
- for ( S32 i = 0; i < faceCount; i++ )
- {
- if ( faceList[i].area > 0.001f )
- used[ faceList[i].id ] = -1;
- }
- for ( S32 i = 0; i < startPlaneCount; i++ )
- {
- if ( used[i] != -1 )
- removedPlanes->push_back( used[i] );
- }
-
- dQsort( removedPlanes->address(), removedPlanes->size(), sizeof( U32 ), sortDescendingU32 );
- for ( S32 i = 0; i < removedPlanes->size(); i++ )
- {
- mPlanes.erase( (*removedPlanes)[i] );
- mSurfaces.erase( (*removedPlanes)[i] );
- }
- delete [] used;
- }
- void ConvexShape::exportToCollada()
- {
- if ( mSurfaces.size() == 0 )
- {
- Con::errorf( "ConvexShape::exportToCollada() - has no surfaces to export!" );
- return;
- }
- }
- void ConvexShape::resizePlanes( const Point3F &size )
- {
- //Point3F nSize;
- //mWorldToObj.mulV( nSize );
- for ( S32 i = 0; i < mSurfaces.size(); i++ )
- {
- MatrixF objToPlane( mSurfaces[i] );
- objToPlane.inverse();
- Point3F lim;
- objToPlane.mulV( size, &lim );
- F32 sign = ( mPlanes[i].d > 0.0f ) ? 1.0f : -1.0f;
- mPlanes[i].d = mFabs(lim.z) * 0.5f * sign;
-
- //mPlanes[i].d = -lim.z * 0.5f;
- mSurfaces[i].setPosition( mPlanes[i].getPosition() );
- }
- }
- void ConvexShape::getSurfaceLineList( S32 surfId, Vector< Point3F > &lineList )
- {
- if ( surfId < 0 || surfId > mSurfaces.size() - 1 )
- return;
- S32 faceId = -1;
- for ( S32 i = 0; i < mGeometry.faces.size(); i++ )
- {
- if ( mGeometry.faces[i].id == surfId )
- {
- faceId = i;
- break;
- }
- }
- if ( faceId == -1 )
- return;
- ConvexShape::Face &face = mGeometry.faces[faceId];
- const Vector< Point3F > &pointList = mGeometry.points;
- if ( pointList.size() == 0 )
- return;
- for ( S32 i = 0; i < face.winding.size(); i++ )
- lineList.push_back( pointList[ face.points[ face.winding[i] ] ] );
-
- lineList.push_back( pointList[ face.points[ face.winding.first() ] ] );
- }
- void ConvexShape::_updateMaterial()
- {
- //update our custom surface materials
- for (U32 i = 0; i<mSurfaceTextures.size(); i++)
- {
- mSurfaceTextures[i]._setMaterial(mSurfaceTextures[i].getMaterial());
- //If we already have the material inst and it hasn't changed, skip
- if (mSurfaceTextures[i].materialInst &&
- mSurfaceTextures[i].getMaterialAsset()->getMaterialDefinitionName() == mSurfaceTextures[i].materialInst->getMaterial()->getName() &&
- mSurfaceTextures[i].materialInst->getVertexFormat() == getGFXVertexFormat<VertexType>())
- continue;
- SAFE_DELETE(mSurfaceTextures[i].materialInst);
- Material* material = mSurfaceTextures[i].getMaterialResource();
- if (material == nullptr)
- continue;
- mSurfaceTextures[i].materialInst = material->createMatInstance();
- FeatureSet features = MATMGR->getDefaultFeatures();
- mSurfaceTextures[i].materialInst->init(features, getGFXVertexFormat<VertexType>());
- if (!mSurfaceTextures[i].materialInst->isValid())
- {
- SAFE_DELETE(mSurfaceTextures[i].materialInst);
- }
- }
- _setMaterial(getMaterial());
- // If the material name matches then don't bother updating it.
- if (mMaterialInst && getMaterialAsset()->getMaterialDefinitionName() == mMaterialInst->getMaterial()->getName() &&
- mMaterialInst->getVertexFormat() == getGFXVertexFormat<VertexType>())
- return;
- SAFE_DELETE( mMaterialInst );
- Material* material = getMaterialResource();
- if (material == nullptr)
- return;
- mMaterialInst = material->createMatInstance();
- FeatureSet features = MATMGR->getDefaultFeatures();
- //features.addFeature( MFT_DiffuseVertColor );
- mMaterialInst->init( features, getGFXVertexFormat<VertexType>() );
- if ( !mMaterialInst->isValid() )
- {
- SAFE_DELETE( mMaterialInst );
- }
- }
- void ConvexShape::_updateGeometry( bool updateCollision )
- {
- mPlanes.clear();
- for ( S32 i = 0; i < mSurfaces.size(); i++ )
- mPlanes.push_back( PlaneF( mSurfaces[i].getPosition(), mSurfaces[i].getUpVector() ) );
- Vector< Point3F > tangents;
- for (S32 i = 0; i < mSurfaces.size(); i++)
- tangents.push_back(mSurfaces[i].getRightVector());
- //prepping the texture info
- Vector<Point2F> texOffset;
- Vector<Point2F> texScale;
- Vector<bool> horzFlip;
- Vector<bool> vertFlip;
- //step in here, and add new surfaceTextures if we don't match the count of surfaces, we use
- //msurfaces as the counter, because we need to match it.
- if (mSurfaceUVs.size() > mSurfaces.size())
- {
- for (U32 x = mSurfaceUVs.size(); x > mSurfaces.size(); x--)
- mSurfaceUVs.pop_front();
- }
- else if (mSurfaceUVs.size() < mSurfaces.size())
- {
- for (U32 x = mSurfaceUVs.size(); x <= mSurfaces.size(); x++)
- {
- mSurfaceUVs.increment();
- mSurfaceUVs[x].offset = Point2F(0, 0);
- mSurfaceUVs[x].scale = Point2F(1, 1);
- mSurfaceUVs[x].zRot = 0;
- mSurfaceUVs[x].horzFlip = false;
- mSurfaceUVs[x].vertFlip = false;
- mSurfaceUVs[x].matID = 0;
- }
- }
- for (S32 i = 0; i < mSurfaceUVs.size(); i++)
- {
- //add our offsets/scales for passing to the geometry now
- texOffset.push_back(mSurfaceUVs[i].offset);
- texScale.push_back(mSurfaceUVs[i].scale);
- horzFlip.push_back(mSurfaceUVs[i].horzFlip);
- vertFlip.push_back(mSurfaceUVs[i].vertFlip);
- }
- mGeometry.generate(mPlanes, tangents, mSurfaceTextures, texOffset, texScale, horzFlip, vertFlip);
- AssertFatal(mGeometry.faces.size() <= mSurfaces.size(), "Got more faces than planes?");
- const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
- const Vector< Point3F > &pointList = mGeometry.points;
- // Reset our surface center points.
- for (S32 i = 0; i < faceList.size(); i++)
- mSurfaces[faceList[i].id].setPosition(faceList[i].centroid);
- mPlanes.clear();
- for (S32 i = 0; i < mSurfaces.size(); i++)
- mPlanes.push_back(PlaneF(mSurfaces[i].getPosition(), mSurfaces[i].getUpVector()));
- // Update bounding box.
- updateBounds( false );
- /*mVertexBuffer = NULL;
- mPrimitiveBuffer = NULL;
- mVertCount = 0;
- mPrimCount = 0;*/
- mSurfaceBuffers.clear();
- //set up buffers based on how many materials we have, but we always have at least one for our default mat
- mSurfaceBuffers.increment();
- mSurfaceBuffers[0].mVertexBuffer = NULL;
- mSurfaceBuffers[0].mVertCount = 0;
- mSurfaceBuffers[0].mPrimCount = 0;
- for (U32 i = 0; i < mSurfaceTextures.size(); i++)
- {
- mSurfaceBuffers.increment();
- mSurfaceBuffers[i+1].mVertexBuffer = NULL;
- mSurfaceBuffers[i + 1].mVertCount = 0;
- mSurfaceBuffers[i + 1].mPrimCount = 0;
- }
- if ( updateCollision )
- _updateCollision();
- // Server does not need to generate vertex/prim buffers.
- if ( isServerObject() )
- return;
- if ( faceList.empty() )
- return;
- //We do this in 2 parts. First, going through and building the buffers for all faces with the default material(matID -1)
- //After that, we then through and build buffers for all faces sharing materials. This means we can have a single buffer,
- //or one for each face of the brush, depending on how it's textured
- // Get total vert and prim count.
- for ( S32 i = 0; i < faceList.size(); i++ )
- {
- U32 count = faceList[i].triangles.size();
- mSurfaceBuffers[mSurfaceUVs[i].matID].mPrimCount += count;
- mSurfaceBuffers[mSurfaceUVs[i].matID].mVertCount += count * 3;
- }
- //Build the buffer for our default material
- /*if (mVertCount > 0)
- {
- mVertexBuffer.set(GFX, mVertCount, GFXBufferTypeStatic);
- VertexType *pVert = mVertexBuffer.lock();
- for (S32 i = 0; i < faceList.size(); i++)
- {
- if (mSurfaceUVs[i].matID == -1)
- {
- const ConvexShape::Face &face = faceList[i];
- const Vector< U32 > &facePntMap = face.points;
- const Vector< ConvexShape::Triangle > &triangles = face.triangles;
- const ColorI &faceColor = sgConvexFaceColors[i % sgConvexFaceColorCount];
- const Point3F binormal = mCross(face.normal, face.tangent);
- pVert++;
- }
- }
- }
- }
- mVertexBuffer.unlock();
- // Allocate PB
- mPrimitiveBuffer.set(GFX, mPrimCount * 3, mPrimCount, GFXBufferTypeStatic);
- U16 *pIndex;
- mPrimitiveBuffer.lock(&pIndex);
- for (U16 i = 0; i < mPrimCount * 3; i++)
- {
- *pIndex = i;
- pIndex++;
- }
- mPrimitiveBuffer.unlock();
- }*/
- //
- //
- for (U32 i = 0; i < mSurfaceBuffers.size(); i++)
- {
- if (mSurfaceBuffers[i].mVertCount > 0)
- {
- mSurfaceBuffers[i].mVertexBuffer.set(GFX, mSurfaceBuffers[i].mVertCount, GFXBufferTypeStatic);
- VertexType *pVert = mSurfaceBuffers[i].mVertexBuffer.lock();
- U32 vc = 0;
- for (S32 f = 0; f < faceList.size(); f++)
- {
- if (mSurfaceUVs[f].matID == i)
- {
- const ConvexShape::Face &face = faceList[f];
- const Vector< U32 > &facePntMap = face.points;
- const Vector< ConvexShape::Triangle > &triangles = face.triangles;
- const ColorI &faceColor = sgConvexFaceColors[f % sgConvexFaceColorCount];
- const Point3F binormal = mCross(face.normal, face.tangent);
- for (S32 j = 0; j < triangles.size(); j++)
- {
- for (S32 k = 0; k < 3; k++)
- {
- pVert->normal = face.normal;
- pVert->T = face.tangent;
- pVert->B = mCross(face.normal,face.tangent);
- //pVert->color = faceColor;
- pVert->point = pointList[facePntMap[triangles[j][k]]];
- pVert->texCoord = face.texcoords[triangles[j][k]];
- pVert->texCoord2 = pVert->texCoord;
- pVert++;
- vc++;
- }
- }
- }
- }
- mSurfaceBuffers[i].mVertexBuffer.unlock();
- // Allocate PB
- mSurfaceBuffers[i].mPrimitiveBuffer.set(GFX, mSurfaceBuffers[i].mPrimCount * 3, mSurfaceBuffers[i].mPrimCount, GFXBufferTypeStatic);
- U16 *pIndex;
- mSurfaceBuffers[i].mPrimitiveBuffer.lock(&pIndex);
- for (U16 p = 0; p < mSurfaceBuffers[i].mPrimCount * 3; p++)
- {
- *pIndex = p;
- pIndex++;
- }
- mSurfaceBuffers[i].mPrimitiveBuffer.unlock();
- }
- }
- //
- //
- /*// Allocate VB and copy in data.
- for (S32 i = 0; i < faceList.size(); i++)
- {
- mVertexBuffer.set(GFX, mVertCount, GFXBufferTypeStatic);
- VertexType *pVert = mVertexBuffer.lock();
- for (S32 i = 0; i < faceList.size(); i++)
- {
- const ConvexShape::Face &face = faceList[i];
- const Vector< U32 > &facePntMap = face.points;
- const Vector< ConvexShape::Triangle > &triangles = face.triangles;
- const ColorI &faceColor = sgConvexFaceColors[i % sgConvexFaceColorCount];
- const Point3F binormal = mCross(face.normal, face.tangent);
- for (S32 j = 0; j < triangles.size(); j++)
- {
- for (S32 k = 0; k < 3; k++)
- {
- pVert->normal = face.normal;
- pVert->tangent = face.tangent;
- pVert->color = faceColor;
- pVert->point = pointList[facePntMap[triangles[j][k]]];
- pVert->texCoord = face.texcoords[triangles[j][k]];
- pVert++;
- }
- }
- }
- mVertexBuffer.unlock();
- // Allocate PB
- mPrimitiveBuffer.set(GFX, mPrimCount * 3, mPrimCount, GFXBufferTypeStatic);
- U16 *pIndex;
- mPrimitiveBuffer.lock(&pIndex);
- for (U16 i = 0; i < mPrimCount * 3; i++)
- {
- *pIndex = i;
- pIndex++;
- }
- mPrimitiveBuffer.unlock();
- }*/
- }
- void ConvexShape::_updateCollision()
- {
- SAFE_DELETE( mPhysicsRep );
- if ( !PHYSICSMGR )
- return;
- PhysicsCollision *colShape = PHYSICSMGR->createCollision();
- // We need the points untransformed!
- Vector<Point3F> rawPoints;
- MatrixF xfm( getWorldTransform() );
- xfm.setPosition( Point3F::Zero );
- for ( U32 i=0; i < mGeometry.points.size(); i++ )
- {
- Point3F p = mGeometry.points[i];
- xfm.mulP( p );
- rawPoints.push_back( p );
- }
- // The convex generation from a point cloud
- // can fail at times... give up in that case.
- if ( !colShape->addConvex( mGeometry.points.address(),
- mGeometry.points.size(),
- MatrixF::Identity ) )
- {
- delete colShape;
- return;
- }
- PhysicsWorld *world = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" );
- mPhysicsRep = PHYSICSMGR->createBody();
- mPhysicsRep->init( colShape, 0, 0, this, world );
- mPhysicsRep->setTransform( getTransform() );
- }
- void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mat )
- {
- GFXDrawUtil *drawer = GFX->getDrawUtil();
- GFX->setTexture( 0, NULL );
- // Render world box.
- if (Con::getBoolVariable("$pref::convexDBG::ShowWorldBox", false))
- {
- Box3F wbox( mWorldBox );
- if ( getServerObject() )
- wbox = static_cast<ConvexShape*>( getServerObject() )->mWorldBox;
- GFXStateBlockDesc desc;
- desc.setCullMode( GFXCullNone );
- desc.setFillModeWireframe();
- drawer->drawCube( desc, wbox, ColorI::RED );
- }
- const Vector< Point3F > &pointList = mGeometry.points;
- const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
- // Render Edges.
- if (Con::getBoolVariable("$pref::convexDBG::ShowEdges", false))
- {
- GFXTransformSaver saver;
- //GFXFrustumSaver fsaver;
- MatrixF xfm( getRenderTransform() );
- xfm.scale( getScale() );
- GFX->multWorld( xfm );
- GFXStateBlockDesc desc;
- desc.setZReadWrite( true, false );
- desc.setBlend( true );
- GFX->setStateBlockByDesc( desc );
- //MathUtils::getZBiasProjectionMatrix( 0.01f, state->getFrustum(), )
- const Point3F &camFvec = state->getCameraTransform().getForwardVector();
- for ( S32 i = 0; i < faceList.size(); i++ )
- {
- const ConvexShape::Face &face = faceList[i];
-
- const Vector< ConvexShape::Edge > &edgeList = face.edges;
- const Vector< U32 > &facePntList = face.points;
- PrimBuild::begin( GFXLineList, edgeList.size() * 2 );
-
- PrimBuild::color( LinearColorF(ColorI::WHITE) * 0.8f );
- for ( S32 j = 0; j < edgeList.size(); j++ )
- {
- PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p0 ] ] - camFvec * 0.001f );
- PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p1 ] ] - camFvec * 0.001f );
- }
-
- PrimBuild::end();
- }
- }
- ColorI faceColorsx[4] =
- {
- ColorI( 255, 0, 0 ),
- ColorI( 0, 255, 0 ),
- ColorI( 0, 0, 255 ),
- ColorI( 255, 0, 255 )
- };
- MatrixF objToWorld( mObjToWorld );
- objToWorld.scale( mObjScale );
- // Render faces centers/colors.
- if (Con::getBoolVariable("$pref::convexDBG::ShowFaceColors", false))
- {
- GFXStateBlockDesc desc;
- desc.setCullMode( GFXCullNone );
-
- Point3F size( 0.1f );
- for ( S32 i = 0; i < faceList.size(); i++ )
- {
- ColorI color = faceColorsx[ i % 4 ];
- LinearColorF tCol = LinearColorF(color);
- S32 div = ( i / 4 ) * 4;
- if ( div > 0 )
- tCol /= div;
- tCol.alpha = 1;
- color = tCol.toColorI();
- Point3F pnt;
- objToWorld.mulP( faceList[i].centroid, &pnt );
- drawer->drawCube( desc, size, pnt, color, NULL );
- }
- }
- // Render winding order.
- if (Con::getBoolVariable("$pref::convexDBG::ShowWinding", false))
- {
- GFXStateBlockDesc desc;
- desc.setCullMode( GFXCullNone );
- desc.setZReadWrite( true, false );
- GFX->setStateBlockByDesc( desc );
- U32 pointCount = 0;
- for ( S32 i = 0; i < faceList.size(); i++ )
- pointCount += faceList[i].winding.size();
- PrimBuild::begin( GFXLineList, pointCount * 2 );
-
- for ( S32 i = 0; i < faceList.size(); i++ )
- {
- for ( S32 j = 0; j < faceList[i].winding.size(); j++ )
- {
- Point3F p0 = pointList[ faceList[i].points[ faceList[i].winding[j] ] ];
- Point3F p1 = p0 + mSurfaces[ faceList[i].id ].getUpVector() * 0.75f * ( Point3F::One / mObjScale );
- objToWorld.mulP( p0 );
- objToWorld.mulP( p1 );
- ColorI color = faceColorsx[j % 4];
- LinearColorF tCol = LinearColorF(color);
- S32 div = (j / 4) * 4;
- if (div > 0)
- tCol /= div;
- tCol.alpha = 1;
- color = tCol.toColorI();
-
- PrimBuild::color( color );
- PrimBuild::vertex3fv( p0 );
- PrimBuild::color( color );
- PrimBuild::vertex3fv( p1 );
- }
- }
- PrimBuild::end();
- }
- // Render Points.
- if ( false )
- {
- /*
- GFXTransformSaver saver;
- MatrixF xfm( getRenderTransform() );
- xfm.scale( getScale() );
- GFX->multWorld( xfm );
- GFXStateBlockDesc desc;
- Point3F size( 0.05f );
- */
- }
- // Render surface transforms.
- if (Con::getBoolVariable("$pref::convexDBG::ShowSurfaceTransforms", false))
- {
- GFXStateBlockDesc desc;
- desc.setBlend( false );
- desc.setZReadWrite( true, true );
- Point3F scale(mNormalLength);
- for ( S32 i = 0; i < mSurfaces.size(); i++ )
- {
- objToWorld = mObjToWorld;
- objToWorld.scale( mObjScale );
- MatrixF renderMat;
- renderMat.mul( objToWorld, mSurfaces[i] );
- renderMat.setPosition( renderMat.getPosition() + renderMat.getUpVector() * 0.001f );
-
- drawer->drawTransform( desc, renderMat, &scale, NULL );
- }
- }
- }
- void ConvexShape::renderFaceEdges( S32 faceid, const ColorI &color /*= ColorI::WHITE*/, F32 lineWidth /*= 1.0f */ )
- {
- const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
- if ( faceid >= faceList.size() )
- return;
- GFXTransformSaver saver;
- MatrixF xfm( mObjToWorld );
- xfm.scale( mObjScale );
- GFX->multWorld( xfm );
- GFXStateBlockDesc desc;
- desc.setBlend( true );
- GFX->setStateBlockByDesc( desc );
- MatrixF projBias(true);
- const Frustum& frustum = GFX->getFrustum();
- MathUtils::getZBiasProjectionMatrix( 0.001f, frustum, &projBias );
- GFX->setProjectionMatrix( projBias );
- S32 s = faceid;
- S32 e = faceid + 1;
- if ( faceid == -1 )
- {
- s = 0;
- e = faceList.size();
- }
- for ( S32 i = s; i < e; i++ )
- {
- const ConvexShape::Face &face = faceList[i];
- const Vector< ConvexShape::Edge > &edgeList = face.edges;
- const Vector< U32 > &facePntList = face.points;
- const Vector< Point3F > &pointList = mGeometry.points;
- PrimBuild::begin( GFXLineList, edgeList.size() * 2 );
- PrimBuild::color( color );
- for ( S32 j = 0; j < edgeList.size(); j++ )
- {
- PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p0 ] ] );
- PrimBuild::vertex3fv( pointList[ facePntList[ edgeList[j].p1 ] ] );
- }
- PrimBuild::end();
- }
- }
- void ConvexShape::getSurfaceTriangles( S32 surfId, Vector< Point3F > *outPoints, Vector< Point2F > *outCoords, bool worldSpace )
- {
- S32 faceId = -1;
- for ( S32 i = 0; i < mGeometry.faces.size(); i++ )
- {
- if ( mGeometry.faces[i].id == surfId )
- {
- faceId = i;
- break;
- }
- }
- if ( faceId == -1 )
- return;
- const ConvexShape::Face &face = mGeometry.faces[ faceId ];
- const Vector< Point3F > &pointList = mGeometry.points;
- const MatrixF &surfToObj = mSurfaces[ faceId ];
- MatrixF objToSurf( surfToObj );
- objToSurf.inverse();
- Point3F surfScale( 1.5f, 1.5f, 1.0f );
- for ( S32 i = 0; i < face.triangles.size(); i++ )
- {
- for ( S32 j = 0; j < 3; j++ )
- {
- Point3F pnt( pointList[ face.points[ face.triangles[i][j] ] ] );
-
- objToSurf.mulP( pnt );
- pnt *= surfScale;
- surfToObj.mulP( pnt );
- outPoints->push_back( pnt );
- if ( outCoords )
- outCoords->push_back( face.texcoords[ face.triangles[i][j] ] );
- }
- }
- if ( worldSpace )
- {
- MatrixF objToWorld( mObjToWorld );
- objToWorld.scale( mObjScale );
- for ( S32 i = 0; i < outPoints->size(); i++ )
- objToWorld.mulP( (*outPoints)[i] );
- }
- }
- void ConvexShape::Geometry::generate(const Vector< PlaneF > &planes, const Vector< Point3F > &tangents, const Vector< surfaceMaterial > surfaceTextures, const Vector< Point2F > texOffset, const Vector< Point2F > texScale, const Vector< bool > horzFlip, const Vector< bool > vertFlip)
- {
- PROFILE_SCOPE( Geometry_generate );
- points.clear();
- faces.clear();
- AssertFatal( planes.size() == tangents.size(), "ConvexShape - incorrect plane/tangent count." );
- #ifdef TORQUE_ENABLE_ASSERTS
- for ( S32 i = 0; i < planes.size(); i++ )
- {
- F32 dt = mDot( planes[i], tangents[i] );
- AssertFatal( mIsZero( dt, 0.0001f ), "ConvexShape - non perpendicular input vectors." );
- AssertFatal( planes[i].isUnitLength() && tangents[i].isUnitLength(), "ConvexShape - non unit length input vector." );
- }
- #endif
- const U32 planeCount = planes.size();
- Point3F linePt, lineDir;
- for ( S32 i = 0; i < planeCount; i++ )
- {
- Vector< MathUtils::Line > collideLines;
- // Find the lines defined by the intersection of this plane with all others.
- for ( S32 j = 0; j < planeCount; j++ )
- {
- if ( i == j )
- continue;
- if ( planes[i].intersect( planes[j], linePt, lineDir ) )
- {
- collideLines.increment();
- MathUtils::Line &line = collideLines.last();
- line.origin = linePt;
- line.direction = lineDir;
- }
- }
- if ( collideLines.empty() )
- continue;
- // Find edges and points defined by the intersection of these lines.
- // As we find them we fill them into our working ConvexShape::Face
- // structure.
-
- Face newFace;
- for ( S32 j = 0; j < collideLines.size(); j++ )
- {
- Vector< Point3F > collidePoints;
- for ( S32 k = 0; k < collideLines.size(); k++ )
- {
- if ( j == k )
- continue;
- MathUtils::LineSegment segment;
- MathUtils::mShortestSegmentBetweenLines( collideLines[j], collideLines[k], &segment );
- F32 dist = ( segment.p0 - segment.p1 ).len();
- if ( dist < 0.0005f )
- {
- S32 l = 0;
- for ( ; l < planeCount; l++ )
- {
- if ( planes[l].whichSide( segment.p0 ) == PlaneF::Front )
- break;
- }
- if ( l == planeCount )
- collidePoints.push_back( segment.p0 );
- }
- }
- //AssertFatal( collidePoints.size() <= 2, "A line can't collide with more than 2 other lines in a convex shape..." );
- if ( collidePoints.size() != 2 )
- continue;
- // Push back collision points into our points vector
- // if they are not duplicates and determine the id
- // index for those points to be used by Edge(s).
- const Point3F &pnt0 = collidePoints[0];
- const Point3F &pnt1 = collidePoints[1];
- S32 idx0 = -1;
- S32 idx1 = -1;
- for ( S32 k = 0; k < points.size(); k++ )
- {
- if ( pnt0.equal( points[k] ) )
- {
- idx0 = k;
- break;
- }
- }
- for ( S32 k = 0; k < points.size(); k++ )
- {
- if ( pnt1.equal( points[k] ) )
- {
- idx1 = k;
- break;
- }
- }
- if ( idx0 == -1 )
- {
- points.push_back( pnt0 );
- idx0 = points.size() - 1;
- }
- if ( idx1 == -1 )
- {
- points.push_back( pnt1 );
- idx1 = points.size() - 1;
- }
- // Construct the Face::Edge defined by this collision.
- S32 localIdx0 = newFace.points.push_back_unique( idx0 );
- S32 localIdx1 = newFace.points.push_back_unique( idx1 );
- newFace.edges.increment();
- ConvexShape::Edge &newEdge = newFace.edges.last();
- newEdge.p0 = localIdx0;
- newEdge.p1 = localIdx1;
- }
- if ( newFace.points.size() < 3 )
- continue;
- //AssertFatal( newFace.points.size() == newFace.edges.size(), "ConvexShape - face point count does not equal edge count." );
- // Fill in some basic Face information.
- newFace.id = i;
- newFace.normal = planes[i];
- newFace.tangent = tangents[i];
- // Make a working array of Point3Fs on this face.
- U32 pntCount = newFace.points.size();
- Point3F *workPoints = new Point3F[ pntCount ];
- for ( S32 j = 0; j < pntCount; j++ )
- workPoints[j] = points[ newFace.points[j] ];
- // Calculate the average point for calculating winding order.
- Point3F averagePnt = Point3F::Zero;
- for ( S32 j = 0; j < pntCount; j++ )
- averagePnt += workPoints[j];
- averagePnt /= pntCount;
- // Sort points in correct winding order.
- U32 *vertMap = new U32[pntCount];
- MatrixF quadMat( true );
- quadMat.setPosition( averagePnt );
- quadMat.setColumn( 0, newFace.tangent );
- quadMat.setColumn( 1, mCross( newFace.normal, newFace.tangent ) );
- quadMat.setColumn( 2, newFace.normal );
- quadMat.inverse();
- // Transform working points into quad space
- // so we can work with them as 2D points.
- for ( S32 j = 0; j < pntCount; j++ )
- quadMat.mulP( workPoints[j] );
- MathUtils::sortQuadWindingOrder( true, workPoints, vertMap, pntCount );
- // Save points in winding order.
- for ( S32 j = 0; j < pntCount; j++ )
- newFace.winding.push_back( vertMap[j] );
- // Calculate the area and centroid of the face.
- newFace.area = 0.0f;
- for ( S32 j = 0; j < pntCount; j++ )
- {
- S32 k = ( j + 1 ) % pntCount;
- const Point3F &p0 = workPoints[ vertMap[j] ];
- const Point3F &p1 = workPoints[ vertMap[k] ];
-
- // Note that this calculation returns positive area for clockwise winding
- // and negative area for counterclockwise winding.
- newFace.area += p0.y * p1.x;
- newFace.area -= p0.x * p1.y;
- }
- //AssertFatal( newFace.area > 0.0f, "ConvexShape - face area was not positive." );
- if ( newFace.area > 0.0f )
- newFace.area /= 2.0f;
- F32 factor;
- F32 cx = 0.0f, cy = 0.0f;
-
- for ( S32 j = 0; j < pntCount; j++ )
- {
- S32 k = ( j + 1 ) % pntCount;
- const Point3F &p0 = workPoints[ vertMap[j] ];
- const Point3F &p1 = workPoints[ vertMap[k] ];
- factor = p0.x * p1.y - p1.x * p0.y;
- cx += ( p0.x + p1.x ) * factor;
- cy += ( p0.y + p1.y ) * factor;
- }
-
- factor = 1.0f / ( newFace.area * 6.0f );
- newFace.centroid.set( cx * factor, cy * factor, 0.0f );
- quadMat.inverse();
- quadMat.mulP( newFace.centroid );
- delete [] workPoints;
- workPoints = NULL;
- // Make polygons / triangles for this face.
- const U32 polyCount = pntCount - 2;
- newFace.triangles.setSize( polyCount );
- for ( S32 j = 0; j < polyCount; j++ )
- {
- ConvexShape::Triangle &poly = newFace.triangles[j];
- poly.p0 = vertMap[0];
- if ( j == 0 )
- {
- poly.p1 = vertMap[ 1 ];
- poly.p2 = vertMap[ 2 ];
- }
- else
- {
- poly.p1 = vertMap[ 1 + j ];
- poly.p2 = vertMap[ 2 + j ];
- }
- }
- delete [] vertMap;
- // Calculate texture coordinates for each point in this face.
- const Point3F binormal = mCross( newFace.normal, newFace.tangent );
- PlaneF planey( newFace.centroid - 0.5f * binormal, binormal );
- PlaneF planex( newFace.centroid - 0.5f * newFace.tangent, newFace.tangent );
- newFace.texcoords.setSize( newFace.points.size() );
- for ( S32 j = 0; j < newFace.points.size(); j++ )
- {
- F32 x = planex.distToPlane( points[ newFace.points[ j ] ] );
- F32 y = planey.distToPlane( points[ newFace.points[ j ] ] );
- if (!texOffset.empty())
- {
- x += texOffset[i].x;
- y += texOffset[i].y;
- }
-
- //now scale
- if (!texScale.empty() && !texScale[i].isZero())
- {
- x *= (texScale[i].x);
- y *= (texScale[i].y);
- }
-
- if (horzFlip.size() > 0 && horzFlip[i])
- x *= -1;
-
- if (vertFlip.size() > 0 && vertFlip[i])
- y *= -1;
-
- newFace.texcoords[j].set(-x, -y);
- }
- // Data verification tests.
- #ifdef TORQUE_ENABLE_ASSERTS
- //S32 triCount = newFace.triangles.size();
- //S32 edgeCount = newFace.edges.size();
- //AssertFatal( triCount == edgeCount - 2, "ConvexShape - triangle/edge count do not match." );
- /*
- for ( S32 j = 0; j < triCount; j++ )
- {
- F32 area = MathUtils::mTriangleArea( points[ newFace.points[ newFace.triangles[j][0] ] ],
- points[ newFace.points[ newFace.triangles[j][1] ] ],
- points[ newFace.points[ newFace.triangles[j][2] ] ] );
- AssertFatal( area > 0.0f, "ConvexShape - triangle winding bad." );
- }*/
- #endif
- // Done with this Face.
-
- faces.push_back( newFace );
- }
- }
- DEF_ASSET_BINDS(ConvexShape, Material);
|