// Tools.cpp : Misc. routines // #include "stdafx.h" #include "Tools.h" #include "resource.h" #include "PrefSht.h" #include "lc_application.h" #include #include // Create a bitmap of a given size and color HBITMAP CreateColorBitmap (UINT cx, UINT cy, COLORREF cr) { HWND hwndDesktop = GetDesktopWindow(); HDC hdcDesktop = GetDC(hwndDesktop); HDC hdcMem = CreateCompatibleDC(hdcDesktop); HBRUSH hbr = CreateSolidBrush(cr); HBITMAP hbm = CreateCompatibleBitmap(hdcDesktop, cx, cy); HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbm); // Paint the bitmap FillRect(hdcMem, CRect(0, 0, cx, cy), hbr); // Clean up SelectObject(hdcMem, hbmOld); DeleteObject(hbr); DeleteDC(hdcMem); ReleaseDC(hwndDesktop, hdcDesktop); return hbm; } /////////////////////////////////////// // Hooks for common dialogs #define IDW_BUTTON 5000 UINT APIENTRY PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { /* switch (uiMsg) { case WM_INITDIALOG: { PRINTDLG* pd = (PRINTDLG*)lParam; SetWindowLong(hdlg, GWL_USERDATA, pd->lCustData); RECT rc1, rc2; GetWindowRect(GetDlgItem(hdlg, IDOK), &rc1); GetWindowRect(GetDlgItem(hdlg, IDCANCEL), &rc2); ScreenToClient(hdlg, (LPPOINT)&rc1); ScreenToClient(hdlg, ((LPPOINT)&rc1)+1); ScreenToClient(hdlg, (LPPOINT)&rc2); CreateWindow("BUTTON","&Options...", BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE|WS_TABSTOP, rc1.left+rc1.left-rc2.left, rc1.top, rc1.right-rc1.left, rc1.bottom-rc1.top, hdlg, (HMENU)IDW_BUTTON, AfxGetInstanceHandle(), NULL); HFONT f = (HFONT)SendDlgItemMessage(hdlg, IDOK, WM_GETFONT, 0, 0); SendDlgItemMessage(hdlg, IDW_BUTTON, WM_SETFONT, (WPARAM)f, MAKELPARAM(TRUE, 0)); } break; case WM_COMMAND: { if (LOWORD(wParam) == IDW_BUTTON) { CFrameWnd* pFrame = (CFrameWnd*)GetWindowLong(hdlg, GWL_USERDATA); CView* pView = pFrame->GetActiveView(); CCADDoc* pDoc = (CCADDoc*)pView->GetDocument(); CWnd *w = CWnd::FromHandle(hdlg); CPreferencesSheet propSheet(w); propSheet.m_tabCtrl.m_bPrintOnly = TRUE; propSheet.m_PagePrint.SetOptions(pDoc->m_strHeader, pDoc->m_strFooter); if (propSheet.DoModal() == IDOK) propSheet.m_PagePrint.GetOptions(&pDoc->m_strHeader, &pDoc->m_strFooter); } } break; } */ return 0; } #undef IDW_BUTTON /////////////////////////////////////////////////////////// // Palette Utility Functions static unsigned char threeto8[8] = { 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377 }; static unsigned char twoto8[4] = { 0, 0x55, 0xaa, 0xff }; static unsigned char oneto8[2] = { 0, 255 }; static int defaultOverride[13] = { 0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91 }; static PALETTEENTRY defaultPalEntry[20] = { { 0, 0, 0, 0 }, { 0x80,0, 0, 0 }, { 0, 0x80,0, 0 }, { 0x80,0x80,0, 0 }, { 0, 0, 0x80, 0 }, { 0x80,0, 0x80, 0 }, { 0, 0x80,0x80, 0 }, { 0xC0,0xC0,0xC0, 0 }, { 192, 220, 192, 0 }, { 166, 202, 240, 0 }, { 255, 251, 240, 0 }, { 160, 160, 164, 0 }, { 0x80,0x80,0x80, 0 }, { 0xFF,0, 0, 0 }, { 0, 0xFF,0, 0 }, { 0xFF,0xFF,0, 0 }, { 0, 0, 0xFF, 0 }, { 0xFF,0, 0xFF, 0 }, { 0, 0xFF,0xFF, 0 }, { 0xFF,0xFF,0xFF, 0 } }; static unsigned char ComponentFromIndex(int i, UINT nbits, UINT shift) { unsigned char val = (unsigned char) (i >> shift); switch (nbits) { case 1: val &= 0x1; return oneto8[val]; case 2: val &= 0x3; return twoto8[val]; case 3: val &= 0x7; return threeto8[val]; default: return 0; } } BOOL CreateRGBPalette(HDC hDC, CPalette **ppCPalette) { PIXELFORMATDESCRIPTOR pfd; LOGPALETTE *pPal; WORD n, i; n = OpenGLGetPixelFormat(hDC); OpenGLDescribePixelFormat(hDC, n, sizeof(pfd), &pfd); if (!(pfd.dwFlags & PFD_NEED_PALETTE)) return FALSE; n = 1 << pfd.cColorBits; pPal = (PLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + n * sizeof(PALETTEENTRY)]; ASSERT(pPal != NULL); pPal->palVersion = 0x300; pPal->palNumEntries = n; for (i=0; ipalPalEntry[i].peRed = ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift); pPal->palPalEntry[i].peGreen = ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift); pPal->palPalEntry[i].peBlue = ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift); pPal->palPalEntry[i].peFlags = 0; } // fix up the palette to include the default GDI palette if ((pfd.cColorBits == 8) && (pfd.cRedBits == 3) && (pfd.cRedShift == 0) && (pfd.cGreenBits == 3) && (pfd.cGreenShift == 3) && (pfd.cBlueBits == 2) && (pfd.cBlueShift == 6)) { for (i = 1 ; i <= 12 ; i++) pPal->palPalEntry[defaultOverride[i]] = defaultPalEntry[i]; } BOOL result = (*ppCPalette)->CreatePalette(pPal); delete pPal; return result; } HANDLE MakeDib(HBITMAP hbitmap, UINT bits) { HANDLE hdib; HDC hdc; BITMAP bitmap; UINT wLineLen; DWORD dwSize, wColSize; LPBITMAPINFOHEADER lpbi; LPBYTE lpBits; GetObject(hbitmap, sizeof(BITMAP), &bitmap) ; // DWORD align the width of the DIB // Figure out the size of the colour table // Calculate the size of the DIB wLineLen = (bitmap.bmWidth*bits+31)/32 * 4; wColSize = sizeof(RGBQUAD)*((bits <= 8) ? 1<biSize = sizeof(BITMAPINFOHEADER) ; lpbi->biWidth = bitmap.bmWidth ; lpbi->biHeight = bitmap.bmHeight ; lpbi->biPlanes = 1 ; lpbi->biBitCount = (WORD) bits ; lpbi->biCompression = BI_RGB ; lpbi->biSizeImage = dwSize - sizeof(BITMAPINFOHEADER) - wColSize ; lpbi->biXPelsPerMeter = 0 ; lpbi->biYPelsPerMeter = 0 ; lpbi->biClrUsed = (bits <= 8) ? 1<biClrImportant = 0 ; // Get the bits from the bitmap and stuff them after the LPBI lpBits = (LPBYTE)(lpbi+1)+wColSize; hdc = CreateCompatibleDC(NULL); GetDIBits(hdc,hbitmap,0,bitmap.bmHeight,lpBits,(LPBITMAPINFO)lpbi, DIB_RGB_COLORS); // Fix this if GetDIBits messed it up.... lpbi->biClrUsed = (bits <= 8) ? 1<Free(pidl); } pMalloc->Release(); } return FALSE; } #include "3dsftk\inc\3dsftk.h" #include "globals.h" #include "project.h" #include "piece.h" #include "pieceinf.h" #include "matrix.h" void Export3DStudio() { CFileDialog dlg(FALSE, "*.dat",NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "3D Studio Files (*.3ds)|*.3ds|All Files (*.*)|*.*||", AfxGetMainWnd()); if (dlg.DoModal() != IDOK) return; Project* project = lcGetActiveProject(); ClearErrList3ds(); file3ds *file = OpenFile3ds(dlg.GetPathName(), "w"); database3ds *db = NULL; InitDatabase3ds(&db); CreateNewDatabase3ds(db, MeshFile); // MESH SETTINGS meshset3ds *mesh = NULL; InitMeshSet3ds(&mesh); mesh->ambientlight.r = project->m_fAmbient[0]; mesh->ambientlight.g = project->m_fAmbient[1]; mesh->ambientlight.b = project->m_fAmbient[2]; PutMeshSet3ds(db, mesh); ReleaseMeshSet3ds(&mesh); // BACKGROUND background3ds *bgnd = NULL; InitBackground3ds(&bgnd); float* bg = project->GetBackgroundColor(); bgnd->solid.color.r = bg[0]; bgnd->solid.color.g = bg[1]; bgnd->solid.color.b = bg[2]; bgnd->bgndused = UseSolidBgnd; /* if (m_dwScene & SCENE_BG) { // bgnd->bitmap = // bgnd->bgndused = UseBitmapBgnd; } */ PutBackground3ds(db, bgnd); ReleaseBackground3ds(&bgnd); // ATMOSPHERE atmosphere3ds *atmo = NULL; InitAtmosphere3ds(&atmo); if (project->m_nScene & LC_SCENE_FOG) { atmo->fog.fogcolor.r = project->m_fFogColor[0]; atmo->fog.fogcolor.g = project->m_fFogColor[1]; atmo->fog.fogcolor.b = project->m_fFogColor[2]; atmo->fog.fogbgnd = True3ds; atmo->activeatmo = UseFog; } PutAtmosphere3ds(db, atmo); ReleaseAtmosphere3ds(&atmo); /* // CreatePolygon(db); { int i; light3ds *slite = NULL; kfspot3ds *kflite = NULL; camera3ds *cam = NULL; kfcamera3ds *kfcam = NULL; kfmesh3ds *kobj = NULL; kfambient3ds *amlite = NULL; kfsets3ds *kfsets = NULL; viewport3ds *view = NULL; // CAMERA InitCamera3ds(&cam); ON_ERROR_RETURN; strcpy(cam->name, "Camera1"); cam->position.x = 65.0F; cam->position.y = -3440.0F; cam->position.z = 185.0F; cam->target.x = 25.0F; cam->target.y = 300.0F; cam->target.z = 3000.0F; cam->ranges.cam_near = (float3ds)4000.0; cam->ranges.cam_far = (float3ds)9000.0; cam->roll = 0.0F; cam->fov = 60.0F; cam->showcone = True3ds; PutCamera3ds(db, cam); ON_ERROR_RETURN; ReleaseCamera3ds(&cam); ON_ERROR_RETURN; // SPOTLIGHT InitSpotlight3ds(&slite); ON_ERROR_RETURN; strcpy(slite->name, "Spot1"); slite->pos.x = 1000.0F; slite->pos.y = -4500.0F; slite->pos.z = 3000.0F; slite->color.r = 0.1F; slite->color.g = 0.2F; slite->color.b = 0.3F; slite->dloff = False3ds; slite->attenuation.on = False3ds; slite->attenuation.inner = 10.0F; slite->attenuation.outer = 100.0F; slite->spot->target.x = 0.0F; slite->spot->target.y = 0.0F; slite->spot->target.z = 0.0F; slite->spot->hotspot = 44.0F; slite->spot->falloff = 45.0F; slite->spot->roll = 0.0F; slite->spot->aspect = 1.0F; slite->spot->shadows.cast = False3ds; slite->spot->shadows.type = UseShadowMap; slite->spot->shadows.local = False3ds; slite->spot->shadows.bias = 1.0F; slite->spot->shadows.filter = 3.0F; slite->spot->shadows.mapsize = 512; slite->spot->shadows.raybias = 1.0F; slite->spot->cone.type = Circular; slite->spot->cone.show = True3ds; slite->spot->cone.overshoot = False3ds; slite->spot->projector.use = False3ds; slite->spot->projector.bitmap = NULL; PutSpotlight3ds(db, slite); ON_ERROR_RETURN; ReleaseLight3ds(&slite); ON_ERROR_RETURN; */ // MATERIALS material3ds *matr = NULL; for (int i = 0; i < 28; i++) { InitMaterial3ds(&matr); sprintf(matr->name, "Material%02d", i); matr->ambient.r = matr->diffuse.r = (float)FlatColorArray[i][0]/255; matr->ambient.g = matr->diffuse.g = (float)FlatColorArray[i][1]/255; matr->ambient.b = matr->diffuse.b = (float)FlatColorArray[i][2]/255; matr->specular.r = 0.9f; matr->specular.g = 0.9f; matr->specular.b = 0.9f; matr->shininess = 0.25f; matr->shinstrength = 0.05f; matr->blur = 0.2f; if (i < 14 || i > 21) { matr->transparency = 0.0f; matr->transfalloff = 0.0f; } else { matr->transparency = 0.5f; matr->transfalloff = 0.0f; } matr->selfillumpct = 0.0f; matr->wiresize = 1.0f; matr->shading = Phong; matr->useblur = False3ds; PutMaterial3ds(db, matr); ReleaseMaterial3ds(&matr); } Piece* pPiece; int objcount = 0; for (pPiece = project->m_pPieces; pPiece; pPiece = pPiece->m_pNext) { // MESH OBJECT mesh3ds *mobj = NULL; UINT facecount = 0, i, j = 0, c, col; UINT facemats[LC_COL_DEFAULT+1]; memset(facemats, 0, sizeof(facemats)); PieceInfo* pInfo = pPiece->GetPieceInfo(); if (pInfo->m_nFlags & LC_PIECE_LONGDATA) continue; // 3DS can't handle this // count number of faces used for (c = 0; c < pInfo->m_nGroupCount; c++) { WORD* info = (WORD*)pInfo->m_pGroups[c].drawinfo; col = *info; info++; while (col--) { i = *info; info++; facecount += (*info)*2/4; facemats[i] += (*info)*2/4; info += *info + 1; facecount += (*info)/3; facemats[i] += (*info)/3; info += *info + 1; info += *info + 1; } } InitMeshObj3ds(&mobj, (unsigned short)pInfo->m_nVertexCount, facecount, InitNoExtras3ds); sprintf(mobj->name, "Piece%d", objcount); objcount++; float tmp[3], pos[3], rot[4]; pPiece->GetPosition(pos); pPiece->GetRotation(rot); Matrix mat(rot, pos); for (c = 0; c < pInfo->m_nVertexCount; c++) { mat.TransformPoint(tmp, &pInfo->m_fVertexArray[c*3]); mobj->vertexarray[c].x = tmp[0]; mobj->vertexarray[c].y = tmp[1]; mobj->vertexarray[c].z = tmp[2]; } for (c = 0; c < pInfo->m_nGroupCount; c++) { WORD* info = (WORD*)pInfo->m_pGroups[c].drawinfo; col = *info; info++; while (col--) { info++; for (i = 0; i < *info; i+=4) { mobj->facearray[j].v1 = info[i+1]; mobj->facearray[j].v2 = info[i+2]; mobj->facearray[j].v3 = info[i+3]; mobj->facearray[j].flag = FaceABVisable3ds|FaceBCVisable3ds|FaceCAVisable3ds; j++; mobj->facearray[j].v1 = info[i+3]; mobj->facearray[j].v2 = info[i+4]; mobj->facearray[j].v3 = info[i+1]; mobj->facearray[j].flag = FaceABVisable3ds|FaceBCVisable3ds|FaceCAVisable3ds; j++; } info += *info + 1; for (i = 0; i < *info; i+=3) { mobj->facearray[j].v1 = info[i+1]; mobj->facearray[j].v2 = info[i+2]; mobj->facearray[j].v3 = info[i+3]; mobj->facearray[j].flag = FaceABVisable3ds|FaceBCVisable3ds|FaceCAVisable3ds; j++; } info += *info + 1; info += *info + 1; } } i = 0; for (j = 0; j < LC_COL_DEFAULT+1; j++) if (facemats[j]) i++; mobj->nmats = i; InitMeshObjField3ds (mobj, InitMatArray3ds); i = 0; for (j = 0; j < LC_COL_DEFAULT+1; j++) { if (facemats[j]) { InitMatArrayIndex3ds (mobj, i, facemats[j]); sprintf(mobj->matarray[i].name, "Material%02d", j == LC_COL_DEFAULT ? pPiece->GetColor() : j); mobj->matarray[i].nfaces = facemats[j]; UINT curface = 0; facecount = 0; for (c = 0; c < pInfo->m_nGroupCount; c++) { WORD* info = (WORD*)pInfo->m_pGroups[c].drawinfo; col = *info; info++; while (col--) { if (j == *info) { info++; for (UINT k = 0; k < *info; k += 4) { mobj->matarray[i].faceindex[facecount] = curface; facecount++; curface++; mobj->matarray[i].faceindex[facecount] = curface; facecount++; curface++; } info += *info + 1; for (UINT k = 0; k < *info; k += 3) { mobj->matarray[i].faceindex[facecount] = curface; facecount++; curface++; } info += *info + 1; } else { info++; curface += (*info)*2/4; info += *info + 1; curface += (*info)/3; info += *info + 1; } info += *info + 1; } } i++; } } FillMatrix3ds(mobj); mobj->locmatrix[9] = 0; mobj->locmatrix[10] = 0; mobj->locmatrix[11] = 0; PutMesh3ds(db, mobj); RelMeshObj3ds(&mobj); } /* InitMeshObj3ds(&mobj, 12, 8, InitNoExtras3ds); SetPoint(mobj->vertexarray[0], -46.62F, -2.31F, -103.57F); SetFace(mobj->facearray[7], 7, 4, 8, FaceABVisable3ds|FaceBCVisable3ds|FaceCAVisable3ds); mobj->nmats = 1; InitMeshObjField3ds (mobj, InitMatArray3ds); InitMatArrayIndex3ds (mobj, 0, 7); strcpy(mobj->matarray[0].name, "RedSides"); for (i=0; i<7; i++) mobj->matarray[0].faceindex[i] = i; mobj->matarray[0].nfaces = 7; FillMatrix3ds(mobj); PutMesh3ds(db, mobj); // release later // KEYFRAMER SECTION // Any object used in keyframer section must be defined already // SPOTLIGHT InitSpotlightMotion3ds(&kflite, 3, 2, 1, 1, 1, 2); ON_ERROR_RETURN; // POSITION strcpy (kflite->name, "Spot1"); kflite->pkeys[0].time = 0; SetPoint(kflite->pos[0], 1000.0F, -4500.0F, 3000.0F); kflite->pkeys[1].time = 10; SetPoint(kflite->pos[1], 1000.0F, 0.0F, 3000.0F); kflite->pkeys[2].time = 15; SetPoint(kflite->pos[2], 1000.0F, -4500.0F, -1000.0F); // COLOR kflite->ckeys[0].time = 0; kflite->color[0].r = 0.1F; kflite->color[0].g = 0.2F; kflite->color[0].b = 0.3F; kflite->ckeys[1].time = 30; kflite->color[1].r = 0.5F; kflite->color[1].g = 0.4F; kflite->color[1].b = 0.3F; // HOTSPOT kflite->hkeys[0].time = 0; kflite->hot[0] = 44.0F; // FALLOFF kflite->fkeys[0].time = 0; kflite->fall[0] = 45.0F; // ROLL kflite->rkeys[0].time = 0; kflite->roll[0] = 0.0F; kflite->flags1 = 20; kflite->flags2 = 0; kflite->tkeys[0].time = 0; SetPoint(kflite->tpos[0], 0.0F, 0.0F, 0.0F) kflite->tkeys[1].time = 30; SetPoint(kflite->tpos[1], 0.0F, 0.0F, 3000.0F) PutSpotlightMotion3ds(db, kflite); ON_ERROR_RETURN; ReleaseSpotlightMotion3ds(&kflite); ON_ERROR_RETURN; // CAMERA MOTION InitCameraMotion3ds(&kfcam, 1, 5, 1, 5); ON_ERROR_RETURN; strcpy (kfcam->name, "Camera1"); kfcam->ntflag = TrackLoops3ds; kfcam->flags2 = 1; kfcam->pkeys[0].time = 0; SetPoint(kfcam->pos[0], 65.0F, -3440.0F, 185.0F) kfcam->tkeys[0].time = 0; SetPoint(kfcam->tpos[0], 0.0F, 0.0F, 0.0F) kfcam->tkeys[1].time = 5; SetPoint(kfcam->tpos[1], 25.0F, 0.0F, 300.0F) kfcam->tkeys[2].time = 10; SetPoint(kfcam->tpos[2], 25.0F, -30.0F, 300.0F) kfcam->tkeys[3].time = 15; SetPoint(kfcam->tpos[3], 25.0F, 0.0F, 300.0F) kfcam->tkeys[4].time = 20; SetPoint(kfcam->tpos[4], 25.0F, 30.0F, 300.0F) kfcam->rkeys[0].time = 0; kfcam->roll[0] = 0.0F; kfcam->nfflag = TrackRepeats3ds; kfcam->fkeys[0].time = 0; kfcam->fov[0] = 20.0F; kfcam->fkeys[1].time = 5; kfcam->fov[1] = 30.0F; kfcam->fkeys[2].time = 10; kfcam->fov[2] = 20.0F; kfcam->fkeys[3].time = 15; kfcam->fov[3] = 33.5F; kfcam->fkeys[4].time = 20; kfcam->fov[4] = 20.0F; PutCameraMotion3ds(db, kfcam); // this is the last villan ON_ERROR_RETURN; ReleaseCameraMotion3ds(&kfcam); ON_ERROR_RETURN; // OBJECT MOTION POLY1 InitObjectMotion3ds(&kobj, 6, 2, 1, 0, 0); ON_ERROR_RETURN; strcpy (kobj->name, "Poly1"); // Set the pivot point to the mesh's center SetPoint(kobj->pivot, 0.0F, 0.0F, 0.0F); SetBoundBox3ds (mobj, kobj); ON_ERROR_RETURN; kobj->pkeys[0].time = 0; kobj->pos[0].x = (kobj->boundmax.x - kobj->boundmax.x) / 2.0F; kobj->pos[0].y = (kobj->boundmax.y - kobj->boundmax.y) / 2.0F; kobj->pos[0].z = (kobj->boundmax.z - kobj->boundmax.z) / 2.0F; kobj->pkeys[1].time = 8; SetPoint(kobj->pos[1], -421.5F, -1392.0F, 30.5F) kobj->pkeys[2].time = 15; SetPoint(kobj->pos[2], 403.0F, -1639.0F, 25.0F) kobj->pkeys[3].time = 24; SetPoint(kobj->pos[3], 1145.5F, -484.0F, 71.5F) kobj->pkeys[4].time = 31; SetPoint(kobj->pos[4], 870.5F, 224.0F, 610.5F) kobj->pkeys[5].time = 40; SetPoint(kobj->pos[5], 10.5F, 30.0F, 57.0F) kobj->nrflag = TrackLoops3ds; kobj->nsflag = TrackSingle3ds; kobj->rkeys[0].time = 0; kobj->rot[0].angle = 0.0F; kobj->rot[0].x = 0.0F; kobj->rot[0].y = 0.0F; kobj->rot[0].z = -1.0F; kobj->rkeys[1].time = 20; kobj->rot[1].angle = 3.1415F; kobj->rot[1].x = 0.0F; kobj->rot[1].y = 0.0F; kobj->rot[1].z = -1.0F; PutObjectMotion3ds(db, kobj); ON_ERROR_RETURN; ReleaseObjectMotion3ds (&kobj); ON_ERROR_RETURN; RelMeshObj3ds(&mobj); // SET KEYFRAMER AMBIENT LIGHT InitAmbientLightMotion3ds(&amlite, 1); ON_ERROR_RETURN; amlite->flags1 = (ushort3ds)10; amlite->ckeys[0].time = 15; amlite->ckeys[0].rflags = (ushort3ds)40; amlite->color[0].r = amlite->color[0].g = amlite->color[0].b = 0.5F; PutAmbientLightMotion3ds(db, amlite); ON_ERROR_RETURN; ReleaseAmbientLightMotion3ds(&amlite); ON_ERROR_RETURN; // KEYFRAMER ANIMATION DATA InitKfSets3ds(&kfsets); ON_ERROR_RETURN; kfsets->anim.length = 60; kfsets->anim.curframe = 0; kfsets->seg.use = False3ds; PutKfSets3ds(db, kfsets); ON_ERROR_RETURN; ReleaseKfSets3ds(&kfsets); ON_ERROR_RETURN; // Viewport setup InitViewport3ds(&view); ON_ERROR_RETURN; view->type = CameraView3ds; strcpy(view->camera.name, "Camera1"); PutViewport3ds(db, view); ReleaseViewport3ds(&view); } */ WriteDatabase3ds(file, db); CloseFile3ds(file); ReleaseDatabase3ds(&db); }