|
shun-iwasawa |
832993 |
#include "iwa_floorbumpfx.h"
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
#include "tparamuiconcept.h"
|
|
shun-iwasawa |
832993 |
#include "iwa_fresnel.h"
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
#include <qmatrix></qmatrix>
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
namespace {
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline double cross(const QPointF a, const QPointF b) {
|
|
shun-iwasawa |
832993 |
return a.x() * b.y() - a.y() * b.x();
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline float lerp(const float v1, const float v2, const float r) {
|
|
shun-iwasawa |
832993 |
return v1 * (1.0f - r) + v2 * r;
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
inline QPointF lerpUV(const QPointF p1, const QPointF p2, const float r) {
|
|
shun-iwasawa |
832993 |
return p1 * (1.0 - r) + p2 * r;
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
float4 lerp4(const float4 v1, const float4 v2, const float r) {
|
|
shun-iwasawa |
832993 |
return float4{v1.x * (1.0f - r) + v2.x * r, v1.y * (1.0f - r) + v2.y * r,
|
|
shun-iwasawa |
832993 |
v1.z * (1.0f - r) + v2.z * r, v1.w * (1.0f - r) + v2.w * r};
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline QVector3D lerpPos(const QVector3D v1, const QVector3D v2,
|
|
shun-iwasawa |
832993 |
const float r) {
|
|
shun-iwasawa |
832993 |
return (v1 * (1.0 - r) + v2 * r);
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline QVector3D lerpNormal(const QVector3D v1, const QVector3D v2,
|
|
shun-iwasawa |
832993 |
const float r) {
|
|
shun-iwasawa |
832993 |
return lerpPos(v1, v2, r).normalized();
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline float fresnelFactor(const float radian) {
|
|
shun-iwasawa |
832993 |
float degree = radian / M_PI_180;
|
|
shun-iwasawa |
832993 |
if (degree < 0.0f)
|
|
shun-iwasawa |
832993 |
return fresnel[0];
|
|
shun-iwasawa |
832993 |
else if (degree >= 90.0f)
|
|
shun-iwasawa |
832993 |
return fresnel[90];
|
|
shun-iwasawa |
832993 |
int id = int(std::floor(degree));
|
|
shun-iwasawa |
832993 |
float ratio = degree - float(id);
|
|
shun-iwasawa |
832993 |
return lerp(fresnel[id], fresnel[id + 1], ratio);
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline bool isTextureUsed(int renderMode) {
|
|
shun-iwasawa |
832993 |
return renderMode == Iwa_FloorBumpFx::TextureMode // Texture
|
|
shun-iwasawa |
832993 |
|| renderMode == Iwa_FloorBumpFx::RefractionMode // Refraction
|
|
shun-iwasawa |
832993 |
|| renderMode == Iwa_FloorBumpFx::ReflectionMode; // Reflection
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// pixel height projected on the projection plane
|
|
shun-iwasawa |
832993 |
inline double getVPos(const QPointF &zyPos,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
QPointF a1 = QPointF(0, vars.P_y) - zyPos;
|
|
shun-iwasawa |
832993 |
QPointF a2 = vars.A - vars.B;
|
|
shun-iwasawa |
832993 |
QPointF b1 = vars.A - zyPos;
|
|
shun-iwasawa |
832993 |
QPointF b2 = vars.B - zyPos;
|
|
shun-iwasawa |
832993 |
double s1 = cross(b2, a1) / 2.0;
|
|
shun-iwasawa |
832993 |
double s2 = cross(a1, b1) / 2.0;
|
|
shun-iwasawa |
832993 |
double ratio = s1 / (s1 + s2);
|
|
shun-iwasawa |
832993 |
return vars.H * ratio;
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline float4 getSourcePix(QPointF p, float4 *source_host,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
auto source = [&](QPoint p) {
|
|
shun-iwasawa |
832993 |
return source_host[p.y() * vars.sourceDim.lx + p.x()];
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
QPointF uv = (p + QPointF(vars.margin, vars.margin)) * vars.precision;
|
|
shun-iwasawa |
832993 |
int inc_x = 1, inc_y = 1;
|
|
shun-iwasawa |
832993 |
if (uv.x() < 0.0)
|
|
shun-iwasawa |
832993 |
uv.setX(0.0);
|
|
shun-iwasawa |
832993 |
else if (uv.x() >= vars.sourceDim.lx - 1) {
|
|
shun-iwasawa |
832993 |
uv.setX(vars.sourceDim.lx - 1);
|
|
shun-iwasawa |
832993 |
inc_x = 0;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
if (uv.y() < 0.0)
|
|
shun-iwasawa |
832993 |
uv.setY(0.0);
|
|
shun-iwasawa |
832993 |
else if (uv.y() >= vars.sourceDim.ly - 1) {
|
|
shun-iwasawa |
832993 |
uv.setY(vars.sourceDim.ly - 1);
|
|
shun-iwasawa |
832993 |
inc_y = 0;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
QPoint p00(int(std::floor(uv.x())), int(std::floor(uv.y())));
|
|
shun-iwasawa |
832993 |
QPointF frac = uv - QPointF(p00);
|
|
shun-iwasawa |
832993 |
if (frac.isNull()) return source(p00);
|
|
shun-iwasawa |
832993 |
QPoint p01 = p00 + QPoint(inc_x, 0);
|
|
shun-iwasawa |
832993 |
QPoint p10 = p00 + QPoint(0, inc_y);
|
|
shun-iwasawa |
832993 |
QPoint p11 = p00 + QPoint(inc_x, inc_y);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
return lerp4(lerp4(source(p00), source(p01), frac.x()),
|
|
shun-iwasawa |
832993 |
lerp4(source(p10), source(p11), frac.x()), frac.y());
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline float getMapValue(QPointF p, float *map_host,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
auto map = [&](QPoint p) { return map_host[p.y() * vars.refDim.lx + p.x()]; };
|
|
shun-iwasawa |
832993 |
QPointF uv = p + QPointF(vars.margin, vars.margin);
|
|
shun-iwasawa |
832993 |
int inc_x = 1, inc_y = 1;
|
|
shun-iwasawa |
832993 |
if (uv.x() < 0.0)
|
|
shun-iwasawa |
832993 |
uv.setX(0.0);
|
|
shun-iwasawa |
832993 |
else if (uv.x() >= vars.refDim.lx - 1) {
|
|
shun-iwasawa |
832993 |
uv.setX(vars.refDim.lx - 1);
|
|
shun-iwasawa |
832993 |
inc_x = 0;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
if (uv.y() < 0.0)
|
|
shun-iwasawa |
832993 |
uv.setY(0.0);
|
|
shun-iwasawa |
832993 |
else if (uv.y() >= vars.refDim.ly - 1) {
|
|
shun-iwasawa |
832993 |
uv.setY(vars.refDim.ly - 1);
|
|
shun-iwasawa |
832993 |
inc_y = 0;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
QPoint p00(int(std::floor(uv.x())), int(std::floor(uv.y())));
|
|
shun-iwasawa |
832993 |
QPointF frac = uv - QPointF(p00);
|
|
shun-iwasawa |
832993 |
if (frac.isNull()) return map(p00);
|
|
shun-iwasawa |
832993 |
QPoint p01 = p00 + QPoint(inc_x, 0);
|
|
shun-iwasawa |
832993 |
QPoint p10 = p00 + QPoint(0, inc_y);
|
|
shun-iwasawa |
832993 |
QPoint p11 = p00 + QPoint(inc_x, inc_y);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
return lerp(lerp(map(p00), map(p01), frac.x()),
|
|
shun-iwasawa |
832993 |
lerp(map(p10), map(p11), frac.x()), frac.y());
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute horizontal position of the projected point on the projection
|
|
shun-iwasawa |
832993 |
// plane
|
|
shun-iwasawa |
832993 |
inline double getXPos(QVector3D pos,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
double angle_Q = vars.angle_el - atan((vars.P_y - pos.y()) / pos.z());
|
|
shun-iwasawa |
832993 |
double dist =
|
|
shun-iwasawa |
832993 |
vars.d_PT * cos(vars.angle_el - angle_Q) / (cos(angle_Q) * pos.z());
|
|
shun-iwasawa |
832993 |
return pos.x() * dist + double(vars.resultDim.lx) * 0.5;
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline float4 getTextureOffsetColor(double preTexOff, double texOff,
|
|
shun-iwasawa |
832993 |
float ratio) {
|
|
shun-iwasawa |
832993 |
float val = lerp(preTexOff, texOff, ratio);
|
|
shun-iwasawa |
832993 |
return float4{val, val, val, 1.0};
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
inline float4 getDiffuseColor(QVector3D n,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
float val = QVector3D::dotProduct(n, vars.sunVec);
|
|
shun-iwasawa |
832993 |
if (val < 0.0) val = 0.0;
|
|
shun-iwasawa |
832993 |
return float4{val, val, val, 1.0};
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
inline float4 getDiffuseDifferenceColor(
|
|
shun-iwasawa |
832993 |
QVector3D n, QVector3D base_n, const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
float val = QVector3D::dotProduct(n, vars.sunVec);
|
|
shun-iwasawa |
832993 |
float base_val = QVector3D::dotProduct(base_n, vars.sunVec);
|
|
shun-iwasawa |
832993 |
val = (val - base_val) * 0.5 + 0.5;
|
|
shun-iwasawa |
832993 |
if (val < 0.0)
|
|
shun-iwasawa |
832993 |
val = 0.0;
|
|
shun-iwasawa |
832993 |
else if (val > 1.0)
|
|
shun-iwasawa |
832993 |
val = 1.0;
|
|
shun-iwasawa |
832993 |
return float4{val, val, val, 1.0};
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
inline float4 getSpecularColor(QVector3D n, QVector3D pos,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
QVector3D halfVector =
|
|
shun-iwasawa |
832993 |
((vars.eyePos - pos).normalized() + vars.sunVec).normalized();
|
|
shun-iwasawa |
832993 |
float val = QVector3D::dotProduct(n, halfVector);
|
|
shun-iwasawa |
832993 |
if (val < 0.0) val = 0.0;
|
|
shun-iwasawa |
832993 |
val = std::pow(val, 50.0);
|
|
shun-iwasawa |
832993 |
return float4{val, val, val, 1.0};
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
inline float4 getSpecularDifferenceColor(
|
|
shun-iwasawa |
832993 |
QVector3D n, QVector3D base_n, QVector3D pos, QVector3D base_pos,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
QVector3D halfVector =
|
|
shun-iwasawa |
832993 |
((vars.eyePos - pos).normalized() + vars.sunVec).normalized();
|
|
shun-iwasawa |
832993 |
float ang = std::acos(QVector3D::dotProduct(n, halfVector));
|
|
shun-iwasawa |
832993 |
halfVector =
|
|
shun-iwasawa |
832993 |
((vars.eyePos - base_pos).normalized() + vars.sunVec).normalized();
|
|
shun-iwasawa |
832993 |
float base_ang = std::acos(QVector3D::dotProduct(base_n, halfVector));
|
|
shun-iwasawa |
832993 |
float val = std::abs(ang - base_ang) / M_PI_2;
|
|
shun-iwasawa |
832993 |
if (val > 1.0) val = 1.0;
|
|
shun-iwasawa |
832993 |
return float4{val, val, val, 1.0};
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
inline float4 getFresnelColor(QVector3D n, QVector3D pos,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
float angle =
|
|
shun-iwasawa |
832993 |
acos(QVector3D::dotProduct(n, (vars.eyePos - pos).normalized()));
|
|
shun-iwasawa |
832993 |
float val = (fresnelFactor(angle) - vars.base_fresnel_ref) /
|
|
shun-iwasawa |
832993 |
(1.0f - vars.base_fresnel_ref);
|
|
shun-iwasawa |
832993 |
if (val < 0.0) val = 0.0;
|
|
shun-iwasawa |
832993 |
return float4{val, val, val, 1.0};
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
inline float4 getFresnelDifferenceColor(
|
|
shun-iwasawa |
832993 |
QVector3D n, QVector3D base_n, QVector3D pos,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
float val =
|
|
shun-iwasawa |
832993 |
getFresnelColor(n, pos, vars).x - getFresnelColor(base_n, pos, vars).x;
|
|
shun-iwasawa |
832993 |
if (val < 0.0) val = 0.0;
|
|
shun-iwasawa |
832993 |
return float4{val, val, val, 1.0};
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
// currently the texture is assumed as an image of the bottom WITHOUT WATER.
|
|
shun-iwasawa |
832993 |
// would it be nice to have a mode to handle the texture as
|
|
shun-iwasawa |
832993 |
// an image of the bottom refracted on the surface WITHOUT WAVES?
|
|
shun-iwasawa |
832993 |
inline float4 getRefractionColor(QVector3D n, QVector3D pos,
|
|
shun-iwasawa |
832993 |
float4 *source_host,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
QVector3D eyeVec = (vars.eyePos - pos).normalized();
|
|
shun-iwasawa |
832993 |
// incident angle
|
|
shun-iwasawa |
832993 |
float n_eye = QVector3D::dotProduct(n, eyeVec);
|
|
shun-iwasawa |
832993 |
double angle_inci = acos(n_eye);
|
|
shun-iwasawa |
832993 |
// refraction angle
|
|
shun-iwasawa |
832993 |
double angle_refr = asin(sin(angle_inci) / vars.r_index);
|
|
shun-iwasawa |
832993 |
QVector3D refrRay =
|
|
shun-iwasawa |
832993 |
sin(angle_refr) * (n_eye * n - eyeVec).normalized() - cos(angle_refr) * n;
|
|
shun-iwasawa |
832993 |
double travelLength = -(vars.depth + pos.y()) / refrRay.y();
|
|
shun-iwasawa |
832993 |
QVector3D bottomPos = pos + refrRay * travelLength;
|
|
shun-iwasawa |
832993 |
return getSourcePix(
|
|
shun-iwasawa |
832993 |
QPointF(getXPos(bottomPos, vars),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(bottomPos.z(), bottomPos.y()), vars)),
|
|
shun-iwasawa |
832993 |
source_host, vars);
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline float4 getReflectionColor(QVector3D n, QVector3D pos,
|
|
shun-iwasawa |
832993 |
float4 *source_host,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
// draw nothing behind the reflected object
|
|
shun-iwasawa |
832993 |
if (vars.distance > 0.0 && pos.z() >= vars.distance)
|
|
shun-iwasawa |
832993 |
return float4{0.0, 0.0, 0.0, 0.0};
|
|
shun-iwasawa |
832993 |
QVector3D eyeVec = (vars.eyePos - pos).normalized();
|
|
shun-iwasawa |
832993 |
QVector3D refVec = -eyeVec + 2.0 * QVector3D::dotProduct(eyeVec, n) * n;
|
|
shun-iwasawa |
832993 |
if (refVec.z() <= 0.0) return float4{0.0, 0.0, 0.0, 0.0};
|
|
shun-iwasawa |
832993 |
// if the object is at infinite length, compute the reflected UV by
|
|
shun-iwasawa |
832993 |
// using only the angles of reflection vector
|
|
shun-iwasawa |
832993 |
if (vars.distance < 0.0) {
|
|
shun-iwasawa |
832993 |
double angle_ref_azim = asin(refVec.x());
|
|
shun-iwasawa |
832993 |
double angle_ref_elev = asin(refVec.y());
|
|
shun-iwasawa |
832993 |
double ref_v =
|
|
shun-iwasawa |
832993 |
vars.d_PT * tan(vars.angle_el - angle_ref_elev) + vars.H / 2.0;
|
|
shun-iwasawa |
832993 |
double ref_u =
|
|
shun-iwasawa |
832993 |
vars.d_PT * tan(angle_ref_azim) / cos(vars.angle_el - angle_ref_elev) +
|
|
shun-iwasawa |
832993 |
vars.W / 2.0;
|
|
shun-iwasawa |
832993 |
return getSourcePix(QPointF(ref_u, ref_v), source_host, vars);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
// compute the reflected UV
|
|
shun-iwasawa |
832993 |
double length = (vars.distance - pos.z()) / refVec.z();
|
|
shun-iwasawa |
832993 |
QVector3D boardPos = pos + length * refVec;
|
|
shun-iwasawa |
832993 |
// invert Y coordinate since the texture image is already vertically
|
|
shun-iwasawa |
832993 |
// "reflected"
|
|
shun-iwasawa |
832993 |
boardPos.setY(-boardPos.y());
|
|
shun-iwasawa |
832993 |
return getSourcePix(
|
|
shun-iwasawa |
832993 |
QPointF(getXPos(boardPos, vars),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(boardPos.z(), boardPos.y()), vars)),
|
|
shun-iwasawa |
832993 |
source_host, vars);
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline float4 getColor(QVector3D pre_n, QVector3D cur_n, QVector3D pre_p,
|
|
shun-iwasawa |
832993 |
QVector3D cur_p, float ratio, float4 *source_host,
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars,
|
|
shun-iwasawa |
832993 |
QVector3D pre_base_n = QVector3D(0, 1, 0),
|
|
shun-iwasawa |
832993 |
QVector3D cur_base_n = QVector3D(0, 1, 0),
|
|
shun-iwasawa |
832993 |
QVector3D pre_base_pos = QVector3D(),
|
|
shun-iwasawa |
832993 |
QVector3D cur_base_pos = QVector3D()) {
|
|
shun-iwasawa |
832993 |
if (vars.renderMode == Iwa_FloorBumpFx::DiffuseMode) {
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
return getDiffuseDifferenceColor(
|
|
shun-iwasawa |
832993 |
lerpNormal(pre_n, cur_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpNormal(pre_base_n, cur_base_n, ratio), vars);
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
return getDiffuseColor(lerpNormal(pre_n, cur_n, ratio), vars);
|
|
shun-iwasawa |
832993 |
} else if (vars.renderMode == Iwa_FloorBumpFx::SpecularMode) {
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
return getSpecularDifferenceColor(
|
|
shun-iwasawa |
832993 |
lerpNormal(pre_n, cur_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpNormal(pre_base_n, cur_base_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpPos(pre_p, cur_p, ratio),
|
|
shun-iwasawa |
832993 |
lerpPos(pre_base_pos, cur_base_pos, ratio), vars);
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
return getSpecularColor(lerpNormal(pre_n, cur_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpPos(pre_p, cur_p, ratio), vars);
|
|
shun-iwasawa |
832993 |
} else if (vars.renderMode == Iwa_FloorBumpFx::FresnelMode) {
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
return getFresnelDifferenceColor(
|
|
shun-iwasawa |
832993 |
lerpNormal(pre_n, cur_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpNormal(pre_base_n, cur_base_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpPos(pre_p, cur_p, ratio), vars);
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
return getFresnelColor(lerpNormal(pre_n, cur_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpPos(pre_p, cur_p, ratio), vars);
|
|
shun-iwasawa |
832993 |
} else if (vars.renderMode == Iwa_FloorBumpFx::RefractionMode)
|
|
shun-iwasawa |
832993 |
return getRefractionColor(lerpNormal(pre_n, cur_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpPos(pre_p, cur_p, ratio), source_host, vars);
|
|
shun-iwasawa |
832993 |
else if (vars.renderMode == Iwa_FloorBumpFx::ReflectionMode)
|
|
shun-iwasawa |
832993 |
return getReflectionColor(lerpNormal(pre_n, cur_n, ratio),
|
|
shun-iwasawa |
832993 |
lerpPos(pre_p, cur_p, ratio), source_host, vars);
|
|
shun-iwasawa |
832993 |
};
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
QList<qpointf> getSubPointsList(int subAmount,</qpointf>
|
|
shun-iwasawa |
832993 |
const Iwa_FloorBumpFx::FloorBumpVars &vars) {
|
|
shun-iwasawa |
832993 |
QList<qpointf> ret;</qpointf>
|
|
shun-iwasawa |
832993 |
if (!areAlmostEqual(vars.textureOffsetAmount, 0.0)) {
|
|
shun-iwasawa |
832993 |
for (int su = -subAmount; su <= subAmount; su++) {
|
|
shun-iwasawa |
832993 |
double sub_u = float(su) / float(subAmount);
|
|
shun-iwasawa |
832993 |
for (int sv = -subAmount; sv <= subAmount; sv++) {
|
|
shun-iwasawa |
832993 |
double sub_v = float(sv) / float(subAmount);
|
|
shun-iwasawa |
832993 |
// 円の外ならcontinue
|
|
shun-iwasawa |
832993 |
if (sub_u * sub_u + sub_v * sub_v > 1.0) continue;
|
|
shun-iwasawa |
832993 |
if (su == 0 && sv == 0) continue;
|
|
shun-iwasawa |
832993 |
ret.append(QPointF(vars.spread * sub_u, vars.spread * sub_v));
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
return ret;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
} // namespace
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
Iwa_FloorBumpFx::Iwa_FloorBumpFx()
|
|
shun-iwasawa |
832993 |
: m_renderMode(new TIntEnumParam(TextureMode, "Texture"))
|
|
shun-iwasawa |
832993 |
, m_eyeLevel(0.0)
|
|
shun-iwasawa |
832993 |
, m_drawLevel(-50.0)
|
|
shun-iwasawa |
832993 |
, m_fov(30)
|
|
shun-iwasawa |
832993 |
, m_cameraAltitude(0.0)
|
|
shun-iwasawa |
832993 |
, m_waveHeight(10.0)
|
|
shun-iwasawa |
832993 |
, m_differenceMode(false)
|
|
shun-iwasawa |
832993 |
, m_textureOffsetAmount(0.0)
|
|
shun-iwasawa |
832993 |
, m_textureOffsetSpread(10.0)
|
|
shun-iwasawa |
832993 |
, m_sourcePrecision(300.0 / 162.5)
|
|
shun-iwasawa |
832993 |
, m_souceMargin(0.0)
|
|
shun-iwasawa |
832993 |
, m_displacement(0.0)
|
|
shun-iwasawa |
832993 |
, m_lightAzimuth(-135.0)
|
|
shun-iwasawa |
832993 |
, m_lightElevation(30.0) // default angle_elev will shade horizontal plane
|
|
shun-iwasawa |
832993 |
// 50% gray (cos(60)=0.5)
|
|
shun-iwasawa |
832993 |
, m_depth(30.0)
|
|
shun-iwasawa |
832993 |
, m_refractiveIndex(1.33333)
|
|
shun-iwasawa |
832993 |
, m_distanceLevel(-100.0) {
|
|
shun-iwasawa |
832993 |
addInputPort("Height", m_heightRef);
|
|
shun-iwasawa |
832993 |
addInputPort("Texture", m_texture);
|
|
shun-iwasawa |
832993 |
addInputPort("Displacement", m_dispRef);
|
|
shun-iwasawa |
832993 |
bindParam(this, "renderMode", m_renderMode);
|
|
shun-iwasawa |
832993 |
bindParam(this, "fov", m_fov);
|
|
shun-iwasawa |
832993 |
bindParam(this, "cameraAltitude", m_cameraAltitude);
|
|
shun-iwasawa |
832993 |
bindParam(this, "eyeLevel", m_eyeLevel);
|
|
shun-iwasawa |
832993 |
bindParam(this, "drawLevel", m_drawLevel);
|
|
shun-iwasawa |
832993 |
bindParam(this, "waveHeight", m_waveHeight);
|
|
shun-iwasawa |
832993 |
bindParam(this, "differenceMode", m_differenceMode);
|
|
shun-iwasawa |
832993 |
bindParam(this, "textureOffsetAmount", m_textureOffsetAmount);
|
|
shun-iwasawa |
832993 |
bindParam(this, "textureOffsetSpread", m_textureOffsetSpread);
|
|
shun-iwasawa |
832993 |
bindParam(this, "sourcePrecision", m_sourcePrecision);
|
|
shun-iwasawa |
832993 |
bindParam(this, "souceMargin", m_souceMargin);
|
|
shun-iwasawa |
832993 |
bindParam(this, "displacement", m_displacement);
|
|
shun-iwasawa |
832993 |
bindParam(this, "lightAzimuth", m_lightAzimuth);
|
|
shun-iwasawa |
832993 |
bindParam(this, "lightElevation", m_lightElevation);
|
|
shun-iwasawa |
832993 |
bindParam(this, "depth", m_depth);
|
|
shun-iwasawa |
832993 |
bindParam(this, "refractiveIndex", m_refractiveIndex);
|
|
shun-iwasawa |
832993 |
bindParam(this, "distanceLevel", m_distanceLevel);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
m_renderMode->addItem(DiffuseMode, "Diffuse");
|
|
shun-iwasawa |
832993 |
m_renderMode->addItem(SpecularMode, "Specular");
|
|
shun-iwasawa |
832993 |
m_renderMode->addItem(FresnelMode, "Fresnel reflectivity");
|
|
shun-iwasawa |
832993 |
m_renderMode->addItem(RefractionMode, "Refraction");
|
|
shun-iwasawa |
832993 |
m_renderMode->addItem(ReflectionMode, "Reflection");
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
m_fov->setValueRange(10, 90);
|
|
shun-iwasawa |
832993 |
m_cameraAltitude->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
m_cameraAltitude->setValueRange(0.0, 300.0);
|
|
shun-iwasawa |
832993 |
m_eyeLevel->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
m_drawLevel->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
m_waveHeight->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
m_waveHeight->setValueRange(-1000.0, 1000.0);
|
|
shun-iwasawa |
832993 |
m_textureOffsetAmount->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
m_textureOffsetAmount->setValueRange(-2000.0, 2000.0);
|
|
shun-iwasawa |
832993 |
m_textureOffsetSpread->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
m_textureOffsetSpread->setValueRange(1.0, 300.0);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
m_sourcePrecision->setValueRange(1.0, 2.0);
|
|
shun-iwasawa |
832993 |
m_souceMargin->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
m_souceMargin->setValueRange(0.0, 100.0);
|
|
shun-iwasawa |
832993 |
m_displacement->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
m_displacement->setValueRange(-50.0, 50.0);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
m_lightAzimuth->setValueRange(-360.0, 360.0);
|
|
shun-iwasawa |
832993 |
m_lightElevation->setValueRange(0.0, 90.0);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
m_depth->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
m_depth->setValueRange(0.0, 1000.0);
|
|
shun-iwasawa |
832993 |
m_refractiveIndex->setValueRange(1.0, 3.0);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
m_distanceLevel->setMeasureName("fxLength");
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
bool Iwa_FloorBumpFx::doGetBBox(double frame, TRectD &bBox,
|
|
shun-iwasawa |
832993 |
const TRenderSettings &info) {
|
|
shun-iwasawa |
832993 |
if (m_heightRef.isConnected()) {
|
|
shun-iwasawa |
832993 |
bool ret = m_heightRef->doGetBBox(frame, bBox, info);
|
|
shun-iwasawa |
832993 |
if (ret) bBox = TConsts::infiniteRectD;
|
|
shun-iwasawa |
832993 |
return ret;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
return false;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
bool Iwa_FloorBumpFx::canHandle(const TRenderSettings &info, double frame) {
|
|
shun-iwasawa |
832993 |
return false;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------------------------------
|
|
shun-iwasawa |
832993 |
// convert output values (in float4) to channel value
|
|
shun-iwasawa |
832993 |
//------------------------------------------------------------
|
|
shun-iwasawa |
832993 |
template <typename pixel="" raster,="" typename=""></typename>
|
|
shun-iwasawa |
832993 |
void Iwa_FloorBumpFx::setOutputRaster(float4 *srcMem, const RASTER dstRas,
|
|
shun-iwasawa |
832993 |
TDimensionI dim, int drawLevel) {
|
|
shun-iwasawa |
832993 |
typename PIXEL::Channel halfChan =
|
|
shun-iwasawa |
832993 |
(typename PIXEL::Channel)(PIXEL::maxChannelValue / 2);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
dstRas->fill(PIXEL::Transparent);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
for (int j = 0; j < drawLevel; j++) {
|
|
shun-iwasawa |
832993 |
if (j >= dstRas->getLy()) break;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
PIXEL *pix = dstRas->pixels(j);
|
|
shun-iwasawa |
832993 |
float4 *chan_p = &srcMem[j];
|
|
shun-iwasawa |
832993 |
for (int i = 0; i < dstRas->getLx(); i++, chan_p += drawLevel, pix++) {
|
|
shun-iwasawa |
832993 |
float val;
|
|
shun-iwasawa |
832993 |
val = (*chan_p).x * (float)PIXEL::maxChannelValue + 0.5f;
|
|
shun-iwasawa |
832993 |
pix->r = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
|
|
shun-iwasawa |
832993 |
? (float)PIXEL::maxChannelValue
|
|
shun-iwasawa |
832993 |
: val);
|
|
shun-iwasawa |
832993 |
val = (*chan_p).y * (float)PIXEL::maxChannelValue + 0.5f;
|
|
shun-iwasawa |
832993 |
pix->g = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
|
|
shun-iwasawa |
832993 |
? (float)PIXEL::maxChannelValue
|
|
shun-iwasawa |
832993 |
: val);
|
|
shun-iwasawa |
832993 |
val = (*chan_p).z * (float)PIXEL::maxChannelValue + 0.5f;
|
|
shun-iwasawa |
832993 |
pix->b = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
|
|
shun-iwasawa |
832993 |
? (float)PIXEL::maxChannelValue
|
|
shun-iwasawa |
832993 |
: val);
|
|
shun-iwasawa |
832993 |
val = (*chan_p).w * (float)PIXEL::maxChannelValue + 0.5f;
|
|
shun-iwasawa |
832993 |
pix->m = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue)
|
|
shun-iwasawa |
832993 |
? (float)PIXEL::maxChannelValue
|
|
shun-iwasawa |
832993 |
: val);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
inline void Iwa_FloorBumpFx::initVars(FloorBumpVars &vars, TTile &tile,
|
|
shun-iwasawa |
832993 |
const TRenderSettings &settings,
|
|
shun-iwasawa |
832993 |
double frame) {
|
|
shun-iwasawa |
832993 |
TAffine aff = settings.m_affine;
|
|
shun-iwasawa |
832993 |
double factor = sqrt(std::abs(settings.m_affine.det()));
|
|
shun-iwasawa |
832993 |
double eyeLevel = m_eyeLevel->getValue(frame) * factor;
|
|
shun-iwasawa |
832993 |
double refLevel = m_drawLevel->getValue(frame) * factor;
|
|
shun-iwasawa |
832993 |
vars.waveHeight = m_waveHeight->getValue(frame) * factor;
|
|
shun-iwasawa |
832993 |
vars.displacement = m_displacement->getValue(frame) * factor;
|
|
shun-iwasawa |
832993 |
if (eyeLevel - 1.0 < refLevel) refLevel = eyeLevel - 1.0;
|
|
shun-iwasawa |
832993 |
int drawHeight = std::max(refLevel, vars.waveHeight) - tile.m_pos.y;
|
|
shun-iwasawa |
832993 |
vars.refHeight = int(refLevel - tile.m_pos.y);
|
|
shun-iwasawa |
832993 |
// convert the pixel coordinate from the bottom-left of the camera box
|
|
shun-iwasawa |
832993 |
eyeLevel = eyeLevel - (tile.m_pos.y + tile.getRaster()->getCenterD().y) +
|
|
shun-iwasawa |
832993 |
settings.m_cameraBox.getLy() / 2.0;
|
|
shun-iwasawa |
832993 |
refLevel = refLevel - (tile.m_pos.y + tile.getRaster()->getCenterD().y) +
|
|
shun-iwasawa |
832993 |
settings.m_cameraBox.getLy() / 2.0;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
TRectD rectOut(tile.m_pos, TDimensionD(tile.getRaster()->getLx(),
|
|
shun-iwasawa |
832993 |
tile.getRaster()->getLy()));
|
|
shun-iwasawa |
832993 |
vars.outDim = TDimensionI(rectOut.getLx(), rectOut.getLy());
|
|
shun-iwasawa |
832993 |
vars.resultDim = TDimensionI(rectOut.getLx(),
|
|
shun-iwasawa |
832993 |
std::min(drawHeight, tile.getRaster()->getLy()));
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// get texture image
|
|
shun-iwasawa |
832993 |
vars.margin = tceil(m_souceMargin->getValue(frame) * factor);
|
|
shun-iwasawa |
832993 |
vars.precision = m_sourcePrecision->getValue(frame);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// add margins to all ends and multiply by precision value
|
|
shun-iwasawa |
832993 |
vars.sourceDim = TDimensionI(
|
|
shun-iwasawa |
832993 |
tceil(vars.precision * double(vars.resultDim.lx + vars.margin * 2)),
|
|
shun-iwasawa |
832993 |
tceil(vars.precision * double(vars.resultDim.ly + vars.margin * 2)));
|
|
shun-iwasawa |
832993 |
// only add margins for height image
|
|
shun-iwasawa |
832993 |
vars.refDim = TDimensionI(vars.resultDim.lx + vars.margin * 2,
|
|
shun-iwasawa |
832993 |
vars.refHeight + vars.margin * 2);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// collecting parameters
|
|
shun-iwasawa |
832993 |
double angle_halfFov = m_fov->getValue(frame) * M_PI_180 / 2.0;
|
|
shun-iwasawa |
832993 |
vars.textureOffsetAmount =
|
|
shun-iwasawa |
832993 |
100.0 * m_textureOffsetAmount->getValue(frame) * factor * factor;
|
|
shun-iwasawa |
832993 |
vars.spread = m_textureOffsetSpread->getValue(frame) * factor;
|
|
shun-iwasawa |
832993 |
if (vars.spread < 1.0) vars.spread = 1.0;
|
|
shun-iwasawa |
832993 |
vars.camAltitude = m_cameraAltitude->getValue(frame) * factor;
|
|
shun-iwasawa |
832993 |
vars.differenceMode = m_differenceMode->getValue();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// making pixels in gray128 to be zero level height
|
|
shun-iwasawa |
832993 |
// ( 128/255. IT'S NOT 0.5! )
|
|
shun-iwasawa |
832993 |
vars.zeroLevel = double(128) / double(TPixel32::maxChannelValue);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
vars.H = settings.m_cameraBox.getLy();
|
|
shun-iwasawa |
832993 |
vars.W = settings.m_cameraBox.getLx();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
double el = eyeLevel - vars.H / 2.0;
|
|
shun-iwasawa |
832993 |
// angle between the optical axis and the horizontal axis
|
|
shun-iwasawa |
832993 |
vars.angle_el =
|
|
shun-iwasawa |
832993 |
std::atan(2.0 * el * tan(angle_halfFov) / double(vars.outDim.ly));
|
|
shun-iwasawa |
832993 |
// distance between the Eye (P) and
|
|
shun-iwasawa |
832993 |
// the center of bottom edge of the projection plane (B)
|
|
shun-iwasawa |
832993 |
double d_PB = double(vars.outDim.ly) / (2.0 * sin(angle_halfFov));
|
|
shun-iwasawa |
832993 |
// Y coordinate of the Eye position (P)
|
|
shun-iwasawa |
832993 |
vars.P_y = vars.camAltitude + d_PB * sin((angle_halfFov) + vars.angle_el);
|
|
shun-iwasawa |
832993 |
// distance from the Eye (P) to the center of the projection plane (T)
|
|
shun-iwasawa |
832993 |
vars.d_PT = vars.H / (2.0 * tan(angle_halfFov));
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
QMatrix cam_tilt;
|
|
shun-iwasawa |
832993 |
cam_tilt.rotate(-vars.angle_el / M_PI_180);
|
|
shun-iwasawa |
832993 |
// Z-Y position of the center of top edge of the projection plane (A)
|
|
shun-iwasawa |
832993 |
vars.A =
|
|
shun-iwasawa |
832993 |
cam_tilt.map(QPointF(vars.d_PT, vars.H / 2.0)) + QPointF(0, vars.P_y);
|
|
shun-iwasawa |
832993 |
// Z-Y position of the center of bottom edge of the projection plane (B)
|
|
shun-iwasawa |
832993 |
vars.B =
|
|
shun-iwasawa |
832993 |
cam_tilt.map(QPointF(vars.d_PT, -vars.H / 2.0)) + QPointF(0, vars.P_y);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
vars.C_z = vars.P_y / tan(angle_halfFov + vars.angle_el);
|
|
shun-iwasawa |
832993 |
vars.eyePos = QVector3D(0.0, vars.P_y, 0.0);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
switch (vars.renderMode) {
|
|
shun-iwasawa |
832993 |
// for shading modes ( diffuse & specular )
|
|
shun-iwasawa |
832993 |
case DiffuseMode:
|
|
shun-iwasawa |
832993 |
case SpecularMode: {
|
|
shun-iwasawa |
832993 |
double angle_azim = m_lightAzimuth->getValue(frame) * M_PI_180;
|
|
shun-iwasawa |
832993 |
double angle_elev = m_lightElevation->getValue(frame) * M_PI_180;
|
|
shun-iwasawa |
832993 |
vars.sunVec = QVector3D(sin(angle_azim) * cos(angle_elev), sin(angle_elev),
|
|
shun-iwasawa |
832993 |
cos(angle_azim) * cos(angle_elev));
|
|
shun-iwasawa |
832993 |
break;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
case FresnelMode: { // for fresnel mode
|
|
shun-iwasawa |
832993 |
double angle_base = 0.5 * M_PI - (angle_halfFov + vars.angle_el);
|
|
shun-iwasawa |
832993 |
vars.base_fresnel_ref = fresnelFactor(angle_base);
|
|
shun-iwasawa |
832993 |
break;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
case RefractionMode: {
|
|
shun-iwasawa |
832993 |
// for refraction mode
|
|
shun-iwasawa |
832993 |
vars.depth = m_depth->getValue(frame) * factor;
|
|
shun-iwasawa |
832993 |
vars.r_index = m_refractiveIndex->getValue(frame);
|
|
shun-iwasawa |
832993 |
break;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
case ReflectionMode: {
|
|
shun-iwasawa |
832993 |
// for reflection mode
|
|
shun-iwasawa |
832993 |
double distanceLevel = m_distanceLevel->getValue(frame) * factor;
|
|
shun-iwasawa |
832993 |
double angle_dl = atan(distanceLevel / vars.d_PT);
|
|
shun-iwasawa |
832993 |
// Z-axis distance to the reflected object.
|
|
shun-iwasawa |
832993 |
// distance = -1 means the object is at infinity
|
|
shun-iwasawa |
832993 |
vars.distance = (angle_dl >= vars.angle_el)
|
|
shun-iwasawa |
832993 |
? -1
|
|
shun-iwasawa |
832993 |
: vars.P_y / tan(vars.angle_el - angle_dl);
|
|
shun-iwasawa |
832993 |
break;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
void Iwa_FloorBumpFx::doCompute_CPU(TTile &tile, const double frame,
|
|
shun-iwasawa |
832993 |
const TRenderSettings &settings,
|
|
shun-iwasawa |
832993 |
const FloorBumpVars &vars,
|
|
shun-iwasawa |
832993 |
float4 *source_host, float *ref_host,
|
|
shun-iwasawa |
832993 |
float4 *result_host) {
|
|
shun-iwasawa |
832993 |
//-----------
|
|
shun-iwasawa |
832993 |
// Texture Mode
|
|
shun-iwasawa |
832993 |
if (vars.renderMode == TextureMode) {
|
|
shun-iwasawa |
832993 |
// テクスチャの勾配を調べるサンプリング点
|
|
shun-iwasawa |
832993 |
int subAmount = 10; // これ、パラメータ化するか…?
|
|
shun-iwasawa |
832993 |
QList<qpointf> subPoints = getSubPointsList(subAmount, vars);</qpointf>
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// render pixels in column-major order, from bottom to top
|
|
shun-iwasawa |
832993 |
for (int i = 0; i < vars.resultDim.lx; i++) {
|
|
shun-iwasawa |
832993 |
// cancel check
|
|
shun-iwasawa |
832993 |
if (settings.m_isCanceled && *settings.m_isCanceled) return;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
double maxVPos = 0.0; // maximum height of drawn pixels
|
|
shun-iwasawa |
832993 |
double preVPos = 0.0; // height of the previous segment
|
|
shun-iwasawa |
832993 |
QPointF preUV = QPointF(i, -vars.margin);
|
|
shun-iwasawa |
832993 |
float4 *result_p = &result_host[i * vars.resultDim.ly];
|
|
shun-iwasawa |
832993 |
float4 *end_p = &result_host[(i + 1) * vars.resultDim.ly - 1];
|
|
shun-iwasawa |
832993 |
float preTextureOffset = 0.0;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
bool backled = false;
|
|
shun-iwasawa |
832993 |
double preGrad = 100.0;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// get height pixels from bottom to top
|
|
shun-iwasawa |
832993 |
for (int j = -vars.margin; j < vars.refHeight; j++) {
|
|
shun-iwasawa |
832993 |
// angle between the light axis and the line between (Q) and the eye (P)
|
|
shun-iwasawa |
832993 |
// (Q) is a point on the projection plane at distance of j from (B)
|
|
shun-iwasawa |
832993 |
double angle_Q =
|
|
shun-iwasawa |
832993 |
std::atan((float(j) - (vars.outDim.ly / 2.0)) / vars.d_PT);
|
|
shun-iwasawa |
832993 |
// (R) is an intersection between the XZ plane and the line P->Q
|
|
shun-iwasawa |
832993 |
double R_z = vars.P_y / tan(vars.angle_el - angle_Q);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute (S), a point on the bumped surface in Y-axis direction from
|
|
shun-iwasawa |
832993 |
// (R)
|
|
shun-iwasawa |
832993 |
float refVal =
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), double(j)), ref_host, vars);
|
|
shun-iwasawa |
832993 |
QPointF S(R_z, vars.waveHeight * (refVal - vars.zeroLevel) * 2.0);
|
|
shun-iwasawa |
832993 |
// height of (S) projected on the projection plane
|
|
shun-iwasawa |
832993 |
double vPos = getVPos(S, vars);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// UV coordinate of the texture image
|
|
shun-iwasawa |
832993 |
QPointF currentUV;
|
|
shun-iwasawa |
832993 |
float currentTextureOffset = 0.0;
|
|
shun-iwasawa |
832993 |
if (areAlmostEqual(vars.textureOffsetAmount, 0.0))
|
|
shun-iwasawa |
832993 |
currentUV = QPointF(double(i), getVPos(QPointF(R_z, 0), vars));
|
|
shun-iwasawa |
832993 |
else {
|
|
shun-iwasawa |
832993 |
// length of (1,0,0) vector on the XZ plane, projected on the
|
|
shun-iwasawa |
832993 |
// projection plane
|
|
shun-iwasawa |
832993 |
double dist = (vars.d_PT * sin(vars.angle_el - angle_Q)) / vars.P_y *
|
|
shun-iwasawa |
832993 |
cos(angle_Q);
|
|
shun-iwasawa |
832993 |
// approximate the gradient by difference of the heights of neighbor
|
|
shun-iwasawa |
832993 |
// points
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute gradient of the height image
|
|
shun-iwasawa |
832993 |
QPointF offset;
|
|
shun-iwasawa |
832993 |
for (const QPointF &subPoint : subPoints) {
|
|
shun-iwasawa |
832993 |
// この地点のRefの値を取る
|
|
shun-iwasawa |
832993 |
QPointF subRefPos(double(i) + dist * subPoint.x(),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + subPoint.y(), 0), vars));
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
int sign_u = (subPoint.x() > 0) - (subPoint.x() < 0); // -1, 0, 1
|
|
shun-iwasawa |
832993 |
int sign_v = (subPoint.y() > 0) - (subPoint.y() < 0); // -1, 0, 1
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
float subRefValue = getMapValue(subRefPos, ref_host, vars);
|
|
shun-iwasawa |
832993 |
offset += subRefValue * QPointF(sign_u, sign_v);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
offset *= 1.0 / float(subPoints.count() - subAmount); // サンプル数
|
|
shun-iwasawa |
832993 |
offset *= vars.textureOffsetAmount /
|
|
shun-iwasawa |
832993 |
(vars.spread * (0.5 + 0.5 / float(subAmount))); // 距離
|
|
shun-iwasawa |
832993 |
currentUV = QPointF(double(i) + offset.x() * dist,
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + offset.y(), 0), vars));
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
currentTextureOffset =
|
|
shun-iwasawa |
832993 |
std::sqrt(offset.x() * offset.x() + offset.y() * offset.y()) /
|
|
shun-iwasawa |
832993 |
vars.textureOffsetAmount;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// continue if the current point is behind the forward bumps
|
|
shun-iwasawa |
832993 |
if (vPos <= maxVPos) {
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
preUV = currentUV;
|
|
shun-iwasawa |
832993 |
preTextureOffset = currentTextureOffset;
|
|
shun-iwasawa |
832993 |
continue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// putting colors on pixels
|
|
shun-iwasawa |
832993 |
int currentY = int(std::floor(maxVPos));
|
|
shun-iwasawa |
832993 |
float current_frac = maxVPos - float(currentY);
|
|
shun-iwasawa |
832993 |
int toY = int(std::floor(vPos));
|
|
shun-iwasawa |
832993 |
float to_frac = vPos - float(toY);
|
|
shun-iwasawa |
832993 |
// if the entire current segment is in the same pixel,
|
|
shun-iwasawa |
832993 |
// then add colors with percentage of the fraction part
|
|
shun-iwasawa |
832993 |
if (currentY == toY) {
|
|
shun-iwasawa |
832993 |
float ratio = to_frac - current_frac;
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
*result_p += getTextureOffsetColor(preTextureOffset,
|
|
shun-iwasawa |
832993 |
currentTextureOffset, 0.5) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
*result_p +=
|
|
shun-iwasawa |
832993 |
getSourcePix(lerpUV(preUV, currentUV, 0.5), source_host, vars) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
maxVPos = vPos;
|
|
shun-iwasawa |
832993 |
preUV = currentUV;
|
|
shun-iwasawa |
832993 |
preTextureOffset = currentTextureOffset;
|
|
shun-iwasawa |
832993 |
continue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill fraction part of the start pixel (currentY)
|
|
shun-iwasawa |
832993 |
float k =
|
|
shun-iwasawa |
832993 |
(maxVPos + (1.0 - current_frac) / 2.0 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
float ratio = 1.0 - current_frac;
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
*result_p +=
|
|
shun-iwasawa |
832993 |
getTextureOffsetColor(preTextureOffset, currentTextureOffset, k) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
*result_p +=
|
|
shun-iwasawa |
832993 |
getSourcePix(lerpUV(preUV, currentUV, k), source_host, vars) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
if (result_p == end_p) break;
|
|
shun-iwasawa |
832993 |
result_p++;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill pixels between currentY and toY
|
|
shun-iwasawa |
832993 |
for (int y = currentY + 1; y < toY; y++) {
|
|
shun-iwasawa |
832993 |
k = (float(y) + 0.5 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
*result_p += getTextureOffsetColor(preTextureOffset,
|
|
shun-iwasawa |
832993 |
currentTextureOffset, k);
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
*result_p =
|
|
shun-iwasawa |
832993 |
getSourcePix(lerpUV(preUV, currentUV, k), source_host, vars);
|
|
shun-iwasawa |
832993 |
if (result_p == end_p) break;
|
|
shun-iwasawa |
832993 |
result_p++;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill fraction part of the end pixel (toY)
|
|
shun-iwasawa |
832993 |
k = (float(toY) + to_frac * 0.5 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
*result_p +=
|
|
shun-iwasawa |
832993 |
getTextureOffsetColor(preTextureOffset, currentTextureOffset, k) *
|
|
shun-iwasawa |
832993 |
to_frac;
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
*result_p +=
|
|
shun-iwasawa |
832993 |
getSourcePix(lerpUV(preUV, currentUV, k), source_host, vars) *
|
|
shun-iwasawa |
832993 |
to_frac;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
maxVPos = vPos;
|
|
shun-iwasawa |
832993 |
preUV = currentUV;
|
|
shun-iwasawa |
832993 |
preTextureOffset = currentTextureOffset;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
// Other modes
|
|
shun-iwasawa |
832993 |
// (Diffuse, Specular, Fresnel, Refraction, Reflection)
|
|
shun-iwasawa |
832993 |
else {
|
|
shun-iwasawa |
832993 |
// render pixels in column-major order, from bottom to top
|
|
shun-iwasawa |
832993 |
for (int i = 0; i < vars.resultDim.lx; i++) {
|
|
shun-iwasawa |
832993 |
// cancel check
|
|
shun-iwasawa |
832993 |
if (settings.m_isCanceled && *settings.m_isCanceled) return;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
double maxVPos = 0.0; // maximum height of drawn pixels
|
|
shun-iwasawa |
832993 |
double preVPos = 0.0; // height of the previous segment
|
|
shun-iwasawa |
832993 |
QVector3D preNormal(0, 1, 0);
|
|
shun-iwasawa |
832993 |
QVector3D prePos(i, 0,
|
|
shun-iwasawa |
832993 |
vars.C_z); // actually the x coordinate is not i at the
|
|
shun-iwasawa |
832993 |
// initial position.., but no problem.
|
|
shun-iwasawa |
832993 |
float4 *result_p = &result_host[i * vars.resultDim.ly];
|
|
shun-iwasawa |
832993 |
float4 *end_p = &result_host[(i + 1) * vars.resultDim.ly - 1];
|
|
shun-iwasawa |
832993 |
// get height pixels from bottom to top
|
|
shun-iwasawa |
832993 |
for (int j = -vars.margin; j < vars.refHeight; j++) {
|
|
shun-iwasawa |
832993 |
// angle between the light axis and the line between (Q) and the eye (P)
|
|
shun-iwasawa |
832993 |
// (Q) is a point on the projection plane at distance of j from (B)
|
|
shun-iwasawa |
832993 |
double angle_Q =
|
|
shun-iwasawa |
832993 |
std::atan((float(j) - (vars.outDim.ly / 2.0)) / vars.d_PT);
|
|
shun-iwasawa |
832993 |
// (R) is an intersection between the XZ plane and the line P->Q
|
|
shun-iwasawa |
832993 |
double R_z = vars.P_y / tan(vars.angle_el - angle_Q);
|
|
shun-iwasawa |
832993 |
// In reflection mode, do not draw surface behind the Distance Level
|
|
shun-iwasawa |
832993 |
if (vars.renderMode == ReflectionMode && vars.distance > 0.0 &&
|
|
shun-iwasawa |
832993 |
R_z >= vars.distance)
|
|
shun-iwasawa |
832993 |
break;
|
|
shun-iwasawa |
832993 |
// compute normal vector from cross-product of surface vectors
|
|
shun-iwasawa |
832993 |
QVector3D currentNormal;
|
|
shun-iwasawa |
832993 |
// length of (1,0,0) vector on the XZ plane, projected on the projection
|
|
shun-iwasawa |
832993 |
// plane
|
|
shun-iwasawa |
832993 |
double dist = (vars.d_PT * sin(vars.angle_el - angle_Q)) / vars.P_y *
|
|
shun-iwasawa |
832993 |
cos(angle_Q);
|
|
shun-iwasawa |
832993 |
double xRefGrad =
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i) + dist, double(j)), ref_host, vars) -
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i) - dist, double(j)), ref_host, vars);
|
|
shun-iwasawa |
832993 |
double zRefGrad =
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), getVPos(QPointF(R_z + 1, 0), vars)),
|
|
shun-iwasawa |
832993 |
ref_host, vars) -
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), getVPos(QPointF(R_z - 1, 0), vars)),
|
|
shun-iwasawa |
832993 |
ref_host, vars);
|
|
shun-iwasawa |
832993 |
currentNormal.setX(-xRefGrad * vars.waveHeight * 2.0);
|
|
shun-iwasawa |
832993 |
currentNormal.setY(4.0);
|
|
shun-iwasawa |
832993 |
currentNormal.setZ(-zRefGrad * vars.waveHeight * 2.0);
|
|
shun-iwasawa |
832993 |
currentNormal.normalize();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute (S), a point on the bumped surface in Y-axis direction from
|
|
shun-iwasawa |
832993 |
// (R)
|
|
shun-iwasawa |
832993 |
float refVal =
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), double(j)), ref_host, vars);
|
|
shun-iwasawa |
832993 |
QPointF S(R_z, vars.waveHeight * (refVal - vars.zeroLevel) * 2.0);
|
|
shun-iwasawa |
832993 |
// height of (S) projected on the projection plane
|
|
shun-iwasawa |
832993 |
double vPos = getVPos(S, vars);
|
|
shun-iwasawa |
832993 |
QVector3D currentPos(double(i - vars.resultDim.lx / 2) / dist, S.y(),
|
|
shun-iwasawa |
832993 |
S.x());
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// continue if the current point is behind the forward bumps
|
|
shun-iwasawa |
832993 |
if (vPos <= maxVPos) {
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
preNormal = currentNormal;
|
|
shun-iwasawa |
832993 |
prePos = currentPos;
|
|
shun-iwasawa |
832993 |
continue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// putting colors on pixels
|
|
shun-iwasawa |
832993 |
int currentY = int(std::floor(maxVPos));
|
|
shun-iwasawa |
832993 |
float current_frac = maxVPos - float(currentY);
|
|
shun-iwasawa |
832993 |
int toY = int(std::floor(vPos));
|
|
shun-iwasawa |
832993 |
float to_frac = vPos - float(toY);
|
|
shun-iwasawa |
832993 |
// if the entire current segment is in the same pixel,
|
|
shun-iwasawa |
832993 |
// then add colors with percentage of the fraction part
|
|
shun-iwasawa |
832993 |
if (currentY == toY) {
|
|
shun-iwasawa |
832993 |
float ratio = to_frac - current_frac;
|
|
shun-iwasawa |
832993 |
*result_p += getColor(preNormal, currentNormal, prePos, currentPos,
|
|
shun-iwasawa |
832993 |
0.5, source_host, vars) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
maxVPos = vPos;
|
|
shun-iwasawa |
832993 |
preNormal = currentNormal;
|
|
shun-iwasawa |
832993 |
prePos = currentPos;
|
|
shun-iwasawa |
832993 |
continue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill fraction part of the start pixel (currentY)
|
|
shun-iwasawa |
832993 |
float k =
|
|
shun-iwasawa |
832993 |
(maxVPos + (1.0 - current_frac) / 2.0 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
float4 color = getColor(preNormal, currentNormal, prePos, currentPos, k,
|
|
shun-iwasawa |
832993 |
source_host, vars);
|
|
shun-iwasawa |
832993 |
float ratio = 1.0 - current_frac;
|
|
shun-iwasawa |
832993 |
*result_p += color * ratio;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
if (result_p == end_p) break;
|
|
shun-iwasawa |
832993 |
result_p++;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill pixels between currentY and toY
|
|
shun-iwasawa |
832993 |
for (int y = currentY + 1; y < toY; y++) {
|
|
shun-iwasawa |
832993 |
k = (float(y) + 0.5 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
*result_p = getColor(preNormal, currentNormal, prePos, currentPos, k,
|
|
shun-iwasawa |
832993 |
source_host, vars);
|
|
shun-iwasawa |
832993 |
if (result_p == end_p) break;
|
|
shun-iwasawa |
832993 |
result_p++;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill fraction part of the end pixel (toY)
|
|
shun-iwasawa |
832993 |
k = (float(toY) + to_frac * 0.5 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
color = getColor(preNormal, currentNormal, prePos, currentPos, k,
|
|
shun-iwasawa |
832993 |
source_host, vars);
|
|
shun-iwasawa |
832993 |
*result_p += color * to_frac;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
maxVPos = vPos;
|
|
shun-iwasawa |
832993 |
preNormal = currentNormal;
|
|
shun-iwasawa |
832993 |
prePos = currentPos;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
void Iwa_FloorBumpFx::doCompute_with_Displacement(
|
|
shun-iwasawa |
832993 |
TTile &tile, const double frame, const TRenderSettings &settings,
|
|
shun-iwasawa |
832993 |
const FloorBumpVars &vars, float4 *source_host, float *ref_host,
|
|
shun-iwasawa |
832993 |
float *disp_host, float4 *result_host) {
|
|
shun-iwasawa |
832993 |
//----- Lambdas ------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// テクスチャの勾配を調べるサンプリング点
|
|
shun-iwasawa |
832993 |
int subAmount = 10; // これ、パラメータ化するか…?
|
|
shun-iwasawa |
832993 |
QList<qpointf> subPoints = getSubPointsList(subAmount, vars);</qpointf>
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//-----------
|
|
shun-iwasawa |
832993 |
// Texture Mode
|
|
shun-iwasawa |
832993 |
if (vars.renderMode == TextureMode) {
|
|
shun-iwasawa |
832993 |
// render pixels in column-major order, from bottom to top
|
|
shun-iwasawa |
832993 |
for (int i = 0; i < vars.resultDim.lx; i++) {
|
|
shun-iwasawa |
832993 |
// cancel check
|
|
shun-iwasawa |
832993 |
if (settings.m_isCanceled && *settings.m_isCanceled) return;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
double maxVPos = 0.0; // maximum height of drawn pixels
|
|
shun-iwasawa |
832993 |
double preVPos = 0.0; // height of the previous segment
|
|
shun-iwasawa |
832993 |
QPointF preUV = QPointF(i, -vars.margin);
|
|
shun-iwasawa |
832993 |
float4 *result_p = &result_host[i * vars.resultDim.ly];
|
|
shun-iwasawa |
832993 |
float4 *end_p = &result_host[(i + 1) * vars.resultDim.ly - 1];
|
|
shun-iwasawa |
832993 |
float preTextureOffset = 0.0;
|
|
shun-iwasawa |
832993 |
// get height pixels from bottom to top
|
|
shun-iwasawa |
832993 |
for (int j = -vars.margin; j < vars.refHeight; j++) {
|
|
shun-iwasawa |
832993 |
// angle between the light axis and the line between (Q) and the eye (P)
|
|
shun-iwasawa |
832993 |
// (Q) is a point on the projection plane at distance of j from (B)
|
|
shun-iwasawa |
832993 |
double angle_Q =
|
|
shun-iwasawa |
832993 |
std::atan((float(j) - (vars.outDim.ly / 2.0)) / vars.d_PT);
|
|
shun-iwasawa |
832993 |
// (R) is an intersection between the XZ plane and the line P->Q
|
|
shun-iwasawa |
832993 |
double R_z = vars.P_y / tan(vars.angle_el - angle_Q);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute (S), a point on the bumped surface in Y-axis direction from
|
|
shun-iwasawa |
832993 |
// (R)
|
|
shun-iwasawa |
832993 |
float refVal =
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), double(j)), ref_host, vars);
|
|
shun-iwasawa |
832993 |
QPointF S(R_z, vars.waveHeight * (refVal - vars.zeroLevel) * 2.0);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// length of (1,0,0) vector on the XZ plane, projected on the
|
|
shun-iwasawa |
832993 |
// projection plane
|
|
shun-iwasawa |
832993 |
double dist = (vars.d_PT * sin(vars.angle_el - angle_Q)) / vars.P_y *
|
|
shun-iwasawa |
832993 |
cos(angle_Q);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// UV coordinate of the texture image
|
|
shun-iwasawa |
832993 |
QVector3D uvOffset;
|
|
shun-iwasawa |
832993 |
float currentTextureOffset = 0.0;
|
|
shun-iwasawa |
832993 |
if (vars.textureOffsetAmount == 0.0) {
|
|
shun-iwasawa |
832993 |
// currentUV = QPointF(double(i), getVPos(QPointF(R_z, 0)));
|
|
shun-iwasawa |
832993 |
} else {
|
|
shun-iwasawa |
832993 |
// approximate the gradient by difference of the heights of neighbor
|
|
shun-iwasawa |
832993 |
// points
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute gradient of the height image
|
|
shun-iwasawa |
832993 |
QPointF offset;
|
|
shun-iwasawa |
832993 |
for (const QPointF &subPoint : subPoints) {
|
|
shun-iwasawa |
832993 |
// この地点のRefの値を取る
|
|
shun-iwasawa |
832993 |
QPointF subRefPos(double(i) + dist * subPoint.x(),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + subPoint.y(), 0), vars));
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
int sign_u = (subPoint.x() > 0) - (subPoint.x() < 0); // -1, 0, 1
|
|
shun-iwasawa |
832993 |
int sign_v = (subPoint.y() > 0) - (subPoint.y() < 0); // -1, 0, 1
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
float subRefValue = getMapValue(subRefPos, ref_host, vars);
|
|
shun-iwasawa |
832993 |
offset += subRefValue * QPointF(sign_u, sign_v);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
offset *= 1.0 / float(subPoints.count() - subAmount); // サンプル数
|
|
shun-iwasawa |
832993 |
offset *= vars.textureOffsetAmount /
|
|
shun-iwasawa |
832993 |
(vars.spread * (0.5 + 0.5 / float(subAmount))); // 距離
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
uvOffset.setX(offset.x() * dist);
|
|
shun-iwasawa |
832993 |
uvOffset.setZ(offset.y());
|
|
shun-iwasawa |
832993 |
// currentUV = QPointF(double(i) + offset.x() * dist,
|
|
shun-iwasawa |
832993 |
// getVPos(QPointF(R_z + offset.y(), 0)));
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
currentTextureOffset =
|
|
shun-iwasawa |
832993 |
1000 *
|
|
shun-iwasawa |
832993 |
std::sqrt(offset.x() * offset.x() + offset.y() * offset.y()) /
|
|
shun-iwasawa |
832993 |
vars.textureOffsetAmount;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
QPointF currentDispUV =
|
|
shun-iwasawa |
832993 |
QPointF(double(i) + uvOffset.x(),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + uvOffset.z(), 0), vars));
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// この地点の変位の値を取得する
|
|
shun-iwasawa |
832993 |
float dispValue = getMapValue(currentDispUV, disp_host, vars);
|
|
shun-iwasawa |
832993 |
float dispHeight = dispValue * vars.displacement;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// この地点の法線を取得
|
|
shun-iwasawa |
832993 |
QVector3D currentNormal;
|
|
shun-iwasawa |
832993 |
double xRefGrad =
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i) + dist, double(j)), ref_host, vars) -
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i) - dist, double(j)), ref_host, vars);
|
|
shun-iwasawa |
832993 |
double zRefGrad =
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), getVPos(QPointF(R_z + 1, 0), vars)),
|
|
shun-iwasawa |
832993 |
ref_host, vars) -
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), getVPos(QPointF(R_z - 1, 0), vars)),
|
|
shun-iwasawa |
832993 |
ref_host, vars);
|
|
shun-iwasawa |
832993 |
currentNormal.setX(-xRefGrad * vars.waveHeight * 2.0);
|
|
shun-iwasawa |
832993 |
currentNormal.setY(4.0);
|
|
shun-iwasawa |
832993 |
currentNormal.setZ(-zRefGrad * vars.waveHeight * 2.0);
|
|
shun-iwasawa |
832993 |
currentNormal.normalize();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// 変位後の表面座標 (M)
|
|
shun-iwasawa |
832993 |
// ※法線のX成分は強引にY座標の変位に持ち込んで近似する
|
|
shun-iwasawa |
832993 |
float dispXY = std::sqrt(currentNormal.x() * currentNormal.x() +
|
|
shun-iwasawa |
832993 |
currentNormal.y() * currentNormal.y());
|
|
shun-iwasawa |
832993 |
QPointF M = S + QPointF(currentNormal.z(), dispXY) * dispHeight;
|
|
shun-iwasawa |
832993 |
// float dispXRatio = std::sqrt(currentNormal.x()*currentNormal.x() +
|
|
shun-iwasawa |
832993 |
// currentNormal.y()*currentNormal.y()) / currentNormal.y(); QPointF M =
|
|
shun-iwasawa |
832993 |
// S + QPointF(currentNormal.z(), currentNormal.y()* dispXRatio) *
|
|
shun-iwasawa |
832993 |
// dispHeight;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// height of (M) projected on the projection plane
|
|
shun-iwasawa |
832993 |
double vPos = getVPos(M, vars);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
uvOffset.setY(dispHeight);
|
|
shun-iwasawa |
832993 |
QPointF currentUV =
|
|
shun-iwasawa |
832993 |
QPointF(double(i) + uvOffset.x(),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + uvOffset.z(), uvOffset.y()), vars));
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// 手前のDisplacementで隠されている部分かどうかの判定
|
|
shun-iwasawa |
832993 |
bool isBehind = false;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
if (preUV.y() > currentUV.y()) isBehind = true;
|
|
shun-iwasawa |
832993 |
/*
|
|
shun-iwasawa |
832993 |
if ((vars.displacement > 0.0 && dispValue < 1.0) ||
|
|
shun-iwasawa |
832993 |
(vars.displacement < 0.0 && dispValue > 0.0)) {
|
|
shun-iwasawa |
832993 |
QPointF dUV = (currentDispUV - currentUV) * 0.1;
|
|
shun-iwasawa |
832993 |
QPointF tmpUV = currentUV + dUV;
|
|
shun-iwasawa |
832993 |
float dHeight = dispHeight * 0.1;
|
|
shun-iwasawa |
832993 |
float tmpHeight = dHeight;
|
|
shun-iwasawa |
832993 |
for (int k = 1; k < 10; k++, tmpUV += dUV, tmpHeight += dHeight) {
|
|
shun-iwasawa |
832993 |
if (getMapValue(tmpUV, disp_host, vars) * vars.displacement >
|
|
shun-iwasawa |
832993 |
tmpHeight) {
|
|
shun-iwasawa |
832993 |
isBehind = true;
|
|
shun-iwasawa |
832993 |
break;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}*/
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// continue if the current point is behind the forward bumps
|
|
shun-iwasawa |
832993 |
if (vPos <= maxVPos) {
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
if (!isBehind) preUV = currentUV;
|
|
shun-iwasawa |
832993 |
preTextureOffset = currentTextureOffset;
|
|
shun-iwasawa |
832993 |
continue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// putting colors on pixels
|
|
shun-iwasawa |
832993 |
int currentY = int(std::floor(maxVPos));
|
|
shun-iwasawa |
832993 |
float current_frac = maxVPos - float(currentY);
|
|
shun-iwasawa |
832993 |
int toY = int(std::floor(vPos));
|
|
shun-iwasawa |
832993 |
float to_frac = vPos - float(toY);
|
|
shun-iwasawa |
832993 |
// if the entire current segment is in the same pixel,
|
|
shun-iwasawa |
832993 |
// then add colors with percentage of the fraction part
|
|
shun-iwasawa |
832993 |
if (currentY == toY) {
|
|
shun-iwasawa |
832993 |
if (!isBehind) {
|
|
shun-iwasawa |
832993 |
float ratio = to_frac - current_frac;
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
*result_p += getTextureOffsetColor(preTextureOffset,
|
|
shun-iwasawa |
832993 |
currentTextureOffset, 0.5) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
*result_p += getSourcePix(lerpUV(preUV, currentUV, 0.5),
|
|
shun-iwasawa |
832993 |
source_host, vars) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
preUV = currentUV;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
maxVPos = vPos;
|
|
shun-iwasawa |
832993 |
preTextureOffset = currentTextureOffset;
|
|
shun-iwasawa |
832993 |
continue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill fraction part of the start pixel (currentY)
|
|
shun-iwasawa |
832993 |
if (!isBehind) {
|
|
shun-iwasawa |
832993 |
float k = (maxVPos + (1.0 - current_frac) / 2.0 - preVPos) /
|
|
shun-iwasawa |
832993 |
(vPos - preVPos);
|
|
shun-iwasawa |
832993 |
float ratio = 1.0 - current_frac;
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
*result_p += getTextureOffsetColor(preTextureOffset,
|
|
shun-iwasawa |
832993 |
currentTextureOffset, k) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
*result_p +=
|
|
shun-iwasawa |
832993 |
getSourcePix(lerpUV(preUV, currentUV, k), source_host, vars) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
if (result_p == end_p) break;
|
|
shun-iwasawa |
832993 |
result_p++;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill pixels between currentY and toY
|
|
shun-iwasawa |
832993 |
for (int y = currentY + 1; y < toY; y++) {
|
|
shun-iwasawa |
832993 |
if (!isBehind) {
|
|
shun-iwasawa |
832993 |
float k = (float(y) + 0.5 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
*result_p += getTextureOffsetColor(preTextureOffset,
|
|
shun-iwasawa |
832993 |
currentTextureOffset, k);
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
*result_p =
|
|
shun-iwasawa |
832993 |
getSourcePix(lerpUV(preUV, currentUV, k), source_host, vars);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
if (result_p == end_p) break;
|
|
shun-iwasawa |
832993 |
result_p++;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill fraction part of the end pixel (toY)
|
|
shun-iwasawa |
832993 |
if (!isBehind) {
|
|
shun-iwasawa |
832993 |
float k = (float(toY) + to_frac * 0.5 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode)
|
|
shun-iwasawa |
832993 |
*result_p += getTextureOffsetColor(preTextureOffset,
|
|
shun-iwasawa |
832993 |
currentTextureOffset, k) *
|
|
shun-iwasawa |
832993 |
to_frac;
|
|
shun-iwasawa |
832993 |
else
|
|
shun-iwasawa |
832993 |
*result_p +=
|
|
shun-iwasawa |
832993 |
getSourcePix(lerpUV(preUV, currentUV, k), source_host, vars) *
|
|
shun-iwasawa |
832993 |
to_frac;
|
|
shun-iwasawa |
832993 |
preUV = currentUV;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
maxVPos = vPos;
|
|
shun-iwasawa |
832993 |
preTextureOffset = currentTextureOffset;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
// Other modes
|
|
shun-iwasawa |
832993 |
// (Diffuse, Specular, Fresnel, Refraction, Reflection)
|
|
shun-iwasawa |
832993 |
else {
|
|
shun-iwasawa |
832993 |
// render pixels in column-major order, from bottom to top
|
|
shun-iwasawa |
832993 |
for (int i = 0; i < vars.resultDim.lx; i++) {
|
|
shun-iwasawa |
832993 |
// cancel check
|
|
shun-iwasawa |
832993 |
if (settings.m_isCanceled && *settings.m_isCanceled) return;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
double maxVPos = 0.0; // maximum height of drawn pixels
|
|
shun-iwasawa |
832993 |
double preVPos = 0.0; // height of the previous segment
|
|
shun-iwasawa |
832993 |
QVector3D preDispNormal(0, 1, 0);
|
|
shun-iwasawa |
832993 |
QVector3D preBaseNormal(0, 1, 0);
|
|
shun-iwasawa |
832993 |
QVector3D prePos(i, 0,
|
|
shun-iwasawa |
832993 |
vars.C_z); // actually the x coordinate is not i at the
|
|
shun-iwasawa |
832993 |
// initial position.., but no problem.
|
|
shun-iwasawa |
832993 |
QVector3D preBasePos(i, 0, vars.C_z);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
float4 *result_p = &result_host[i * vars.resultDim.ly];
|
|
shun-iwasawa |
832993 |
float4 *end_p = &result_host[(i + 1) * vars.resultDim.ly - 1];
|
|
shun-iwasawa |
832993 |
// get height pixels from bottom to top
|
|
shun-iwasawa |
832993 |
for (int j = -vars.margin; j < vars.refHeight; j++) {
|
|
shun-iwasawa |
832993 |
// angle between the light axis and the line between (Q) and the eye (P)
|
|
shun-iwasawa |
832993 |
// (Q) is a point on the projection plane at distance of j from (B)
|
|
shun-iwasawa |
832993 |
double angle_Q =
|
|
shun-iwasawa |
832993 |
std::atan((float(j) - (vars.outDim.ly / 2.0)) / vars.d_PT);
|
|
shun-iwasawa |
832993 |
// (R) is an intersection between the XZ plane and the line P->Q
|
|
shun-iwasawa |
832993 |
double R_z = vars.P_y / tan(vars.angle_el - angle_Q);
|
|
shun-iwasawa |
832993 |
// In reflection mode, do not draw surface behind the Distance Level
|
|
shun-iwasawa |
832993 |
if (vars.renderMode == ReflectionMode && vars.distance > 0.0 &&
|
|
shun-iwasawa |
832993 |
R_z >= vars.distance)
|
|
shun-iwasawa |
832993 |
break;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute (S), a point on the bumped surface in Y-axis direction from
|
|
shun-iwasawa |
832993 |
// (R)
|
|
shun-iwasawa |
832993 |
float refVal =
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), double(j)), ref_host, vars);
|
|
shun-iwasawa |
832993 |
QPointF S(R_z, vars.waveHeight * (refVal - vars.zeroLevel) * 2.0);
|
|
shun-iwasawa |
832993 |
// length of (1,0,0) vector on the XZ plane, projected on the projection
|
|
shun-iwasawa |
832993 |
// plane
|
|
shun-iwasawa |
832993 |
double dist = (vars.d_PT * sin(vars.angle_el - angle_Q)) / vars.P_y *
|
|
shun-iwasawa |
832993 |
cos(angle_Q);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// UV coordinate of the texture image
|
|
shun-iwasawa |
832993 |
QVector3D uvOffset;
|
|
shun-iwasawa |
832993 |
if (vars.textureOffsetAmount == 0.0) {
|
|
shun-iwasawa |
832993 |
// currentUV = QPointF(double(i), getVPos(QPointF(R_z, 0)));
|
|
shun-iwasawa |
832993 |
} else {
|
|
shun-iwasawa |
832993 |
// approximate the gradient by difference of the heights of neighbor
|
|
shun-iwasawa |
832993 |
// points
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute gradient of the height image
|
|
shun-iwasawa |
832993 |
QPointF offset;
|
|
shun-iwasawa |
832993 |
for (const QPointF &subPoint : subPoints) {
|
|
shun-iwasawa |
832993 |
// この地点のRefの値を取る
|
|
shun-iwasawa |
832993 |
QPointF subRefPos(double(i) + dist * subPoint.x(),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + subPoint.y(), 0), vars));
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
int sign_u = (subPoint.x() > 0) - (subPoint.x() < 0); // -1, 0, 1
|
|
shun-iwasawa |
832993 |
int sign_v = (subPoint.y() > 0) - (subPoint.y() < 0); // -1, 0, 1
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
float subRefValue = getMapValue(subRefPos, ref_host, vars);
|
|
shun-iwasawa |
832993 |
offset += subRefValue * QPointF(sign_u, sign_v);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
offset *= 1.0 / float(subPoints.count() - subAmount); // サンプル数
|
|
shun-iwasawa |
832993 |
offset *= vars.textureOffsetAmount /
|
|
shun-iwasawa |
832993 |
(vars.spread * (0.5 + 0.5 / float(subAmount))); // 距離
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
uvOffset.setX(offset.x() * dist);
|
|
shun-iwasawa |
832993 |
uvOffset.setZ(offset.y());
|
|
shun-iwasawa |
832993 |
// currentUV = QPointF(double(i) + offset.x() * dist,
|
|
shun-iwasawa |
832993 |
// getVPos(QPointF(R_z + offset.y(), 0)));
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
QPointF currentDispUV =
|
|
shun-iwasawa |
832993 |
QPointF(double(i) + uvOffset.x(),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + uvOffset.z(), 0), vars));
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// この地点の変位の値を取得する
|
|
shun-iwasawa |
832993 |
float dispHeight =
|
|
shun-iwasawa |
832993 |
getMapValue(currentDispUV, disp_host, vars) * vars.displacement;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute normal vector from cross-product of surface vectors
|
|
shun-iwasawa |
832993 |
QVector3D rightPos(
|
|
shun-iwasawa |
832993 |
1.0,
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i) + dist, double(j)), ref_host, vars) *
|
|
shun-iwasawa |
832993 |
vars.waveHeight,
|
|
shun-iwasawa |
832993 |
0.0);
|
|
shun-iwasawa |
832993 |
QVector3D leftPos(
|
|
shun-iwasawa |
832993 |
-1.0,
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i) - dist, double(j)), ref_host, vars) *
|
|
shun-iwasawa |
832993 |
vars.waveHeight,
|
|
shun-iwasawa |
832993 |
0.0);
|
|
shun-iwasawa |
832993 |
QVector3D farPos(
|
|
shun-iwasawa |
832993 |
0.0,
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), getVPos(QPointF(R_z + 1, 0), vars)),
|
|
shun-iwasawa |
832993 |
ref_host, vars) *
|
|
shun-iwasawa |
832993 |
vars.waveHeight,
|
|
shun-iwasawa |
832993 |
1.0);
|
|
shun-iwasawa |
832993 |
QVector3D nearPos(
|
|
shun-iwasawa |
832993 |
0.0,
|
|
shun-iwasawa |
832993 |
getMapValue(QPointF(double(i), getVPos(QPointF(R_z - 1, 0), vars)),
|
|
shun-iwasawa |
832993 |
ref_host, vars) *
|
|
shun-iwasawa |
832993 |
vars.waveHeight,
|
|
shun-iwasawa |
832993 |
-1.0);
|
|
shun-iwasawa |
832993 |
// 左手系座標なので外積を反転する
|
|
shun-iwasawa |
832993 |
QVector3D currentNormal =
|
|
shun-iwasawa |
832993 |
-QVector3D::crossProduct(rightPos - leftPos, farPos - nearPos);
|
|
shun-iwasawa |
832993 |
currentNormal.normalize();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// 変位後の表面座標 (M)
|
|
shun-iwasawa |
832993 |
// ※法線のX成分は強引にY座標の変位に持ち込んで近似する
|
|
shun-iwasawa |
832993 |
float dispXY = std::sqrt(currentNormal.x() * currentNormal.x() +
|
|
shun-iwasawa |
832993 |
currentNormal.y() * currentNormal.y());
|
|
shun-iwasawa |
832993 |
QPointF M = S + QPointF(currentNormal.z(), dispXY) * dispHeight;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// 前後左右の座標に変位を加える
|
|
shun-iwasawa |
832993 |
QPointF rightDispUV = currentDispUV + QPointF(dist, 0);
|
|
shun-iwasawa |
832993 |
QPointF leftDispUV = currentDispUV + QPointF(-dist, 0);
|
|
shun-iwasawa |
832993 |
QPointF farDispUV(currentDispUV.x(),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + uvOffset.z() + 1, 0), vars));
|
|
shun-iwasawa |
832993 |
QPointF nearDispUV(currentDispUV.x(),
|
|
shun-iwasawa |
832993 |
getVPos(QPointF(R_z + uvOffset.z() - 1, 0), vars));
|
|
shun-iwasawa |
832993 |
float rightDispHeight =
|
|
shun-iwasawa |
832993 |
getMapValue(rightDispUV, disp_host, vars) * vars.displacement;
|
|
shun-iwasawa |
832993 |
float leftDispHeight =
|
|
shun-iwasawa |
832993 |
getMapValue(leftDispUV, disp_host, vars) * vars.displacement;
|
|
shun-iwasawa |
832993 |
float farDispHeight =
|
|
shun-iwasawa |
832993 |
getMapValue(farDispUV, disp_host, vars) * vars.displacement;
|
|
shun-iwasawa |
832993 |
float nearDispHeight =
|
|
shun-iwasawa |
832993 |
getMapValue(nearDispUV, disp_host, vars) * vars.displacement;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
rightPos += currentNormal * rightDispHeight;
|
|
shun-iwasawa |
832993 |
leftPos += currentNormal * leftDispHeight;
|
|
shun-iwasawa |
832993 |
farPos += currentNormal * farDispHeight;
|
|
shun-iwasawa |
832993 |
nearPos += currentNormal * nearDispHeight;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// 外積で法線を求める 左手系座標なので外積を反転する
|
|
shun-iwasawa |
832993 |
QVector3D dispNormal =
|
|
shun-iwasawa |
832993 |
-QVector3D::crossProduct(rightPos - leftPos, farPos - nearPos);
|
|
shun-iwasawa |
832993 |
dispNormal.normalize();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// height of (M) projected on the projection plane
|
|
shun-iwasawa |
832993 |
double vPos = getVPos(M, vars);
|
|
shun-iwasawa |
832993 |
QVector3D currentPos(double(i - vars.resultDim.lx / 2) / dist, M.y(),
|
|
shun-iwasawa |
832993 |
M.x());
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// Diffuse差分取得のために、変形無しの状態の法線を取得する
|
|
shun-iwasawa |
832993 |
QVector3D baseNormal;
|
|
shun-iwasawa |
832993 |
// Specular差分取得のために、変形無しの状態の位置も取得
|
|
shun-iwasawa |
832993 |
QVector3D basePos;
|
|
shun-iwasawa |
832993 |
if (vars.differenceMode) {
|
|
shun-iwasawa |
832993 |
baseNormal = -QVector3D::crossProduct(
|
|
shun-iwasawa |
832993 |
QVector3D(2.0, rightDispHeight - leftDispHeight, 0.0),
|
|
shun-iwasawa |
832993 |
QVector3D(0.0, farDispHeight - nearDispHeight, 2.0));
|
|
shun-iwasawa |
832993 |
basePos = QVector3D(currentPos.x() + uvOffset.x() / dist, dispHeight,
|
|
shun-iwasawa |
832993 |
currentPos.z() + uvOffset.z());
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// continue if the current point is behind the forward bumps
|
|
shun-iwasawa |
832993 |
if (vPos <= maxVPos) {
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
preDispNormal = dispNormal;
|
|
shun-iwasawa |
832993 |
preBaseNormal = baseNormal;
|
|
shun-iwasawa |
832993 |
prePos = currentPos;
|
|
shun-iwasawa |
832993 |
preBasePos = basePos;
|
|
shun-iwasawa |
832993 |
continue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// putting colors on pixels
|
|
shun-iwasawa |
832993 |
int currentY = int(std::floor(maxVPos));
|
|
shun-iwasawa |
832993 |
float current_frac = maxVPos - float(currentY);
|
|
shun-iwasawa |
832993 |
int toY = int(std::floor(vPos));
|
|
shun-iwasawa |
832993 |
float to_frac = vPos - float(toY);
|
|
shun-iwasawa |
832993 |
// if the entire current segment is in the same pixel,
|
|
shun-iwasawa |
832993 |
// then add colors with percentage of the fraction part
|
|
shun-iwasawa |
832993 |
if (currentY == toY) {
|
|
shun-iwasawa |
832993 |
float ratio = to_frac - current_frac;
|
|
shun-iwasawa |
832993 |
*result_p += getColor(preDispNormal, dispNormal, prePos, currentPos,
|
|
shun-iwasawa |
832993 |
0.5, source_host, vars, preBaseNormal,
|
|
shun-iwasawa |
832993 |
baseNormal, preBasePos, basePos) *
|
|
shun-iwasawa |
832993 |
ratio;
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
maxVPos = vPos;
|
|
shun-iwasawa |
832993 |
preDispNormal = dispNormal;
|
|
shun-iwasawa |
832993 |
preBaseNormal = baseNormal;
|
|
shun-iwasawa |
832993 |
prePos = currentPos;
|
|
shun-iwasawa |
832993 |
preBasePos = basePos;
|
|
shun-iwasawa |
832993 |
continue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill fraction part of the start pixel (currentY)
|
|
shun-iwasawa |
832993 |
float k =
|
|
shun-iwasawa |
832993 |
(maxVPos + (1.0 - current_frac) / 2.0 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
float4 color = getColor(preDispNormal, dispNormal, prePos, currentPos,
|
|
shun-iwasawa |
832993 |
k, source_host, vars, preBaseNormal, baseNormal,
|
|
shun-iwasawa |
832993 |
preBasePos, basePos);
|
|
shun-iwasawa |
832993 |
float ratio = 1.0 - current_frac;
|
|
shun-iwasawa |
832993 |
*result_p += color * ratio;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
if (result_p == end_p) break;
|
|
shun-iwasawa |
832993 |
result_p++;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill pixels between currentY and toY
|
|
shun-iwasawa |
832993 |
for (int y = currentY + 1; y < toY; y++) {
|
|
shun-iwasawa |
832993 |
k = (float(y) + 0.5 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
*result_p = getColor(preDispNormal, dispNormal, prePos, currentPos, k,
|
|
shun-iwasawa |
832993 |
source_host, vars, preBaseNormal, baseNormal,
|
|
shun-iwasawa |
832993 |
preBasePos, basePos);
|
|
shun-iwasawa |
832993 |
if (result_p == end_p) break;
|
|
shun-iwasawa |
832993 |
result_p++;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// fill fraction part of the end pixel (toY)
|
|
shun-iwasawa |
832993 |
k = (float(toY) + to_frac * 0.5 - preVPos) / (vPos - preVPos);
|
|
shun-iwasawa |
832993 |
color = getColor(preDispNormal, dispNormal, prePos, currentPos, k,
|
|
shun-iwasawa |
832993 |
source_host, vars, preBaseNormal, baseNormal,
|
|
shun-iwasawa |
832993 |
preBasePos, basePos);
|
|
shun-iwasawa |
832993 |
*result_p += color * to_frac;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
preVPos = vPos;
|
|
shun-iwasawa |
832993 |
maxVPos = vPos;
|
|
shun-iwasawa |
832993 |
preDispNormal = dispNormal;
|
|
shun-iwasawa |
832993 |
preBaseNormal = baseNormal;
|
|
shun-iwasawa |
832993 |
prePos = currentPos;
|
|
shun-iwasawa |
832993 |
preBasePos = basePos;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------------------------------
|
|
shun-iwasawa |
832993 |
// convert input tile's channel values to float4 values
|
|
shun-iwasawa |
832993 |
//------------------------------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
template <typename pixel="" raster,="" typename=""></typename>
|
|
shun-iwasawa |
832993 |
void Iwa_FloorBumpFx::setSourceRaster(const RASTER srcRas, float4 *srcMem,
|
|
shun-iwasawa |
832993 |
TDimensionI dim) {
|
|
shun-iwasawa |
832993 |
float4 *s_p = srcMem;
|
|
shun-iwasawa |
832993 |
for (int j = 0; j < dim.ly; j++) {
|
|
shun-iwasawa |
832993 |
PIXEL *s_pix = srcRas->pixels(j);
|
|
shun-iwasawa |
832993 |
for (int i = 0; i < dim.lx; i++, s_pix++, s_p++) {
|
|
shun-iwasawa |
832993 |
(*s_p).x = (float)s_pix->r / (float)PIXEL::maxChannelValue;
|
|
shun-iwasawa |
832993 |
(*s_p).y = (float)s_pix->g / (float)PIXEL::maxChannelValue;
|
|
shun-iwasawa |
832993 |
(*s_p).z = (float)s_pix->b / (float)PIXEL::maxChannelValue;
|
|
shun-iwasawa |
832993 |
(*s_p).w = (float)s_pix->m / (float)PIXEL::maxChannelValue;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
void Iwa_FloorBumpFx::setRefRaster(const TRaster64P refRas, float *refMem,
|
|
shun-iwasawa |
832993 |
TDimensionI dim, bool isRef) {
|
|
shun-iwasawa |
832993 |
float zeroLevel =
|
|
shun-iwasawa |
832993 |
(isRef) ? float(128) / float(TPixel32::maxChannelValue) : 0.0;
|
|
shun-iwasawa |
832993 |
float *r_p = refMem;
|
|
shun-iwasawa |
832993 |
for (int j = 0; j < dim.ly; j++) {
|
|
shun-iwasawa |
832993 |
TPixel64 *r_pix = refRas->pixels(j);
|
|
shun-iwasawa |
832993 |
for (int i = 0; i < dim.lx; i++, r_pix++, r_p++) {
|
|
shun-iwasawa |
832993 |
float r = (float)r_pix->r / (float)TPixel64::maxChannelValue;
|
|
shun-iwasawa |
832993 |
float g = (float)r_pix->g / (float)TPixel64::maxChannelValue;
|
|
shun-iwasawa |
832993 |
float b = (float)r_pix->b / (float)TPixel64::maxChannelValue;
|
|
shun-iwasawa |
832993 |
float m = (float)r_pix->m / (float)TPixel64::maxChannelValue;
|
|
shun-iwasawa |
832993 |
// taking brightness
|
|
shun-iwasawa |
832993 |
float brightness = 0.298912f * r + 0.586610f * g + 0.114478f * b;
|
|
shun-iwasawa |
832993 |
(*r_p) = brightness * m + zeroLevel * (1.0 - m);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
void Iwa_FloorBumpFx::doCompute(TTile &tile, double frame,
|
|
shun-iwasawa |
832993 |
const TRenderSettings &rend_sets) {
|
|
shun-iwasawa |
832993 |
FloorBumpVars vars;
|
|
shun-iwasawa |
832993 |
vars.renderMode = m_renderMode->getValue();
|
|
shun-iwasawa |
832993 |
if ((isTextureUsed(vars.renderMode) && !m_texture.isConnected()) ||
|
|
shun-iwasawa |
832993 |
!m_heightRef.isConnected()) {
|
|
shun-iwasawa |
832993 |
tile.getRaster()->clear();
|
|
shun-iwasawa |
832993 |
return;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
initVars(vars, tile, rend_sets, frame);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// メモリの確保
|
|
shun-iwasawa |
832993 |
float4 *source_host = nullptr;
|
|
shun-iwasawa |
832993 |
float *ref_host;
|
|
shun-iwasawa |
832993 |
float *disp_host = nullptr;
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
TRasterGR8P source_host_ras;
|
|
shun-iwasawa |
832993 |
if (isTextureUsed(vars.renderMode)) {
|
|
shun-iwasawa |
832993 |
source_host_ras =
|
|
shun-iwasawa |
832993 |
TRasterGR8P(vars.sourceDim.lx * sizeof(float4), vars.sourceDim.ly);
|
|
shun-iwasawa |
832993 |
source_host_ras->lock();
|
|
shun-iwasawa |
832993 |
source_host = (float4 *)source_host_ras->getRawData();
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
TRasterGR8P ref_host_ras(vars.refDim.lx * sizeof(float), vars.refDim.ly);
|
|
shun-iwasawa |
832993 |
ref_host_ras->lock();
|
|
shun-iwasawa |
832993 |
ref_host = (float *)ref_host_ras->getRawData();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
TRasterGR8P disp_host_ras;
|
|
shun-iwasawa |
832993 |
if (vars.displacement != 0.0 &&
|
|
shun-iwasawa |
832993 |
m_dispRef.isConnected()) { // renderMode すべてに対応させるかはTBD
|
|
shun-iwasawa |
832993 |
disp_host_ras = TRasterGR8P(vars.refDim.lx * sizeof(float), vars.refDim.ly);
|
|
shun-iwasawa |
832993 |
disp_host_ras->lock();
|
|
shun-iwasawa |
832993 |
disp_host = (float *)disp_host_ras->getRawData();
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// 画像の取得、格納
|
|
shun-iwasawa |
832993 |
{
|
|
shun-iwasawa |
832993 |
if (isTextureUsed(vars.renderMode)) {
|
|
shun-iwasawa |
832993 |
TRenderSettings source_sets(rend_sets);
|
|
shun-iwasawa |
832993 |
TPointD sourceTilePos =
|
|
shun-iwasawa |
832993 |
(tile.m_pos - TPointD(vars.margin, vars.margin)) * vars.precision;
|
|
shun-iwasawa |
832993 |
source_sets.m_affine *= TScale(vars.precision, vars.precision);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
TTile sourceTile;
|
|
shun-iwasawa |
832993 |
m_texture->allocateAndCompute(sourceTile, sourceTilePos, vars.sourceDim,
|
|
shun-iwasawa |
832993 |
tile.getRaster(), frame, source_sets);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
TRaster32P ras32 = (TRaster32P)sourceTile.getRaster();
|
|
shun-iwasawa |
832993 |
TRaster64P ras64 = (TRaster64P)sourceTile.getRaster();
|
|
shun-iwasawa |
832993 |
if (ras32)
|
|
shun-iwasawa |
832993 |
setSourceRaster<traster32p, tpixel32="">(ras32, source_host,</traster32p,>
|
|
shun-iwasawa |
832993 |
vars.sourceDim);
|
|
shun-iwasawa |
832993 |
else if (ras64)
|
|
shun-iwasawa |
832993 |
setSourceRaster<traster64p, tpixel64="">(ras64, source_host,</traster64p,>
|
|
shun-iwasawa |
832993 |
vars.sourceDim);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
// height image is always computed in 16bpc regardless of the current render
|
|
shun-iwasawa |
832993 |
// settings in order to get smooth gradient
|
|
shun-iwasawa |
832993 |
TRenderSettings ref_sets(rend_sets);
|
|
shun-iwasawa |
832993 |
TPointD refTilePos = tile.m_pos - TPointD(vars.margin, vars.margin);
|
|
shun-iwasawa |
832993 |
ref_sets.m_bpp = 64;
|
|
shun-iwasawa |
832993 |
TTile refTile;
|
|
shun-iwasawa |
832993 |
m_heightRef->allocateAndCompute(refTile, refTilePos, vars.refDim,
|
|
shun-iwasawa |
832993 |
TRasterP(), frame, ref_sets);
|
|
shun-iwasawa |
832993 |
setRefRaster((TRaster64P)refTile.getRaster(), ref_host, vars.refDim, true);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// disp imageも同様
|
|
shun-iwasawa |
832993 |
if (disp_host) {
|
|
shun-iwasawa |
832993 |
TTile dispTile;
|
|
shun-iwasawa |
832993 |
m_dispRef->allocateAndCompute(dispTile, refTilePos, vars.refDim,
|
|
shun-iwasawa |
832993 |
TRasterP(), frame, ref_sets);
|
|
shun-iwasawa |
832993 |
setRefRaster((TRaster64P)dispTile.getRaster(), disp_host, vars.refDim,
|
|
shun-iwasawa |
832993 |
false);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// prepare the memory for result image
|
|
shun-iwasawa |
832993 |
TRasterGR8P result_host_ras(vars.resultDim.lx * sizeof(float4),
|
|
shun-iwasawa |
832993 |
vars.resultDim.ly);
|
|
shun-iwasawa |
832993 |
float4 *result_host;
|
|
shun-iwasawa |
832993 |
result_host_ras->lock();
|
|
shun-iwasawa |
832993 |
result_host = (float4 *)result_host_ras->getRawData();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// compute
|
|
shun-iwasawa |
832993 |
if (disp_host) {
|
|
shun-iwasawa |
832993 |
doCompute_with_Displacement(tile, frame, rend_sets, vars, source_host,
|
|
shun-iwasawa |
832993 |
ref_host, disp_host, result_host);
|
|
shun-iwasawa |
832993 |
} else {
|
|
shun-iwasawa |
832993 |
doCompute_CPU(tile, frame, rend_sets, vars, source_host, ref_host,
|
|
shun-iwasawa |
832993 |
result_host);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
if (isTextureUsed(vars.renderMode)) source_host_ras->unlock();
|
|
shun-iwasawa |
832993 |
ref_host_ras->unlock();
|
|
shun-iwasawa |
832993 |
if (disp_host) disp_host_ras->unlock();
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// cancel check
|
|
shun-iwasawa |
832993 |
if (rend_sets.m_isCanceled && *rend_sets.m_isCanceled) {
|
|
shun-iwasawa |
832993 |
tile.getRaster()->clear();
|
|
shun-iwasawa |
832993 |
return;
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
// output the result
|
|
shun-iwasawa |
832993 |
TRaster32P outRas32 = (TRaster32P)tile.getRaster();
|
|
shun-iwasawa |
832993 |
TRaster64P outRas64 = (TRaster64P)tile.getRaster();
|
|
shun-iwasawa |
832993 |
if (outRas32)
|
|
shun-iwasawa |
832993 |
setOutputRaster<traster32p, tpixel32="">(result_host, outRas32, vars.outDim,</traster32p,>
|
|
shun-iwasawa |
832993 |
vars.resultDim.ly);
|
|
shun-iwasawa |
832993 |
else if (outRas64)
|
|
shun-iwasawa |
832993 |
setOutputRaster<traster64p, tpixel64="">(result_host, outRas64, vars.outDim,</traster64p,>
|
|
shun-iwasawa |
832993 |
vars.resultDim.ly);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
result_host_ras->unlock();
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
void Iwa_FloorBumpFx::getParamUIs(TParamUIConcept *&concepts, int &length) {
|
|
shun-iwasawa |
832993 |
concepts = new TParamUIConcept[length = 3];
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
concepts[0].m_type = TParamUIConcept::VERTICAL_POS;
|
|
shun-iwasawa |
832993 |
concepts[0].m_label = "Eye Level";
|
|
shun-iwasawa |
832993 |
concepts[0].m_params.push_back(m_eyeLevel);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
concepts[1].m_type = TParamUIConcept::VERTICAL_POS;
|
|
shun-iwasawa |
832993 |
concepts[1].m_label = "Draw Level";
|
|
shun-iwasawa |
832993 |
concepts[1].m_params.push_back(m_drawLevel);
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
concepts[2].m_type = TParamUIConcept::VERTICAL_POS;
|
|
shun-iwasawa |
832993 |
concepts[2].m_label = "Distance Level";
|
|
shun-iwasawa |
832993 |
concepts[2].m_params.push_back(m_distanceLevel);
|
|
shun-iwasawa |
832993 |
concepts[2].m_params.push_back(m_renderMode);
|
|
shun-iwasawa |
832993 |
}
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
//------------------------------------
|
|
shun-iwasawa |
832993 |
|
|
shun-iwasawa |
832993 |
FX_PLUGIN_IDENTIFIER(Iwa_FloorBumpFx, "iwa_FloorBumpFx")
|