UVIS.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File: uvis.cpp
  6.  *
  7.  ***************************************************************************/
  8. #include <math.h>
  9. #include <stdlib.h>
  10. #include <d3d.h>
  11. #include "d3dmacs.h"
  12. #include "rmdemo.h"
  13. typedef struct _Flame {
  14.     int valid;
  15.     D3DVECTOR velocity; /* direction the flame is going */
  16.     D3DVECTOR orientation; /* random vector normal to velocity */
  17.     D3DVECTOR position; /* current position */
  18.     int time; /* current time */
  19.     int lifetime; /* time to die */
  20. } Flame;
  21. /*
  22.  * A flame is a diamond shape oriented along its direction vector.
  23.  * This updates the four vertices of the flame, given its current time.
  24.  */
  25. void UpdateFlame(Flame* flame, D3DVERTEX v[])
  26. {
  27.     D3DVECTOR dir = flame->velocity;
  28.     D3DVECTOR off = flame->orientation;
  29.     D3DVECTOR norm;
  30.     D3DVECTOR start, end, left, right;
  31.     double size;
  32.     int i;
  33.     D3DRMVectorNormalise(&dir);
  34.     /*
  35.      * Calculate a normal vector to the flame
  36.      */
  37.     D3DRMVectorCrossProduct(&norm, &dir, &off);
  38.     D3DRMVectorNormalise(&norm);
  39.     /*
  40.      * The size starts off small, gets bigger towards the middle
  41.      * and smaller towards the end.
  42.      */
  43.     if (flame->time < flame->lifetime / 2)
  44. size = (double) flame->time / (double)(flame->lifetime / 2);
  45.     else
  46. size = ((double) (flame->lifetime - flame->time)
  47. / (double)(flame->lifetime / 2));
  48.     /*
  49.      * Calculate the four corners of the diamond.
  50.      */
  51.     D3DRMVectorScale(&dir, &dir, D3DVAL(size));
  52.     D3DRMVectorScale(&off, &off, D3DVAL(size / 4));
  53.     start = flame->position;
  54.     D3DRMVectorAdd(&end, &start, &dir);
  55.     D3DRMVectorScale(&dir, &dir, D3DVAL(0.5));
  56.     D3DRMVectorAdd(&left, &start, &dir);
  57.     right = left;
  58.     D3DRMVectorAdd(&left, &left, &off);
  59.     D3DRMVectorSubtract(&right, &right, &off);
  60.     /*
  61.      * Update the flame's position.
  62.      */
  63.     D3DRMVectorAdd(&flame->position, &flame->position, &flame->velocity);
  64.     flame->time++;
  65.     if (flame->time == flame->lifetime)
  66. flame->valid = 0;
  67.     /*
  68.      * And fill in the vertices.  There are eight, four for each side of
  69.      * the flame.
  70.      */
  71.     i = 0;
  72.     v[i].x = start.x; v[i].y = start.y; v[i].z = start.z;
  73.     v[i].nx = -norm.x; v[i].ny = -norm.y; v[i].nz = -norm.z;
  74.     v[i].tu = D3DVAL(0); v[i].tv = D3DVAL(0);
  75.     i++;
  76.     v[i].x = left.x; v[i].y = left.y; v[i].z = left.z;
  77.     v[i].nx = -norm.x; v[i].ny = -norm.y; v[i].nz = -norm.z;
  78.     v[i].tu = D3DVAL(1); v[i].tv = D3DVAL(0);
  79.     i++;
  80.     v[i].x = end.x; v[i].y = end.y; v[i].z = end.z;
  81.     v[i].nx = -norm.x; v[i].ny = -norm.y; v[i].nz = -norm.z;
  82.     v[i].tu = D3DVAL(1); v[i].tv = D3DVAL(1);
  83.     i++;
  84.     v[i].x = right.x; v[i].y = right.y; v[i].z = right.z;
  85.     v[i].nx = -norm.x; v[i].ny = -norm.y; v[i].nz = -norm.z;
  86.     v[i].tu = D3DVAL(0); v[i].tv = D3DVAL(1);
  87.     i++;
  88.     v[i].x = start.x; v[i].y = start.y; v[i].z = start.z;
  89.     v[i].nx = norm.x; v[i].ny = norm.y; v[i].nz = norm.z;
  90.     v[i].tu = D3DVAL(0); v[i].tv = D3DVAL(0);
  91.     i++;
  92.     v[i].x = right.x; v[i].y = right.y; v[i].z = right.z;
  93.     v[i].nx = norm.x; v[i].ny = norm.y; v[i].nz = norm.z;
  94.     v[i].tu = D3DVAL(0); v[i].tv = D3DVAL(1);
  95.     i++;
  96.     v[i].x = end.x; v[i].y = end.y; v[i].z = end.z;
  97.     v[i].nx = norm.x; v[i].ny = norm.y; v[i].nz = norm.z;
  98.     v[i].tu = D3DVAL(1); v[i].tv = D3DVAL(1);
  99.     i++;
  100.     v[i].x = left.x; v[i].y = left.y; v[i].z = left.z;
  101.     v[i].nx = norm.x; v[i].ny = norm.y; v[i].nz = norm.z;
  102.     v[i].tu = D3DVAL(1); v[i].tv = D3DVAL(0);
  103.     i++;
  104. }
  105. void InitFlame(Flame* flame)
  106. {
  107.     D3DVECTOR d, u;
  108.     flame->valid = TRUE;
  109.     do {
  110.       D3DRMVectorRandom(&d);
  111.       d.y = d.y * d.y;
  112.       d.y = d.y * d.y;
  113.     } while (d.y < D3DVAL(0.3));
  114.     /*
  115.      * Pick a vector normal to d
  116.      */
  117.     if (d.y != D3DVAL(0.0) || d.z != D3DVAL(0.0))
  118.     {
  119. u.x = D3DVAL(0.0);
  120. if (d.y == D3DVAL(0.0))
  121. {
  122.     u.y = D3DVAL(1.0);
  123.     u.z = D3DVAL(0.0);
  124. } else {
  125.     D3DVALUE n_fix =
  126. D3DVAL(1.0)
  127. + D3DDivide(D3DMultiply(d.z, d.z), D3DMultiply(d.y, d.y));
  128.     u.z = D3DVAL(sqrt(D3DDivide(D3DVAL(1.0), D3DVAL(n_fix))));
  129.     u.y = -D3DMultiply(u.z, D3DDivide(d.z, d.y));
  130. }
  131.     } else {
  132. u.x = D3DVAL(0.0);
  133. u.y = D3DVAL(0.0);
  134. u.z = D3DVAL(1.0);
  135.     }
  136.     /*
  137.      * Randomize it.
  138.      */
  139.     D3DRMVectorRotate(&u, &u, &d, D3DDivide(D3DVAL(6.28 * (rand() % 100)),
  140.          D3DVAL(100.0)));
  141.     D3DRMVectorScale(&d, &d, D3DVAL(0.1));
  142.     flame->velocity = d;
  143.     flame->orientation = u;
  144.     flame->position.x = D3DVAL(0);
  145.     flame->position.y = D3DVAL(0);
  146.     flame->position.z = D3DVAL(0);
  147.     flame->time = 0;
  148.     do {
  149. flame->lifetime = rand() % 30;
  150.     } while (flame->lifetime < 5);
  151. }
  152. #define MAX_FLAMES 100
  153. typedef struct _Fire {
  154.     Flame flames[MAX_FLAMES];
  155.     LPDIRECT3DRMDEVICE dev;
  156.     LPDIRECT3DEXECUTEBUFFER eb;
  157.     LPDIRECT3DMATERIAL mat;
  158. } Fire;
  159. void CDECL CleanupFireObjects(LPDIRECT3DRMOBJECT dev, void* arg)
  160. {
  161.     Fire* fire = (Fire*) arg;
  162.     if (fire->eb) {
  163. fire->eb->Release();
  164. fire->mat->Release();
  165. fire->eb = NULL;
  166. fire->dev = NULL;
  167.     }
  168. }
  169. typedef struct _FireExecuteBuffer {
  170.     D3DVERTEX v[8 * MAX_FLAMES];
  171.     D3DINSTRUCTION op_state_light1;
  172.     D3DSTATE state1;
  173.     D3DINSTRUCTION op_set_status;
  174.     D3DSTATUS setstatus1;
  175.     D3DINSTRUCTION op_process_vertices1;
  176.     D3DPROCESSVERTICES processvertices1;
  177.     D3DINSTRUCTION op_state_render;
  178.     D3DSTATE state2;
  179.     D3DSTATE state3;
  180.     D3DSTATE state4;
  181.     D3DINSTRUCTION op_triangle_list;
  182.     D3DTRIANGLE tri[4 * MAX_FLAMES];
  183.     D3DINSTRUCTION exit1;
  184. } FireExecuteBuffer;
  185. BOOL CreateFireObjects(Fire* fire, LPDIRECT3DRMDEVICE dev)
  186. {
  187.     D3DEXECUTEBUFFERDESC desc;
  188.     D3DEXECUTEDATA data;
  189.     LPDIRECT3D lpD3D = NULL;
  190.     LPDIRECT3DDEVICE lpD3DDev = NULL;
  191.     LPDIRECT3DMATERIAL mat = NULL;
  192.     LPDIRECT3DEXECUTEBUFFER eb = NULL;
  193.     D3DMATERIALHANDLE hMat;
  194.     D3DMATERIAL orange;
  195.     void* p;
  196.     int i;
  197.     RELEASE(fire->eb);
  198.     dev->GetDirect3DDevice(&lpD3DDev);
  199.     if (!lpD3DDev)
  200. goto generic_error;
  201.     if (FAILED(lpD3DDev->GetDirect3D(&lpD3D)))
  202. goto generic_error;
  203.     desc.dwSize = sizeof(desc);
  204.     desc.dwFlags = D3DDEB_BUFSIZE;
  205.     desc.dwBufferSize = sizeof(FireExecuteBuffer);
  206.     
  207.     if (FAILED(lpD3DDev->CreateExecuteBuffer(&desc, &eb, NULL)))
  208. goto generic_error;
  209.     if (FAILED(lpD3D->CreateMaterial(&mat, NULL)))
  210. goto generic_error;
  211.     if (FAILED(mat->GetHandle(lpD3DDev, &hMat)))
  212. goto generic_error;
  213.     memset(&orange, 0, sizeof(orange));
  214.     orange.dwSize = sizeof(orange);
  215.     orange.diffuse.r = D3DVAL(1.0);
  216.     orange.diffuse.g = D3DVAL(0.5);
  217.     orange.diffuse.b = D3DVAL(0.0);
  218.     orange.ambient.r = D3DVAL(1.0);
  219.     orange.ambient.g = D3DVAL(0.5);
  220.     orange.ambient.b = D3DVAL(0.0);
  221.     orange.dwRampSize = 32;
  222.     if (FAILED(mat->SetMaterial(&orange)))
  223. goto generic_error;
  224.     if (FAILED(eb->Lock(&desc)))
  225. goto generic_error;
  226.     p = (void*) ((char*) desc.lpData + 8 * MAX_FLAMES * sizeof(D3DVERTEX));
  227.     OP_STATE_LIGHT(1, p);
  228. STATE_DATA(D3DLIGHTSTATE_MATERIAL, hMat, p);
  229.     OP_SET_STATUS(D3DSETSTATUS_ALL, D3DSTATUS_DEFAULT, 2048, 2048, 0, 0, p);
  230.     
  231.     OP_PROCESS_VERTICES(1, p);
  232. PROCESSVERTICES_DATA(D3DPROCESSVERTICES_TRANSFORMLIGHT,
  233.  0, 8 * MAX_FLAMES, p);
  234.     OP_STATE_RENDER(3, p);
  235. STATE_DATA(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT, p);
  236. STATE_DATA(D3DRENDERSTATE_TEXTUREHANDLE, 0, p);
  237. STATE_DATA(D3DRENDERSTATE_BLENDENABLE, FALSE, p);
  238.     OP_TRIANGLE_LIST(4 * MAX_FLAMES, p);
  239.     for (i = 0; i < MAX_FLAMES; i++) {
  240. D3DTRIANGLE* t;
  241. int base;
  242. t = (D3DTRIANGLE*) p;
  243. base = 4 * i;
  244. t->v1 = base + 0;
  245. t->v2 = base + 1;
  246. t->v3 = base + 3;
  247. t->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
  248. t++;
  249. t->v1 = base + 1;
  250. t->v2 = base + 2;
  251. t->v3 = base + 3;
  252. t->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
  253. t++;
  254. t->v1 = base + 0;
  255. t->v2 = base + 1;
  256. t->v3 = base + 3;
  257. t->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
  258. t++;
  259. t->v1 = base + 1;
  260. t->v2 = base + 2;
  261. t->v3 = base + 3;
  262. t->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
  263. t++;
  264. p = (char*) t;
  265.     }
  266.     OP_EXIT(p);
  267.     if (FAILED(eb->Unlock()))
  268. goto generic_error;
  269.     data.dwSize = sizeof(data);
  270.     data.dwVertexOffset = 0;
  271.     data.dwVertexCount = 8 * MAX_FLAMES;
  272.     data.dwInstructionOffset = 8 * MAX_FLAMES * sizeof(D3DVERTEX);
  273.     data.dwInstructionLength = sizeof(FireExecuteBuffer) - data.dwInstructionOffset;
  274.     data.dwHVertexOffset = 0;
  275.     if (FAILED(eb->SetExecuteData(&data)))
  276. goto generic_error;
  277.     fire->eb = eb;
  278.     fire->mat = mat;
  279.     fire->dev = dev;
  280.     if (FAILED(dev->AddDestroyCallback(CleanupFireObjects, fire)))
  281. goto generic_error;
  282.     RELEASE(lpD3DDev);
  283.     RELEASE(lpD3D);
  284.     return TRUE;
  285. generic_error:
  286.     RELEASE(lpD3D);
  287.     RELEASE(lpD3DDev);
  288.     RELEASE(mat);
  289.     RELEASE(eb);
  290.     return FALSE;
  291. }
  292. BOOL RenderFire(Fire* fire, LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMVIEWPORT view)
  293. {
  294.     D3DVERTEX* v;
  295.     D3DEXECUTEBUFFERDESC desc;
  296.     D3DEXECUTEDATA data;
  297.     LPDIRECT3DDEVICE lpD3DDev = NULL;
  298.     LPDIRECT3DVIEWPORT lpD3DView = NULL;
  299.     int i;
  300.     if (fire->dev != dev) {
  301. if (!CreateFireObjects(fire, dev))
  302.     return FALSE;
  303.     }
  304.     dev->GetDirect3DDevice(&lpD3DDev);
  305.     view->GetDirect3DViewport(&lpD3DView);
  306.     if (!lpD3DDev || !lpD3DView)
  307. goto ret_with_error;
  308.     for (i = 0; i < MAX_FLAMES; i++)
  309. if (!fire->flames[i].valid)
  310.     InitFlame(&fire->flames[i]);
  311.     desc.dwSize = sizeof(desc);
  312.     desc.dwFlags = 0;
  313.     
  314.     if (FAILED(fire->eb->Lock(&desc)))
  315. goto ret_with_error;
  316.     v = (D3DVERTEX*) desc.lpData;
  317.     for (i = 0; i < MAX_FLAMES; i++)
  318. UpdateFlame(&fire->flames[i], &v[8 * i]);
  319.     if (FAILED(fire->eb->Unlock()))
  320. goto ret_with_error;
  321.     if (FAILED(lpD3DDev->Execute(fire->eb, lpD3DView, D3DEXECUTE_CLIPPED)))
  322. goto ret_with_error;
  323.     data.dwSize = sizeof data;
  324.     if (FAILED(fire->eb->GetExecuteData(&data)))
  325. goto ret_with_error;
  326.     if (FAILED(view->ForceUpdate(data.dsStatus.drExtent.x1,
  327.       data.dsStatus.drExtent.y1,
  328.       data.dsStatus.drExtent.x2,
  329.       data.dsStatus.drExtent.y2)))
  330.       goto ret_with_error;
  331.     RELEASE(lpD3DDev);
  332.     RELEASE(lpD3DView);
  333.     return TRUE;
  334. ret_with_error:
  335.     RELEASE(lpD3DDev);
  336.     RELEASE(lpD3DView);
  337.     return FALSE;
  338. }
  339. int CDECL FireCallback(LPDIRECT3DRMUSERVISUAL uvis,
  340.  void* arg,
  341.  D3DRMUSERVISUALREASON reason,
  342.  LPDIRECT3DRMDEVICE dev,
  343.  LPDIRECT3DRMVIEWPORT view)
  344. {
  345.     Fire* fire = (Fire*) arg;
  346.     if (reason == D3DRMUSERVISUAL_CANSEE)
  347. return TRUE;
  348.     if (reason == D3DRMUSERVISUAL_RENDER) {
  349. if (!RenderFire(fire, dev, view))
  350.     return DDERR_GENERIC;
  351. else
  352.     return D3D_OK;
  353.     }
  354.     return 0;
  355. }
  356. void CDECL DestroyFire(LPDIRECT3DRMOBJECT obj, void* arg)
  357. {
  358.     Fire* fire = (Fire*) arg;
  359.     if (fire->dev)
  360. fire->dev->DeleteDestroyCallback(CleanupFireObjects, arg);
  361.     CleanupFireObjects((LPDIRECT3DRMOBJECT)fire->dev, (void*) fire);
  362.     free(fire);
  363. }
  364. LPDIRECT3DRMUSERVISUAL CreateFire()
  365. {
  366.     Fire* fire;
  367.     LPDIRECT3DRMUSERVISUAL uvis = NULL;
  368.     fire = (Fire*)malloc(sizeof(Fire));
  369.     if (!fire)
  370. goto ret_with_error;
  371.     memset(fire, 0, sizeof(Fire));
  372.     if (FAILED(lpD3DRM->CreateUserVisual(FireCallback, (void*) fire, &uvis)))
  373. goto ret_with_error;
  374.     if (FAILED(uvis->AddDestroyCallback(DestroyFire, (void*) fire)))
  375. goto ret_with_error;   
  376.     return uvis;
  377. ret_with_error:
  378.     if (fire)
  379. free(fire);
  380.     RELEASE(uvis);
  381.     return NULL;
  382. }
  383. BOOL
  384. BuildScene(LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMVIEWPORT view,
  385.    LPDIRECT3DRMFRAME scene, LPDIRECT3DRMFRAME camera)
  386. {
  387.     D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
  388.     LPDIRECT3DRMFRAME lights = NULL;
  389.     LPDIRECT3DRMFRAME frame = NULL;
  390.     LPDIRECT3DRMLIGHT light1 = NULL;
  391.     LPDIRECT3DRMLIGHT light2 = NULL;
  392.     LPDIRECT3DRMUSERVISUAL uvis = NULL;
  393.     view = view; /* not used */
  394.     if (FAILED(dev->SetQuality(quality)))
  395. goto generic_error;
  396.     /*
  397.      * initialize the lights in the scene
  398.      */
  399.     if (FAILED(lpD3DRM->CreateFrame(scene, &lights)))
  400. goto generic_error;
  401.     if (FAILED(lights->SetPosition(scene, D3DVAL(5), D3DVAL(5), -D3DVAL(1))))
  402. goto generic_error;
  403.     if(FAILED(lights->SetOrientation(scene, D3DVAL(0), D3DVAL(0), D3DVAL(1),
  404.    D3DVAL(0), D3DVAL(1), D3DVAL(1))))
  405.    goto generic_error;
  406.     if(FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, D3DVAL(0.9),
  407.   D3DVAL(0.8), D3DVAL(0.7), &light1)))
  408.   goto generic_error;
  409.     if (FAILED(lights->AddLight(light1)))
  410. goto generic_error;
  411.     if(FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVAL(0.1),
  412.   D3DVAL(0.1), D3DVAL(0.1), &light2)))
  413.   goto generic_error;
  414.     if (FAILED(scene->AddLight(light2)))
  415. goto generic_error;
  416.     /*
  417.      * create a frame within the scene
  418.      */
  419.     if (FAILED(lpD3DRM->CreateFrame(scene, &frame)))
  420. goto generic_error;
  421.     /*
  422.      * add the fire into the frame
  423.      */
  424.     uvis = CreateFire();
  425.     if (!uvis)
  426. goto generic_error;
  427.     if (FAILED(frame->AddVisual(uvis)))
  428. goto generic_error;
  429.     /*
  430.      * set up the frames position, orientation and rotation
  431.      */
  432.     if (FAILED(camera->SetPosition(scene, D3DVAL(0), D3DVAL(0.5), -D3DVAL(10))))
  433. goto generic_error;
  434.     if(FAILED(camera->SetOrientation(scene, D3DVAL(0), D3DVAL(0), D3DVAL(1), D3DVAL(0),
  435.    D3DVAL(1), D3DVAL(0))))
  436.    goto generic_error;
  437.     if(FAILED(frame->SetRotation(scene, D3DVAL(0), D3DVAL(1), D3DVAL(0),
  438.        D3DVAL(0.02))))
  439.        goto generic_error;
  440.     RELEASE(uvis);
  441.     RELEASE(frame);
  442.     RELEASE(lights);
  443.     RELEASE(light1);
  444.     RELEASE(light2);
  445.     return TRUE;
  446. generic_error:
  447.     Msg("A failure occurred while building the scene.n");
  448.     RELEASE(lights);
  449.     RELEASE(frame);
  450.     RELEASE(light1);
  451.     RELEASE(light2);
  452.     RELEASE(uvis);
  453.     return FALSE;
  454. }
  455. void
  456. OverrideDefaults(Defaults *defaults)
  457. {
  458.     defaults->bConstRenderQuality = TRUE;
  459.     defaults->bNoTextures = TRUE;
  460.     lstrcpy(defaults->Name, "User Visual Direct3DRM Example");
  461. }