nr-3dutils.cpp revision af0732a2bf24fbea12a085b855224577e7101851
2N/A/*
2N/A * 3D utils.
2N/A *
2N/A * Authors:
2N/A * Jean-Rene Reinhard <jr@komite.net>
2N/A *
2N/A * Copyright (C) 2007 authors
2N/A *
2N/A * Released under GNU GPL, read the file 'COPYING' for more information
2N/A */
2N/A
2N/A#include <glib/gmessages.h>
2N/A
2N/A#include "libnr/nr-pixblock.h"
2N/A#include "libnr/nr-matrix.h"
2N/A#include "display/nr-3dutils.h"
2N/A#include <cmath>
2N/A
2N/Anamespace NR {
2N/A
2N/A#define BEGIN 0 // TOP or LEFT
2N/A#define MIDDLE 1
2N/A#define END 2 // BOTTOM or RIGHT
2N/A
2N/A#define START(v) ((v)==BEGIN? 1 : 0)
2N/A#define FINISH(v) ((v)==END? 1 : 2)
2N/A
2N/Asigned char K_X[3][3][3][3] = {
2N/A //K_X[TOP]
2N/A {
2N/A //K_X[TOP][LEFT]
2N/A {
2N/A { 0, 0, 0},
2N/A { 0, -2, 2},
2N/A { 0, -1, 1}
2N/A },
2N/A {
2N/A { 0, 0, 0},
2N/A {-2, 0, 2},
2N/A {-1, 0, 1}
2N/A },
2N/A {
2N/A { 0, 0, 0},
2N/A {-2, 2, 0},
2N/A {-1, 1, 0}
2N/A }
2N/A },
2N/A //K_X[MIDDLE]
2N/A {
2N/A //K_X[MIDDLE][LEFT]
2N/A {
2N/A { 0, -1, 1},
2N/A { 0, -2, 2},
2N/A { 0, -1, 1}
2N/A },
2N/A {
2N/A {-1, 0, 1},
2N/A {-2, 0, 2},
2N/A {-1, 0, 1}
2N/A },
2N/A {
2N/A {-1, 1, 0},
2N/A {-2, 2, 0},
2N/A {-1, 1, 0}
2N/A }
2N/A },
2N/A //K_X[BOTTOM]
2N/A {
2N/A //K_X[BOTTOM][LEFT]
2N/A {
2N/A { 0, -1, 1},
2N/A { 0, -2, 2},
2N/A { 0, 0, 0}
2N/A },
2N/A {
2N/A {-1, 0, 1},
2N/A {-2, 0, 2},
2N/A { 0, 0, 0}
2N/A },
2N/A {
2N/A {-1, 1, 0},
2N/A {-2, 2, 0},
2N/A { 0, 0, 0}
2N/A }
2N/A }
2N/A};
2N/A
2N/A//K_Y is obtained by transposing K_X globally and each of its components
2N/A
2N/Agdouble FACTOR_X[3][3] = {
2N/A {2./3, 1./3, 2./3},
2N/A {1./2, 1./4, 1./2},
2N/A {2./3, 1./3, 2./3}
2N/A};
2N/A
2N/A//FACTOR_Y is obtained by transposing FACTOR_X
2N/A
2N/Ainline
2N/Aint get_carac(int i, int len, int delta) {
2N/A if (i < delta)
2N/A return BEGIN;
2N/A else if (i > len - 1 - delta)
2N/A return END;
2N/A else
2N/A return MIDDLE;
2N/A}
2N/A
2N/A//assumes in is RGBA
2N/A//should be made more resistant
2N/Avoid compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j, int dx, int dy) {
2N/A int w = in->area.x1 - in->area.x0;
2N/A int h = in->area.y1 - in->area.y0;
2N/A int k, l, alpha_idx, alpha_idx_y;
2N/A int x_carac, y_carac;
2N/A gdouble alpha;
2N/A gdouble accu_x;
2N/A gdouble accu_y;
2N/A unsigned char *data = NR_PIXBLOCK_PX (in);
2N/A g_assert(in->mode == NR_PIXBLOCK_MODE_R8G8B8A8P);
2N/A x_carac = get_carac(j, w, dx); //LEFT, MIDDLE or RIGHT
2N/A y_carac = get_carac(i, h, dy); //TOP, MIDDLE or BOTTOM
2N/A alpha_idx = 4*(i*w + j);
2N/A accu_x = 0;
2N/A accu_y = 0;
2N/A for (k = START(y_carac); k <= FINISH(y_carac); k++) {
2N/A alpha_idx_y = alpha_idx + 4*(k-1)*dy*w;
2N/A for (l = START(x_carac); l <= FINISH(x_carac); l++) {
2N/A alpha = (data + alpha_idx_y + 4*dx*(l-1))[3];
2N/A accu_x += K_X[y_carac][x_carac][k][l] * alpha / 255;
2N/A accu_y += K_X[x_carac][y_carac][l][k] * alpha / 255;
2N/A }
2N/A }
2N/A N[X_3D] = -1 * ss * FACTOR_X[y_carac][x_carac] * accu_x / dx;
2N/A N[Y_3D] = -1 * ss * FACTOR_X[x_carac][y_carac] * accu_y / dy;
2N/A N[Z_3D] = 1;
2N/A normalize_vector(N);
2N/A //std::cout << "(" << N[X_3D] << ", " << N[Y_3D] << ", " << N[Z_3D] << ")" << std::endl;
2N/A}
2N/A
2N/Avoid convert_coord(gdouble &x, gdouble &y, gdouble &z, Matrix const &trans) {
2N/A Point p = Point(x, y);
2N/A p *= trans;
2N/A x = p[X];
2N/A y = p[Y];
2N/A z *= trans[0];
2N/A}
2N/A
2N/Agdouble norm(const Fvector &v) {
2N/A return sqrt(v[X_3D]*v[X_3D] + v[Y_3D]*v[Y_3D] + v[Z_3D]*v[Z_3D]);
2N/A}
2N/A
2N/Avoid normalize_vector(Fvector &v) {
2N/A int i, j;
2N/A gdouble nv = norm(v);
2N/A //TODO test nv == 0
2N/A for (j = 0; j < 3; j++) {
2N/A v[j] /= nv;
2N/A }
2N/A}
2N/A
2N/Agdouble scalar_product(const Fvector &a, const Fvector &b) {
2N/A return a[X_3D] * b[X_3D] +
2N/A a[Y_3D] * b[Y_3D] +
2N/A a[Z_3D] * b[Z_3D];
2N/A}
2N/A
2N/Avoid normalized_sum(Fvector &r, const Fvector &a, const Fvector &b) {
2N/A r[X_3D] = a[X_3D] + b[X_3D];
2N/A r[Y_3D] = a[Y_3D] + b[Y_3D];
2N/A r[Z_3D] = a[Z_3D] + b[Z_3D];
2N/A normalize_vector(r);
2N/A}
2N/A
2N/A}/* namespace NR */
2N/A
2N/A/*
2N/A Local Variables:
2N/A mode:c++
2N/A c-file-style:"stroustrup"
2N/A c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
2N/A indent-tabs-mode:nil
2N/A fill-column:99
2N/A End:
2N/A*/
2N/A// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
2N/A