mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
fix some off-by-one errors
This commit is contained in:
parent
4c2eb3d326
commit
85014ba179
@ -105,10 +105,10 @@ extrude(const Lens *lens) {
|
||||
// Create an implicit UV coordinate for each point.
|
||||
LPoint2 uv_scale(1.0, 1.0);
|
||||
if (_pfm.get_x_size() > 1) {
|
||||
uv_scale[0] = 1.0 / PN_stdfloat(_pfm.get_x_size() - 1);
|
||||
uv_scale[0] = 1.0 / PN_stdfloat(_pfm.get_x_size());
|
||||
}
|
||||
if (_pfm.get_y_size() > 1) {
|
||||
uv_scale[1] = 1.0 / PN_stdfloat(_pfm.get_y_size() - 1);
|
||||
uv_scale[1] = 1.0 / PN_stdfloat(_pfm.get_y_size());
|
||||
}
|
||||
for (int yi = 0; yi < _pfm.get_y_size(); ++yi) {
|
||||
for (int xi = 0; xi < _pfm.get_x_size(); ++xi) {
|
||||
@ -116,8 +116,8 @@ extrude(const Lens *lens) {
|
||||
continue;
|
||||
}
|
||||
LPoint3 p;
|
||||
p.set((PN_stdfloat)xi * uv_scale[0],
|
||||
(PN_stdfloat)yi * uv_scale[1],
|
||||
p.set(((PN_stdfloat)xi + 0.5) * uv_scale[0],
|
||||
((PN_stdfloat)yi + 0.5) * uv_scale[1],
|
||||
(PN_stdfloat)_pfm.get_point1(xi, yi));
|
||||
|
||||
from_uv.xform_point_in_place(p);
|
||||
@ -221,10 +221,10 @@ generate_vis_points() const {
|
||||
|
||||
LPoint2f uv_scale(1.0, 1.0);
|
||||
if (_pfm.get_x_size() > 1) {
|
||||
uv_scale[0] = 1.0f / PN_float32(_pfm.get_x_size() - 1);
|
||||
uv_scale[0] = 1.0f / PN_float32(_pfm.get_x_size());
|
||||
}
|
||||
if (_pfm.get_y_size() > 1) {
|
||||
uv_scale[1] = 1.0f / PN_float32(_pfm.get_y_size() - 1);
|
||||
uv_scale[1] = 1.0f / PN_float32(_pfm.get_y_size());
|
||||
}
|
||||
|
||||
int num_points = 0;
|
||||
@ -235,8 +235,8 @@ generate_vis_points() const {
|
||||
}
|
||||
|
||||
const LPoint3f &point = _pfm.get_point(xi, yi);
|
||||
LPoint2f uv(PN_float32(xi) * uv_scale[0],
|
||||
PN_float32(yi) * uv_scale[1]);
|
||||
LPoint2f uv((PN_float32(xi) + 0.5) * uv_scale[0],
|
||||
(PN_float32(yi) + 0.5) * uv_scale[1]);
|
||||
if (_vis_inverse) {
|
||||
vertex.add_data2f(uv);
|
||||
texcoord.add_data3f(point);
|
||||
@ -306,7 +306,7 @@ generate_vis_mesh(MeshFace face) const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmVizzer::calc_max_u_displacement
|
||||
// Access: Private
|
||||
// Access: Published
|
||||
// Description: Computes the maximum amount of shift, in pixels
|
||||
// either left or right, of any pixel in the distortion
|
||||
// map. This can be passed to make_displacement(); see
|
||||
@ -326,7 +326,7 @@ calc_max_u_displacement() const {
|
||||
}
|
||||
|
||||
const LPoint3f &point = _pfm.get_point(xi, yi);
|
||||
double nxi = point[0] * (double)(x_size - 1);
|
||||
double nxi = point[0] * (double)x_size - 0.5;
|
||||
|
||||
max_u = max(max_u, cabs(nxi - (double)xi));
|
||||
}
|
||||
@ -337,7 +337,7 @@ calc_max_u_displacement() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmVizzer::calc_max_v_displacement
|
||||
// Access: Private
|
||||
// Access: Published
|
||||
// Description: Computes the maximum amount of shift, in pixels
|
||||
// either up or down, of any pixel in the distortion
|
||||
// map. This can be passed to make_displacement(); see
|
||||
@ -357,7 +357,7 @@ calc_max_v_displacement() const {
|
||||
}
|
||||
|
||||
const LPoint3f &point = _pfm.get_point(xi, yi);
|
||||
double nyi = point[1] * (double)(y_size - 1);
|
||||
double nyi = point[1] * (double)y_size - 0.5;
|
||||
|
||||
max_v = max(max_v, cabs(nyi - (double)yi));
|
||||
}
|
||||
@ -368,7 +368,7 @@ calc_max_v_displacement() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmVizzer::make_displacement
|
||||
// Access: Private
|
||||
// Access: Published
|
||||
// Description: Assuming the underlying PfmFile is a 2-d distortion
|
||||
// mesh, with the U and V in the first two components
|
||||
// and the third component unused, this computes an
|
||||
@ -389,7 +389,17 @@ make_displacement(PNMImage &result, double max_u, double max_v) const {
|
||||
int x_size = _pfm.get_x_size();
|
||||
int y_size = _pfm.get_y_size();
|
||||
result.clear(x_size, y_size, 3, PNM_MAXMAXVAL);
|
||||
result.fill(0.5);
|
||||
result.fill_val(0, 0, PNM_MAXMAXVAL);
|
||||
|
||||
// After Effects defines this as the zero (no-change) value. It's
|
||||
// not exactly 0.5, because they round up.
|
||||
static const int midval = (PNM_MAXMAXVAL + 1) / 2;
|
||||
|
||||
// After Effects seems to always undershift by exactly this amount.
|
||||
static const double scale_factor = 256.0 / 255.0;
|
||||
|
||||
double u_scale = scale_factor * 0.5 * (PNM_MAXMAXVAL - 1) / max_u;
|
||||
double v_scale = scale_factor * 0.5 * (PNM_MAXMAXVAL - 1) / max_v;
|
||||
|
||||
for (int yi = 0; yi < y_size; ++yi) {
|
||||
for (int xi = 0; xi < x_size; ++xi) {
|
||||
@ -398,16 +408,86 @@ make_displacement(PNMImage &result, double max_u, double max_v) const {
|
||||
}
|
||||
|
||||
const LPoint3f &point = _pfm.get_point(xi, yi);
|
||||
double nxi = point[0] * (double)(x_size - 1);
|
||||
double nyi = point[1] * (double)(y_size - 1);
|
||||
double nxi = point[0] * (double)x_size - 0.5;
|
||||
double nyi = point[1] * (double)y_size - 0.5;
|
||||
|
||||
double u_shift = (nxi - (double)xi) / max_u;
|
||||
double v_shift = (nyi - (double)yi) / max_v;
|
||||
double x_shift = (nxi - (double)xi);
|
||||
double y_shift = (nyi - (double)yi);
|
||||
|
||||
result.set_red(xi, yi, u_shift * 0.5 + 0.5);
|
||||
result.set_green(xi, yi, v_shift * 0.5 + 0.5);
|
||||
int u_val = midval + (int)cfloor(x_shift * u_scale + 0.5);
|
||||
int v_val = midval + (int)cfloor(y_shift * v_scale + 0.5);
|
||||
|
||||
// We use the blue channel to mark holes, so we can fill them in
|
||||
// later.
|
||||
result.set_xel_val(xi, yi, u_val, v_val, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Now fill in holes.
|
||||
for (int yi = 0; yi < y_size; ++yi) {
|
||||
for (int xi = 0; xi < x_size; ++xi) {
|
||||
if (!_pfm.has_point(xi, yi)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const LPoint3f &point = _pfm.get_point(xi, yi);
|
||||
double nxi = point[0] * (double)x_size - 0.5;
|
||||
double nyi = point[1] * (double)y_size - 0.5;
|
||||
|
||||
r_fill_displacement(result, xi - 1, yi, nxi, nyi, u_scale, v_scale, 1);
|
||||
r_fill_displacement(result, xi + 1, yi, nxi, nyi, u_scale, v_scale, 1);
|
||||
r_fill_displacement(result, xi, yi - 1, nxi, nyi, u_scale, v_scale, 1);
|
||||
r_fill_displacement(result, xi, yi + 1, nxi, nyi, u_scale, v_scale, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, reset the blue channel for cleanliness.
|
||||
for (int yi = 0; yi < y_size; ++yi) {
|
||||
for (int xi = 0; xi < x_size; ++xi) {
|
||||
result.set_blue_val(xi, yi, midval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmVizzer::r_fill_displacement
|
||||
// Access: Private
|
||||
// Description: Recursively fills in holes with the color of their
|
||||
// nearest neighbor after processing the image. This
|
||||
// avoids sudden discontinuities in the displacement map
|
||||
// at the edge of the screen geometry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PfmVizzer::
|
||||
r_fill_displacement(PNMImage &result, int xi, int yi,
|
||||
double nxi, double nyi, double u_scale, double v_scale,
|
||||
int distance) const {
|
||||
if (xi < 0 || yi < 0 ||
|
||||
xi >= result.get_x_size() || yi >= result.get_y_size()) {
|
||||
// Stop at the edge.
|
||||
return;
|
||||
}
|
||||
|
||||
if (distance > 1000) {
|
||||
// Avoid runaway recursion.
|
||||
return;
|
||||
}
|
||||
|
||||
int val = result.get_blue_val(xi, yi);
|
||||
if (val > distance) {
|
||||
// We've found a point that's closer.
|
||||
static const int midval = (PNM_MAXMAXVAL + 1) / 2;
|
||||
|
||||
double x_shift = (nxi - (double)xi);
|
||||
double y_shift = (nyi - (double)yi);
|
||||
int u_val = midval + (int)cfloor(x_shift * u_scale + 0.5);
|
||||
int v_val = midval + (int)cfloor(y_shift * v_scale + 0.5);
|
||||
result.set_xel_val(xi, yi, u_val, v_val, distance);
|
||||
|
||||
r_fill_displacement(result, xi - 1, yi, nxi, nyi, u_scale, v_scale, distance + 1);
|
||||
r_fill_displacement(result, xi + 1, yi, nxi, nyi, u_scale, v_scale, distance + 1);
|
||||
r_fill_displacement(result, xi, yi - 1, nxi, nyi, u_scale, v_scale, distance + 1);
|
||||
r_fill_displacement(result, xi, yi + 1, nxi, nyi, u_scale, v_scale, distance + 1);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -710,8 +790,8 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo
|
||||
switch (_source) {
|
||||
case CT_texcoord2:
|
||||
{
|
||||
LPoint2f uv(PN_float32(xi) / PN_float32(pfm.get_x_size() - 1),
|
||||
PN_float32(yi) / PN_float32(pfm.get_y_size() - 1));
|
||||
LPoint2f uv((PN_float32(xi) + 0.5) / PN_float32(pfm.get_x_size()),
|
||||
(PN_float32(yi) + 0.5) / PN_float32(pfm.get_y_size()));
|
||||
transform_point(uv);
|
||||
vwriter.set_data2f(uv);
|
||||
}
|
||||
@ -719,8 +799,8 @@ add_data(const PfmVizzer &vizzer, GeomVertexWriter &vwriter, int xi, int yi, boo
|
||||
|
||||
case CT_texcoord3:
|
||||
{
|
||||
LPoint3f uv(PN_float32(xi) / PN_float32(pfm.get_x_size() - 1),
|
||||
PN_float32(yi) / PN_float32(pfm.get_y_size() - 1),
|
||||
LPoint3f uv((PN_float32(xi) + 0.5) / PN_float32(pfm.get_x_size()),
|
||||
(PN_float32(yi) + 0.5) / PN_float32(pfm.get_y_size()),
|
||||
0.0f);
|
||||
transform_point(uv);
|
||||
vwriter.set_data3f(uv);
|
||||
|
@ -79,6 +79,10 @@ PUBLISHED:
|
||||
BLOCKING void make_displacement(PNMImage &result, double max_u, double max_v) const;
|
||||
|
||||
private:
|
||||
void r_fill_displacement(PNMImage &result, int xi, int yi,
|
||||
double nxi, double nyi, double u_scale, double v_scale,
|
||||
int distance) const;
|
||||
|
||||
void make_vis_mesh_geom(GeomNode *gnode, bool inverted) const;
|
||||
|
||||
|
||||
|
@ -748,10 +748,10 @@ resize(int new_x_size, int new_y_size) {
|
||||
PN_float32 y_scale = 1.0;
|
||||
|
||||
if (new_x_size > 1) {
|
||||
x_scale = (PN_float32)(_x_size - 1) / (PN_float32)(new_x_size - 1);
|
||||
x_scale = (PN_float32)_x_size / (PN_float32)new_x_size;
|
||||
}
|
||||
if (new_y_size > 1) {
|
||||
y_scale = (PN_float32)(_y_size - 1) / (PN_float32)(new_y_size - 1);
|
||||
y_scale = (PN_float32)_y_size / (PN_float32)new_y_size;
|
||||
}
|
||||
|
||||
switch (_num_channels) {
|
||||
@ -759,12 +759,12 @@ resize(int new_x_size, int new_y_size) {
|
||||
{
|
||||
from_y0 = 0.0;
|
||||
for (int to_y = 0; to_y < new_y_size; ++to_y) {
|
||||
from_y1 = (to_y + 0.5) * y_scale;
|
||||
from_y1 = (to_y + 1.0) * y_scale;
|
||||
from_y1 = min(from_y1, (PN_float32) _y_size);
|
||||
|
||||
from_x0 = 0.0;
|
||||
for (int to_x = 0; to_x < new_x_size; ++to_x) {
|
||||
from_x1 = (to_x + 0.5) * x_scale;
|
||||
from_x1 = (to_x + 1.0) * x_scale;
|
||||
from_x1 = min(from_x1, (PN_float32) _x_size);
|
||||
|
||||
// Now the box from (from_x0, from_y0) - (from_x1, from_y1)
|
||||
@ -784,12 +784,12 @@ resize(int new_x_size, int new_y_size) {
|
||||
{
|
||||
from_y0 = 0.0;
|
||||
for (int to_y = 0; to_y < new_y_size; ++to_y) {
|
||||
from_y1 = (to_y + 0.5) * y_scale;
|
||||
from_y1 = (to_y + 1.0) * y_scale;
|
||||
from_y1 = min(from_y1, (PN_float32) _y_size);
|
||||
|
||||
from_x0 = 0.0;
|
||||
for (int to_x = 0; to_x < new_x_size; ++to_x) {
|
||||
from_x1 = (to_x + 0.5) * x_scale;
|
||||
from_x1 = (to_x + 1.0) * x_scale;
|
||||
from_x1 = min(from_x1, (PN_float32) _x_size);
|
||||
|
||||
// Now the box from (from_x0, from_y0) - (from_x1, from_y1)
|
||||
@ -811,12 +811,12 @@ resize(int new_x_size, int new_y_size) {
|
||||
{
|
||||
from_y0 = 0.0;
|
||||
for (int to_y = 0; to_y < new_y_size; ++to_y) {
|
||||
from_y1 = (to_y + 0.5) * y_scale;
|
||||
from_y1 = (to_y + 1.0) * y_scale;
|
||||
from_y1 = min(from_y1, (PN_float32) _y_size);
|
||||
|
||||
from_x0 = 0.0;
|
||||
for (int to_x = 0; to_x < new_x_size; ++to_x) {
|
||||
from_x1 = (to_x + 0.5) * x_scale;
|
||||
from_x1 = (to_x + 1.0) * x_scale;
|
||||
from_x1 = min(from_x1, (PN_float32) _x_size);
|
||||
|
||||
// Now the box from (from_x0, from_y0) - (from_x1, from_y1)
|
||||
@ -956,7 +956,7 @@ xform(const LMatrix4f &transform) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::forward_distort
|
||||
// Access: Published
|
||||
// Description: Applys the distortion indicated in the supplied dist
|
||||
// Description: Applies the distortion indicated in the supplied dist
|
||||
// map to the current map. The dist map is understood
|
||||
// to be a mapping of points in the range 0..1 in the
|
||||
// first two dimensions. Each (u,v) point in the
|
||||
@ -994,8 +994,8 @@ forward_distort(const PfmFile &dist) {
|
||||
continue;
|
||||
}
|
||||
LPoint2f uv = dist_p->get_point2(xi, yi);
|
||||
int dist_xi = int(uv[0] * (_x_size - 1));
|
||||
int dist_yi = int(uv[1] * (_y_size - 1));
|
||||
int dist_xi = (int)cfloor(uv[0] * (double)_x_size);
|
||||
int dist_yi = (int)cfloor(uv[0] * (double)_y_size);
|
||||
if (dist_xi < 0 || dist_xi >= _x_size ||
|
||||
dist_yi < 0 || dist_yi >= _y_size) {
|
||||
continue;
|
||||
@ -1015,7 +1015,7 @@ forward_distort(const PfmFile &dist) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PfmFile::reverse_distort
|
||||
// Access: Published
|
||||
// Description: Applys the distortion indicated in the supplied dist
|
||||
// Description: Applies the distortion indicated in the supplied dist
|
||||
// map to the current map. The dist map is understood
|
||||
// to be a mapping of points in the range 0..1 in the
|
||||
// first two dimensions. Each (x,y) point in the
|
||||
@ -1055,8 +1055,8 @@ reverse_distort(const PfmFile &dist) {
|
||||
continue;
|
||||
}
|
||||
LPoint2f uv = dist_p->get_point2(xi, yi);
|
||||
int dist_xi = int(uv[0] * (_x_size - 1));
|
||||
int dist_yi = int(uv[1] * (_y_size - 1));
|
||||
int dist_xi = (int)cfloor(uv[0] * (double)_x_size);
|
||||
int dist_yi = (int)cfloor(uv[0] * (double)_y_size);
|
||||
if (dist_xi < 0 || dist_xi >= _x_size ||
|
||||
dist_yi < 0 || dist_yi >= _y_size) {
|
||||
continue;
|
||||
@ -1163,17 +1163,18 @@ clear_to_texcoords(int x_size, int y_size) {
|
||||
clear(x_size, y_size, 3);
|
||||
|
||||
LPoint2f uv_scale(1.0, 1.0);
|
||||
if (_x_size > 1) {
|
||||
uv_scale[0] = 1.0f / PN_float32(_x_size - 1);
|
||||
if (_x_size > 0) {
|
||||
uv_scale[0] = 1.0f / PN_float32(_x_size);
|
||||
}
|
||||
if (_y_size > 1) {
|
||||
uv_scale[1] = 1.0f / PN_float32(_y_size - 1);
|
||||
if (_y_size > 0) {
|
||||
uv_scale[1] = 1.0f / PN_float32(_y_size);
|
||||
}
|
||||
|
||||
for (int yi = 0; yi < _y_size; ++yi) {
|
||||
for (int xi = 0; xi < _x_size; ++xi) {
|
||||
LPoint3f uv(PN_float32(xi) * uv_scale[0],
|
||||
PN_float32(yi) * uv_scale[1], 0.0f);
|
||||
LPoint3f uv(PN_float32(xi) * uv_scale[0] + 0.5,
|
||||
PN_float32(yi) * uv_scale[1] + 0.5,
|
||||
0.0f);
|
||||
set_point(xi, yi, uv);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user