DACTL.CPP

#include "dactl.h" 

void dump_com_error( _com_error &e )
{
char buf[2048];

sprintf(buf, _T( "Oops - hit an error!\n\tCode = %08lx\n\tCode meaning = %s\n" ),
e.Error(), e.ErrorMessage());
OutputDebugString(buf);
}

// If this is placed in the scope of the smart pointers, they must be
// explicitly Release(d) before CoUninitialize() is called. If any reference
// count is non-zero, a protection fault will occur.

CDAViewerCtl::CDAViewerCtl()
:_vc(NULL)
{
try {
_vc.CreateInstance(__uuidof(DAViewerControlWindowed));
} catch( _com_error &e ) {
dump_com_error( e );
}
}

void CDAViewerCtl::CreateModel() {
try {
// Create the statics object
IDAStaticsPtr e;
e = _vc->GetMeterLibrary();

// Import Media (geometries, images and in this case).
// The GetCurrentDirectory() is used as a starting
// point for relative file importing.
TCHAR szMediaBase[_MAX_PATH];
TCHAR szImg[_MAX_PATH];
TCHAR szGeo[_MAX_PATH];
TCHAR szSnd[_MAX_PATH];

GetModuleFileName(GetModuleHandle("Pick3Cntrl.exe"),
szMediaBase,sizeof(szMediaBase));
char *pos = strrchr( szMediaBase, (int)'\\' );
int result = pos - szMediaBase + 1;
szMediaBase[result]= NULL;

_tcscat(szMediaBase,_T("../../../../../media/"));

_tcscpy(szImg,szMediaBase);
_tcscpy(szGeo,szMediaBase);
_tcscpy(szSnd,szMediaBase);

_tcscat(szImg,_T("image/"));
_tcscat(szGeo,_T("geometry/"));
_tcscat(szSnd,_T("sound/"));

// Define constants
SIZE = e->Scale3Uniform(0.25);
PICKEVENTL = e->LeftButtonDown;
PICKEVENTR = e->RightButtonDown;
SPEED = e->DANumber(0.07);
PI = 3.14159265359;

// import background.
IDAImagePtr stillSky = e->ImportImage(_bstr_t(szImg) + _bstr_t("cldtile.jpg"));

IDAPoint2Ptr maxSky = stillSky->BoundingBox->Max;
IDAImagePtr tiledSky = stillSky->Tile();
IDAImagePtr movingSky = tiledSky->Transform(e->Translate2Anim(e->Mul(e->LocalTime,
e->Div(maxSky->X,e->DANumber(8))), e->Mul(e->LocalTime,e->Div(maxSky->X,e->DANumber(16)))));

// Import the geometries.
IDAGeometryPtr rawCube =
e->ImportGeometry( _bstr_t(szGeo) + _bstr_t( "cube.x" ) );
rawCube = rawCube->Transform(SIZE);

IDAGeometryPtr rawCylinder =
e->ImportGeometry(_bstr_t(szGeo) + _bstr_t("cylinder.x"));
rawCylinder = rawCylinder->Transform(SIZE);

IDAGeometryPtr rawCone =
e->ImportGeometry(_bstr_t(szGeo) + _bstr_t("cone.x"));
rawCone = rawCone->Transform(SIZE);

// Make the geometries pickable.
IDAGeometryPtr cone1 = activate(rawCone, e->Green, e);

IDAGeometryPtr cube1 = activate(rawCube, e->Magenta, e);

IDAGeometryPtr cube2 = activate(rawCube, e->ColorHslAnim(e->Div(e->LocalTime,
e->DANumber(8)), e->DANumber(1), e->DANumber(0.5)), e);

IDAGeometryPtr cylinder = activate(rawCylinder, e->ColorRgb(0.8,0.4,0.4), e);

// Construct the final geometry, scale and rotate it.
IDAGeometryPtr multigeo = e->UnionGeometry(cone1->Transform(e->Translate3(0,1,0)),
e->UnionGeometry(cube1->Transform(e->Translate3(0,0,1)),
e->UnionGeometry(cube2->Transform(e->Translate3(0,0,-1)),cylinder)));

IDAGeometryPtr geo = multigeo->Transform(e->Scale3Anim(e->Add(e->Abs(e->Sin(e->Mul(e->LocalTime,
e->DANumber(0.2)))),e->DANumber(0.5)),e->Add(e->Abs(e->Sin(e->Mul(e->LocalTime,
e->DANumber(0.26)))),e->DANumber(0.5)),e->Add(e->Abs(e->Sin(e->Mul(e->LocalTime,
e->DANumber(0.14)))),e->DANumber(0.5))));

IDATransform3Ptr transform1 = e->Rotate3Anim(e->ZVector3,
e->Mul(e->DANumber(0.07), e->Mul(e->LocalTime, e->DANumber(1.9))));

IDATransform3Ptr transform2 = e->Rotate3Anim(e->YVector3,
e->Mul(e->DANumber(0.07), e->Mul(e->LocalTime, e->DANumber(PI))));

IDAImagePtr movingGeoImg = geometryImage(geo->Transform(e->Compose3(e->Rotate3Anim(e->ZVector3,
e->Mul(e->DANumber(0.07),e->Mul(e->LocalTime,e->DANumber(1.9)))), e->Rotate3Anim(e->YVector3,
e->Mul(e->DANumber(0.07),e->Mul(e->LocalTime,e->DANumber(PI)))))), e);

IDAFontStylePtr fs = e->DefaultFont->Color(e->Black);
IDAImagePtr titleIm = e->StringImage("Left Click On An Object",
fs)->Transform(e->Translate2(0,0.03));

IDAImagePtr model = e->Overlay( titleIm, e->Overlay( movingGeoImg, movingSky ) );

// And set the model's image to this image.
_vc->PutImage( model );

// Set the cap for the frame rate. If we don't do this, DA
// will hog the cpu and the mouse and keyboard won't be very
// responsive. If you're running in full screen mode, you may
// want to remove this line to get better frame rate.
_vc->put_UpdateInterval(0.2);

// Start the model on the view. The WndProc will
// generate the frames.
_vc->Start();

} catch( _com_error &e ) {
dump_com_error( e );
}
}

IDAGeometryPtr CDAViewerCtl::activate(IDAGeometryPtr unpickedGeo,
IDAColorPtr col, IDAStaticsPtr e) {
IDAPickableResultPtr pickGeo = unpickedGeo->Pickable();
IDAEventPtr pickEvent = e->AndEvent(PICKEVENTL, pickGeo->PickEvent);

IDANumberPtr numcyc;
numcyc.CreateInstance( L"DirectAnimation.DANumber");
numcyc->Init(e->Until(e->DANumber(0),pickEvent,
e->Until(e->DANumber(1), pickEvent, numcyc)));

IDAColorPtr colcyc;
colcyc.CreateInstance( L"DirectAnimation.DAColor");
colcyc->Init(e->Until(e->White, pickEvent, e->Until(col, pickEvent, colcyc)));

IDATransform3Ptr xf = e->Rotate3Anim(e->XVector3, e->Integral(numcyc));

return pickGeo->Geometry->DiffuseColor(colcyc)->Transform(xf);

}

IDAImagePtr CDAViewerCtl::geometryImage(IDAGeometryPtr geo, IDAStaticsPtr e) {
IDANumberPtr scaleFactor = e->DANumber(0.02);

IDATransform3Ptr perspTransform;
perspTransform.CreateInstance( L"DirectAnimation.DATransform3");
perspTransform->Init(e->Until(e->Compose3(e->Rotate3Anim(e->XVector3,
e->Mul(SPEED,e->LocalTime)),e->Translate3(0, 0, 0.2)),PICKEVENTR,
e->Until(e->Rotate3Anim(e->XVector3, e->Mul(SPEED,e->LocalTime)),
PICKEVENTR, perspTransform)));

IDAGeometryPtr myLight =
e->UnionGeometry(e->DirectionalLight->Transform(perspTransform), e->DirectionalLight);

IDACameraPtr perspectiveCam = (e->PerspectiveCamera(1,0))->Transform(e->Compose3(e->Rotate3Anim(e->XVector3,
e->Mul(SPEED,e->LocalTime)),e->Translate3(0,0,0.2)));

IDACameraPtr parallelCam = (e->ParallelCamera(1))->Transform(e->Rotate3Anim(e->XVector3,
e->Mul(SPEED,e->LocalTime)));

IDACameraPtr camera;
camera.CreateInstance( L"DirectAnimation.DACamera");
camera->Init(e->Until(perspectiveCam, PICKEVENTR,
e->Until(parallelCam, PICKEVENTR, camera)));

// Display text which tells the user what camera is currently being used.
IDAStringPtr camText;
camText.CreateInstance( L"DirectAnimation.DAString");
camText->Init(e->Until(e->DAString("Perspective - Right Click to Switch"), PICKEVENTR,
e->Until(e->DAString("Parallel - Right Click to Switch"),PICKEVENTR, camText)));

IDAFontStylePtr fs = e->DefaultFont->Color(e->Red);
IDAImagePtr camIm = e->StringImageAnim(camText, fs);
camIm = camIm->Transform(e->Translate2(0, -0.03));

return e->Overlay(camIm, e->UnionGeometry(geo->Transform(e->Scale3UniformAnim(scaleFactor)),
myLight)->Render(camera));
}

HRESULT CDAViewerCtl::GetIUnknown(IUnknown **pUnk) {
if (!pUnk)
return E_POINTER;

if (_vc == NULL)
return E_NOINTERFACE;

return _vc->QueryInterface(IID_IUnknown, (LPVOID *)pUnk);
}