| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: /Commando/Code/Tools/max2w3d/meshsave.cpp 109 3/14/02 4:19p Greg_h $ */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando / G *
- * *
- * File Name : MESHSAVE.CPP *
- * *
- * Programmer : Greg Hjelstrom *
- * *
- * Start Date : 06/10/97 *
- * *
- * Last Update : 10/20/1999997 [GH] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * MeshSaveClass::MeshSaveClass -- constructor, processes a Max mesh *
- * MeshSaveClass::~MeshSaveClass -- destructor, frees all allocated memory *
- * MeshSaveClass::write_verts -- write the vertex chunk into a wtm file *
- * MeshSaveClass::write_header -- write a mesh header chunk into a wtm file *
- * MeshSaveClass::Write_To_File -- Append the mesh to an open wtm file *
- * MeshSaveClass::write_normals -- writes the vertex normals chunk into a wtm file *
- * MeshSaveClass::write_vert_normals -- Writes the surrender normal chunk into a wtm file *
- * MeshSaveClass::write_triangles -- Write the triangles chunk into a wtm file. *
- * MeshSaveClass::write_sr_triangles -- writes the triangles in surrender friendly format *
- * MeshSaveClass::write_triangles -- write the triangles chunk *
- * MeshSaveClass::compute_surrender_vertex -- Compute the surrender vertex normals *
- * MeshSaveClass::setup_material -- Gets the texture names and base colors for a material *
- * MeshSaveClass::compute_bounding_volumes -- computes a bounding box and bounding sphere for*
- * MeshSaveClass::set_transform -- set the default transformation matrix for the mesh *
- * MeshSaveClass::compute_physical_properties -- computes the volume and moment of inertia *
- * MeshSaveClass::prep_mesh -- pre-transform the MAX mesh by a specified matrix *
- * MeshSaveClass::write_user_text -- write the user text chunk *
- * MeshSaveClass::get_htree_bone_index_for_inode -- searches the htree for the given INode *
- * MeshSaveClass::get_skin_modifier_objects -- Searches for the WWSkin modifier for this mes *
- * MeshSaveClass::inv_deform_mesh -- preprocess the mesh for skinning *
- * MeshSaveClass::create_materials -- create the materials for this mesh *
- * MeshSaveClass::write_ps2_shaders -- Write shaders specific to the PS2 in their own chunk. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "meshsave.h"
- #include <Max.h>
- #include <stdmat.h>
- #include <modstack.h>
- #include "gamemtl.h"
- #include "errclass.h"
- #include "vxl.h"
- #include "vxldbg.h"
- #include "nodelist.h"
- #include "hiersave.h"
- #include "util.h"
- #include "w3dappdata.h"
- #include "skin.h"
- #include "skindata.h"
- #include "meshbuild.h"
- #include "alphamodifier.h"
- #include "aabtreebuilder.h"
- #include "exportlog.h"
- static char _string1[512];
- const int VOXEL_RESOLUTION = 64; // resolution to use when computing I, V and CM
- #define DEBUG_VOXELS 0
- #define MIN_AABTREE_POLYGONS 8
- /************************************************************************************
- **
- ** check if this is a mesh which should use a simple rendering method. I don't
- ** compute vertex normals or store u-v's in that case (prevents vertex splitting)
- **
- ************************************************************************************/
- bool use_simple_rendering(int geo_type)
- {
- geo_type &= W3D_MESH_FLAG_GEOMETRY_TYPE_MASK;
- if ( (geo_type == OBSOLETE_W3D_MESH_FLAG_GEOMETRY_TYPE_SHADOW) ||
- (geo_type == W3D_MESH_FLAG_GEOMETRY_TYPE_AABOX) ||
- (geo_type == W3D_MESH_FLAG_GEOMETRY_TYPE_OBBOX) )
- {
- return true;
- } else {
- return false;
- }
- }
- /************************************************************************************
- **
- ** build the bitfield of W3D mesh attributes for the given node
- **
- ************************************************************************************/
- uint32 setup_mesh_attributes(INode * node)
- {
- uint32 attributes = W3D_MESH_FLAG_NONE;
- /*
- ** Mesh will be one of:
- ** W3D_MESH_FLAG_NONE,
- ** W3D_MESH_FLAG_COLLISION_BOX,
- ** W3D_MESH_FLAG_SKIN,
- ** W3D_MESH_FLAG_ALIGNED
- ** W3D_MESH_FLAG_ORIENTED
- */
- if (Is_Collision_AABox(node)) {
- attributes = W3D_MESH_FLAG_GEOMETRY_TYPE_AABOX;
- } else if (Is_Collision_OBBox(node)) {
- attributes = W3D_MESH_FLAG_GEOMETRY_TYPE_OBBOX;
- } else if (Is_Skin(node)) {
- attributes = W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN;
- } else if (Is_Camera_Aligned_Mesh(node)) {
- attributes = W3D_MESH_FLAG_GEOMETRY_TYPE_CAMERA_ALIGNED;
- } else if (Is_Camera_Oriented_Mesh(node)) {
- attributes = W3D_MESH_FLAG_GEOMETRY_TYPE_CAMERA_ORIENTED;
- }
- /*
- ** And, a mesh may have one or more types of collision detection enabled.
- ** W3D_MESH_FLAG_COLLISION_TYPE_PHYSICAL
- ** W3D_MESH_FLAG_COLLISION_TYPE_PROJECTILE
- ** However, if the mesh is SKIN, SHADOW, ALIGNED, ORIENTED or NULL, don't let
- ** the collision bits get set...
- */
- if ( attributes != W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN &&
- attributes != W3D_MESH_FLAG_GEOMETRY_TYPE_CAMERA_ALIGNED &&
- attributes != W3D_MESH_FLAG_GEOMETRY_TYPE_CAMERA_ORIENTED )
- {
-
- if (Is_Physical_Collision(node)) {
- attributes |= W3D_MESH_FLAG_COLLISION_TYPE_PHYSICAL;
- }
- if (Is_Projectile_Collision(node)) {
- attributes |= W3D_MESH_FLAG_COLLISION_TYPE_PROJECTILE;
- }
- if (Is_Vis_Collision(node)) {
- attributes |= W3D_MESH_FLAG_COLLISION_TYPE_VIS;
- }
- if (Is_Camera_Collision(node)) {
- attributes |= W3D_MESH_FLAG_COLLISION_TYPE_CAMERA;
- }
-
- if (Is_Vehicle_Collision(node)) {
- attributes |= W3D_MESH_FLAG_COLLISION_TYPE_VEHICLE;
- }
- }
- /*
- ** A mesh may have one of the following bits set as well
- */
- if (Is_Hidden(node)) {
- attributes |= W3D_MESH_FLAG_HIDDEN;
- }
- if (Is_Two_Sided(node)) {
- attributes |= W3D_MESH_FLAG_TWO_SIDED;
- }
- if (Is_Shadow(node)) {
- attributes |= W3D_MESH_FLAG_CAST_SHADOW;
- }
- if (Is_Shatterable(node)) {
- attributes |= W3D_MESH_FLAG_SHATTERABLE;
- }
- if (Is_NPatchable(node)) {
- attributes |= W3D_MESH_FLAG_NPATCHABLE;
- }
- return attributes;
- }
- /***********************************************************************************************
- * MeshSaveClass::MeshSaveClass -- constructor, processes a Max mesh *
- * *
- * This class takes a MAX mesh and computes the information for a W3D mesh or skin. *
- * *
- * INPUT: *
- * *
- * inode - the max INode containing the mesh/skin to export *
- * exportspace - matrix defining the desired coordinate system for the mesh *
- * htree - hierarchy tree that this mesh is being connected to *
- * curtime - current time in Max. *
- * meter - progress meter *
- * mesh_name - name to use for the mesh *
- * container_name - name of the container *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/10/1997 GH : Created. *
- *=============================================================================================*/
- MeshSaveClass::MeshSaveClass
- (
- char * mesh_name,
- char * container_name,
- INode * inode,
- const Mesh * input_mesh,
- Matrix3 & exportspace,
- W3DAppData2Struct & exportoptions,
- HierarchySaveClass * htree,
- TimeValue curtime,
- Progress_Meter_Class & meter,
- WorldInfoClass * world_info
- ) :
- MaxINode(inode),
- ExportOptions(exportoptions),
- CurTime(curtime),
- ExportSpace(exportspace),
- HTree(htree),
- UserText(NULL),
- VertInfluences(NULL),
- MaterialRemapTable(NULL)
- {
- Mesh mesh = *input_mesh; // copy the mesh so we can modify it
- Mtl * nodemtl = inode->GetMtl();
- DWORD wirecolor = inode->GetWireColor();
- PS2Material = FALSE;
- // Check to see if the mesh uses PS2 game materials. If so, set a flag so
- // that write_shaders will know to make a PS2 shader chunk.
- if (nodemtl) {
- if (nodemtl->ClassID() == PS2GameMaterialClassID) {
- PS2Material = TRUE;
- } else if (nodemtl->IsMultiMtl()) {
- for (int i = 0; i < nodemtl->NumSubMtls(); i++) {
- Mtl *sub = nodemtl->GetSubMtl(i);
- if (sub->ClassID() == PS2GameMaterialClassID) {
- PS2Material = TRUE;
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////
- // Check if the mesh is being inverted by its transform. If this
- // is the case, then we will need to reverse the winding of all
- // polygons later.
- //////////////////////////////////////////////////////////////////////
- Matrix3 objtm = MaxINode->GetObjectTM(curtime);
- MeshInverted = (Compute_3x3_Determinant(objtm) < 0.0f);
- //////////////////////////////////////////////////////////////////////
- // Prep the mesh by transforming it by the delta between exportspace
- // and this INodes current space
- // (this is the delta between the bone and the mesh if one exists...)
- //////////////////////////////////////////////////////////////////////
- MeshToExportSpace = objtm * Inverse(ExportSpace);
- prep_mesh(mesh,MeshToExportSpace);
- //////////////////////////////////////////////////////////////////////
- // Prepare the mesh header.
- //////////////////////////////////////////////////////////////////////
- assert(mesh_name != NULL);
- assert(container_name != NULL);
- memset(&Header,0,sizeof(Header));
- Set_W3D_Name(Header.MeshName,mesh_name);
- Set_W3D_Name(Header.ContainerName,container_name);
- Header.Version = W3D_CURRENT_MESH_VERSION;
- Header.Attributes = setup_mesh_attributes(MaxINode);
- meter.Finish_In_Steps(
- 3*Header.NumTris + // normals
- Header.NumVertices + // surrender normals
- 64 // voxelization
- );
- ExportLog::printf("\nProcessing Mesh: %s\n",Header.MeshName);
- //////////////////////////////////////////////////////////////////////
- // Enforce that we have enough data to actually make a mesh
- //////////////////////////////////////////////////////////////////////
- if (mesh.getNumFaces() <= 0) {
- throw ErrorClass("No Triangles in Mesh: %s",Header.MeshName);
- }
- if (mesh.getNumVerts() <= 0) {
- throw ErrorClass("No Vertices in Mesh: %s",Header.MeshName);
- }
- //////////////////////////////////////////////////////////////////////
- // process the materials
- //////////////////////////////////////////////////////////////////////
- DebugPrint("processing materials\n");
- scan_used_materials(mesh,nodemtl);
- create_materials(nodemtl,wirecolor);
-
- //////////////////////////////////////////////////////////////////////
- // what face and vertex attributes are we going to export?
- //////////////////////////////////////////////////////////////////////
- Header.FaceChannels = W3D_FACE_CHANNEL_FACE;
- Header.VertexChannels = W3D_VERTEX_CHANNEL_LOCATION;
- if (!use_simple_rendering(Header.Attributes)) {
- Header.VertexChannels |= W3D_VERTEX_CHANNEL_NORMAL;
- }
- if (((Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK) == W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN) && (HTree != NULL)) {
- Header.VertexChannels |= W3D_VERTEX_CHANNEL_BONEID;
- }
-
- //////////////////////////////////////////////////////////////////////
- // Process the mesh
- //////////////////////////////////////////////////////////////////////
- Builder.Set_World_Info (world_info);
- Build_Mesh(mesh, nodemtl);
- //////////////////////////////////////////////////////////////////////
- // Determine if the deformer should use alpha or v-color info
- //////////////////////////////////////////////////////////////////////
- if (ExportOptions.Is_Vertex_Alpha_Enabled()) {
- unsigned int alpha_passes = 0;
- for (int pass=0; pass < MaterialDesc.Pass_Count(); pass++) {
- if (MaterialDesc.Pass_Uses_Vertex_Alpha(pass)) {
- alpha_passes |= (1 << pass);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////
- // Set the counts in the mesh header
- //////////////////////////////////////////////////////////////////////
- Header.NumTris = Builder.Get_Face_Count();
- Header.NumVertices = Builder.Get_Vertex_Count();
- //////////////////////////////////////////////////////////////////////
- // Compute the mesh's bounding box and sphere. This must be done
- // before we pre-deform the mesh (if its a skin).
- //////////////////////////////////////////////////////////////////////
- compute_bounding_volumes();
- //////////////////////////////////////////////////////////////////////
- // Voxelize the mesh and compute the Moment of Inertia and
- // Center of Mass. This must come after we compute the bounding
- // volumes and before we pre-deform the mesh.
- //////////////////////////////////////////////////////////////////////
- Progress_Meter_Class voxelmeter(meter, 64.0f * meter.Increment);
- compute_physical_constants(MaxINode,voxelmeter,false /*usevoxelizer*/);
-
- //////////////////////////////////////////////////////////////////////
- // If this is a skin, pre-deform the mesh.
- //////////////////////////////////////////////////////////////////////
- if (((Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK) == W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN) && (HTree != NULL)) {
- inv_deform_mesh();
- }
-
- //////////////////////////////////////////////////////////////////////
- // Get the user text from MAX's properties window.
- //////////////////////////////////////////////////////////////////////
- TSTR usertext;
- MaxINode->GetUserPropBuffer(usertext);
- CStr usertext8 = usertext;
- if (usertext8.Length() > 0) {
- UserText = new char[usertext8.Length() + 1];
- memset(UserText,0,usertext8.Length() + 1);
- memcpy(UserText,usertext8.data(),usertext8.Length());
- }
- }
- /***********************************************************************************************
- * MeshSaveClass::~MeshSaveClass -- destructor, frees all allocated memory *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/10/1997 GH : Created. *
- *=============================================================================================*/
- MeshSaveClass::~MeshSaveClass(void)
- {
- if (UserText) {
- delete[] UserText;
- UserText = NULL;
- }
- if (VertInfluences) {
- delete[] VertInfluences;
- VertInfluences = NULL;
- }
-
- if (MaterialRemapTable) {
- delete[] MaterialRemapTable;
- MaterialRemapTable = NULL;
- }
- }
- void MeshSaveClass::Build_Mesh(Mesh & mesh, Mtl *node_mtl)
- {
- int vert_counter;
- int face_index;
- int pass;
- int stage;
- float *vdata = NULL;
- Builder.Reset(true,mesh.getNumFaces(),mesh.getNumFaces()/3);
- // Get a pointer to the channel that has alpha values entered by the artist.
- // This pointer will be NULL if they didn't use the channel.
- vdata = mesh.vertexFloat(ALPHA_VERTEX_CHANNEL);
- /*
- ** Get the skin info
- */
- bool is_skin = false;
- SkinDataClass * skindata = NULL;
- SkinWSMObjectClass * skinobj = NULL;
-
- get_skin_modifier_objects(&skindata,&skinobj);
-
- if ( ((Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK) == W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN) &&
- (HTree != NULL) )
- {
- is_skin = ((skindata != NULL) && (skinobj != NULL));
- }
- /*
- ** Submit all of the faces
- */
- MeshBuilderClass::FaceClass face;
- for (face_index = 0; face_index < mesh.getNumFaces(); face_index++) {
- Face maxface = mesh.faces[face_index];
- int mat_index = 0;
- if (Header.NumMaterials > 0) {
- mat_index = MaterialRemapTable[(maxface.getMatID() % Header.NumMaterials)];
- }
- assert(mat_index != -1);
- for (pass=0; pass<MaterialDesc.Pass_Count(); pass++) {
- face.ShaderIndex[pass] = MaterialDesc.Get_Shader_Index(mat_index,pass);
- for (stage=0; stage<W3dMaterialClass::MAX_STAGES; stage++) {
- face.TextureIndex[pass][stage] = MaterialDesc.Get_Texture_Index(mat_index,pass,stage);
- }
- }
-
- int geo_type = Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK;
- if ( use_simple_rendering(geo_type) ) {
- face.SmGroup = 0xFFFFFFFF;
- } else {
- face.SmGroup = maxface.getSmGroup();
- }
- face.Index = face_index;
- face.Attributes = 0;
- face.SurfaceType = 0;
- /*
- ** Lookup this face's surface type
- */
- Mtl *mtl_to_use = node_mtl;
- if ((node_mtl != NULL) && (node_mtl->NumSubMtls() > 1)) {
- mtl_to_use = node_mtl->GetSubMtl (maxface.getMatID() % node_mtl->NumSubMtls());
- }
- if ((mtl_to_use != NULL) && ((mtl_to_use->ClassID() == GameMaterialClassID) ||
- (mtl_to_use->ClassID() == PS2GameMaterialClassID))) {
- face.SurfaceType = ((GameMtl *)mtl_to_use)->Get_Surface_Type ();
- }
- for (vert_counter = 0; vert_counter < 3; vert_counter++) {
- /*
- ** if this mesh is being inverted, we need to insert the verts in
- ** the opposite order. max_vert_counter will count backwards
- ** in this case; causing all vertex data to be entered in the
- ** reverse winding.
- */
- int max_vert_counter;
-
- if (MeshInverted) {
- max_vert_counter = 2 - vert_counter;
- } else {
- max_vert_counter = vert_counter;
- }
-
- int max_vert_index = maxface.v[max_vert_counter];
- /*
- ** Vertex Id, to prevent unwanted welding!
- */
- face.Verts[vert_counter].Id = max_vert_index;
- /*
- ** Vertex Position
- */
- face.Verts[vert_counter].Position.X = mesh.verts[max_vert_index].x;
- face.Verts[vert_counter].Position.Y = mesh.verts[max_vert_index].y;
- face.Verts[vert_counter].Position.Z = mesh.verts[max_vert_index].z;
- if (vdata) {
- // If an alpha channel has been created, use its value.
- for (int pass=0; pass < MaterialDesc.Pass_Count(); pass++) {
- if (MaterialDesc.Pass_Uses_Vertex_Alpha(pass)) {
- // Mulitiply by .01 to change from percentage.
- face.Verts[vert_counter].Alpha[pass] = vdata[max_vert_index] * .01;
- }
- }
- }
- /*
- ** Texture coordinate. Apply uv coords if the mesh has them and is not being
- ** instructed to ignore them.
- ** - check if the mesh needs them (uses_simple_rendering() == false)
- ** - for each pass and stage, look up what map channel this face's material is using
- ** - ask Max for the tfaces and tverts for that map channel
- ** - copy the values into each vertex
- */
- for (pass=0; pass<MaterialDesc.Pass_Count(); pass++) {
- for (stage=0; stage<W3dMaterialClass::MAX_STAGES; stage++) {
- /*
- ** Start with a 0,0 uv coordinate
- */
- UVVert tvert(0.0,0.0,0.0);
- /*
- ** If the mesh needs uv coords and they are present, copy the uv into tvert
- */
- if (!use_simple_rendering(Header.Attributes)) {
-
- int channel = MaterialDesc.Get_Map_Channel(mat_index,pass,stage);
-
- UVVert * uvarray = mesh.mapVerts(channel);
- TVFace * tvfacearray = mesh.mapFaces(channel);
- if ((uvarray != NULL) && (tvfacearray != NULL)) {
-
- int tvert_index = tvfacearray[face_index].t[max_vert_counter];
- tvert = uvarray[tvert_index];
- }
- }
- /*
- ** Copy the texture coordinate into the vertex structure
- */
- face.Verts[vert_counter].TexCoord[pass][stage].X = tvert.x;
- face.Verts[vert_counter].TexCoord[pass][stage].Y = tvert.y;
- }
- }
- /*
- ** Vertex Color
- */
- if (mesh.vcFace) {
-
- /*
- ** If the mesh is being mirrored, remap the index
- */
- int max_cvert_index = mesh.vcFace[face_index].t[max_vert_counter];
-
- VertColor vc;
- vc = mesh.vertCol[max_cvert_index];
-
- /*
- ** If Vertex Alpha is specified, the vertex color is converted
- ** to alpha. If the (obsolete) Node-flag for vertex alpha is enabled,
- ** the alpha is put into each pass which has alpha enabled. Otherwise,
- ** we check the material settings for which passes should get the alpha
- ** values. If neither alpha options are enabled, we put the color
- ** value into the first pass.
- */
- if (ExportOptions.Is_Vertex_Alpha_Enabled()) {
-
- float alpha = (vc.x + vc.y + vc.z) / 3.0f;
- for (int pass=0; pass < MaterialDesc.Pass_Count(); pass++) {
- if (MaterialDesc.Pass_Uses_Vertex_Alpha(pass)) {
- face.Verts[vert_counter].Alpha[pass] = alpha;
- }
- }
- } else {
- face.Verts[vert_counter].DiffuseColor[0].X = vc.x;
- face.Verts[vert_counter].DiffuseColor[0].Y = vc.y;
- face.Verts[vert_counter].DiffuseColor[0].Z = vc.z;
- }
-
- face.Verts[vert_counter].MaxVertColIndex = max_cvert_index;
- } else {
- face.Verts[vert_counter].MaxVertColIndex = 0;
- }
- /*
- ** Vertex materials
- */
- for (pass = 0; pass<MaterialDesc.Pass_Count(); pass++) {
- face.Verts[vert_counter].VertexMaterialIndex[pass] = MaterialDesc.Get_Vertex_Material_Index(mat_index,pass);
- }
- face.Verts[vert_counter].Attribute0 = max_vert_index;
- face.Verts[vert_counter].Attribute1 = face_index;
- /*
- ** Skin attachment
- */
- face.Verts[vert_counter].BoneIndex = 0;
- if (is_skin) {
-
- int skin_bone_index = skindata->VertData[max_vert_index].BoneIdx[0];
-
- // If this is a valid bone, try to find the corresponding bone index in the HTree
- if ( (skin_bone_index != -1) &&
- (skin_bone_index < skinobj->Num_Bones()) &&
- (skinobj->BoneTab[skin_bone_index] != NULL) )
- {
- face.Verts[vert_counter].BoneIndex = get_htree_bone_index_for_inode(skinobj->BoneTab[skin_bone_index]);
- }
- }
- }
-
- Builder.Add_Face(face);
- }
- /*
- ** Process the mesh
- */
- Builder.Build_Mesh(true);
- const MeshBuilderClass::MeshStatsStruct & stats = Builder.Get_Mesh_Stats();
- int vcount = Builder.Get_Vertex_Count();
- int pcount = mesh.numFaces;
- float vert_poly_ratio = (float)vcount / (float)pcount;
-
- ExportLog::printf(" triangle count: %d\n",pcount);
- ExportLog::printf(" final vertex count: %d\n",vcount);
- ExportLog::printf(" vertex/triangle ratio: %f\n",vert_poly_ratio);
- ExportLog::printf(" strip count: %d\n",stats.StripCount);
- ExportLog::printf(" average strip length: %f\n",stats.AvgStripLength);
- ExportLog::printf(" longest strip: %d\n",stats.MaxStripLength);
- }
- /***********************************************************************************************
- * MeshSaveClass::get_skin_modifier_objects -- Searches for the WWSkin modifier for this mesh *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- *=============================================================================================*/
- void MeshSaveClass::get_skin_modifier_objects(SkinDataClass ** skin_data_ptr,SkinWSMObjectClass ** skin_obj_ptr)
- {
- *skin_data_ptr = NULL;
- *skin_obj_ptr = NULL;
- // loop through the references that our node has
- for (int i = 0; i < MaxINode->NumRefs(); i++) {
- ReferenceTarget *refTarg = MaxINode->GetReference(i);
-
- // if the reference is a WSM Derived Object.
- if (refTarg != NULL && refTarg->ClassID() == Class_ID(WSM_DERIVOB_CLASS_ID,0)) {
- IDerivedObject * wsm_der_obj = (IDerivedObject *)refTarg;
- // loop through the WSM's attached to this WSM Derived object
- for (int j = 0; j < wsm_der_obj->NumModifiers(); j++) {
- Modifier * mod = wsm_der_obj->GetModifier(j);
- if (mod->ClassID() == SKIN_MOD_CLASS_ID) {
- // This is our modifier! Get the data from it!
- SkinModifierClass * skinmod = (SkinModifierClass *)mod;
- ModContext * mc = wsm_der_obj->GetModContext(j);
- *skin_data_ptr = (SkinDataClass *)(mc->localData);
- *skin_obj_ptr = (SkinWSMObjectClass *)skinmod->GetReference(SkinModifierClass::OBJ_REF);
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * MeshSaveClass::get_htree_bone_index_for_inode -- searches the htree for the given INode *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 5/1/2000 gth : Created. *
- *=============================================================================================*/
- int MeshSaveClass::get_htree_bone_index_for_inode(INode * node)
- {
- // index of this INode in the hierarchy tree (it better be there :-)
- char w3dname[W3D_NAME_LEN];
- Set_W3D_Name(w3dname,node->GetName());
- int bindex = HTree->Find_Named_Node(w3dname);
- // If the desired bone isn't being exported, export the point
- // relative to the root.
- if (bindex == -1) {
- bindex = 0;
- }
- return bindex;
- }
- /***********************************************************************************************
- * MeshSaveClass::inv_deform_mesh -- preprocess the mesh for skinning *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/26/1997 GH : Created. *
- * 5/1/2000 gth : Created. *
- *=============================================================================================*/
- void MeshSaveClass::inv_deform_mesh()
- {
- // Got the skinning info, now pre-deform each vertex and
- // create an array of vertex influence indexes.
- VertInfluences = new W3dVertInfStruct[Builder.Get_Vertex_Count()];
- memset(VertInfluences,0,sizeof(W3dVertInfStruct) * Builder.Get_Vertex_Count());
- Header.VertexChannels |= W3D_VERTEX_CHANNEL_BONEID;
- for (int vert_index = 0; vert_index < Builder.Get_Vertex_Count(); vert_index++) {
-
- MeshBuilderClass::VertClass & vert = Builder.Get_Vertex(vert_index);
- if (vert.BoneIndex == 0) {
- // set the influence to 0 (root node) and leave the vert and normal unchanged
- // (gth) 07/11/2000: Note that in this case, the mesh coordinates have already been
- // transformed relative to the user or scene origin and do not need to be further modified.
- VertInfluences[vert_index].BoneIdx = 0;
- } else {
-
- // here we go! get the matrix from the hierarchy tree and transform
- // the point into the bone's coordinate system.
- // (gth) 07/11/2000: The origin_offset_tm is no longer needed because
- // skin meshes are transformed into the origin coordinate system before
- // we get to this code.
- Matrix3 bonetm = HTree->Get_Node_Transform(vert.BoneIndex);
- Matrix3 invbonetm = Inverse(bonetm);
- Point3 pos;
-
- pos.x = vert.Position.X;
- pos.y = vert.Position.Y;
- pos.z = vert.Position.Z;
-
- pos = pos * invbonetm;
-
- vert.Position.X = pos.x;
- vert.Position.Y = pos.y;
- vert.Position.Z = pos.z;
- // Now, transform the normal into the bone's coordinate system.
- invbonetm.NoTrans();
- Point3 norm;
- norm.x = vert.Normal.X;
- norm.y = vert.Normal.Y;
- norm.z = vert.Normal.Z;
- norm = norm * invbonetm;
- vert.Normal.X = norm.x;
- vert.Normal.Y = norm.y;
- vert.Normal.Z = norm.z;
- VertInfluences[vert_index].BoneIdx = vert.BoneIndex;
- }
- }
- }
- /***********************************************************************************************
- * MeshSaveClass::Write_To_File -- Append the mesh to an open wtm file *
- * *
- * INPUT: *
- * csave - ChunkSaveClass object to handle writing the chunk-based file *
- * export_aabtree - should we generate an aabtree for this mesh *
- * *
- * OUTPUT: *
- * 0 if nothing went wrong, Non-Zero otherwise *
- * *
- * WARNINGS: *
- * *
- * *
- * HISTORY: *
- * 06/10/1997 GH : Created. *
- *=============================================================================================*/
- int MeshSaveClass::Write_To_File(ChunkSaveClass & csave,bool export_aabtree)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_MESH)) {
- return 1;
- }
- if (write_header(csave) != 0) {
- return 1;
- }
- if (write_user_text(csave) != 0) {
- return 1;
- }
- if (write_verts(csave) != 0) {
- return 1;
- }
- if (write_vert_normals(csave) != 0) {
- return 1;
- }
- if (write_triangles(csave) != 0) {
- return 1;
- }
- if (write_vert_influences(csave) != 0) {
- return 1;
- }
- if (write_vert_shade_indices(csave) != 0) {
- return 1;
- }
- if (write_material_info(csave) != 0) {
- return 1;
- }
- if (write_vertex_materials(csave) != 0) {
- return 1;
- }
-
- if (PS2Material == TRUE) {
- // The ps2 shaders must be written out first.
- if (write_ps2_shaders(csave) != 0) {
- return 1;
- }
- }
- if (write_shaders(csave) != 0) {
- return 1;
- }
-
- if (write_textures(csave) != 0) {
- return 1;
- }
- for (int pass=0; pass<MaterialDesc.Pass_Count(); pass++) {
- if (write_pass(csave,pass) != 0) {
- return 1;
- }
- }
- if (export_aabtree == true) {
- if (write_aabtree(csave) != 0) {
- return 1;
- }
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- /***********************************************************************************************
- * MeshSaveClass::write_header -- write a mesh header chunk into a wtm file *
- * *
- * INPUT: *
- * csave - chunk save object *
- * *
- * OUTPUT: *
- * 0 if nothing went wrong, Non-Zero otherwise *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/10/1997 GH : Created. *
- *=============================================================================================*/
- int MeshSaveClass::write_header(ChunkSaveClass & csave)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_MESH_HEADER3)) {
- return 1;
- }
-
- if (csave.Write(&Header,sizeof(W3dMeshHeader3Struct)) != sizeof(W3dMeshHeader3Struct)) {
- return 1;
- }
-
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- /***********************************************************************************************
- * MeshSaveClass::write_user_text -- write the user text chunk *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/20/1997 GH : Created. *
- *=============================================================================================*/
- int MeshSaveClass::write_user_text(ChunkSaveClass & csave)
- {
- // If there's no user text, just don't write the chunk
- if (UserText == NULL) {
- return 0;
- }
- if (!csave.Begin_Chunk(W3D_CHUNK_MESH_USER_TEXT)) {
- return 1;
- }
-
- // write the user text buffer (writing one extra byte to include the NULL)
- if (csave.Write(UserText,strlen(UserText) + 1) != strlen(UserText) + 1) {
- return 1;
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- /***********************************************************************************************
- * MeshSaveClass::write_verts -- write the vertex chunk into a wtm file *
- * *
- * INPUT: *
- * csave - chunk save object *
- * *
- * OUTPUT: *
- * 0 if nothing went wrong, Non-Zero otherwise *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/10/1997 GH : Created. *
- *=============================================================================================*/
- int MeshSaveClass::write_verts(ChunkSaveClass & csave)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_VERTICES)) {
- return 1;
- }
-
- assert(Builder.Get_Vertex_Count() > 0);
- assert(Builder.Get_Vertex_Count() == (int)Header.NumVertices);
- for (int i=0; i<Builder.Get_Vertex_Count(); i++) {
- const MeshBuilderClass::VertClass & vert = Builder.Get_Vertex(i);
- if ((Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK) != W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN) {
-
- assert(vert.Position.X <= Header.Max.X);
- assert(vert.Position.Y <= Header.Max.Y);
- assert(vert.Position.Z <= Header.Max.Z);
- assert(vert.Position.X >= Header.Min.X);
- assert(vert.Position.Y >= Header.Min.Y);
- assert(vert.Position.Z >= Header.Min.Z);
-
- }
- W3dVectorStruct w3dvert;
- w3dvert.X = vert.Position.X;
- w3dvert.Y = vert.Position.Y;
- w3dvert.Z = vert.Position.Z;
-
- if (csave.Write(&(w3dvert),sizeof(W3dVectorStruct)) != sizeof(W3dVectorStruct)) {
- return 1;
- }
- }
-
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- /***********************************************************************************************
- * MeshSaveClass::write_vert_normals -- Writes the surrender normal chunk into a wtm file *
- * *
- * INPUT: *
- * csave - chunk save object *
- * *
- * OUTPUT: *
- * 0 if nothing went wrong, Non-Zero otherwise *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/10/1997 GH : Created. *
- *=============================================================================================*/
- int MeshSaveClass::write_vert_normals(ChunkSaveClass & csave)
- {
- if (!(Header.VertexChannels & W3D_VERTEX_CHANNEL_NORMAL)) return 0;
-
- if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_NORMALS)) {
- return 1;
- }
-
- for (int i=0; i < Builder.Get_Vertex_Count(); i++) {
- const MeshBuilderClass::VertClass & vert = Builder.Get_Vertex(i);
- W3dVectorStruct norm;
- if (ExportOptions.Is_ZNormals_Enabled()) {
- norm.X = 0.0f;
- norm.Y = 0.0f;
- norm.Z = 1.0f;
- } else {
- norm.X = vert.Normal.X;
- norm.Y = vert.Normal.Y;
- norm.Z = vert.Normal.Z;
- }
-
- if (csave.Write(&(norm),sizeof(W3dVectorStruct)) != sizeof(W3dVectorStruct)) {
- return 1;
- }
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- /***********************************************************************************************
- * MeshSaveClass::write_vert_influences -- skins will have this chunk that binds verts to bones*
- * *
- * INPUT: *
- * csave - chunk save object *
- * *
- * OUTPUT: *
- * 0 if nothing went wrong, Non-Zero otherwise *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 06/10/1997 GH : Created. *
- *=============================================================================================*/
- int MeshSaveClass::write_vert_influences(ChunkSaveClass & csave)
- {
- if (((Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK) != W3D_MESH_FLAG_GEOMETRY_TYPE_SKIN) ||
- !(Header.VertexChannels & W3D_VERTEX_CHANNEL_BONEID) ||
- (VertInfluences == NULL)) {
- return 0;
- }
- if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_INFLUENCES)) {
- return 1;
- }
-
- int count = Builder.Get_Vertex_Count();
- if (csave.Write(VertInfluences,count * sizeof(W3dVertInfStruct)) != count * sizeof(W3dVertInfStruct)) {
- return 1;
- }
-
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- /***********************************************************************************************
- * MeshSaveClass::write_triangles -- write the triangles chunk *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 4/7/98 GTH : Created. *
- *=============================================================================================*/
- int MeshSaveClass::write_triangles(ChunkSaveClass & csave)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_TRIANGLES)) {
- return 1;
- }
- assert(Builder.Get_Face_Count() == (int)Header.NumTris);
- for (int i=0; i<Builder.Get_Face_Count(); i++) {
- const MeshBuilderClass::FaceClass & face = Builder.Get_Face(i);
- W3dTriStruct tri;
- memset(&tri,0,sizeof(W3dTriStruct));
- // convert each triangle into surrender format
- tri.Vindex[0] = face.VertIdx[0];
- tri.Vindex[1] = face.VertIdx[1];
- tri.Vindex[2] = face.VertIdx[2];
-
- tri.Attributes = face.SurfaceType;
- tri.Normal.X = face.Normal.X;
- tri.Normal.Y = face.Normal.Y;
- tri.Normal.Z = face.Normal.Z;
- tri.Dist = face.Dist;
- // write each triangle
- if (csave.Write(&tri,sizeof(W3dTriStruct)) != sizeof(W3dTriStruct)) {
- return 1;
- }
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_vert_shade_indices(ChunkSaveClass & csave)
- {
- if (!(Header.VertexChannels & W3D_VERTEX_CHANNEL_NORMAL)) return 0;
-
- if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_SHADE_INDICES)) {
- return 1;
- }
-
- for (int i=0; i < Builder.Get_Vertex_Count(); i++) {
- const MeshBuilderClass::VertClass & vert = Builder.Get_Vertex(i);
- uint32 shade_index = vert.ShadeIndex;
-
- if (csave.Write(&(shade_index),sizeof(shade_index)) != sizeof(shade_index)) {
- return 1;
- }
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_material_info(ChunkSaveClass & csave)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_MATERIAL_INFO)) {
- return 1;
- }
- W3dMaterialInfoStruct matinfo;
- matinfo.PassCount = MaterialDesc.Pass_Count();
- matinfo.VertexMaterialCount = MaterialDesc.Vertex_Material_Count();
- matinfo.ShaderCount = MaterialDesc.Shader_Count();
- matinfo.TextureCount = MaterialDesc.Texture_Count();
- if (csave.Write(&matinfo,sizeof(matinfo)) != sizeof(matinfo)) {
- return 1;
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_vertex_materials(ChunkSaveClass & csave)
- {
- if (MaterialDesc.Vertex_Material_Count() <= 0) return 0;
- // open a chunk which wraps all of the vertex materials
- if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_MATERIALS)) {
- return 1;
- }
- for (int i=0; i<MaterialDesc.Vertex_Material_Count(); i++) {
-
- csave.Begin_Chunk(W3D_CHUNK_VERTEX_MATERIAL);
-
- // write the filename
- const char * name = MaterialDesc.Get_Vertex_Material_Name(i);
- if (name != NULL) {
- csave.Begin_Chunk(W3D_CHUNK_VERTEX_MATERIAL_NAME);
- if (csave.Write(name,strlen(name) + 1) != strlen(name) + 1) {
- return 1;
- }
- csave.End_Chunk();
- }
- // write the struct
- W3dVertexMaterialStruct * vmat = MaterialDesc.Get_Vertex_Material(i);
- csave.Begin_Chunk(W3D_CHUNK_VERTEX_MATERIAL_INFO);
- if (csave.Write(vmat,sizeof(W3dVertexMaterialStruct)) != sizeof(W3dVertexMaterialStruct)) {
- return 1;
- }
- csave.End_Chunk();
- // write the mapper args
- const char * args = MaterialDesc.Get_Mapper_Args(i, 0);
- if (args != NULL) {
- csave.Begin_Chunk(W3D_CHUNK_VERTEX_MAPPER_ARGS0);
- if (csave.Write(args,strlen(args) + 1) != strlen(args) + 1) {
- return 1;
- }
- csave.End_Chunk();
- }
- args = MaterialDesc.Get_Mapper_Args(i, 1);
- if (args != NULL) {
- csave.Begin_Chunk(W3D_CHUNK_VERTEX_MAPPER_ARGS1);
- if (csave.Write(args,strlen(args) + 1) != strlen(args) + 1) {
- return 1;
- }
- csave.End_Chunk();
- }
- csave.End_Chunk();
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_shaders(ChunkSaveClass & csave)
- {
- assert(MaterialDesc.Shader_Count() > 0);
-
- if (PS2Material == TRUE) {
- // Make the PC shader as close to the PS2 shader as possible.
- // This will allow for viewing in W3D View.
- setup_PC_shaders_from_PS2_shaders();
- }
- if (!csave.Begin_Chunk(W3D_CHUNK_SHADERS)) {
- return 1;
- }
- W3dShaderStruct * shader;
- for (int i=0; i<MaterialDesc.Shader_Count(); i++) {
- shader = MaterialDesc.Get_Shader(i);
- if (csave.Write(shader,sizeof(W3dShaderStruct)) != sizeof(W3dShaderStruct)) {
- return 1;
- }
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- /***********************************************************************************************
- * MeshSaveClass::write_ps2_shaders -- Write shaders specific to the PS2 in their own chunk. *
- * *
- * *
- * *
- * *
- * HISTORY: *
- * 10/20/1999MLL: Created. *
- *=============================================================================================*/
- int MeshSaveClass::write_ps2_shaders(ChunkSaveClass & csave)
- {
- if (!csave.Begin_Chunk(W3D_CHUNK_PS2_SHADERS)) {
- return 1;
- }
- W3dShaderStruct *shader;
- W3dPS2ShaderStruct ps2shader;
- for (int i=0; i<MaterialDesc.Shader_Count(); i++) {
- shader = MaterialDesc.Get_Shader(i);
- ps2shader.AlphaTest = W3d_Shader_Get_Alpha_Test(shader);
- ps2shader.AParam = W3d_Shader_Get_PS2_Param_A(shader);
- ps2shader.BParam = W3d_Shader_Get_PS2_Param_B(shader);
- ps2shader.CParam = W3d_Shader_Get_PS2_Param_C(shader);
- ps2shader.DParam = W3d_Shader_Get_PS2_Param_D(shader);
- // Write out the PS2 native form.
- switch (W3d_Shader_Get_Depth_Compare(shader))
- {
- case PSS_DEPTHCOMPARE_PASS_NEVER:
- ps2shader.DepthCompare = 0;
- break;
- case PSS_DEPTHCOMPARE_PASS_LESS:
- ps2shader.DepthCompare = 3;
- break;
- case PSS_DEPTHCOMPARE_PASS_ALWAYS:
- ps2shader.DepthCompare = 1;
- break;
- case PSS_DEPTHCOMPARE_PASS_LEQUAL:
- ps2shader.DepthCompare = 2;
- break;
- }
- ps2shader.DepthMask = !W3d_Shader_Get_Depth_Mask(shader);
- switch (W3d_Shader_Get_Pri_Gradient(shader))
- {
- case PSS_PRIGRADIENT_MODULATE:
- ps2shader.PriGradient = PSS_PS2_PRIGRADIENT_MODULATE;
- break;
- case PSS_PRIGRADIENT_HIGHLIGHT:
- ps2shader.PriGradient = PSS_PS2_PRIGRADIENT_HIGHLIGHT;
- break;
- case PSS_PRIGRADIENT_HIGHLIGHT2:
- ps2shader.PriGradient = PSS_PS2_PRIGRADIENT_HIGHLIGHT2;
- break;
- case PSS_PRIGRADIENT_DECAL:
- ps2shader.PriGradient = PSS_PS2_PRIGRADIENT_DECAL;
- break;
- }
- ps2shader.Texturing = W3d_Shader_Get_Texturing(shader);
- if (csave.Write(&ps2shader,sizeof(W3dPS2ShaderStruct)) != sizeof(W3dPS2ShaderStruct)) {
- return 1;
- }
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return (0);
- }
- void MeshSaveClass::setup_PC_shaders_from_PS2_shaders()
- {
- W3dShaderStruct *shader;
- for (int i=0; i<MaterialDesc.Shader_Count(); i++) {
- shader = MaterialDesc.Get_Shader(i);
- // DepthCompare on the PS2 doesn't have as many options as on the PC.
- switch (W3d_Shader_Get_Depth_Compare(shader))
- {
- case PSS_DEPTHCOMPARE_PASS_NEVER:
- W3d_Shader_Set_Depth_Compare(shader, W3DSHADER_DEPTHCOMPARE_PASS_NEVER);
- break;
- case PSS_DEPTHCOMPARE_PASS_LESS:
- W3d_Shader_Set_Depth_Compare(shader, W3DSHADER_DEPTHCOMPARE_PASS_LESS);
- break;
- case PSS_DEPTHCOMPARE_PASS_LEQUAL:
- W3d_Shader_Set_Depth_Compare(shader, W3DSHADER_DEPTHCOMPARE_PASS_LEQUAL);
- break;
- case PSS_DEPTHCOMPARE_PASS_ALWAYS:
- W3d_Shader_Set_Depth_Compare(shader, W3DSHADER_DEPTHCOMPARE_PASS_ALWAYS);
- break;
- }
- // The PS2 has more gradient functions than the PC.
- switch (W3d_Shader_Get_Pri_Gradient(shader))
- {
- case PSS_PRIGRADIENT_MODULATE:
- W3d_Shader_Set_Pri_Gradient(shader, W3DSHADER_PRIGRADIENT_MODULATE);
- break;
- // No PC equivalent. Set to default: modulate.
- case PSS_PRIGRADIENT_HIGHLIGHT:
- case PSS_PRIGRADIENT_HIGHLIGHT2:
- case PSS_PRIGRADIENT_DECAL:
- W3d_Shader_Set_Pri_Gradient(shader, W3DSHADER_PRIGRADIENT_MODULATE);
- break;
- }
- }
- }
- int MeshSaveClass::write_textures(ChunkSaveClass & csave)
- {
- if (MaterialDesc.Texture_Count() <= 0) return 0;
- // open a chunk which wraps all textures
- if (!csave.Begin_Chunk(W3D_CHUNK_TEXTURES)) {
- return 1;
- }
- for (int i=0; i<MaterialDesc.Texture_Count(); i++) {
-
- W3dMapClass * map = MaterialDesc.Get_Texture(i);
-
- csave.Begin_Chunk(W3D_CHUNK_TEXTURE);
-
- // write the filename
- csave.Begin_Chunk(W3D_CHUNK_TEXTURE_NAME);
- if (csave.Write(map->Filename,strlen(map->Filename) + 1) != strlen(map->Filename) + 1) return 1;
- csave.End_Chunk();
- // optionally write an animation info chunk
- if (map->AnimInfo != NULL) {
- csave.Begin_Chunk(W3D_CHUNK_TEXTURE_INFO);
- if (csave.Write(map->AnimInfo,sizeof(W3dTextureInfoStruct)) != sizeof(W3dTextureInfoStruct)) return 1;
- csave.End_Chunk();
- }
- csave.End_Chunk();
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_pass(ChunkSaveClass & csave,int pass)
- {
- assert(pass >= 0);
- assert(pass < MaterialDesc.Pass_Count());
- if (!csave.Begin_Chunk(W3D_CHUNK_MATERIAL_PASS)) {
- return 1;
- }
- const MeshBuilderClass::MeshStatsStruct & stats = Builder.Get_Mesh_Stats();
- if (stats.HasVertexMaterial[pass]) {
- write_vertex_material_ids(csave,pass);
- }
- if (stats.HasShader[pass]) {
- write_shader_ids(csave,pass);
- }
- if (stats.HasDiffuseColor[pass]) {
- write_dcg(csave,pass);
- }
- for (int stage = 0; stage < MeshBuilderClass::MAX_STAGES; stage++) {
- write_texture_stage(csave,pass,stage);
- }
-
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_vertex_material_ids(ChunkSaveClass & csave,int pass)
- {
- const MeshBuilderClass::MeshStatsStruct & stats = Builder.Get_Mesh_Stats();
- if (!csave.Begin_Chunk(W3D_CHUNK_VERTEX_MATERIAL_IDS)) {
- return 1;
- }
- uint32 matid;
- if (stats.HasPerVertexMaterial[pass]) {
- for (int i=0; i<Builder.Get_Vertex_Count(); i++) {
- matid = Builder.Get_Vertex(i).VertexMaterialIndex[pass];
- if (csave.Write(&matid,sizeof(uint32)) != sizeof(uint32)) return 1;
- }
- } else {
- matid = Builder.Get_Vertex(0).VertexMaterialIndex[pass];
- if (csave.Write(&matid,sizeof(uint32)) != sizeof(uint32)) return 1;
- }
-
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_shader_ids(ChunkSaveClass & csave,int pass)
- {
- const MeshBuilderClass::MeshStatsStruct & stats = Builder.Get_Mesh_Stats();
- if (!csave.Begin_Chunk(W3D_CHUNK_SHADER_IDS)) {
- return 1;
- }
- uint32 shaderid;
- if (stats.HasPerPolyShader[pass]) {
- for (int i=0; i<Builder.Get_Face_Count(); i++) {
- shaderid = Builder.Get_Face(i).ShaderIndex[pass];
- if (csave.Write(&shaderid,sizeof(uint32)) != sizeof(uint32)) return 1;
- }
- } else {
- shaderid = Builder.Get_Face(0).ShaderIndex[pass];
- if (csave.Write(&shaderid,sizeof(uint32)) != sizeof(uint32)) return 1;
- }
-
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_dcg(ChunkSaveClass & csave,int pass)
- {
- const MeshBuilderClass::MeshStatsStruct & stats = Builder.Get_Mesh_Stats();
- if (!csave.Begin_Chunk(W3D_CHUNK_DCG)) {
- return 1;
- }
- for (int i=0; i<Builder.Get_Vertex_Count(); i++) {
- Vector3 vcolor = Builder.Get_Vertex(i).DiffuseColor[pass];
- W3dRGBAStruct color;
- color.R = (uint8)(255.0f * vcolor.X);
- color.G = (uint8)(255.0f * vcolor.Y);
- color.B = (uint8)(255.0f * vcolor.Z);
- float a = Builder.Get_Vertex(i).Alpha[pass];
- color.A = (uint8)(255.0f * a);
- if (csave.Write(&(color),sizeof(W3dRGBAStruct)) != sizeof(W3dRGBAStruct)) {
- return 1;
- }
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_texture_stage(ChunkSaveClass & csave,int pass,int stage)
- {
- const MeshBuilderClass::MeshStatsStruct & stats = Builder.Get_Mesh_Stats();
- if (!stats.HasTexture[pass][stage]) return 0;
- if (!csave.Begin_Chunk(W3D_CHUNK_TEXTURE_STAGE)) {
- return 1;
- }
-
- write_texture_ids(csave,pass,stage);
- write_texture_coords(csave,pass,stage);
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_texture_ids(ChunkSaveClass & csave,int pass,int stage)
- {
- const MeshBuilderClass::MeshStatsStruct & stats = Builder.Get_Mesh_Stats();
- if (!csave.Begin_Chunk(W3D_CHUNK_TEXTURE_IDS)) {
- return 1;
- }
- uint32 texid;
- if (stats.HasPerPolyTexture[pass][stage]) {
- for (int i=0; i<Builder.Get_Face_Count(); i++) {
- texid = Builder.Get_Face(i).TextureIndex[pass][stage];
- if (csave.Write(&texid,sizeof(uint32)) != sizeof(uint32)) return 1;
- }
- } else {
- texid = Builder.Get_Face(0).TextureIndex[pass][stage];
- if (csave.Write(&texid,sizeof(uint32)) != sizeof(uint32)) return 1;
- }
-
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_texture_coords(ChunkSaveClass & csave,int pass,int stage)
- {
- const MeshBuilderClass::MeshStatsStruct & stats = Builder.Get_Mesh_Stats();
- if (stats.HasTexCoords[pass][stage] == false) return 0;
- if (!csave.Begin_Chunk(W3D_CHUNK_STAGE_TEXCOORDS)) {
- return 1;
- }
- for (int i=0; i<Builder.Get_Vertex_Count(); i++) {
- W3dTexCoordStruct tex;
- tex.U = Builder.Get_Vertex(i).TexCoord[pass][stage].X;
- tex.V = Builder.Get_Vertex(i).TexCoord[pass][stage].Y;
-
- if (csave.Write(&(tex),sizeof(W3dTexCoordStruct)) != sizeof(W3dTexCoordStruct)) {
- return 1;
- }
- }
- if (!csave.End_Chunk()) {
- return 1;
- }
- return 0;
- }
- int MeshSaveClass::write_aabtree(ChunkSaveClass & csave)
- {
- /*
- ** Don't bother with an AABTree if this not a normal mesh or if it has very few polygons
- */
- if ( (Builder.Get_Face_Count() >= MIN_AABTREE_POLYGONS) &&
- ((Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK) == W3D_MESH_FLAG_GEOMETRY_TYPE_NORMAL)
- )
- {
- /*
- ** Build temporary array representations of the mesh
- */
- int vertcount = Builder.Get_Vertex_Count();
- int polycount = Builder.Get_Face_Count();
- Vector3 * verts = new Vector3[vertcount];
- Vector3i * polys = new Vector3i[polycount];
-
- for (int vi=0; vi<vertcount; vi++) {
- verts[vi] = Builder.Get_Vertex(vi).Position;
- }
- for (int pi=0; pi<polycount; pi++) {
- polys[pi].I = Builder.Get_Face(pi).VertIdx[0];
- polys[pi].J = Builder.Get_Face(pi).VertIdx[1];
- polys[pi].K = Builder.Get_Face(pi).VertIdx[2];
- }
- /*
- ** Build the AABTree and save it
- */
- AABTreeBuilderClass aabtree_builder;
- aabtree_builder.Build_AABTree(polycount,polys,vertcount,verts);
- aabtree_builder.Export(csave);
-
- /*
- ** Release the allocated resources
- */
- delete[] verts;
- delete[] polys;
- }
-
- return 0;
- }
- int MeshSaveClass::scan_used_materials(Mesh & mesh,Mtl * nodemtl)
- {
- int face_index;
- int mat_index;
- if ((nodemtl == NULL) || (nodemtl->NumSubMtls() <= 1)) {
- MaterialRemapTable = new int[1];
- MaterialRemapTable[0] = 0;
- return 1;
- } else {
-
- int sub_mtl_count = nodemtl->NumSubMtls();
- MaterialRemapTable = new int[sub_mtl_count];
-
- // Initialize each remap to -1 (indicates that the material is un-used)
- for (mat_index=0; mat_index<sub_mtl_count; mat_index++) {
- MaterialRemapTable[mat_index] = -1;
- }
- // Set a 1 for each material actually referenced by the mesh
- for (face_index=0; face_index<mesh.getNumFaces(); face_index++) {
- int max_mat_index = mesh.faces[face_index].getMatID();
- int mat_index = (max_mat_index % sub_mtl_count);
- MaterialRemapTable[mat_index] = 1;
- }
- // Replace each 1 entry with an incrementing material index
- int matcount = 0;
- for (mat_index=0; mat_index<sub_mtl_count; mat_index++) {
- if (MaterialRemapTable[mat_index] == 1) {
- MaterialRemapTable[mat_index] = matcount;
- matcount++;
- }
- }
-
- assert(matcount > 0);
- return matcount;
- }
- }
- /***********************************************************************************************
- * MeshSaveClass::create_materials -- create the materials for this mesh *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 10/26/1997 GH : Created. *
- * 2/8/99 GTH : modified to use the MaterialRemapTable *
- *=============================================================================================*/
- void MeshSaveClass::create_materials(Mtl * nodemtl,DWORD wirecolor)
- {
- bool domaps = !use_simple_rendering(Header.Attributes);
-
- //////////////////////////////////////////////////////////////////////
- // Create materials
- // Four cases:
- // - Creating a collision object: use a hard-coded material
- // - The material is null: use wire color
- // - The material is a simple material: create one material
- // - The material is a multi-material: create n materials
- //////////////////////////////////////////////////////////////////////
- int geo_type = Header.Attributes & W3D_MESH_FLAG_GEOMETRY_TYPE_MASK;
- if ((geo_type == W3D_MESH_FLAG_GEOMETRY_TYPE_AABOX) ||
- (geo_type == W3D_MESH_FLAG_GEOMETRY_TYPE_OBBOX))
- {
- Header.NumMaterials = 1;
- W3dVertexMaterialStruct vmat;
- W3dShaderStruct shader;
- W3dMaterialClass material;
- Color diffuse;
- if (Header.Attributes & W3D_MESH_FLAG_COLLISION_TYPE_PHYSICAL) {
- diffuse.r = 0.0f;
- diffuse.g = 0.0f;
- diffuse.b = 1.0f;
- } else {
- diffuse.r = 0.4f;
- diffuse.g = 1.0f;
- diffuse.b = 0.4f;
- }
- W3d_Shader_Reset(&shader);
- W3d_Shader_Set_Dest_Blend_Func(&shader,W3DSHADER_DESTBLENDFUNC_ONE_MINUS_SRC_ALPHA);
- W3d_Shader_Set_Src_Blend_Func(&shader,W3DSHADER_SRCBLENDFUNC_SRC_ALPHA);
- W3d_Vertex_Material_Reset(&vmat);
- vmat.Opacity = 0.5f;
- // add material 0
- vmat.Diffuse.R = (uint8)(diffuse.r * 255.0f);
- vmat.Diffuse.G = (uint8)(diffuse.g * 255.0f);
- vmat.Diffuse.B = (uint8)(diffuse.b * 255.0f);
- material.Set_Pass_Count(1);
- material.Set_Vertex_Material(vmat,0);
- material.Set_Shader(shader,0);
- MaterialDesc.Add_Material(material);
- assert(MaterialDesc.Material_Count() == 1);
- } else if (!nodemtl) {
- // Create a single material using the wire color
- Header.NumMaterials = 1;
-
- W3dVertexMaterialStruct vmat;
- W3dShaderStruct shader;
- W3dMaterialClass material;
- W3d_Vertex_Material_Reset(&vmat);
- W3d_Shader_Reset(&shader);
- vmat.Diffuse.R = GetRValue(wirecolor);
- vmat.Diffuse.G = GetGValue(wirecolor);
- vmat.Diffuse.B = GetBValue(wirecolor);
- material.Set_Pass_Count(1);
- material.Set_Vertex_Material(vmat,0);
- material.Set_Shader(shader,0);
- MaterialDesc.Add_Material(material,"WireColor");
- assert(MaterialDesc.Material_Count() == 1);
- } else if (!nodemtl->IsMultiMtl()) {
- Header.NumMaterials = 1;
- W3dMaterialClass mat;
- mat.Init(nodemtl);
- W3dMaterialDescClass::ErrorType err;
- err = MaterialDesc.Add_Material(mat,nodemtl->GetName());
- if (err == W3dMaterialDescClass::MULTIPASS_TRANSPARENT) {
- sprintf(_string1,"Exporting Materials for Mesh: %s\nMaterial %s is multi-pass and transparent\nMulti-pass transparent materials are not allowed.\n",
- Header.MeshName,
- nodemtl->GetName());
- ExportLog::printf(_string1);
- throw ErrorClass(_string1);
- }
- assert(MaterialDesc.Material_Count() == 1);
- } else {
- Header.NumMaterials = nodemtl->NumSubMtls();
- W3dMaterialClass mat;
- for (unsigned mi = 0; mi < Header.NumMaterials; mi++) {
- // only process materials that were found to be used in the scan_used_materials call
- if (MaterialRemapTable[mi] != -1) {
-
- mat.Init(nodemtl->GetSubMtl(mi));//,domaps);
-
- char * name;
- W3dMaterialDescClass::ErrorType err;
- name = nodemtl->GetSubMtl(mi)->GetName();
- err = MaterialDesc.Add_Material(mat,name);
-
- if (err == W3dMaterialDescClass::INCONSISTENT_PASSES) {
- sprintf(_string1,"Exporting Materials for Mesh: %s\nMaterial %s has %d passes.\nThe other materials have %d passes.\nAll Materials must have the same number of passes.\n",
- Header.MeshName,
- nodemtl->GetSubMtl(mi)->GetName(),
- mat.Get_Pass_Count(),
- MaterialDesc.Pass_Count());
- ExportLog::printf(_string1);
- throw ErrorClass(_string1);
- }
- if (err == W3dMaterialDescClass::MULTIPASS_TRANSPARENT) {
- sprintf(_string1,"Exporting Materials for Mesh: %s\nMaterial %s is multi-pass and transparent\nMulti-pass transparent materials are not allowed.\n",
- Header.MeshName,
- nodemtl->GetSubMtl(mi)->GetName());
- throw ErrorClass(_string1);
- }
- if (err == W3dMaterialDescClass::INCONSISTENT_SORT_LEVEL) {
- sprintf(_string1,"Exporting Materials for Mesh: %s\nMaterial %s does not have the same Static Sort Level as other materials used on the mesh.\nAll materials for a mesh must use the same Static Sort Level value.\n",
- Header.MeshName,
- nodemtl->GetSubMtl(mi)->GetName());
- ExportLog::printf(_string1);
- throw ErrorClass(_string1);
- }
- }
- }
- }
- // Store the material's sort level in the mesh header.
- Header.SortLevel = MaterialDesc.Get_Sort_Level();
- }
- /***********************************************************************************************
- * MeshSaveClass::compute_bounding_volumes -- computes a bounding box and bounding sphere for *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/01/1997 GH : Created. *
- *=============================================================================================*/
- void MeshSaveClass::compute_bounding_volumes(void)
- {
- Vector3 min,max,center;
- float radius;
- Builder.Compute_Bounding_Box(&min,&max);
- Builder.Compute_Bounding_Sphere(¢er,&radius);
- Header.SphCenter.X = center.X;
- Header.SphCenter.Y = center.Y;
- Header.SphCenter.Z = center.Z;
- Header.SphRadius = radius;
- Header.Min.X = min.X;
- Header.Min.Y = min.Y;
- Header.Min.Z = min.Z;
- Header.Max.X = max.X;
- Header.Max.Y = max.Y;
- Header.Max.Z = max.Z;
- }
- /***********************************************************************************************
- * MeshSaveClass::compute_physical_properties -- computes the volume and moment of inertia *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/01/1997 GH : Created. *
- *=============================================================================================*/
- void MeshSaveClass::compute_physical_constants
- (
- INode * inode,
- Progress_Meter_Class & meter,
- bool voxelize
- )
- {
- #if 0 // IF we need this again, move the data to a physics chunk (header doesn't have it anymore)
- if (voxelize) {
-
- // Create an INodeList object for this mesh
- AnyINodeFilter nodefilt;
- INodeListClass meshlist(CurTime,&nodefilt);
- meshlist.Insert(inode);
- // Create a Voxel object for this mesh
- VoxelClass * voxel = new VoxelClass
- (
- meshlist,
- VOXEL_RESOLUTION,
- ExportSpace,
- CurTime,
- meter
- );
- #if DEBUG_VOXELS
- VoxelDebugWindowClass dbgwin(voxel);
- dbgwin.Display_Window();
- #endif
-
- double vol[1];
- double cm[3];
- double inertia[9];
- voxel->Compute_Physical_Properties(vol,cm,inertia);
- Header.Volume = (float)vol[0];
- Header.MassCenter.X = (float)cm[0];
- Header.MassCenter.Y = (float)cm[1];
- Header.MassCenter.Z = (float)cm[2];
- Header.Inertia[0] = (float)inertia[0];
- Header.Inertia[1] = (float)inertia[1];
- Header.Inertia[2] = (float)inertia[2];
- Header.Inertia[3] = (float)inertia[3];
- Header.Inertia[4] = (float)inertia[4];
- Header.Inertia[5] = (float)inertia[5];
- Header.Inertia[6] = (float)inertia[6];
- Header.Inertia[7] = (float)inertia[7];
- Header.Inertia[8] = (float)inertia[8];
- } else {
- // Set mass center to the center of the bounding box
- Header.MassCenter.X = (Header.Max.X + Header.Min.X) / 2.0f;
- Header.MassCenter.Y = (Header.Max.Y + Header.Min.Y) / 2.0f;
- Header.MassCenter.Z = (Header.Max.Z + Header.Min.Z) / 2.0f;
- // Set inertia tensor to inertia tensor of the bounding box
- // (gth) !!!! DO THIS !!!!
- Header.Inertia[0] = 1.0f;
- Header.Inertia[1] = 0.0f;
- Header.Inertia[2] = 0.0f;
- Header.Inertia[3] = 0.0f;
- Header.Inertia[4] = 1.0f;
- Header.Inertia[5] = 0.0f;
- Header.Inertia[6] = 0.0f;
- Header.Inertia[7] = 0.0f;
- Header.Inertia[8] = 1.0f;
- Header.Volume = (Header.Max.X - Header.Min.X) * (Header.Max.Y - Header.Min.Y) * (Header.Max.Z - Header.Min.Z);
- }
- #endif
- }
- /***********************************************************************************************
- * MeshSaveClass::prep_mesh -- pre-transform the MAX mesh by a specified matrix *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/01/1997 GH : Created. *
- *=============================================================================================*/
- void MeshSaveClass::prep_mesh(Mesh & mesh,Matrix3 & objoff)
- {
- int vert_index;
- // Transform the mesh's vertices so that they are relative to the coordinate
- // system that we want to use with the mesh
- for (vert_index = 0; vert_index < mesh.getNumVerts (); vert_index++) {
- mesh.verts[vert_index] = mesh.verts[vert_index] * objoff;
- }
- // Re-Build the normals.
- mesh.buildNormals();
- }
|