mirror of
https://github.com/OpenTrespasser/JurassicParkTrespasser.git
synced 2024-12-20 07:31:56 +00:00
1141 lines
27 KiB
C++
1141 lines
27 KiB
C++
|
/**********************************************************************************************
|
|||
|
*
|
|||
|
* Copyright <EFBFBD> DreamWorks Interactive. 1996
|
|||
|
*
|
|||
|
* Shell to test wave modeling.
|
|||
|
*
|
|||
|
* Bugs:
|
|||
|
* Sometimes, when drawing the wave with multiple mouse drags, the timer is not paused
|
|||
|
* for the whole sequence, and the step value for the next render is large.
|
|||
|
*
|
|||
|
* To do:
|
|||
|
*
|
|||
|
**********************************************************************************************
|
|||
|
*
|
|||
|
* $Log:: /JP2_PC/Source/Test/Physics/WaveTest.cpp $
|
|||
|
*
|
|||
|
* 18 97/10/02 12:09 Speter
|
|||
|
* Added boundary condition parameter back into CSimWater2D.
|
|||
|
*
|
|||
|
* 17 97-05-06 17:16 Speter
|
|||
|
* Resurrected wavetest, updating for changes in lib.
|
|||
|
*
|
|||
|
* 16 96/12/31 17:08 Speter
|
|||
|
* Updated for rptr.
|
|||
|
*
|
|||
|
* 15 96/11/14 17:06 Speter
|
|||
|
* Updated for change in mr_gravity parameter.
|
|||
|
*
|
|||
|
* 14 96/11/11 19:15 Speter
|
|||
|
* Added flags to enable greyscale rendering.
|
|||
|
*
|
|||
|
* 13 96/11/08 18:32 Speter
|
|||
|
* Added menus to the app.
|
|||
|
* Added a random depth-generation function.
|
|||
|
* Converted separate mouse coords to CVector2<>'s.
|
|||
|
*
|
|||
|
* 12 96/11/05 20:47 Speter
|
|||
|
* Added depth dependence to 2D sim, with interface.
|
|||
|
*
|
|||
|
* 11 96/11/05 16:45 Speter
|
|||
|
* Added interface for setting wave height in 2D sim.
|
|||
|
* Now use CAppShell::bKeyState() to keep track of mouse buttons.
|
|||
|
*
|
|||
|
* 10 96/11/04 16:59 Speter
|
|||
|
* Put variable-velocity sims back in, with real-time integrator. Added Iterate and
|
|||
|
* ApplyBoundary virtual functions.
|
|||
|
* Changed TMeasure from double to float.
|
|||
|
*
|
|||
|
*
|
|||
|
* 9 96/11/01 17:40 Speter
|
|||
|
* Made LineDraw class round to integer screen coords: fixed problem of apparently not damping.
|
|||
|
* Commented out water version until it gets restored in Waves.cpp.
|
|||
|
* Minor changes to timings and initial wave values.
|
|||
|
*
|
|||
|
* 8 96/10/31 18:26 Speter
|
|||
|
* Added driver for 2D wave sim.
|
|||
|
*
|
|||
|
*
|
|||
|
* 6 96/10/28 14:49 Speter
|
|||
|
* Added capability for varying velocity.
|
|||
|
* Added capability and interface for varying water depth.
|
|||
|
*
|
|||
|
* 5 96/10/25 14:40 Speter
|
|||
|
* Corrected damping parameter in equations, added more parameters.
|
|||
|
* Fixed mouse wave drawing for the most part.
|
|||
|
*
|
|||
|
* 4 96/10/18 19:02 Speter
|
|||
|
* Now use vpMain to scale coordinates to screen.
|
|||
|
*
|
|||
|
* 3 96/10/15 20:04 Speter
|
|||
|
* Now we have gravity and damping.
|
|||
|
*
|
|||
|
* 2 96/10/15 18:18 Speter
|
|||
|
* First working version. Actually models 1-d waves with rigid endpoints!
|
|||
|
*
|
|||
|
**********************************************************************************************/
|
|||
|
|
|||
|
#include "Common.hpp"
|
|||
|
#include "Lib/W95/WinInclude.hpp"
|
|||
|
#include "Shell/AppShell.hpp"
|
|||
|
#include "Shell/WinRenderTools.hpp"
|
|||
|
#include "Lib/Transform/Vector.hpp"
|
|||
|
#include "Lib/Physics/Waves.hpp"
|
|||
|
#include "Lib/Math/FastTrig.hpp"
|
|||
|
#include "Lib/View/Viewport.hpp"
|
|||
|
#include "Lib/Std/Random.hpp"
|
|||
|
#include "Lib/Sys/Timer.hpp"
|
|||
|
#include "Lib/Sys/Textout.hpp"
|
|||
|
|
|||
|
static const float fSQRT2 = sqrt(2.0);
|
|||
|
static const float fINV_SQRT2 = sqrt(0.5);
|
|||
|
|
|||
|
class CLineDraw
|
|||
|
{
|
|||
|
private:
|
|||
|
// Storage for the old pen object.
|
|||
|
HPEN hpenOld;
|
|||
|
|
|||
|
// Screen Device context.
|
|||
|
rptr<CRasterWin> praswWin;
|
|||
|
CViewport* pvpScr;
|
|||
|
HDC hdcScreen;
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
// Constructor.
|
|||
|
//
|
|||
|
|
|||
|
CLineDraw(rptr<CRasterWin> prasw, CViewport* pvp)
|
|||
|
{
|
|||
|
// Get the device contect for the raster.
|
|||
|
praswWin = prasw;
|
|||
|
pvpScr = pvp;
|
|||
|
prasw->Unlock();
|
|||
|
hdcScreen = prasw->hdcGet();
|
|||
|
|
|||
|
hpenOld = 0;
|
|||
|
|
|||
|
// Create the new pen object and set its colour to white.
|
|||
|
LineColour(CColour(255, 255, 255));
|
|||
|
}
|
|||
|
|
|||
|
~CLineDraw()
|
|||
|
{
|
|||
|
// Delete the old pen object.
|
|||
|
if (hpenOld)
|
|||
|
{
|
|||
|
hpenOld = (HPEN)SelectObject(hdcScreen, hpenOld);
|
|||
|
DeleteObject(hpenOld);
|
|||
|
}
|
|||
|
|
|||
|
// Restore the device context for the raster.
|
|||
|
praswWin->ReleaseDC(hdcScreen);
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
// Member functions.
|
|||
|
//
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
void LineColour(CColour clr)
|
|||
|
{
|
|||
|
Assert(hdcScreen)
|
|||
|
|
|||
|
// Delete the old pen.
|
|||
|
if (hpenOld)
|
|||
|
{
|
|||
|
hpenOld = (HPEN)SelectObject(hdcScreen, GetStockObject(WHITE_PEN));
|
|||
|
if (hpenOld)
|
|||
|
{
|
|||
|
DeleteObject(hpenOld);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Create the new pen with the requested colour.
|
|||
|
HPEN hpen_new = CreatePen(PS_SOLID, 1, clr.clrReverseRGB());
|
|||
|
hpenOld = (HPEN)SelectObject(hdcScreen, hpen_new);
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
void MoveTo(float f_x, float f_y)
|
|||
|
{
|
|||
|
Assert(hdcScreen)
|
|||
|
|
|||
|
// Draw the line.
|
|||
|
::MoveToEx
|
|||
|
(
|
|||
|
hdcScreen,
|
|||
|
pvpScr->scScreenX(f_x) + 0.5,
|
|||
|
pvpScr->scScreenY(f_y) + 0.5,
|
|||
|
0
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
void LineTo(float f_x, float f_y)
|
|||
|
{
|
|||
|
Assert(hdcScreen)
|
|||
|
|
|||
|
::LineTo
|
|||
|
(
|
|||
|
hdcScreen,
|
|||
|
pvpScr->scScreenX(f_x) + 0.5,
|
|||
|
pvpScr->scScreenY(f_y) + 0.5
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
void Line(float f_x0, float f_y0, float f_x1, float f_y1)
|
|||
|
{
|
|||
|
// Draw the line.
|
|||
|
MoveTo(f_x0, f_y0);
|
|||
|
LineTo(f_x1, f_y1);
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
class CAppShellWave: public CAppShell, public CSimWater
|
|||
|
//
|
|||
|
// Implement the CAppShell interface.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
typedef CSimWater parent;
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
CViewport vpScr;
|
|||
|
CTimer tmrStep;
|
|||
|
bool bFirst;
|
|||
|
CVector2<> v2Mouse;
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
// Constructor.
|
|||
|
//
|
|||
|
|
|||
|
CAppShellWave()
|
|||
|
: CSimWater
|
|||
|
(
|
|||
|
128, // Number of elements along length.
|
|||
|
100.0, // Length of wave medium.
|
|||
|
10.0, // Default depth.
|
|||
|
.2, // Damping. (alpha)
|
|||
|
25, // Restoring. (beta)
|
|||
|
0 // Gravity.
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
/*
|
|||
|
// Set the waves to an initial value.
|
|||
|
for (int u = 0; u < pamAmplitude.uLen; u++)
|
|||
|
pamAmplitude[u] = 25 * mrFunk((float)u / pamAmplitude.uLen);
|
|||
|
CopyPrev();
|
|||
|
*/
|
|||
|
// pamAmplitude[pamAmplitude.uLen/2] = -0.5;
|
|||
|
|
|||
|
// Stick a sine wave in the middle.
|
|||
|
for (int u = 0; u < pamAmplitude.uLen; u++)
|
|||
|
pamAmplitude[u] = 10 * mrFunk((float)u / pamAmplitude.uLen);
|
|||
|
CopyPrev();
|
|||
|
|
|||
|
// Set the new wave based on the velocity of propagation rightward, and time step.
|
|||
|
// for (u = 1; u < pamAmplitude.uLen; u++)
|
|||
|
// pamAmplitude[u] = 0.25 * mrFunk((float)u / pamAmplitude.uLen * 2 - 0.5 - (mrVelocity * sStep / mLength));
|
|||
|
|
|||
|
/*
|
|||
|
for (int u = 0; u < pamAmplitude.uLen/10; u++)
|
|||
|
pamAmplitude[pamAmplitude.uLen/2 + u] = - 0.49 * CAngle(dPI * 10 * (float)u / pamAmplitude.uLen).fSin();
|
|||
|
SwapPrev();
|
|||
|
for (u = 0; u < pamAmplitude.uLen/10; u++)
|
|||
|
pamAmplitude[pamAmplitude.uLen/2 + u] = - 0.50 * CAngle(dPI * 10 * (float)u / pamAmplitude.uLen).fSin();
|
|||
|
*/
|
|||
|
|
|||
|
bFirst = true;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
// Member functions.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
static TMeasure mrFunk(TMeasure mr_pos)
|
|||
|
{
|
|||
|
if (!bWithin(mr_pos, 0, 1))
|
|||
|
return 0;
|
|||
|
CAngle ang = d2_PI * mr_pos;
|
|||
|
return ang.fSin();
|
|||
|
|
|||
|
/*
|
|||
|
float ang_r = asin(sin(ang) / 1.33);
|
|||
|
float f_sin1 = sin(ang - ang_r);
|
|||
|
float f_sin2 = sin(ang + ang_r);
|
|||
|
float f_tan1 = tan(ang - ang_r);
|
|||
|
float f_tan2 = tan(ang + ang_r);
|
|||
|
|
|||
|
return f_sin1 * f_sin1 / 2.0 / f_sin2 / f_sin2
|
|||
|
+ f_tan1 * f_tan1 / 2.0 / f_tan2 / f_tan2;
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
void ModifyWave(CVector2<> v2_mouse)
|
|||
|
{
|
|||
|
//
|
|||
|
// Set the wave values according to line between previous and current mouse positions.
|
|||
|
//
|
|||
|
|
|||
|
int i_index0 = v2Mouse.tX / mInterval;
|
|||
|
int i_index = v2_mouse.tX / mInterval;
|
|||
|
|
|||
|
float f_slope = i_index != i_index0 ? (v2Mouse.tY - v2_mouse.tY) / (i_index0 - i_index) : 0;
|
|||
|
|
|||
|
while (i_index < i_index0)
|
|||
|
{
|
|||
|
if (i_index < pamAmplitude.uLen)
|
|||
|
{
|
|||
|
if (bKeyState(VK_LBUTTON))
|
|||
|
pamAmplitude[i_index] = v2_mouse.tY;
|
|||
|
else if (bKeyState(VK_RBUTTON))
|
|||
|
pamDepth[i_index] = -v2_mouse.tY;
|
|||
|
}
|
|||
|
v2_mouse.tY += f_slope;
|
|||
|
i_index++;
|
|||
|
}
|
|||
|
while (i_index >= i_index0)
|
|||
|
{
|
|||
|
if (i_index < pamAmplitude.uLen)
|
|||
|
{
|
|||
|
if (bKeyState(VK_LBUTTON))
|
|||
|
pamAmplitude[i_index] = v2_mouse.tY;
|
|||
|
else if (bKeyState(VK_RBUTTON))
|
|||
|
pamDepth[i_index] = -v2_mouse.tY;
|
|||
|
}
|
|||
|
v2_mouse.tY -= f_slope;
|
|||
|
i_index--;
|
|||
|
}
|
|||
|
if (!bContinuous())
|
|||
|
Repaint();
|
|||
|
}
|
|||
|
|
|||
|
void MouseMove(CVector2<> v2_mouse)
|
|||
|
{
|
|||
|
// Handle virtual coords.
|
|||
|
if (bKeyState(VK_LBUTTON) || bKeyState(VK_RBUTTON))
|
|||
|
ModifyWave(v2_mouse);
|
|||
|
v2Mouse = v2_mouse;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
// Overrides.
|
|||
|
//
|
|||
|
|
|||
|
void Init()
|
|||
|
{
|
|||
|
vpScr.SetVirtualSize(mLength, -mLength);
|
|||
|
vpScr.SetVirtualOrigin(0, -mLength/2);
|
|||
|
|
|||
|
SetContinuous(true);
|
|||
|
}
|
|||
|
|
|||
|
void NewRaster()
|
|||
|
{
|
|||
|
vpScr.SetSize(prasMainScreen->iWidth, prasMainScreen->iHeight);
|
|||
|
}
|
|||
|
|
|||
|
void Paint()
|
|||
|
{
|
|||
|
prasMainScreen->Clear(CColour(0, 0, 0));
|
|||
|
|
|||
|
CLineDraw ld(prasMainScreen, &vpScr);
|
|||
|
|
|||
|
// First draw base line, in dark green.
|
|||
|
ld.LineColour(CColour(0.0, 0.5, 0.0));
|
|||
|
ld.Line(0, 0, mLength, 0);
|
|||
|
|
|||
|
// Now draw wave, in green.
|
|||
|
ld.LineColour(CColour(0.0, 1.0, 0.0));
|
|||
|
ld.MoveTo(0, pamAmplitude[0]);
|
|||
|
|
|||
|
for (int u = 0; u < pamAmplitude.uLen; u++)
|
|||
|
{
|
|||
|
ld.LineTo(u * mInterval, pamAmplitude[u]);
|
|||
|
}
|
|||
|
|
|||
|
// Now draw bottom, in yellow.
|
|||
|
ld.LineColour(CColour(1.0, 1.0, 0.0));
|
|||
|
ld.MoveTo(0, -pamDepth[0]);
|
|||
|
for (u = 0; u < pamDepth.uLen; u++)
|
|||
|
{
|
|||
|
ld.LineTo(u * mInterval, -pamDepth[u]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void Step()
|
|||
|
{
|
|||
|
if (bFirst)
|
|||
|
{
|
|||
|
tmrStep.sElapsed();
|
|||
|
bFirst = false;
|
|||
|
}
|
|||
|
else
|
|||
|
parent::Step(tmrStep.sElapsed());
|
|||
|
Repaint();
|
|||
|
|
|||
|
conStd.ClearScreen();
|
|||
|
// ConShowStats();
|
|||
|
conStd.Print("Step quantum: %.2f ms\n", sStepMax * 1000.0);
|
|||
|
conStd.Show();
|
|||
|
}
|
|||
|
|
|||
|
void MouseMove(int i_x, int i_y)
|
|||
|
{
|
|||
|
// Call function handling virtual coordinates.
|
|||
|
MouseMove(CVector2<>(vpScr.vcVirtualX(i_x), vpScr.vcVirtualY(i_y)));
|
|||
|
}
|
|||
|
|
|||
|
void KeyPress(int i_key)
|
|||
|
{
|
|||
|
switch (i_key)
|
|||
|
{
|
|||
|
// Left button draws the wave.
|
|||
|
case VK_LBUTTON:
|
|||
|
CTimer::Pause(true);
|
|||
|
SetContinuous(false);
|
|||
|
ModifyWave(v2Mouse);
|
|||
|
break;
|
|||
|
case -VK_LBUTTON:
|
|||
|
CopyPrev();
|
|||
|
break;
|
|||
|
|
|||
|
// Right button draws the bottom.
|
|||
|
case VK_RBUTTON:
|
|||
|
CTimer::Pause(true);
|
|||
|
SetContinuous(false);
|
|||
|
ModifyWave(v2Mouse);
|
|||
|
break;
|
|||
|
case -VK_RBUTTON:
|
|||
|
CopyPrev();
|
|||
|
UpdateDepth();
|
|||
|
break;
|
|||
|
|
|||
|
case ' ':
|
|||
|
CTimer::Pause(false);
|
|||
|
SetContinuous(true);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
template<class T> T Sqr
|
|||
|
(
|
|||
|
T t
|
|||
|
)
|
|||
|
{
|
|||
|
return t * t;
|
|||
|
}
|
|||
|
|
|||
|
#define GRID 1
|
|||
|
#define GREY 0
|
|||
|
#define DRAW_SPHERE 0
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
class CAppShellWave2D: public CAppShell, public CSimWater2D
|
|||
|
//
|
|||
|
// Implement the CAppShell interface.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
typedef CSimWater2D parent;
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
TMeasure mrDepthDefault;
|
|||
|
|
|||
|
CViewport vpScr;
|
|||
|
CTimer tmrStep;
|
|||
|
bool bFirst;
|
|||
|
TPixel pixClut[256];
|
|||
|
|
|||
|
CVector2<> v2Mouse;
|
|||
|
|
|||
|
CVector2<> v2Start;
|
|||
|
CVector2<> v2Mod;
|
|||
|
|
|||
|
CAArray<TMeasure> pamDepth1, pamDepth2;
|
|||
|
|
|||
|
int iPrevDepthIndex;
|
|||
|
bool bShowWater, bShowBottom;
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
// Constructor.
|
|||
|
//
|
|||
|
|
|||
|
CAppShellWave2D()
|
|||
|
: CSimWater2D
|
|||
|
(
|
|||
|
48, // Number of elements along length.
|
|||
|
/*
|
|||
|
1000.0, 1000.0, // Length and width of wave medium.
|
|||
|
100.0, // Default depth.
|
|||
|
.0, // Damping. (alpha)
|
|||
|
*/
|
|||
|
50.0, 50.0, // Length and width of wave medium.
|
|||
|
1, // Boundary condition.
|
|||
|
5.0, // Default depth.
|
|||
|
.05, // Damping (alpha).
|
|||
|
25 // Restoring (beta).
|
|||
|
),
|
|||
|
pamDepth1(pa2mDepth.iHeight), pamDepth2(pa2mDepth.iWidth),
|
|||
|
mrDepthDefault(2.0)
|
|||
|
{
|
|||
|
pamDepth1.Fill(mrDepthDefault);
|
|||
|
pamDepth2.Fill(mrDepthDefault);
|
|||
|
|
|||
|
// Set the waves to an initial value.
|
|||
|
|
|||
|
/*
|
|||
|
// Stick a sine wave in the middle.
|
|||
|
for (int i_y = 0; i_y < pa2mAmplitude.iHeight; i_y++)
|
|||
|
for (int i_x = 0; i_x < pa2mAmplitude.iWidth; i_x++)
|
|||
|
pa2mAmplitude[i_y][i_x] = 15 * mrFunk(CVector2<>
|
|||
|
(
|
|||
|
8 * ((float)i_y / pa2mAmplitude.iHeight - 0.5),
|
|||
|
8 * ((float)i_x / pa2mAmplitude.iWidth - 0.5)
|
|||
|
).tLenSqr());
|
|||
|
CopyPrev();
|
|||
|
*/
|
|||
|
/*
|
|||
|
// Make a depth barrier with a double slit.
|
|||
|
for (int i_x = 0; i_x < pa2mDepth.iWidth; i_x++)
|
|||
|
{
|
|||
|
if (!bWithin(float(i_x) / pa2mDepth.iWidth, 0.3, 0.4) &&
|
|||
|
!bWithin(float(i_x) / pa2mDepth.iWidth, 0.6, 0.7))
|
|||
|
pa2mDepth[pa2mAmplitude.iHeight / 2][i_x] = 0;
|
|||
|
}
|
|||
|
UpdateDepth();
|
|||
|
*/
|
|||
|
bFirst = true;
|
|||
|
iPrevDepthIndex = -1;
|
|||
|
bShowWater = bShowBottom = true;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
// Member functions.
|
|||
|
//
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
static TMeasure mrFunk(TMeasure mr_pos)
|
|||
|
{
|
|||
|
return bWithin(mr_pos, -1, 1) ? CAngle(dPI_2 * mr_pos).fCos() : 0;
|
|||
|
}
|
|||
|
|
|||
|
#if GRID
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
CVector2<> v2Project
|
|||
|
(
|
|||
|
CVector3<> v3 // 3D position in sim coords.
|
|||
|
)
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// Projection of v3 onto virtual viewport coords.
|
|||
|
//
|
|||
|
// Uses an isometric projection, as follows:
|
|||
|
// X => X
|
|||
|
// Z => Y
|
|||
|
// Y => 45 degrees, between X and Y
|
|||
|
//
|
|||
|
// Thus:
|
|||
|
// sx = x + y/sqrt(2)
|
|||
|
// sy = z + y/sqrt(2)
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
return CVector2<>(v3.tX + fINV_SQRT2 * v3.tY, v3.tZ + fINV_SQRT2 * v3.tY);
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
CVector3<> v3ProjectXY
|
|||
|
(
|
|||
|
CVector2<> v2_scr, // 2D screen position.
|
|||
|
TMeasure mr_z // Z position to project to.
|
|||
|
)
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// The location on the xy plane corresponding to v2_scr.
|
|||
|
//
|
|||
|
// Since:
|
|||
|
// sx = x + y/sqrt(2)
|
|||
|
// sy = z + y/sqrt(2)
|
|||
|
//
|
|||
|
// We find that:
|
|||
|
// y = (sy - z)*sqrt(2)
|
|||
|
// x = sx - y/sqrt(2)
|
|||
|
// = sx - sy + z
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
return CVector3<>(v2_scr.tX - v2_scr.tY + mr_z, (v2_scr.tY - mr_z) * fSQRT2, mr_z);
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
CVector3<> v3ProjectXZ
|
|||
|
(
|
|||
|
CVector2<> v2_scr, // 2D screen position.
|
|||
|
TMeasure mr_y // Y position to project to.
|
|||
|
)
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// The location on the xz plane corresponding to v2_scr.
|
|||
|
//
|
|||
|
// We find that:
|
|||
|
// x = sx - y/sqrt(2)
|
|||
|
// z = sy - y/sqrt(2)
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
mr_y *= fINV_SQRT2;
|
|||
|
return CVector3<>(v2_scr.tX - mr_y, mr_y, v2_scr.tY - mr_y);
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
CVector3<> v3ProjectYZ
|
|||
|
(
|
|||
|
CVector2<> v2_scr, // 2D screen position.
|
|||
|
TMeasure mr_x // X position to project to.
|
|||
|
)
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// The location on the yz plane corresponding to v2_scr.
|
|||
|
//
|
|||
|
// sx = x + y/sqrt(2)
|
|||
|
// sy = z + y/sqrt(2)
|
|||
|
// We find that:
|
|||
|
// y = (sx - x)*sqrt(2)
|
|||
|
// z = sy - y/sqrt(2)
|
|||
|
// = sy - sx + x
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
return CVector3<>(0, (v2_scr.tX - mr_x) * fSQRT2, v2_scr.tY - v2_scr.tX + mr_x);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#if DRAW_SPHERE
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
void SetModifyPoint
|
|||
|
(
|
|||
|
CVector2<> v2_mouse
|
|||
|
)
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
v2Start = v2_mouse;
|
|||
|
v2Mod = v3ProjectXY(v2_mouse, 0);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
void ModifyWave
|
|||
|
(
|
|||
|
CVector2<> v2_mouse
|
|||
|
)
|
|||
|
//
|
|||
|
// Modify the wave height, based on current mouse position. This works as follows:
|
|||
|
// The y distance from the starting mouse position indicates height.
|
|||
|
// The x distance indicates radius.
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
#if DRAW_SPHERE
|
|||
|
TMeasure mr_height = v2_mouse.tY - v2Start.tY;
|
|||
|
TMeasure mr_radius = Abs(v2_mouse.tX - v2Start.tX);
|
|||
|
|
|||
|
// Create a hump of the given height and radius.
|
|||
|
for (int i_y = 0; i_y < pa2mAmplitude.iHeight; i_y++)
|
|||
|
{
|
|||
|
for (int i_x = 0; i_x < pa2mAmplitude.iWidth; i_x++)
|
|||
|
{
|
|||
|
TMeasure mr_dist = CVector2<>(i_y * mInterval - v2Mod.tX, i_x * mInterval - v2Mod.tY).tLen();
|
|||
|
if (mr_dist <= mr_radius)
|
|||
|
{
|
|||
|
TMeasure mr_val = CAngle(mr_dist / mr_radius).fCos();
|
|||
|
if (bKeyState(VK_LBUTTON))
|
|||
|
pa2mAmplitude[i_y][i_x] = mr_height * mr_val * mr_val;
|
|||
|
else if (bKeyState(VK_RBUTTON))
|
|||
|
pa2mDepth[i_y][i_x] = - mr_height * mr_val * mr_val;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#else
|
|||
|
const TMeasure mr_mod_radius = mInterval/2;
|
|||
|
|
|||
|
// Implement the Klay-Doodle: Depress the current water height with a small hemisphere.
|
|||
|
#if GRID
|
|||
|
CVector2<> v2_plane = v3ProjectXY(v2_mouse, 0);
|
|||
|
#else
|
|||
|
CVector2<> v2_plane = v2_mouse;
|
|||
|
#endif
|
|||
|
CVector2<> v2_start = (v2_plane - CVector2<>(mr_mod_radius, mr_mod_radius)) / mInterval;
|
|||
|
CVector2<> v2_end = (v2_plane + CVector2<>(mr_mod_radius, mr_mod_radius)) / mInterval;
|
|||
|
|
|||
|
for (int i_y = v2_start.tX; i_y <= v2_end.tX; i_y++)
|
|||
|
for (int i_x = v2_start.tY; i_x <= v2_end.tY; i_x++)
|
|||
|
if (i_y < pa2mAmplitude.iHeight && i_x < pa2mAmplitude.iWidth)
|
|||
|
{
|
|||
|
TMeasure mr_dist = (CVector2<>(i_y * mInterval, i_x * mInterval) - v2_plane).tLen();
|
|||
|
pa2mAmplitude[i_y][i_x] -= mr_dist;
|
|||
|
}
|
|||
|
#endif
|
|||
|
if (!bContinuous())
|
|||
|
Repaint();
|
|||
|
}
|
|||
|
|
|||
|
#if !DRAW_SPHERE
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
void ModifyDepth
|
|||
|
(
|
|||
|
CVector2<> v2_mouse
|
|||
|
)
|
|||
|
//
|
|||
|
// Modify the wave depth, based on current mouse position.
|
|||
|
// If the mouse is in front of the water, draw the depth along the x axis.
|
|||
|
// If the mouse is to the right of the water, draw the depth along the y axis.
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
CVector3<> v3_draw, v3_draw_prev;
|
|||
|
|
|||
|
v3_draw = v3ProjectXZ(v2_mouse, 0);
|
|||
|
|
|||
|
if (bWithin(v3_draw.tX, 0, mLength) && v3_draw.tZ < 0)
|
|||
|
{
|
|||
|
// We're drawing X depth.
|
|||
|
int i1 = v3_draw.tX / mInterval;
|
|||
|
if (iPrevDepthIndex < 0)
|
|||
|
iPrevDepthIndex = i1;
|
|||
|
Swap(i1, iPrevDepthIndex);
|
|||
|
for (;;)
|
|||
|
{
|
|||
|
pamDepth1[i1] = -v3_draw.tZ;
|
|||
|
|
|||
|
// Update depth.
|
|||
|
for (int i2 = 0; i2 < pa2mDepth.iWidth; i2++)
|
|||
|
pa2mDepth[i1][i2] = Min(pamDepth1[i1], pamDepth2[i2]);
|
|||
|
|
|||
|
if (i1 < iPrevDepthIndex)
|
|||
|
i1++;
|
|||
|
else if (i1 > iPrevDepthIndex)
|
|||
|
i1--;
|
|||
|
else
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
v3_draw = v3ProjectYZ(v2_mouse, mLength);
|
|||
|
if (bWithin(v3_draw.tY, 0, mWidth) && v3_draw.tZ < 0)
|
|||
|
{
|
|||
|
// We're drawing Y depth.
|
|||
|
int i2 = v3_draw.tY / mInterval;
|
|||
|
if (iPrevDepthIndex < 0)
|
|||
|
iPrevDepthIndex = i2;
|
|||
|
Swap(i2, iPrevDepthIndex);
|
|||
|
for (;;)
|
|||
|
{
|
|||
|
pamDepth2[i2] = -v3_draw.tZ;
|
|||
|
|
|||
|
// Update depth.
|
|||
|
for (int i1 = 0; i1 < pa2mDepth.iHeight; i1++)
|
|||
|
pa2mDepth[i1][i2] = Min(pamDepth1[i1], pamDepth2[i2]);
|
|||
|
|
|||
|
if (i2 < iPrevDepthIndex)
|
|||
|
i2++;
|
|||
|
else if (i2 > iPrevDepthIndex)
|
|||
|
i2--;
|
|||
|
else
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (!bContinuous())
|
|||
|
Repaint();
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
void MakeRandomDepth()
|
|||
|
//
|
|||
|
// Create a random depth array.
|
|||
|
//
|
|||
|
// Method:
|
|||
|
// Travel around the perimeter of the rectangle. At every point, calculate a random
|
|||
|
// radius (adjusted from radius at previous point). The point at this radius from the
|
|||
|
// centre becomes the edge of the pond, and the depth decreases linearly from the centre
|
|||
|
// to the edge.
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
//
|
|||
|
// First create an array of radius values for every angle.
|
|||
|
// Let's use as many angle steps as there are points on the perimter.
|
|||
|
//
|
|||
|
int i_steps = (pa2mDepth.iHeight + pa2mDepth.iWidth) * 2;
|
|||
|
CAArray<TMeasure> pamr_radius(i_steps);
|
|||
|
|
|||
|
//
|
|||
|
// The starting radius is the maximum that will fit within the sim.
|
|||
|
// The radius is allowed to become larger or smaller than that.
|
|||
|
//
|
|||
|
TMeasure mr_radius = Min(mLength, mWidth) / 2;
|
|||
|
TMeasure mr_radius_mod = mr_radius * 0.1;
|
|||
|
|
|||
|
static CRandom rand;
|
|||
|
|
|||
|
for (int i = 0; i < i_steps; i++)
|
|||
|
{
|
|||
|
mr_radius += rand(-mr_radius_mod, +mr_radius_mod);
|
|||
|
|
|||
|
// Can't get too low.
|
|||
|
SetMax(mr_radius, mr_radius_mod);
|
|||
|
pamr_radius[i] = mr_radius;
|
|||
|
}
|
|||
|
|
|||
|
// Now go through the entire area, and set the depth based on polar coordinates.
|
|||
|
for (int i_x = 0; i_x < pa2mDepth.iHeight; i_x++)
|
|||
|
for (int i_y = 0; i_y < pa2mDepth.iWidth; i_y++)
|
|||
|
{
|
|||
|
// Figure out the polar coordinates for this element.
|
|||
|
TMeasure mr_x = i_x * mInterval - mLength/2;
|
|||
|
TMeasure mr_y = i_y * mInterval - mWidth/2;
|
|||
|
|
|||
|
mr_radius = CVector2<>(mr_x, mr_y).tLen();
|
|||
|
float f_ang = atan2(mr_x, mr_y);
|
|||
|
if (f_ang < 0)
|
|||
|
f_ang += d2_PI;
|
|||
|
int i_ang = f_ang / d2_PI * (i_steps-1);
|
|||
|
|
|||
|
//
|
|||
|
// The depth is proportional to the percentage distance the point is
|
|||
|
// from the radius for this angle to the centre.
|
|||
|
//
|
|||
|
pa2mDepth[i_x][i_y] = mrDepthDefault * (pamr_radius[i_ang] - mr_radius) / pamr_radius[i_ang];
|
|||
|
}
|
|||
|
|
|||
|
UpdateDepth();
|
|||
|
}
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
//
|
|||
|
// Overrides.
|
|||
|
//
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
enum
|
|||
|
{
|
|||
|
iMENU_QUELL = iMENU_ID_START,
|
|||
|
iMENU_DEPTH,
|
|||
|
iMENU_SHOW_WATER,
|
|||
|
iMENU_SHOW_BOTTOM
|
|||
|
};
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
void Init()
|
|||
|
{
|
|||
|
#if GREY
|
|||
|
vpScr.SetVirtualSize(mLength, mWidth, true);
|
|||
|
vpScr.SetVirtualOrigin(0, 0);
|
|||
|
#else
|
|||
|
CVector2<> v2 = v2Project(CVector3<>(mLength, mWidth, 0));
|
|||
|
vpScr.SetVirtualSize(v2.tX, -v2.tY * 1.2, true);
|
|||
|
vpScr.SetVirtualOrigin(0, -v2.tY * 1.1);
|
|||
|
#endif
|
|||
|
|
|||
|
SetContinuous(true);
|
|||
|
|
|||
|
// Add some menus here.
|
|||
|
HMENU hmenu = hmenuAddSubMenu(0, "&Wave");
|
|||
|
|
|||
|
AddMenuItem(hmenu, "&Quell", iMENU_QUELL);
|
|||
|
AddMenuItem(hmenu, "Make &Depth", iMENU_DEPTH);
|
|||
|
AddMenuItem(hmenu, "Show &Water", iMENU_SHOW_WATER, &bShowWater);
|
|||
|
AddMenuItem(hmenu, "Show &Bottom", iMENU_SHOW_BOTTOM, &bShowBottom);
|
|||
|
}
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
void NewRaster()
|
|||
|
{
|
|||
|
vpScr.SetSize(prasMainScreen->iWidth, prasMainScreen->iHeight);
|
|||
|
#if GREY
|
|||
|
// Build my own mini-clut.
|
|||
|
CColour clrWater(0.0, 1.0, 1.0);
|
|||
|
for (int i = 0; i < 256; i++)
|
|||
|
pixClut[i] = prasMainScreen->pixFromColour(CColour(0, i, i));
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
void Paint()
|
|||
|
{
|
|||
|
#if GREY
|
|||
|
// Fill the screen with the water map, showing height via colour.
|
|||
|
int i_x_prev = 0;
|
|||
|
for (int i_1 = 0; i_1 < pa2mAmplitude.iHeight; i_1++)
|
|||
|
{
|
|||
|
int i_x = vpScr.scScreenX((i_1+1) * mInterval);
|
|||
|
|
|||
|
int i_y_prev = 0;
|
|||
|
for (int i_2 = 0; i_2 < pa2mAmplitude.iWidth; i_2++)
|
|||
|
{
|
|||
|
int i_y = vpScr.scScreenY((i_2+1) * mInterval);
|
|||
|
// Get the colour associated with the height here.
|
|||
|
TMeasure mr_height = pa2mAmplitude[i_1][i_2];
|
|||
|
int i_index = MinMax(int(mr_height / (mLength/8) * 256) + 128, 0, 255);
|
|||
|
|
|||
|
prasMainScreen->Rect(pixClut[i_index], SRect
|
|||
|
(
|
|||
|
i_x_prev, i_y_prev,
|
|||
|
i_x - i_x_prev, i_y - i_y_prev
|
|||
|
));
|
|||
|
i_y_prev = i_y;
|
|||
|
}
|
|||
|
i_x_prev = i_x;
|
|||
|
}
|
|||
|
#else
|
|||
|
prasMainScreen->Clear(CColour(0, 0, 0));
|
|||
|
|
|||
|
CLineDraw ld(prasMainScreen, &vpScr);
|
|||
|
|
|||
|
if (bShowBottom)
|
|||
|
{
|
|||
|
// Draw the depth in brown.
|
|||
|
ld.LineColour(CColour(0.5, 0.2, 0.0));
|
|||
|
|
|||
|
for (int i_x = 0; i_x < pa2mDepth.iWidth; i_x++)
|
|||
|
for (int i_y = 0; i_y < pa2mDepth.iHeight; i_y++)
|
|||
|
{
|
|||
|
CVector2<> v2 = v2Project(CVector3<>
|
|||
|
(
|
|||
|
i_y * mInterval, i_x * mInterval, -pa2mDepth[i_y][i_x]
|
|||
|
));
|
|||
|
if (i_y == 0)
|
|||
|
ld.MoveTo(v2.tX, v2.tY);
|
|||
|
else
|
|||
|
ld.LineTo(v2.tX, v2.tY);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
// Draw the 2 controlling depth curves.
|
|||
|
for (int i_y = 0; i_y < pamDepth1.uLen; i_y++)
|
|||
|
{
|
|||
|
CVector2<> v2 = v2Project(CVector3<>
|
|||
|
(
|
|||
|
i_y * mInterval, 0, -pamDepth1[i_y]
|
|||
|
));
|
|||
|
if (i_y == 0)
|
|||
|
ld.MoveTo(v2.tX, v2.tY);
|
|||
|
else
|
|||
|
ld.LineTo(v2.tX, v2.tY);
|
|||
|
}
|
|||
|
|
|||
|
for (i_x = 0; i_x < pamDepth2.uLen; i_x++)
|
|||
|
{
|
|||
|
CVector2<> v2 = v2Project(CVector3<>
|
|||
|
(
|
|||
|
mLength, i_x * mInterval, -pamDepth2[i_x]
|
|||
|
));
|
|||
|
if (i_y == 0)
|
|||
|
ld.MoveTo(v2.tX, v2.tY);
|
|||
|
else
|
|||
|
ld.LineTo(v2.tX, v2.tY);
|
|||
|
}
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
if (bShowWater)
|
|||
|
{
|
|||
|
// Now draw wave, in green.
|
|||
|
ld.LineColour(CColour(0.0, 1.0, 0.0));
|
|||
|
|
|||
|
// Draw the vertical lines.
|
|||
|
for (int i_y = 0; i_y < pa2mAmplitude.iHeight; i_y++)
|
|||
|
{
|
|||
|
bool b_drew = false;
|
|||
|
for (int i_x = 0; i_x < pa2mAmplitude.iWidth; i_x++)
|
|||
|
{
|
|||
|
if (pa2mDepth[i_y][i_x] > 0)
|
|||
|
{
|
|||
|
CVector2<> v2 = v2Project(CVector3<>
|
|||
|
(
|
|||
|
i_y * mInterval, i_x * mInterval, pa2mAmplitude[i_y][i_x]
|
|||
|
));
|
|||
|
if (!b_drew)
|
|||
|
ld.MoveTo(v2.tX, v2.tY);
|
|||
|
else
|
|||
|
ld.LineTo(v2.tX, v2.tY);
|
|||
|
b_drew = true;
|
|||
|
}
|
|||
|
else
|
|||
|
b_drew = false;
|
|||
|
}
|
|||
|
}
|
|||
|
/*
|
|||
|
// Draw the horizontal lines.
|
|||
|
for (i_x = 0; i_x < pa2mAmplitude.iWidth; i_x++)
|
|||
|
for (int i_y = 0; i_y < pa2mAmplitude.iHeight; i_y++)
|
|||
|
{
|
|||
|
CVector2<> v2 = v2Project(CVector3<>
|
|||
|
(
|
|||
|
i_y * mInterval, i_x * mInterval, pa2mAmplitude[i_y][i_x]
|
|||
|
));
|
|||
|
if (i_y == 0)
|
|||
|
ld.MoveTo(v2.tX, v2.tY);
|
|||
|
else
|
|||
|
ld.LineTo(v2.tX, v2.tY);
|
|||
|
}
|
|||
|
*/
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
void Step()
|
|||
|
{
|
|||
|
if (bFirst)
|
|||
|
{
|
|||
|
tmrStep.sElapsed();
|
|||
|
bFirst = false;
|
|||
|
}
|
|||
|
else
|
|||
|
parent::Step(tmrStep.sElapsed());
|
|||
|
|
|||
|
Repaint();
|
|||
|
|
|||
|
conStd.ClearScreen();
|
|||
|
// ConShowStats();
|
|||
|
conStd.Print("Step quantum: %.2f ms\n", sStepMax * 1000.0);
|
|||
|
conStd.Show();
|
|||
|
}
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
void KeyPress(int i_key)
|
|||
|
{
|
|||
|
switch (i_key)
|
|||
|
{
|
|||
|
#if DRAW_SPHERE
|
|||
|
case VK_LBUTTON:
|
|||
|
case VK_RBUTTON:
|
|||
|
CTimer::Pause(true);
|
|||
|
SetContinuous(false);
|
|||
|
SetModifyPoint(v2Mouse);
|
|||
|
break;
|
|||
|
case -VK_LBUTTON:
|
|||
|
CopyPrev();
|
|||
|
CTimer::Pause(false);
|
|||
|
SetContinuous(true);
|
|||
|
break;
|
|||
|
case -VK_RBUTTON:
|
|||
|
UpdateDepth ();
|
|||
|
break;
|
|||
|
|
|||
|
case ' ':
|
|||
|
CTimer::Pause(false);
|
|||
|
SetContinuous(true);
|
|||
|
break;
|
|||
|
#else
|
|||
|
case VK_LBUTTON:
|
|||
|
ModifyWave(v2Mouse);
|
|||
|
break;
|
|||
|
|
|||
|
case VK_RBUTTON:
|
|||
|
SetContinuous(false);
|
|||
|
ModifyDepth(v2Mouse);
|
|||
|
break;
|
|||
|
|
|||
|
case -VK_RBUTTON:
|
|||
|
SetContinuous(true);
|
|||
|
UpdateDepth ();
|
|||
|
iPrevDepthIndex = -1;
|
|||
|
break;
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
void MouseMove(CVector2<> v2_mouse)
|
|||
|
{
|
|||
|
// Handle virtual coords.
|
|||
|
#if DRAW_SPHERE
|
|||
|
if (bKeyState(VK_LBUTTON) || bKeyState(VK_RBUTTON))
|
|||
|
ModifyWave(v2_mouse);
|
|||
|
#else
|
|||
|
if (bKeyState(VK_LBUTTON))
|
|||
|
ModifyWave(v2_mouse);
|
|||
|
if (bKeyState(VK_RBUTTON))
|
|||
|
ModifyDepth(v2_mouse);
|
|||
|
#endif
|
|||
|
v2Mouse = v2_mouse;
|
|||
|
}
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
void MouseMove(int i_x, int i_y)
|
|||
|
{
|
|||
|
// Call function handling virtual coordinates.
|
|||
|
MouseMove(CVector2<>(vpScr.vcVirtualX(i_x), vpScr.vcVirtualY(i_y)));
|
|||
|
}
|
|||
|
|
|||
|
//********************************************************************************************
|
|||
|
void MenuCommand(int i_command, bool*)
|
|||
|
{
|
|||
|
switch (i_command)
|
|||
|
{
|
|||
|
case iMENU_QUELL:
|
|||
|
{
|
|||
|
// Reset the waves.
|
|||
|
for (int u_1 = 0; u_1 < pa2mAmplitude.iHeight; u_1++)
|
|||
|
for (int u_2 = 0; u_2 < pa2mAmplitude.iWidth; u_2++)
|
|||
|
pa2mAmplitude[u_1][u_2] = Max(0, -pa2mDepth[u_1][u_2]);
|
|||
|
CopyPrev();
|
|||
|
break;
|
|||
|
}
|
|||
|
case iMENU_DEPTH:
|
|||
|
MakeRandomDepth();
|
|||
|
CopyPrev();
|
|||
|
break;
|
|||
|
}
|
|||
|
if (!bContinuous())
|
|||
|
Repaint();
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
CAppShell* pappMain = new CAppShellWave2D;
|
|||
|
|