| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446 |
- /*
- ** Command & Conquer Generals Zero Hour(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/MeshDeform.cpp 7 5/01/01 8:56p Greg_h $ */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando / G 3D engine *
- * *
- * File Name : MeshDeform.cpp *
- * *
- * Programmer : Patrick Smith *
- * *
- * Start Date : 04/19/99 *
- * *
- * Last Update :
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "MeshDeform.H"
- #include "MeshDeformData.H"
- #include "MeshDeformPanel.H"
- #include "MeshDeformUndo.H"
- #include "DLLMain.H"
- #include "Resource.H"
- #include "Util.H"
- #if defined W3D_MAX4 //defined as in the project (.dsp)
- static GenSubObjType _SubObjectTypeVertex(1);
- #endif
- ///////////////////////////////////////////////////////////////////////////
- //
- // MeshDeformClass Class ID
- //
- ///////////////////////////////////////////////////////////////////////////
- Class_ID _MeshDeformClassID(0x51981f5b, 0x1db2bf3);
- ///////////////////////////////////////////////////////////////////////////
- //
- // MeshDeformClassDesc
- //
- ///////////////////////////////////////////////////////////////////////////
- class MeshDeformClassDesc : public ClassDesc
- {
- public:
- int IsPublic (void) { return 1; }
- void * Create (BOOL loading) { return new MeshDeformClass (); }
- const TCHAR * ClassName () { return _T("WWDeform"); }
- SClass_ID SuperClassID () { return OSM_CLASS_ID; }
- Class_ID ClassID () { return _MeshDeformClassID; }
- const TCHAR* Category () { return _T("Westwood Modifiers"); }
- };
- ///////////////////////////////////////////////////////////////////////////
- //
- // Static class desc instance
- //
- ///////////////////////////////////////////////////////////////////////////
- #if 0 // (gth) MeshDeform is obsolete! making sure nobody uses it...
- static MeshDeformClassDesc _MeshDeformCD;
- ClassDesc * Get_Mesh_Deform_Desc (void) { return &_MeshDeformCD; }
- #else
- ClassDesc * Get_Mesh_Deform_Desc (void) { return NULL; }
- #endif
- ///////////////////////////////////////////////////////////////////////////
- //
- // ChannelsUsed
- //
- ///////////////////////////////////////////////////////////////////////////
- ChannelMask
- MeshDeformClass::ChannelsUsed (void)
- {
- return GEOM_CHANNEL | SELECT_CHANNEL | SUBSEL_TYPE_CHANNEL | VERTCOLOR_CHANNEL;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // ChannelsChanged
- //
- ///////////////////////////////////////////////////////////////////////////
- ChannelMask
- MeshDeformClass::ChannelsChanged (void)
- {
- return GEOM_CHANNEL | SELECT_CHANNEL | SUBSEL_TYPE_CHANNEL | VERTCOLOR_CHANNEL;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // ModifyObject
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::ModifyObject
- (
- TimeValue time,
- ModContext & mod_context,
- ObjectState * object_state,
- INode * /*node*/
- )
- {
- assert(object_state->obj->IsSubClassOf(triObjectClassID));
-
- MeshDeformModData *mod_data = NULL;
- if (mod_context.localData == NULL) {
- mod_data = new MeshDeformModData;
- mod_context.localData = mod_data;
- } else {
- mod_data = static_cast <MeshDeformModData *> (mod_context.localData);
- }
- // Display the verts
- TriObject *tri_obj = (TriObject *)object_state->obj;
- tri_obj->mesh.SetDispFlag (DISP_SELVERTS | DISP_VERTTICKS);
-
- // Record the initial state of the mesh
- bool lock_sets = false;
- if (m_pPanel != NULL) {
- lock_sets = (m_pPanel->Are_Sets_Tied () == TRUE);
- }
- mod_data->Record_Mesh_State (*tri_obj, m_DeformState, lock_sets);
- tri_obj->PointsWereChanged();
- // Kind of a waste when there's no animation...
- tri_obj->UpdateValidity (GEOM_CHAN_NUM, Interval (time, time + 1));
- tri_obj->UpdateValidity (SELECT_CHAN_NUM, Interval (time, time + 1));
- tri_obj->UpdateValidity (SUBSEL_TYPE_CHAN_NUM, Interval (time, time + 1));
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // InputType
- //
- ///////////////////////////////////////////////////////////////////////////
- Class_ID
- MeshDeformClass::InputType (void)
- {
- return triObjectClassID;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // NotifyRefChanged
- //
- ///////////////////////////////////////////////////////////////////////////
- RefResult
- MeshDeformClass::NotifyRefChanged
- (
- Interval time,
- RefTargetHandle htarget,
- PartID &part_id,
- RefMessage mesage
- )
- {
- return REF_SUCCEED;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // GetCreateMouseCallBack
- //
- ///////////////////////////////////////////////////////////////////////////
- CreateMouseCallBack *
- MeshDeformClass::GetCreateMouseCallBack (void)
- {
- return NULL;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // BeginEditParams
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::BeginEditParams
- (
- IObjParam *max_interface,
- ULONG flags,
- Animatable *prev
- )
- {
- m_MaxInterface = max_interface;
- Update_Set_Count ();
- Set_Max_Deform_Sets (m_MaxSets);
- // Add our rollup to the command panel
- m_hRollupWnd = m_MaxInterface->AddRollupPage (AppInstance,
- MAKEINTRESOURCE (IDD_MESH_DEFORM_PANEL),
- MeshDeformPanelClass::Message_Proc,
- "Westwood Mesh Deform",
- 0,
- 0);
- //
- // Update the UI
- //
- m_pPanel = MeshDeformPanelClass::Get_Object (m_hRollupWnd);
- m_pPanel->Set_Deformer (this);
- m_pPanel->Set_Max_Sets (m_MaxSets);
- m_pPanel->Set_Current_Set (m_CurrentSet);
- Set_Current_Set (m_CurrentSet, false);
- //
- // Register the desired sub-object selection types.
- //
- const TCHAR * ptype[] = { "Vertices" };
- #if defined W3D_MAX4 //defined as in the project (.dsp)
- max_interface->SetSubObjectLevel(1);
- #else
- //---This call is obsolete from max4.
- max_interface->RegisterSubObjectTypes( ptype, 1);
- #endif
- //
- // Create the mode handlers
- //
- m_ModeSelect = new SelectModBoxCMode (this, max_interface);
- m_ModeMove = new MoveModBoxCMode (this, max_interface);
- m_ModeRotate = new RotateModBoxCMode (this, max_interface);
- m_ModeUScale = new UScaleModBoxCMode (this, max_interface);
- m_ModeNUScale = new NUScaleModBoxCMode (this, max_interface);
- m_ModeSquash = new SquashModBoxCMode (this, max_interface);
- //
- // Restore the selection level.
- ///
- max_interface->SetSubObjectLevel (1);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // EndEditParams
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::EndEditParams
- (
- IObjParam *max_interface,
- ULONG flags,
- Animatable *next
- )
- {
- // Remove our deform rollup
- if (m_hRollupWnd != NULL) {
- max_interface->DeleteRollupPage (m_hRollupWnd);
- m_hRollupWnd = NULL;
- }
- //
- // Free the mode handlers
- //
- max_interface->DeleteMode (m_ModeMove);
- max_interface->DeleteMode (m_ModeSelect);
- max_interface->DeleteMode (m_ModeRotate);
- max_interface->DeleteMode (m_ModeNUScale);
- max_interface->DeleteMode (m_ModeUScale);
- max_interface->DeleteMode (m_ModeSquash);
- SAFE_DELETE (m_ModeMove);
- SAFE_DELETE (m_ModeSelect);
- SAFE_DELETE (m_ModeRotate);
- SAFE_DELETE (m_ModeNUScale);
- SAFE_DELETE (m_ModeUScale);
- SAFE_DELETE (m_ModeSquash);
-
- // Release our hold on the max interface pointer
- m_MaxInterface = NULL;
- m_pPanel = NULL;
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // ActivateSubobjSel
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::ActivateSubobjSel
- (
- int level,
- XFormModes &modes
- )
- {
- switch (level)
- {
- // Vertex manipulation
- case 1:
- modes = XFormModes (m_ModeMove, m_ModeRotate, m_ModeNUScale, m_ModeUScale, m_ModeSquash, m_ModeSelect);
- break;
- }
- /*
- ** Notify our dependents that the subselection type,
- ** and the display have changed
- */
- NotifyDependents(FOREVER, PART_SUBSEL_TYPE|PART_DISPLAY, REFMSG_CHANGE);
- /*
- ** Notify the pipeline that the selection level has changed.
- */
- m_MaxInterface->PipeSelLevelChanged();
- /*
- ** Notify our dependents that the selection channel,
- ** display attributes, and subselection type channels have changed
- */
- NotifyDependents(FOREVER, VERTCOLOR_CHANNEL|SELECT_CHANNEL|DISP_ATTRIB_CHANNEL|SUBSEL_TYPE_CHANNEL, REFMSG_CHANGE);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // HitTest
- //
- ///////////////////////////////////////////////////////////////////////////
- int
- MeshDeformClass::HitTest
- (
- TimeValue time_value,
- INode * node,
- int type,
- int crossing,
- int flags,
- IPoint2 * point,
- ViewExp * viewport,
- ModContext * mod_context
- )
- {
- // Initialize the HitRegion
- HitRegion hit_rgn;
- MakeHitRegion (hit_rgn, type, crossing, 4, point);
- Matrix3 transform = node->GetObjectTM (time_value);
- Object * obj = node->EvalWorldState(time_value).obj;
- TriObject * tri = (TriObject *)obj->ConvertToType(time_value, triObjectClassID);
- //
- // Set up the graphics window to do the hit-test
- //
- GraphicsWindow *graphics_wnd = viewport->getGW ();
- graphics_wnd->setHitRegion (&hit_rgn);
- graphics_wnd->setTransform (transform);
-
- int saved_limits = graphics_wnd->getRndLimits ();
- graphics_wnd->setRndLimits ((saved_limits | GW_PICK) & ~(GW_ILLUM | GW_BACKCULL));
- graphics_wnd->clearHitCode ();
- //
- // Perform the hit test
- //
- SubObjHitList hitlist;
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context->localData);
- Mesh &mesh = tri->mesh;//mod_data->Peek_Mesh ();
- int result = mesh.SubObjectHitTest (graphics_wnd,
- graphics_wnd->getMaterial (),
- &hit_rgn,
- flags | SUBHIT_VERTS,
- hitlist);
-
- //
- // Record all of the hits
- //
- for (MeshSubHitRec *hit_record = hitlist.First ();
- hit_record != NULL;
- hit_record = hit_record->Next ()) {
- // rec->index is the index of vertex which was hit!
- viewport->LogHit (node, mod_context, hit_record->dist, hit_record->index, NULL);
- }
- // Cleanup
- graphics_wnd->setRndLimits (saved_limits);
-
- // Return the integer result code
- return result;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // HitTest
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::SelectSubComponent
- (
- HitRecord * hit_record,
- BOOL selected,
- BOOL all,
- BOOL invert
- )
- {
- // Loop through all the hit records
- for (; hit_record != NULL; hit_record = hit_record->Next ()) {
- // Peek at the vertex selection array for this hit record
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (hit_record->modContext->localData);
- Mesh *mesh = mod_data->Peek_Mesh ();
- BitArray &array = (mesh->vertSel);
- if (all & invert) {
- /*
- ** hitRec->hitInfo is the MeshSubHitRec::index that was stored in the
- ** HitTest method through LogHit
- */
- if (array[hit_record->hitInfo]) {
- array.Clear (hit_record->hitInfo);
- } else {
- array.Set (hit_record->hitInfo, selected);
- }
- } else {
- array.Set (hit_record->hitInfo, selected);
- }
-
- if (!all) break;
- }
- m_pPanel->Update_Vertex_Color ();
- NotifyDependents (FOREVER, PART_SELECT, REFMSG_CHANGE);
- m_bSetDirty = true;
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // GetSubObjectTMs
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::GetSubObjectTMs
- (
- SubObjAxisCallback *cb,
- TimeValue t,
- INode *node,
- ModContext *mc
- )
- {
- int test = 0;
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // HitTest
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::GetSubObjectCenters
- (
- SubObjAxisCallback * callback,
- TimeValue time_val,
- INode * node,
- ModContext * mod_context
- )
- {
- // Peek at the vertex selection array for this hit record
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context->localData);
- const Point3 *vertex_array = mod_data->Peek_Orig_Vertex_Array ();
- Mesh *mesh = mod_data->Peek_Mesh ();
-
- BitArray sel_array = mesh->vertSel;
- Matrix3 transform = node->GetObjectTM (time_val);
- Box3 box;
- // Loop through all the selected verticies and create a bounding
- // box which we can use to determine the selection center.
- for (int index = 0; index < mesh->getNumVerts (); index++ ) {
- if (sel_array[index]) {
- box += mesh->getVert (index) * transform;
- }
- }
- // Pass the 'selection' center onto MAX
- callback->Center (box.Center (), 0);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // ClearSelection
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::ClearSelection (int selLevel)
- {
- ModContextList mod_context_list;
- INodeTab nodes;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- for (int i = 0; i < mod_context_list.Count (); i++) {
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[i]->localData);
-
- if (mod_data != NULL) {
- mod_data->Peek_Mesh ()->vertSel.ClearAll ();
- }
- }
-
- /*
- ** Get rid of the temporary copies of the INodes.
- */
- nodes.DisposeTemporary ();
- /*
- ** Tell our dependents that the selection set has changed
- */
- NotifyDependents (FOREVER, PART_SELECT, REFMSG_CHANGE);
- m_bSetDirty = true;
- return ;
- }
- static Point3 last_delta;
- static Point3 last_scale;
- static Matrix3 last_rot;
- ///////////////////////////////////////////////////////////////////////////
- //
- // Move
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Move
- (
- TimeValue time_val,
- Matrix3 & parent_tm,
- Matrix3 & tm_axis,
- Point3 & displacement,
- BOOL local_origin
- )
- {
- if (m_pPanel->Is_Edit_Mode ()) {
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- // Get the data we've cached for this modifier context
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- Mesh *mesh = mod_data->Peek_Mesh ();
- const Point3 *vertex_array = mod_data->Peek_Orig_Vertex_Array ();
- Point3 *opstart_array = mod_data->Peek_Vertex_OPStart_Array ();
-
- // Loop through all the selected verts
- for (int vert = 0; vert < mesh->numVerts; vert ++) {
- if (mesh->vertSel[vert]) {
-
- // Do the 'displacment' in axis-space
- Point3 vert_ws = parent_tm * mesh->verts[vert];
- Point3 vert_as = Inverse (tm_axis) * vert_ws;
- vert_as += displacement - last_delta;
- // Convert back to obj-space
- vert_ws = tm_axis * vert_as;
- mesh->verts[vert] = Inverse (parent_tm) * vert_ws;
- // Record the delta
- //delta_array[vert] = mesh->verts[vert] - vertex_array[vert];
- }
- }
- //
- // Record these changes in the current set
- //
- mod_data->Update_Set (m_CurrentSet, VERT_POSITION);
- }
- }
- // Remember what our last displacement was because we
- // want to perform our calculations relative to the current
- // position.
- last_delta = displacement;
- // Repaint the view
- nodes.DisposeTemporary ();
- NotifyDependents (FOREVER, PART_GEOM, REFMSG_CHANGE);
- }
- m_OperationName = "Move";
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Move
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Scale
- (
- TimeValue time_val,
- Matrix3 & parent_tm,
- Matrix3 & tm_axis,
- Point3 & value,
- BOOL local_origin
- )
- {
- Point3 test = value - last_scale;
- bool bok = (test.x != 0) && (test.y != 0) && (test.z != 0);
- if (m_pPanel->Is_Edit_Mode () && bok) {
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- // Get the data we've cached for this modifier context
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- Mesh *mesh = mod_data->Peek_Mesh ();
- const Point3 *vertex_array = mod_data->Peek_Orig_Vertex_Array ();
- Point3 *opstart_array = mod_data->Peek_Vertex_OPStart_Array ();
-
- // Loop through all the selected verts
- for (int vert = 0; vert < mesh->numVerts; vert ++) {
- if (mesh->vertSel[vert]) {
- // Do the 'scale' in axis-space
- Point3 vert_ws = parent_tm * opstart_array[vert];//mesh->verts[vert];
- Point3 vert_as = Inverse (tm_axis) * vert_ws;
- vert_as = ScaleMatrix (value) * vert_as;
- // Convert back to obj-space
- vert_ws = tm_axis * vert_as;
- mesh->verts[vert] = Inverse (parent_tm) * vert_ws;
- // Record the delta
- //delta_array[vert] = mesh->verts[vert] - vertex_array[vert];
- }
- }
- //
- // Record these changes in the current set
- //
- mod_data->Update_Set (m_CurrentSet, VERT_POSITION);
- }
- }
- // Remember what our last displacement was because we
- // want to perform our calculations relative to the current
- // position.
- //last_scale = value - Point3 (1,1,1);
- //last_delta = displacement;
- // Repaint the view
- nodes.DisposeTemporary ();
- NotifyDependents (FOREVER, PART_GEOM, REFMSG_CHANGE);
- }
- m_OperationName = "Scale";
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Rotate
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Rotate
- (
- TimeValue time_val,
- Matrix3 & parent_tm,
- Matrix3 & tm_axis,
- Quat & rotation,
- BOOL local_origin
- )
- {
- if (m_pPanel->Is_Edit_Mode ()) {
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- Matrix3 matrix_rot;
- rotation.MakeMatrix (matrix_rot);
- Matrix3 rel_rot;
- rel_rot = Inverse (last_rot) * matrix_rot;
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- // Get the data we've cached for this modifier context
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- Mesh *mesh = mod_data->Peek_Mesh ();
- const Point3 *vertex_array = mod_data->Peek_Orig_Vertex_Array ();
- Point3 *opstart_array = mod_data->Peek_Vertex_OPStart_Array ();
-
- // Loop through all the selected verts
- for (int vert = 0; vert < mesh->numVerts; vert ++) {
- if (mesh->vertSel[vert]) {
-
- // Do the 'displacment' in axis-space
- Point3 vert_ws = parent_tm * mesh->verts[vert];
- Point3 vert_as = Inverse (tm_axis) * vert_ws;
- vert_as = (rel_rot * vert_as);
- // Convert back to obj-space
- vert_ws = tm_axis * vert_as;
- mesh->verts[vert] = Inverse (parent_tm) * vert_ws;
- // Record the delta
- //delta_array[vert] = mesh->verts[vert] - vertex_array[vert];
- }
- }
- //
- // Record these changes in the current set
- //
- mod_data->Update_Set (m_CurrentSet, VERT_POSITION);
- }
- }
- // Remember what our last displacement was because we
- // want to perform our calculations relative to the current
- // position.
- //last_delta = displacement;
- last_rot = matrix_rot;
- // Repaint the view
- nodes.DisposeTemporary ();
- NotifyDependents (FOREVER, PART_GEOM, REFMSG_CHANGE);
- // Make sure our current 'set' knows what verts have changed
- //Update_Current_Set ();
- }
- m_OperationName = "Rotate";
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // TransformStart
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::TransformStart (TimeValue time_val)
- {
- if (m_MaxInterface != NULL) {
- m_MaxInterface->LockAxisTripods (TRUE);
- }
-
- // Reset our last-delta value
- last_delta.x = 0;
- last_delta.y = 0;
- last_delta.z = 0;
- last_rot.IdentityMatrix ();
- last_scale.x = 0;
- last_scale.y = 0;
- last_scale.z = 0;
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- // Begin the undo operation
- theHold.Begin ();
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- // Get the data we've cached for this modifier context
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- Mesh *mesh = mod_data->Peek_Mesh ();
- Point3 *opstart_array = mod_data->Peek_Vertex_OPStart_Array ();
-
- // Copy the current state of the mesh
- for (int vert = 0; vert < mesh->numVerts; vert ++) {
- opstart_array[vert] = mesh->verts[vert];
- }
- // Add the 'position restore' object to the undo stack
- theHold.Put (new VertexPositionRestoreClass (mesh, this, mod_data));
- }
- }
- // Repaint the view
- nodes.DisposeTemporary ();
- NotifyDependents (FOREVER, PART_GEOM, REFMSG_CHANGE);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // TransformFinish
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::TransformFinish (TimeValue time_val)
- {
- if (m_MaxInterface != NULL) {
- m_MaxInterface->LockAxisTripods (FALSE);
- }
- // Accept the undo operation
- theHold.Accept (m_OperationName);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // TransformCancel
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::TransformCancel (TimeValue time_val)
- {
- if (m_MaxInterface != NULL) {
- m_MaxInterface->LockAxisTripods (FALSE);
- }
- // Cancel the undo operation
- theHold.Cancel ();
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Set_Deform_State
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Set_Deform_State (float state)
- {
- if ((m_MaxInterface != NULL) && (state != m_DeformState)) {
- m_DeformState = state;
- NotifyDependents (FOREVER, PART_GEOM | PART_VERTCOLOR, REFMSG_CHANGE);
- m_MaxInterface->RedrawViews (m_MaxInterface->GetTime ());
- if (m_pPanel != NULL) {
- m_pPanel->Update_Vertex_Color ();
- }
- }
-
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Set_Vertex_Color
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Set_Vertex_Color (const Point3 &color, bool button_up)
- {
- if (m_MaxInterface != NULL) {
-
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- bool save_undo = false;
- if ((button_up == false) && (m_VertColorChanging == false)) {
- theHold.Begin ();
- m_VertColorChanging = true;
- save_undo = true;
- }
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- // Get the data we've cached for this modifier context
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- Mesh *mesh = mod_data->Peek_Mesh ();
- //
- // Record the original color in the undo stack
- //
- if (save_undo) {
- theHold.Put (new VertexColorRestoreClass (mesh, this, mod_data));
- }
- // Only do this if the mesh is using vertex coloring
- if (mesh->numCVerts >= mesh->numVerts) {
- //
- // Loop through all the per-face verts
- //
- for (int face = 0; face < mesh->numFaces; face ++) {
- for (int vert = 0; vert < 3; vert ++) {
-
- //
- // If the vertex is selected, then change its color
- //
- if (mesh->vertSel[mesh->faces[face].v[vert]]) {
- int color_index = mesh->vcFace[face].t[vert];
- mesh->vertCol[color_index] = color;
- }
- }
- }
- }
- //
- // Record these changes in the current set
- //
- mod_data->Update_Set (m_CurrentSet, VERT_COLORS);
- }
- }
- if (button_up && m_VertColorChanging) {
- theHold.Accept ("Vertex Color");
- }
- // Repaint the model
- nodes.DisposeTemporary ();
- NotifyDependents (FOREVER, PART_GEOM | PART_VERTCOLOR, REFMSG_CHANGE);
- m_MaxInterface->RedrawViews (m_MaxInterface->GetTime ());
- }
- m_VertColorChanging = !button_up;
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Get_Vertex_Color
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Get_Vertex_Color (Point3 &color)
- {
- // Assume black
- color.x = 0;
- color.y = 0;
- color.z = 0;
- if (m_MaxInterface != NULL) {
-
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- //
- // Loop through all the modifier contexts
- //
- int sel_count = 0;
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- //
- // Get the data we've cached for this modifier context
- //
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- Mesh *mesh = mod_data->Peek_Mesh ();
- // Only do this if the mesh is using vertex coloring
- if (mesh->numCVerts >= mesh->numVerts) {
- //
- // Loop through all the per-face verts
- //
- for (int face = 0; face < mesh->numFaces; face ++) {
- for (int vert = 0; vert < 3; vert ++) {
- //
- // If this vert is selected, then add its color to the total
- //
- if (mesh->vertSel[mesh->faces[face].v[vert]]) {
- int color_index = mesh->vcFace[face].t[vert];
- Point3 vert_color = mesh->vertCol[color_index];
- color += vert_color;
- sel_count ++;
- }
- }
- }
- }
- }
- }
- //
- // Normalize the selected color
- //
- if (sel_count > 0) {
- color = color / sel_count;
- }
- nodes.DisposeTemporary ();
- }
-
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Update_UI
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Update_UI (MeshDeformModData *mod_data)
- {
- assert (mod_data != NULL);
- if (m_pPanel != NULL) {
- Update_Set_Count ();
- m_CurrentSet = mod_data->Get_Current_Set ();
- int keyframe = mod_data->Peek_Set (m_CurrentSet).Get_Current_Key_Frame ();
- Set_Deform_State ((float(keyframe + 1) + 0.5F) / 10.0F);
- m_pPanel->Update_Vertex_Color ();
- m_pPanel->Set_Max_Sets (m_MaxSets);
- m_pPanel->Set_Current_Set (m_CurrentSet);
- m_pPanel->Set_Current_State (m_DeformState);
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Auto_Apply
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Auto_Apply (bool auto_apply)
- {
- if (m_MaxInterface != NULL) {
-
- // Get a list of contexts that we are part of.
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- //
- // Let the mod context know what it's auto apply state is
- //
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- mod_data->Auto_Apply (auto_apply);
- }
- }
- // Cleanup
- nodes.DisposeTemporary ();
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Set_Max_Deform_Sets
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Set_Max_Deform_Sets (int max)
- {
- //
- // Make sure the current set doesn't exceed the total sets
- //
- if (m_CurrentSet >= max) {
- Set_Current_Set (max - 1, true);
- }
- m_MaxSets = max;
- if (m_MaxInterface != NULL) {
-
- // Get a list of contexts that we are part of.
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- //
- // Let the mod context know the max sets have changed
- //
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- mod_data->Set_Max_Deform_Sets (max);
- }
- }
- // Cleanup
- nodes.DisposeTemporary ();
- NotifyDependents (FOREVER, PART_SELECT, REFMSG_CHANGE);
- m_MaxInterface->RedrawViews (m_MaxInterface->GetTime ());
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Update_Set_Count
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Update_Set_Count (void)
- {
- m_MaxSets = 1;
- if (m_MaxInterface != NULL) {
-
- // Get a list of contexts that we are part of.
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- //
- // Get the count of sets for this context
- //
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if ((mod_data != NULL) && (mod_data->Get_Set_Count () > m_MaxSets)) {
- m_MaxSets = mod_data->Get_Set_Count ();
- }
- }
- // Cleanup
- nodes.DisposeTemporary ();
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Set_Current_Set
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Set_Current_Set
- (
- int index,
- bool update_selection
- )
- {
- last_delta.x = 0;
- last_delta.y = 0;
- last_delta.z = 0;
- m_CurrentSet = index;
- if (m_MaxInterface != NULL) {
- if (update_selection) {
- ClearSelection (1);
- }
- // Get a list of contexts that we are part of.
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- //
- // Have the mod context select the verts in its set
- //
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- mod_data->Set_Current_Set (m_CurrentSet);
- if (update_selection) {
- mod_data->Select_Set (m_CurrentSet);
- }
- m_pPanel->Set_Auto_Apply_Check (mod_data->Is_Auto_Apply ());
- }
- }
- // Repaint the model
- nodes.DisposeTemporary ();
- if (update_selection) {
- NotifyDependents (FOREVER, PART_SELECT, REFMSG_CHANGE);
- m_MaxInterface->RedrawViews (m_MaxInterface->GetTime ());
- }
- // Update the current 'vertex color' on the UI panel
- m_pPanel->Update_Vertex_Color ();
- }
-
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // Update_Current_Set
- //
- ///////////////////////////////////////////////////////////////////////////
- void
- MeshDeformClass::Update_Current_Set (void)
- {
- if (m_MaxInterface != NULL) {
- // Get a list of contexts that we are part of.
- INodeTab nodes;
- ModContextList mod_context_list;
- m_MaxInterface->GetModContexts (mod_context_list, nodes);
- // Loop through all the modifier contexts
- for (int index = 0; index < mod_context_list.Count (); index ++) {
- //
- // Notify the mod context so it can update its list of verts
- // in the current set.
- //
- MeshDeformModData *mod_data = static_cast <MeshDeformModData *> (mod_context_list[index]->localData);
- if (mod_data != NULL) {
- //mod_data->Update_Set (m_CurrentSet);
- }
- }
- // Cleanup
- nodes.DisposeTemporary ();
- m_bSetDirty = false;
- }
-
- return ;
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // SaveLocalData
- //
- ///////////////////////////////////////////////////////////////////////////
- IOResult
- MeshDeformClass::SaveLocalData (ISave *save_obj, LocalModData *mod_context)
- {
- assert (mod_context != NULL);
- return ((MeshDeformModData *)mod_context)->Save (save_obj);
- }
- ///////////////////////////////////////////////////////////////////////////
- //
- // LoadLocalData
- //
- ///////////////////////////////////////////////////////////////////////////
- IOResult
- MeshDeformClass::LoadLocalData (ILoad *load_obj, LocalModData **mod_context)
- {
- assert (mod_context != NULL);
- MeshDeformModData *mod_data = new MeshDeformModData;
- (*mod_context) = mod_data;
- return mod_data->Load (load_obj);
- }
- #if 0
- void SkinModifierClass::SelectAll(int selLevel)
- {
- int needsdel = 0;
- Interval valid = FOREVER;
- ModContextList mclist;
- INodeTab nodes;
- if (!InterfacePtr) return;
-
- InterfacePtr->GetModContexts(mclist,nodes);
- InterfacePtr->ClearCurNamedSelSet();
- for (int i = 0; i < mclist.Count(); i++) {
- SkinDataClass * skindata = (SkinDataClass *)mclist[i]->localData;
-
- if (skindata==NULL) continue;
-
- ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
- TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
- switch (SubObjSelLevel) {
- case OBJECT_SEL_LEVEL:
- assert(0);
- return;
- case VERTEX_SEL_LEVEL:
- #if 0 // undo/redo
- if (theHold.Holding()) {
- theHold.Put(new VertexSelRestore(meshData,this));
- }
- #endif
- tobj->mesh.vertSel.SetAll();
- skindata->VertSel.SetAll();
- break;
- }
- if (needsdel) {
- tobj->DeleteThis();
- }
- }
-
- /*
- ** Get rid of the temporary copies of the INodes.
- */
- nodes.DisposeTemporary();
- /*
- ** Tell our dependents that the selection set has changed
- */
- NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
- }
- void SkinModifierClass::InvertSelection(int selLevel)
- {
- int needsdel = 0;
- Interval valid = FOREVER;
- ModContextList mclist;
- INodeTab nodes;
- if (!InterfacePtr) return;
-
- InterfacePtr->GetModContexts(mclist,nodes);
- InterfacePtr->ClearCurNamedSelSet();
- for (int i = 0; i < mclist.Count(); i++) {
- SkinDataClass * skindata = (SkinDataClass *)mclist[i]->localData;
-
- if (skindata==NULL) continue;
-
- ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
- TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
- switch (SubObjSelLevel) {
- case OBJECT_SEL_LEVEL:
- assert(0);
- return;
- case VERTEX_SEL_LEVEL:
- #if 0 // undo/redo
- if (theHold.Holding()) {
- theHold.Put(new VertexSelRestore(meshData,this));
- }
- #endif
- for (int j=0; j<tobj->mesh.vertSel.GetSize(); j++) {
- if (tobj->mesh.vertSel[j]) tobj->mesh.vertSel.Clear(j);
- else tobj->mesh.vertSel.Set(j);
- }
- skindata->VertSel = tobj->mesh.vertSel;
- break;
- }
- if (needsdel) {
- tobj->DeleteThis();
- }
- }
-
- /*
- ** Get rid of the temporary copies of the INodes.
- */
- nodes.DisposeTemporary();
- /*
- ** Tell our dependents that the selection set has changed
- */
- NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
- }
- #endif // 0
- #if defined W3D_MAX4 //defined as in the project (.dsp)
- ////////////////////////////////////////////////////////////////////////////////////////
- int MeshDeformClass::NumSubObjTypes()
- {
- return 1;
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- ISubObjType *MeshDeformClass::GetSubObjType(int i)
- {
- static bool _initialized = false;
- if(!_initialized){
- _initialized = true;
- _SubObjectTypeVertex.SetName("Vertices");
- }
- if(i == -1){
- if(GetSubObjectLevel() > 0){
- return GetSubObjType(GetSubObjectLevel()-1);
- }
- }
- return &_SubObjectTypeVertex;
- }
- #endif
|