895 lines
21 KiB
C++
895 lines
21 KiB
C++
#include "stdafx.h"
|
|
#include "editpat.h"
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
#define DBGWELD_DUMPx
|
|
#define DBGWELD_ACTIONx
|
|
#define DBG_NAMEDSELSx
|
|
|
|
#define PROMPT_TIME 2000
|
|
|
|
extern void DeletePatchParts(PatchMesh *patch, RPatchMesh *rpatch, BitArray &delVerts, BitArray &delPatches);
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
static BOOL IsCompatible(BitArray &a, BitArray &b)
|
|
{
|
|
return (a.GetSize() == b.GetSize()) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
BOOL ClearPVertSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
sel = patch->vertSel;
|
|
patch->vertSel.ClearAll();
|
|
return TRUE;
|
|
}
|
|
|
|
#define CVSR_SEL_CHUNK 0x1000
|
|
|
|
IOResult ClearPVertSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case CVSR_SEL_CHUNK:
|
|
res = sel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
BOOL SetPVertSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
sel = patch->vertSel;
|
|
patch->vertSel.SetAll();
|
|
return TRUE;
|
|
}
|
|
|
|
#define SVSR_SEL_CHUNK 0x1000
|
|
|
|
IOResult SetPVertSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case SVSR_SEL_CHUNK:
|
|
res = sel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL InvertPVertSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
patch->vertSel = ~patch->vertSel;
|
|
return TRUE;
|
|
}
|
|
|
|
IOResult InvertPVertSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
// switch(iload->CurChunkID()) {
|
|
// default:
|
|
// break;
|
|
// }
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL ClearPEdgeSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
sel = patch->edgeSel;
|
|
patch->edgeSel.ClearAll();
|
|
return TRUE;
|
|
}
|
|
|
|
#define CESR_SEL_CHUNK 0x1000
|
|
|
|
IOResult ClearPEdgeSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case CESR_SEL_CHUNK:
|
|
res = sel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL SetPEdgeSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
sel = patch->edgeSel;
|
|
patch->edgeSel.SetAll();
|
|
return TRUE;
|
|
}
|
|
|
|
#define SESR_SEL_CHUNK 0x1000
|
|
|
|
IOResult SetPEdgeSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case SESR_SEL_CHUNK:
|
|
res = sel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL InvertPEdgeSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
patch->edgeSel = ~patch->edgeSel;
|
|
return TRUE;
|
|
}
|
|
|
|
IOResult InvertPEdgeSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
// switch(iload->CurChunkID()) {
|
|
// default:
|
|
// break;
|
|
// }
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL ClearPatchSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
sel = patch->patchSel;
|
|
patch->patchSel.ClearAll();
|
|
return TRUE;
|
|
}
|
|
|
|
#define CPSR_SEL_CHUNK 0x1000
|
|
|
|
IOResult ClearPatchSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case CPSR_SEL_CHUNK:
|
|
res = sel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL SetPatchSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
sel = patch->patchSel;
|
|
patch->patchSel.SetAll();
|
|
return TRUE;
|
|
}
|
|
|
|
#define SPSR_SEL_CHUNK 0x1000
|
|
|
|
IOResult SetPatchSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case SPSR_SEL_CHUNK:
|
|
res = sel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL InvertPatchSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
patch->patchSel = ~patch->patchSel;
|
|
return TRUE;
|
|
}
|
|
|
|
IOResult InvertPatchSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
// switch(iload->CurChunkID()) {
|
|
// default:
|
|
// break;
|
|
// }
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PVertSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (!IsCompatible(patch->vertSel, newSel))
|
|
return FALSE;
|
|
patch->vertSel = newSel;
|
|
return TRUE;
|
|
}
|
|
|
|
#define VSR_OLDSEL_CHUNK 0x1000
|
|
#define VSR_NEWSEL_CHUNK 0x1010
|
|
|
|
IOResult PVertSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case VSR_OLDSEL_CHUNK:
|
|
res = oldSel.Load(iload);
|
|
break;
|
|
case VSR_NEWSEL_CHUNK:
|
|
res = newSel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PEdgeSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (!IsCompatible(patch->edgeSel, newSel))
|
|
return FALSE;
|
|
patch->edgeSel = newSel;
|
|
return TRUE;
|
|
}
|
|
|
|
#define ESR_OLDSEL_CHUNK 0x1000
|
|
#define ESR_NEWSEL_CHUNK 0x1010
|
|
|
|
IOResult PEdgeSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case ESR_OLDSEL_CHUNK:
|
|
res = oldSel.Load(iload);
|
|
break;
|
|
case ESR_NEWSEL_CHUNK:
|
|
res = newSel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PatchSelRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (!IsCompatible(patch->patchSel, newSel))
|
|
return FALSE;
|
|
patch->patchSel = newSel;
|
|
return TRUE;
|
|
}
|
|
|
|
#define PSR_OLDSEL_CHUNK 0x1000
|
|
#define PSR_NEWSEL_CHUNK 0x1010
|
|
|
|
IOResult PatchSelRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case PSR_OLDSEL_CHUNK:
|
|
res = oldSel.Load(iload);
|
|
break;
|
|
case PSR_NEWSEL_CHUNK:
|
|
res = newSel.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
#define PDELR_PATCH_CHUNK 0x1060
|
|
|
|
IOResult PatchDeleteRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
// switch(iload->CurChunkID()) {
|
|
// case PDELR_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
// }
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PVertMoveRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (!delta.IsCompatible(*patch))
|
|
return FALSE;
|
|
delta.Apply(*patch);
|
|
return TRUE;
|
|
}
|
|
|
|
#define VMR_DELTA_CHUNK 0x1000
|
|
|
|
IOResult PVertMoveRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case VMR_DELTA_CHUNK:
|
|
res = delta.Load(iload);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
extern void DeleteSelVerts(PatchMesh *patch, RPatchMesh *rpatch);
|
|
|
|
BOOL PVertDeleteRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
{
|
|
oldPatch = *patch;
|
|
roldPatch = *rpatch;
|
|
}
|
|
DeleteSelVerts(patch, rpatch);
|
|
return TRUE;
|
|
}
|
|
|
|
#define VDELR_PATCH_CHUNK 0x1060
|
|
|
|
IOResult PVertDeleteRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
// switch(iload->CurChunkID()) {
|
|
// case VDELR_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
// }
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PVertChangeRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
{
|
|
oldPatch = *patch;
|
|
roldPatch = *rpatch;
|
|
}
|
|
patch->ChangeVertType(index, type);
|
|
return TRUE;
|
|
}
|
|
|
|
#define VCHG_GENERAL_CHUNK 0x1001
|
|
#define VCHG_PATCH_CHUNK 0x1010
|
|
|
|
IOResult PVertChangeRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
ULONG nb;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case VCHG_GENERAL_CHUNK:
|
|
res = iload->Read(&index, sizeof(int), &nb);
|
|
res = iload->Read(&type, sizeof(int), &nb);
|
|
break;
|
|
// case VCHG_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PAttachRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
oldPatchCount = patch->numPatches;
|
|
patch->Attach(&attPatch, mtlOffset);
|
|
return TRUE;
|
|
}
|
|
|
|
#define ATTR_GENERAL_CHUNK 0x1001
|
|
#define ATTR_ATTPATCH_CHUNK 0x1010
|
|
#define ATTR_MTLOFFSET_CHUNK 0x1020
|
|
|
|
IOResult PAttachRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
ULONG nb;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case ATTR_GENERAL_CHUNK:
|
|
res = iload->Read(&oldPatchCount, sizeof(int), &nb);
|
|
break;
|
|
case ATTR_ATTPATCH_CHUNK:
|
|
res = attPatch.Load(iload);
|
|
break;
|
|
case ATTR_MTLOFFSET_CHUNK:
|
|
res = iload->Read(&mtlOffset, sizeof(int), &nb);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PatchDetachRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord && !copy)
|
|
{
|
|
oldPatch = *patch;
|
|
roldPatch = *rpatch;
|
|
}
|
|
if (!copy)
|
|
{
|
|
BitArray vdel(patch->numVerts);
|
|
vdel.ClearAll();
|
|
BitArray pdel = patch->patchSel;
|
|
DeletePatchParts(patch, rpatch, vdel, pdel);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#define PDETR_GENERAL_CHUNK 0x1000
|
|
#define PDETR_PATCH_CHUNK 0x1030
|
|
|
|
IOResult PatchDetachRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
ULONG nb;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case PDETR_GENERAL_CHUNK:
|
|
res = iload->Read(©, sizeof(int), &nb);
|
|
break;
|
|
// case PDETR_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PatchMtlRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
for (int i = 0; i < patch->numPatches; ++i)
|
|
{
|
|
if (patch->patchSel[i])
|
|
patch->patches[i].setMatID(index);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#define PMTLR_GENERAL_CHUNK 0x1000
|
|
#define PMTLR_INDEX_CHUNK 0x1020
|
|
|
|
IOResult PatchMtlRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
ULONG nb;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case PMTLR_INDEX_CHUNK:
|
|
res = iload->Read(&index, sizeof(MtlID), &nb);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
void ChangePatchType(PatchMesh *patch, int index, int type)
|
|
{
|
|
// If positive vertex number, do it to just one vertex
|
|
if (index >= 0)
|
|
{
|
|
patch->patches[index].flags = type;
|
|
patch->computeInteriors();
|
|
return;
|
|
}
|
|
|
|
// Otherwise, do it to all selected vertices!
|
|
int patches = patch->numPatches;
|
|
BitArray &psel = patch->patchSel;
|
|
for (int i = 0; i < patches; ++i)
|
|
{
|
|
if (psel[i])
|
|
patch->patches[i].flags = type;
|
|
}
|
|
patch->computeInteriors();
|
|
}
|
|
|
|
|
|
|
|
BOOL PatchChangeRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (index >= 0 && index >= patch->numPatches)
|
|
return FALSE;
|
|
if (reRecord)
|
|
{
|
|
oldPatch = *patch;
|
|
roldPatch = *rpatch;
|
|
}
|
|
ChangePatchType(patch, index, type);
|
|
return TRUE;
|
|
}
|
|
|
|
#define PCHG_GENERAL_CHUNK 0x1001
|
|
#define PCHG_PATCH_CHUNK 0x1010
|
|
|
|
IOResult PatchChangeRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
ULONG nb;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case PCHG_GENERAL_CHUNK:
|
|
res = iload->Read(&index, sizeof(int), &nb);
|
|
res = iload->Read(&type, sizeof(int), &nb);
|
|
break;
|
|
// case PCHG_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
#define PADDR_TYPE_CHUNK 0x1000
|
|
#define PADDR_PATCH_CHUNK 0x1010
|
|
#define PADDR_POSTWELD_CHUNK 0x1020
|
|
|
|
IOResult PatchAddRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
ULONG nb;
|
|
postWeld = FALSE;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case PADDR_TYPE_CHUNK:
|
|
res = iload->Read(&type, sizeof(int), &nb);
|
|
break;
|
|
// case PADDR_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
// If the following chunk is present, it's a MAX 2.0 file and a post-addition
|
|
// weld is to be performed
|
|
case PADDR_POSTWELD_CHUNK:
|
|
postWeld = TRUE;
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
// Compute midpoint division for patch vectors -- Provide patchmesh, patch number, 4 bez points
|
|
// returns 2 new vectors
|
|
/*
|
|
static Point3 InterpPoint(PatchMesh *patch, int index, float pct, int e1, int i1, int i2, int e2, Point3 *v1 = NULL, Point3 *v2 = NULL, Point3 *v3 = NULL, Point3 *v4 = NULL)
|
|
{
|
|
PatchVec *v = patch->vecs;
|
|
Patch &p = patch->patches[index];
|
|
Point3 pe1 = v[p.vec[e1]].p;
|
|
Point3 pe2 = v[p.vec[e2]].p;
|
|
Point3 pi1 = v[p.interior[i1]].p;
|
|
Point3 pi2 = v[p.interior[i2]].p;
|
|
Point3 e1i1 = pe1 +(pi1 - pe1) * pct;
|
|
Point3 i1i2 = pi1 +(pi2 - pi1) * pct;
|
|
Point3 i2e2 = pi2 +(pe2 - pi2) * pct;
|
|
Point3 a = e1i1 +(i1i2 - e1i1) * pct;
|
|
Point3 b = i1i2 +(i2e2 - i1i2) * pct;
|
|
if (v1)
|
|
*v1 = e1i1;
|
|
if (v2)
|
|
*v2 = a;
|
|
if (v3)
|
|
*v3 = b;
|
|
if (v4)
|
|
*v4 = i2e2;
|
|
return a +(b - a) * pct;
|
|
}
|
|
|
|
static Point3 InterpPoint(float pct, Point3 e1, Point3 i1, Point3 i2, Point3 e2, Point3 *v1 = NULL, Point3 *v2 = NULL, Point3 *v3 = NULL, Point3 *v4 = NULL)
|
|
{
|
|
Point3 e1i1 = e1 +(i1 - e1) * pct;
|
|
Point3 i1i2 = i1 +(i2 - i1) * pct;
|
|
Point3 i2e2 = i2 +(e2 - i2) * pct;
|
|
Point3 a = e1i1 +(i1i2 - e1i1) * pct;
|
|
Point3 b = i1i2 +(i2e2 - i1i2) * pct;
|
|
if (v1)
|
|
*v1 = e1i1;
|
|
if (v2)
|
|
*v2 = a;
|
|
if (v3)
|
|
*v3 = b;
|
|
if (v4)
|
|
*v4 = i2e2;
|
|
return a +(b - a) * pct;
|
|
}
|
|
|
|
static Point3 InterpLinear(Point3 a, Point3 b, float interp)
|
|
{
|
|
return a +(a - b) * interp;
|
|
}
|
|
|
|
static Point3 InterpDegree2(Point3 a, Point3 b, Point3 c, float interp)
|
|
{
|
|
Point3 ab = a +(b - a) * interp;
|
|
Point3 bc = b +(c - b) * interp;
|
|
return ab +(bc - ab) * interp;
|
|
}
|
|
|
|
static Point3 InterpDegree3(Point3 a, Point3 b, Point3 c, Point3 d, float interp)
|
|
{
|
|
Point3 ab = a +(b - a) * interp;
|
|
Point3 bc = b +(c - b) * interp;
|
|
Point3 cd = c +(d - c) * interp;
|
|
Point3 abbc = ab +(bc - ab) * interp;
|
|
Point3 bccd = bc +(cd - bc) * interp;
|
|
return abbc +(bccd - abbc) * interp;
|
|
}
|
|
*/
|
|
extern void SubdividePatch(int type, BOOL propagate, PatchMesh *patch, RPatchMesh *rpatch);
|
|
|
|
BOOL EdgeSubdivideRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
{
|
|
oldPatch = *patch;
|
|
roldPatch = *rpatch;
|
|
}
|
|
SubdividePatch(SUBDIV_EDGES, propagate, patch, rpatch);
|
|
return TRUE;
|
|
}
|
|
|
|
#define ESUBR_PROPAGATE_CHUNK 0x1000
|
|
#define ESUBR_PATCH_CHUNK 0x1010
|
|
|
|
IOResult EdgeSubdivideRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
propagate = FALSE;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case ESUBR_PROPAGATE_CHUNK:
|
|
propagate = TRUE;
|
|
break;
|
|
// case ESUBR_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
BOOL PatchSubdivideRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
{
|
|
oldPatch = *patch;
|
|
roldPatch = *rpatch;
|
|
}
|
|
SubdividePatch(SUBDIV_PATCHES, propagate, patch, rpatch);
|
|
return TRUE;
|
|
}
|
|
|
|
#define PSUBR_PROPAGATE_CHUNK 0x1000
|
|
#define PSUBR_PATCH_CHUNK 0x1010
|
|
|
|
IOResult PatchSubdivideRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
propagate = FALSE;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case PSUBR_PROPAGATE_CHUNK:
|
|
propagate = TRUE;
|
|
break;
|
|
// case PSUBR_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
BOOL PVertWeldRecord::Redo(PatchMesh *patch, RPatchMesh *rpatch, int reRecord)
|
|
{
|
|
if (reRecord)
|
|
{
|
|
oldPatch = *patch;
|
|
roldPatch = *rpatch;
|
|
}
|
|
patch->Weld(thresh);
|
|
return TRUE;
|
|
}
|
|
|
|
#define WELDR_THRESH_CHUNK 0x1010
|
|
#define WELDR_PATCH_CHUNK 0x1000
|
|
|
|
IOResult PVertWeldRecord::Load(ILoad *iload)
|
|
{
|
|
IOResult res;
|
|
ULONG nb;
|
|
propagate = FALSE;
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
{
|
|
switch (iload->CurChunkID())
|
|
{
|
|
case WELDR_THRESH_CHUNK:
|
|
res = iload->Read(&thresh, sizeof(float), &nb);
|
|
break;
|
|
// case WELDR_PATCH_CHUNK:
|
|
// res = oldPatch.Load(iload);
|
|
// break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res != IO_OK)
|
|
return res;
|
|
}
|
|
return IO_OK;
|
|
}
|