static float
_bilinear_interpolate(float ll, float lr, float rl, float rr, float lambda1, float lambda2)
{
        float il = _lerp(ll, rl, lambda1);
        float ir = _lerp(lr, rr, lambda1);
        return _lerp(il,ir,lambda2);
}
Exemplo n.º 2
0
static void _get_split_vertex(vertex &v_ret, const vertex &va, const vertex &vb, float y) {
    float ly = (y - va.y) / (vb.y - va.y);
    v_ret.x = _lerp(va.x, vb.x, ly);
    v_ret.y = y;
    v_ret.z = _lerp(va.z, vb.z, ly);
    v_ret.w = 1;
    v_ret.r = _lerp(va.r, vb.r, ly);
    v_ret.g = _lerp(va.g, vb.g, ly);
    v_ret.b = _lerp(va.b, vb.b, ly);
    v_ret.a = _lerp(va.a, vb.a, ly);
    v_ret.u = _lerp(va.u, vb.u, ly);
    v_ret.v = _lerp(va.v, vb.v, ly);
}
Exemplo n.º 3
0
	//-----------------------------------------------------------------------
	double Noise3D::_noise(double x, double y, double z)
	{
		int X = (int)floor(x) & 255;
		int Y = (int)floor(y) & 255;
		int Z = (int)floor(z) & 255;
		x -= floor(x);
		y -= floor(y);
		z -= floor(z);
		double u = _fade(x);
		double v = _fade(y);
		double w = _fade(z);
		int A = p[X  ]+Y, AA = p[A]+Z, AB = p[A+1]+Z;
		int B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;

		double lrp = _lerp(w,	_lerp(v, _lerp(u, _grad(p[AA], x, y, z),
									_grad(p[BA], x-1, y, z)),
								_lerp(u, _grad(p[AB], x, y-1, z),
									_grad(p[BB], x-1, y-1, z))),
								_lerp(v, _lerp(u, _grad(p[AA+1], x, y  , z-1),
									_grad(p[BA+1], x-1, y, z-1)),
								_lerp(u, _grad(p[AB+1], x, y-1, z-1),
									_grad(p[BB+1], x-1, y-1, z-1))));
		return Ogre::Math::Abs((Ogre::Real)lrp); // Use absolute value, because lrp in between [-1, 1]
	}
Exemplo n.º 4
0
    G_GNUC_PURE
    guint32 turbulencePixel(Geom::Point const &p) const {
        int wrapx = _wrapx, wrapy = _wrapy, wrapw = _wrapw, wraph = _wraph;

        double pixel[4];
        double x = p[Geom::X] * _baseFreq[Geom::X];
        double y = p[Geom::Y] * _baseFreq[Geom::Y];
        double ratio = 1.0;

        for (int k = 0; k < 4; ++k)
            pixel[k] = 0.0;

        for(int octave = 0; octave < _octaves; ++octave)
        {
            double tx = x + PerlinOffset;
            double bx = floor(tx);
            double rx0 = tx - bx, rx1 = rx0 - 1.0;
            int bx0 = bx, bx1 = bx0 + 1;

            double ty = y + PerlinOffset;
            double by = floor(ty);
            double ry0 = ty - by, ry1 = ry0 - 1.0;
            int by0 = by, by1 = by0 + 1;

            if (_stitchTiles) {
                if (bx0 >= wrapx) bx0 -= wrapw;
                if (bx1 >= wrapx) bx1 -= wrapw;
                if (by0 >= wrapy) by0 -= wraph;
                if (by1 >= wrapy) by1 -= wraph;
            }
            bx0 &= BMask;
            bx1 &= BMask;
            by0 &= BMask;
            by1 &= BMask;

            int i = _latticeSelector[bx0];
            int j = _latticeSelector[bx1];
            int b00 = _latticeSelector[i + by0];
            int b01 = _latticeSelector[i + by1];
            int b10 = _latticeSelector[j + by0];
            int b11 = _latticeSelector[j + by1];

            double sx = _scurve(rx0);
            double sy = _scurve(ry0);

            double result[4];
            // channel numbering: R=0, G=1, B=2, A=3
            for (int k = 0; k < 4; ++k) {
                double const *qxa = _gradient[b00][k];
                double const *qxb = _gradient[b10][k];
                double a = _lerp(sx, rx0 * qxa[0] + ry0 * qxa[1],
                                     rx1 * qxb[0] + ry0 * qxb[1]);
                double const *qya = _gradient[b01][k];
                double const *qyb = _gradient[b11][k];
                double b = _lerp(sx, rx0 * qya[0] + ry1 * qya[1],
                                     rx1 * qyb[0] + ry1 * qyb[1]);
                result[k] = _lerp(sy, a, b);
            }

            if (_fractalnoise) {
                for (int k = 0; k < 4; ++k)
                    pixel[k] += result[k] / ratio;
            } else {
                for (int k = 0; k < 4; ++k)
                    pixel[k] += fabs(result[k]) / ratio;
            }

            x *= 2;
            y *= 2;
            ratio *= 2;

            if(_stitchTiles)
            {
                // Update stitch values. Subtracting PerlinOffset before the multiplication and
                // adding it afterward simplifies to subtracting it once.
                wrapw *= 2;
                wraph *= 2;
                wrapx = wrapx*2 - PerlinOffset;
                wrapy = wrapy*2 - PerlinOffset;
            }
        }

        if (_fractalnoise) {
            guint32 r = CLAMP_D_TO_U8((pixel[0]*255.0 + 255.0) / 2);
            guint32 g = CLAMP_D_TO_U8((pixel[1]*255.0 + 255.0) / 2);
            guint32 b = CLAMP_D_TO_U8((pixel[2]*255.0 + 255.0) / 2);
            guint32 a = CLAMP_D_TO_U8((pixel[3]*255.0 + 255.0) / 2);
            r = premul_alpha(r, a);
            g = premul_alpha(g, a);
            b = premul_alpha(b, a);
            ASSEMBLE_ARGB32(pxout, a,r,g,b);
            return pxout;
        } else {
            guint32 r = CLAMP_D_TO_U8(pixel[0]*255.0);
            guint32 g = CLAMP_D_TO_U8(pixel[1]*255.0);
            guint32 b = CLAMP_D_TO_U8(pixel[2]*255.0);
            guint32 a = CLAMP_D_TO_U8(pixel[3]*255.0);
            r = premul_alpha(r, a);
            g = premul_alpha(g, a);
            b = premul_alpha(b, a);
            ASSEMBLE_ARGB32(pxout, a,r,g,b);
            return pxout;
        }
    }
int
wind_file_get_wind(wind_file_t* file, float lat, float lon, float height, 
                float* windu, float *windv, float *uvar, float *vvar)
{
        // we use static variables to 'cache' the last left and right lat/longs
        // and heights so that we can avoid searching the axes if necessary
        static int have_valid_latlon_cache = 0;
        static int have_valid_pressure_cache = 0;

        static unsigned int left_lat_idx, right_lat_idx;
        static unsigned int left_lon_idx, right_lon_idx;
        static unsigned int left_pr_idx, right_pr_idx;

        static float left_lat, right_lat;
        static float left_lon, right_lon;

        int i;
        float left_height, right_height;
        float lat_lambda, lon_lambda, pr_lambda;

        assert(file);
        assert(windu && windv);

        // canonicalise the longitude
        lon = _canonicalise_longitude(lon);

        // by default, return nothing in case of error.
        *windu = *windv = 0.f;

        // see if the cache is indeed valid
        if(have_valid_latlon_cache)
        {
                if((left_lat > lat) || 
                   (right_lat < lat) ||
                   !_longitude_is_left_of(left_lon, lon) || 
                   !_longitude_is_left_of(lon, right_lon))
                {
                        have_valid_latlon_cache = 0;
                }
        }

        // if we have no cached grid locations, look for them.
        if(!have_valid_latlon_cache)
        {
                // look for latitude along second axis 
                if(!_wind_file_axis_find_value(file->axes[1], lat,
                                        _float_is_left_of, &left_lat_idx, &right_lat_idx))
                {
                        fprintf(stderr, "ERROR: Latitude %f is not covered by file.\n", lat);
                        return 0;
                }
                left_lat = file->axes[1]->values[left_lat_idx];
                right_lat = file->axes[1]->values[right_lat_idx];

                // look for longitude along third axis
                if(!_wind_file_axis_find_value(file->axes[2], lon,
                                        _longitude_is_left_of, &left_lon_idx, &right_lon_idx))
                {
                        fprintf(stderr, "ERROR: Longitude %f is not covered by file.\n", lon);
                        return 0;
                }
                left_lon = file->axes[2]->values[left_lon_idx];
                right_lon = file->axes[2]->values[right_lon_idx];

                if(verbosity > 1)
                        fprintf(stderr, "INFO: Moved to latitude/longitude "
                                        "cell (%f,%f)-(%f,%f)\n",
                                        left_lat, left_lon, right_lat, right_lon);

                have_valid_latlon_cache = 1;
        }

        // compute the normalised lat/lon co-ordinate within the cell we're in.
        if(left_lat_idx != right_lat_idx)
                lat_lambda = (lat - left_lat) / (right_lat - left_lat);
        else
                lat_lambda = 0.5f;

        if(left_lon_idx != right_lon_idx)
                lon_lambda = _longitude_distance(lon, left_lon) 
                        / _longitude_distance(right_lon, left_lon);
        else
                lon_lambda = 0.5f;

        // munge the lambdas into the right range. Numerical approximations can nudge them
        // ~1e-08 either side sometimes.
        lat_lambda = (lat_lambda < 0.f) ? 0.f : lat_lambda;
        lat_lambda = (lat_lambda > 1.f) ? 1.f : lat_lambda;
        lon_lambda = (lon_lambda < 0.f) ? 0.f : lon_lambda;
        lon_lambda = (lon_lambda > 1.f) ? 1.f : lon_lambda;

        // use this normalised co-ordinate to check the left and right heights
        if(have_valid_pressure_cache)
        {
                float ll_height, lr_height, rl_height, rr_height;

                // left
                ll_height = _wind_file_get_height(file, left_lat_idx, left_lon_idx, left_pr_idx);
                lr_height = _wind_file_get_height(file, left_lat_idx, right_lon_idx, left_pr_idx);
                rl_height = _wind_file_get_height(file, right_lat_idx, left_lon_idx, left_pr_idx);
                rr_height = _wind_file_get_height(file, right_lat_idx, right_lon_idx, left_pr_idx);
                left_height = _bilinear_interpolate(ll_height, lr_height, rl_height, rr_height,
                                lat_lambda, lon_lambda);
                // if the leftmost height is too small and we can go lower...
                if((left_height > height) && (left_pr_idx > 0))
                        have_valid_pressure_cache = 0;

                // right
                ll_height = _wind_file_get_height(file, left_lat_idx, left_lon_idx, right_pr_idx);
                lr_height = _wind_file_get_height(file, left_lat_idx, right_lon_idx, right_pr_idx);
                rl_height = _wind_file_get_height(file, right_lat_idx, left_lon_idx, right_pr_idx);
                rr_height = _wind_file_get_height(file, right_lat_idx, right_lon_idx, right_pr_idx);
                right_height = _bilinear_interpolate(ll_height, lr_height, rl_height, rr_height,
                                lat_lambda, lon_lambda);
                // if the rightmost height is too small and we can go higher...
                if((right_height < height) && (right_pr_idx < file->axes[0]->n_values-1))
                        have_valid_pressure_cache = 0;
        }
        
        // if our height cache is out of whack, find a better cell.
        if(!have_valid_pressure_cache)
        {
                // search along all heights to find what pressure level we're at
                left_pr_idx = right_pr_idx = file->axes[0]->n_values;
                left_height = right_height = -1.f;
                for(i=0; i<file->axes[0]->n_values; ++i)
                {
                        // get heights for each corner of our lat/lon cell.
                        float ll_height = _wind_file_get_height(file, 
                                        left_lat_idx, left_lon_idx, i);
                        float lr_height = _wind_file_get_height(file, 
                                        left_lat_idx, right_lon_idx, i);
                        float rl_height = _wind_file_get_height(file, 
                                        right_lat_idx, left_lon_idx, i);
                        float rr_height = _wind_file_get_height(file,
                                        right_lat_idx, right_lon_idx, i);

                        // interpolate within our cell.
                        float interp_height = _bilinear_interpolate(
                                        ll_height, lr_height, rl_height, rr_height,
                                        lat_lambda, lon_lambda);

                        if((interp_height <= height) && 
                           ((interp_height >= left_height) || 
                            (left_pr_idx == file->axes[0]->n_values)))
                        {
                                left_pr_idx = i;
                                left_height = interp_height;
                        }

                        if((interp_height >= height) && 
                           ((interp_height <= right_height) ||
                            (right_pr_idx == file->axes[0]->n_values)))
                        {
                                right_pr_idx = i;
                                right_height = interp_height;
                        }
                }

                if(left_pr_idx == file->axes[0]->n_values)
                {
                        left_pr_idx = right_pr_idx;
                        if(verbosity > 0)
                                fprintf(stderr, "WARN: Moved to %.2fm, below height where we "
                                                "have data. "
                                                "Assuming we're at %.fmb or approx. %.2fm.\n",
                                                height,
                                                file->axes[0]->values[left_pr_idx],
                                                _wind_file_get_height(file,
                                                        left_lat_idx, left_lon_idx, left_pr_idx));
                }

                if(right_pr_idx == file->axes[0]->n_values)
                {
                        right_pr_idx = left_pr_idx;
                        if(verbosity > 0)
                                fprintf(stderr, "WARN: Moved to %.2fm, above height where we "
                                                "have data. "
                                                "Assuming we're at %.fmb or approx. %.2fm.\n",
                                                height,
                                                file->axes[0]->values[right_pr_idx],
                                                _wind_file_get_height(file,
                                                        left_lat_idx, left_lon_idx, right_pr_idx));
                }

                if((left_pr_idx == file->axes[0]->n_values) ||
                   (right_pr_idx == file->axes[0]->n_values))
                {
                        fprintf(stderr, "ERROR: Moved to a totally stupid height (%f). "
                                        "Giving up!\n", height);
                        return 0;
                }

                if(verbosity > 1)
                        fprintf(stderr, "INFO: Moved to pressure cell (%.fmb, %.fmb)\n", 
                                        file->axes[0]->values[left_pr_idx],
                                        file->axes[0]->values[right_pr_idx]);

                have_valid_pressure_cache = 1;
        }

        // compute the normalised pressure co-ordinate within the cell we're in.
        if(left_pr_idx != right_pr_idx)
                pr_lambda = (height - left_height) / (right_height - left_height);
        else
                pr_lambda = 0.5f;

        // pr_lambda might be outside of the range [0,1] depending on if we went
        // above or below our data, munge it appropriately.
        pr_lambda = (pr_lambda < 0.f) ? 0.f : pr_lambda;
        pr_lambda = (pr_lambda > 1.f) ? 1.f : pr_lambda;

        assert(lat_lambda >= 0.f);
        assert(lon_lambda >= 0.f);
        assert(pr_lambda >= 0.f);
        assert(lat_lambda <= 1.f);
        assert(lon_lambda <= 1.f);
        assert(pr_lambda <= 1.f);

        // By this point we have left/right co-ordinates which describe the
        // latitude, longitude and pressure boundaries of our data cell along
        // with normalised co-ordinates within it. We can now actually find
        // some data...
        //
        // We compute the lerped u and v along with the neighbourhood mean and
        // square mean to calculate the neighbourhood variance.
        {
                float llu, lru, rlu, rru;
                float llv, lrv, rlv, rrv;

                float lowu, lowv, highu, highv;

                float umean = 0.f;
                float usqmean = 0.f;
                float vmean = 0.f;
                float vsqmean = 0.f;

                // let's get the wind u and v for the lower lat/lon cell
                _wind_file_get_wind_raw(file, 
                                left_lat_idx, left_lon_idx, left_pr_idx, &llu, &llv);
                _wind_file_get_wind_raw(file, 
                                left_lat_idx, right_lon_idx, left_pr_idx, &lru, &lrv);
                _wind_file_get_wind_raw(file, 
                                right_lat_idx, left_lon_idx, left_pr_idx, &rlu, &rlv);
                _wind_file_get_wind_raw(file, 
                                right_lat_idx, right_lon_idx, left_pr_idx, &rru, &rrv);

                lowu = _bilinear_interpolate(llu, lru, rlu, rru, lat_lambda, lon_lambda);
                lowv = _bilinear_interpolate(llv, lrv, rlv, rrv, lat_lambda, lon_lambda);

                umean = llu + lru + rlu + rru;
                vmean = llv + lrv + rlv + rrv;
                usqmean = llu*llu + lru*lru + rlu*rlu + rru*rru;
                vsqmean = llv*llv + lrv*lrv + rlv*rlv + rrv*rrv;

                /*
                lowusq = _bilinear_interpolate(llu*llu, lru*lru, rlu*rlu, rru*rru,
                                lat_lambda, lon_lambda);
                lowvsq = _bilinear_interpolate(llv*llv, lrv*lrv, rlv*rlv, rrv*rrv, 
                                lat_lambda, lon_lambda);
                                */
                
                // let's get the wind u and v for the upper lat/lon cell
                _wind_file_get_wind_raw(file, 
                                left_lat_idx, left_lon_idx, right_pr_idx, &llu, &llv);
                _wind_file_get_wind_raw(file, 
                                left_lat_idx, right_lon_idx, right_pr_idx, &lru, &lrv);
                _wind_file_get_wind_raw(file, 
                                right_lat_idx, left_lon_idx, right_pr_idx, &rlu, &rlv);
                _wind_file_get_wind_raw(file, 
                                right_lat_idx, right_lon_idx, right_pr_idx, &rru, &rrv);

                highu = _bilinear_interpolate(llu, lru, rlu, rru, lat_lambda, lon_lambda);
                highv = _bilinear_interpolate(llv, lrv, rlv, rrv, lat_lambda, lon_lambda);

                umean += llu + lru + rlu + rru;
                vmean += llv + lrv + rlv + rrv;
                usqmean += llu*llu + lru*lru + rlu*rlu + rru*rru;
                vsqmean += llv*llv + lrv*lrv + rlv*rlv + rrv*rrv;

                /*
                highusq = _bilinear_interpolate(llu*llu, lru*lru, rlu*rlu, rru*rru,
                                lat_lambda, lon_lambda);
                highvsq = _bilinear_interpolate(llv*llv, lrv*lrv, rlv*rlv, rrv*rrv, 
                                lat_lambda, lon_lambda);
                                */

                *windu = _lerp(lowu, highu, pr_lambda);
                *windv = _lerp(lowv, highv, pr_lambda);

                // We will calculate the variance by making use of the fact
                // that the lerping is effectively a weighted mean or
                // expectation and that
                // var = E[X^2] - E[X]^2.
                //
                // In effect this calculates the instantaneous variance by considering the
                // contributions from the cube surrounding the point in question.
                // This is highly cunning and, on the face of it, not entirely wrong.

                umean *= 0.125f; usqmean *= 0.125f;
                vmean *= 0.125f; vsqmean *= 0.125f;

                *uvar = usqmean - umean * umean;
                *vvar = vsqmean - vmean * vmean;
        }

        return 1;
}
Exemplo n.º 6
0
static void _smooth_draw_triangle_flat_bottom(vertex &v0, vertex &v1, vertex &v2) {
    if (v0.y == v1.y) {
        _swap_vertex(v0, v2);
    }
    else if (v0.y == v2.y) {
        _swap_vertex(v0, v1);
    }
    if (v1.x > v2.x) {
        _swap_vertex(v1, v2);
    }

    int x0 = v0.x;
    int y0 = v0.y;
    int x1 = v1.x;
    int y1 = v1.y;
    int x2 = v2.x;
    int y2 = v2.y;

    float xs = x0;
    float xe = x0;
    int y_end = (y1 > y2) ? y1 : y2;
    float y_dis = y_end - y0;
    float crs = v0.r;
    float cre = v0.r;
    float cgs = v0.g;
    float cge = v0.g;
    float cbs = v0.b;
    float cbe = v0.b;
    float cas = v0.a;
    float cae = v0.a;
    float tus = v0.u;
    float tue = v0.u;
    float tvs = v0.v;
    float tve = v0.v;
    float ds = v0.z;
    float de = v0.z;
    bool texturing = (tus != -1 && tvs != -1);
    color c;

    for (int y = y0; y < y_end; y++) {
        float ly = ((float)y - y0) / y_dis;
        xs = _lerp(x0, x1, ly);
        xe = _lerp(x0, x2, ly);
        crs = _lerp(v0.r, v1.r, ly);
        cre = _lerp(v0.r, v2.r, ly);
        cgs = _lerp(v0.g, v1.g, ly);
        cge = _lerp(v0.g, v2.g, ly);
        cbs = _lerp(v0.b, v1.b, ly);
        cbe = _lerp(v0.b, v2.b, ly);
        cas = _lerp(v0.a, v1.a, ly);
        cae = _lerp(v0.a, v2.a, ly);
        if (texturing) {
            tus = _lerp(v0.u, v1.u, ly);
            tue = _lerp(v0.u, v2.u, ly);
            tvs = _lerp(v0.v, v1.v, ly);
            tve = _lerp(v0.v, v2.v, ly);
        }
        ds = _lerp(v0.z, v1.z, ly);
        de = _lerp(v0.z, v2.z, ly);
        float x_dis = xe - xs;
        for (int x = xs; x < xe; x++) {
            float lx = ((float)x - xs) / x_dis;
            float d = _lerp(ds, de, lx);
            if (!depth_buffer::get_instance()->d_test(x, y, d)) {
                continue;
            }
            if (!texturing) {
                c.r = _lerp(crs, cre, lx);
                c.g = _lerp(cgs, cge, lx);
                c.b = _lerp(cbs, cbe, lx);
                c.a = _lerp(cas, cae, lx);
            }
            else {
                float u = _lerp(tus, tue, lx);
                float v = _lerp(tvs, tve, lx);
                c = texture::get_instance()->sampling(u, v);
            }
            color_buffer::get_intance()->write_color(x, y, c);
        }
    }
}