171 lines
4.5 KiB
C++
171 lines
4.5 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "twine/scene/rain.h"
|
|
#include "twine/renderer/renderer.h"
|
|
#include "twine/scene/grid.h"
|
|
#include "twine/twine.h"
|
|
|
|
namespace TwinE {
|
|
|
|
#define RAIN_VX 200
|
|
#define RAIN_VY 2500
|
|
#define RAIN_WEIGHT 30
|
|
#define RAIN_STOP 0
|
|
#define RAIN_DELTA_X 128
|
|
#define RAIN_DELTA_Y 256
|
|
#define RAIN_DELTA_Z 128
|
|
|
|
void Rain::InitOneRain(T_RAIN *pt) {
|
|
IVec3 cameraPos = _engine->_renderer->getCameraPosition();
|
|
|
|
int32 rndy = _engine->getRandomNumber(cameraPos.y + 10000);
|
|
|
|
pt->YRain = cameraPos.y + rndy;
|
|
|
|
rndy = rndy / 2 + 15000;
|
|
|
|
pt->XRain = cameraPos.x - rndy + _engine->getRandomNumber(30000);
|
|
pt->ZRain = cameraPos.z - rndy + _engine->getRandomNumber(30000);
|
|
pt->Timer = 0;
|
|
}
|
|
|
|
void Rain::InitRain() {
|
|
for (int32 i = 0; i < MAX_RAIN; i++) {
|
|
InitOneRain(&TabRain[i]);
|
|
}
|
|
|
|
LastTimer = 0;
|
|
}
|
|
|
|
void Rain::GereRain() {
|
|
int32 temp = _engine->timerRef;
|
|
DeltaRain = LastTimer ? (temp - LastTimer) * 10 : 0;
|
|
LastTimer = temp;
|
|
|
|
for (int32 i = 0; i < MAX_RAIN; i++) {
|
|
if (!TabRain[i].Timer) {
|
|
TabRain[i].XRain += DeltaRain / 2;
|
|
TabRain[i].ZRain += DeltaRain / 2;
|
|
TabRain[i].YRain -= DeltaRain;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Rain::ClearImpactRain() {
|
|
for (int32 i = 0; i < MAX_RAIN; i++) {
|
|
if (TabRain[i].Timer) {
|
|
InitOneRain(&TabRain[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Rain::AffRain() {
|
|
int32 lFactorX = _engine->_renderer->getLFactorX();
|
|
int32 lFactorY = _engine->_renderer->getLFactorY();
|
|
IVec3 cameraRot = _engine->_renderer->getCameraRotation();
|
|
int32 cameraZr = cameraRot.z;
|
|
|
|
// ClipZFar approximation
|
|
int32 clipZFar = 14000; // Default value from CREDITS.CPP
|
|
int32 startZFog = 5000; // Default value from CREDITS.CPP
|
|
|
|
for (int32 i = 0; i < MAX_RAIN; i++) {
|
|
if (TabRain[i].Timer) {
|
|
int32 dt = LastTimer - TabRain[i].Timer;
|
|
|
|
int32 c = TabRain[i].XRain >> 16;
|
|
int32 x = (int16)(TabRain[i].XRain & 0xFFFF);
|
|
int32 y = TabRain[i].YRain;
|
|
int32 z = TabRain[i].ZRain;
|
|
|
|
int32 xp, yp;
|
|
yp = (RAIN_VY - RAIN_WEIGHT * dt) * dt / 256;
|
|
if (yp < 0) {
|
|
yp = 0;
|
|
xp = RAIN_VX * RAIN_VY / RAIN_WEIGHT / 256;
|
|
} else {
|
|
xp = RAIN_VX * dt / 256;
|
|
yp = (yp * lFactorY) / z;
|
|
}
|
|
|
|
xp = (xp * lFactorX) / z;
|
|
|
|
int32 x0 = x - xp;
|
|
int32 x1 = x + xp;
|
|
|
|
// int32 y0 = y - yp;
|
|
// int32 y1 = y;
|
|
|
|
// z = ruleThree32(0, 65535, clipZFar, z);
|
|
|
|
// Draw splash
|
|
_engine->_workVideoBuffer.drawLine(x, y, x0, y - yp, c);
|
|
_engine->_workVideoBuffer.drawLine(x, y, x1, y - yp, c);
|
|
|
|
if (dt && !yp) {
|
|
InitOneRain(&TabRain[i]);
|
|
}
|
|
} else {
|
|
if (TabRain[i].YRain <= RAIN_STOP) {
|
|
InitOneRain(&TabRain[i]);
|
|
continue;
|
|
}
|
|
|
|
IVec3 p1 = _engine->_renderer->longWorldRot(TabRain[i].XRain - RAIN_DELTA_X, TabRain[i].YRain + RAIN_DELTA_Y, TabRain[i].ZRain - RAIN_DELTA_Z);
|
|
IVec3 proj1 = _engine->_renderer->projectPoint(p1);
|
|
|
|
int32 xp = proj1.x;
|
|
int32 yp = proj1.y;
|
|
int32 z0 = ruleThree32(0, 65535, clipZFar, cameraZr - p1.z);
|
|
|
|
IVec3 p2 = _engine->_renderer->longWorldRot(TabRain[i].XRain, TabRain[i].YRain, TabRain[i].ZRain);
|
|
IVec3 proj2 = _engine->_renderer->projectPoint(p2);
|
|
|
|
int32 Z0 = cameraZr - p2.z;
|
|
// int32 z1 = ruleThree32(0, 65535, clipZFar, Z0);
|
|
|
|
int32 c = boundRuleThree(16 * 3 + 10, 16 * 3 + 3, clipZFar - startZFog, Z0);
|
|
|
|
// Draw rain drop
|
|
_engine->_workVideoBuffer.drawLine(xp, yp, proj2.x, proj2.y, c);
|
|
|
|
// Check collision with ground
|
|
int32 groundHeight = 0;
|
|
IVec3 pos(TabRain[i].XRain, TabRain[i].YRain, TabRain[i].ZRain);
|
|
_engine->_grid->getBlockBufferGround(pos, groundHeight);
|
|
|
|
if (TabRain[i].YRain <= groundHeight) {
|
|
// Splash
|
|
TabRain[i].XRain = ((xp & 0xFFFF) | (c << 16));
|
|
TabRain[i].YRain = yp;
|
|
TabRain[i].ZRain = z0;
|
|
TabRain[i].Timer = LastTimer;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Rain::Rain(TwinEEngine *engine) : _engine(engine) {
|
|
}
|
|
|
|
} // namespace TwinE
|