12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159 |
- //-----------------------------------------------------------------------------
- // 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()
- {
- 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);
|