gpuray_glsl

diff src/camera.cc @ 0:f234630e38ff

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 09 Nov 2014 13:03:36 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/camera.cc	Sun Nov 09 13:03:36 2014 +0200
     1.3 @@ -0,0 +1,199 @@
     1.4 +#include <stdio.h>
     1.5 +#include <math.h>
     1.6 +#include "camera.h"
     1.7 +
     1.8 +static void calc_sample_pos_rec(int sidx, float xsz, float ysz, float *pos);
     1.9 +
    1.10 +Camera::Camera()
    1.11 +{
    1.12 +	vfov = M_PI / 4.0;
    1.13 +	cached_matrix_valid = false;
    1.14 +
    1.15 +	rdir_cache_width = rdir_cache_height = 0;
    1.16 +	rdir_cache = 0;
    1.17 +}
    1.18 +
    1.19 +Camera::Camera(const Vector3 &p)
    1.20 +	: pos(p)
    1.21 +{
    1.22 +	vfov = M_PI / 4.0;
    1.23 +	cached_matrix_valid = false;
    1.24 +
    1.25 +	rdir_cache_width = rdir_cache_height = 0;
    1.26 +	rdir_cache = 0;
    1.27 +}
    1.28 +
    1.29 +Camera::~Camera()
    1.30 +{
    1.31 +	delete [] rdir_cache;
    1.32 +}
    1.33 +
    1.34 +void Camera::set_fov(float vfov)
    1.35 +{
    1.36 +	this->vfov = vfov;
    1.37 +
    1.38 +	// invalidate the dir cache
    1.39 +	delete [] rdir_cache;
    1.40 +}
    1.41 +
    1.42 +float Camera::get_fov() const
    1.43 +{
    1.44 +	return vfov;
    1.45 +}
    1.46 +
    1.47 +void Camera::set_position(const Vector3 &pos)
    1.48 +{
    1.49 +	this->pos = pos;
    1.50 +	cached_matrix_valid = false;	// invalidate the cached matrix
    1.51 +}
    1.52 +
    1.53 +const Vector3 &Camera::get_position() const
    1.54 +{
    1.55 +	return pos;
    1.56 +}
    1.57 +
    1.58 +const Matrix4x4 &Camera::get_matrix() const
    1.59 +{
    1.60 +	if(!cached_matrix_valid) {
    1.61 +		calc_matrix(&cached_matrix);
    1.62 +		cached_matrix_valid = true;
    1.63 +	}
    1.64 +	return cached_matrix;
    1.65 +}
    1.66 +
    1.67 +Vector2 Camera::calc_sample_pos(int x, int y, int xsz, int ysz, int sample) const
    1.68 +{
    1.69 +	float ppos[2];
    1.70 +	float aspect = (float)xsz / (float)ysz;
    1.71 +
    1.72 +	float pwidth = 2.0 * aspect / (float)xsz;
    1.73 +	float pheight = 2.0 / (float)ysz;
    1.74 +
    1.75 +	ppos[0] = (float)x * pwidth - aspect;
    1.76 +	ppos[1] = 1.0 - (float)y * pheight;
    1.77 +
    1.78 +	calc_sample_pos_rec(sample, pwidth, pheight, ppos);
    1.79 +	return Vector2(ppos[0], ppos[1]);
    1.80 +}
    1.81 +
    1.82 +Ray Camera::get_primary_ray(int x, int y, int xsz, int ysz, int sample) const
    1.83 +{
    1.84 +	if(!rdir_cache || rdir_cache_width != xsz || rdir_cache_height != ysz) {
    1.85 +		printf("calculating primary ray direction cache\n");
    1.86 +
    1.87 +		delete [] rdir_cache;
    1.88 +		rdir_cache = new Vector3[xsz * ysz];
    1.89 +
    1.90 +		for(int i=0; i<ysz; i++) {
    1.91 +			Vector3 *rdir = rdir_cache + i * xsz;
    1.92 +			for(int j=0; j<xsz; j++) {
    1.93 +				Vector2 ppos = calc_sample_pos(j, i, xsz, ysz, 0);
    1.94 +
    1.95 +				rdir->x = ppos.x;
    1.96 +				rdir->y = ppos.y;
    1.97 +				rdir->z = 1.0 / tan(vfov / 2.0);
    1.98 +				rdir->normalize();
    1.99 +
   1.100 +				rdir++;
   1.101 +			}
   1.102 +		}
   1.103 +		rdir_cache_width = xsz;
   1.104 +		rdir_cache_height = ysz;
   1.105 +	}
   1.106 +
   1.107 +	Ray ray;
   1.108 +	ray.origin = pos;
   1.109 +	ray.dir = rdir_cache[y * xsz + x];
   1.110 +
   1.111 +	// transform the ray direction with the camera matrix
   1.112 +	Matrix4x4 mat = get_matrix();
   1.113 +	mat.m[0][3] = mat.m[1][3] = mat.m[2][3] = mat.m[3][0] = mat.m[3][1] = mat.m[3][2] = 0.0;
   1.114 +	mat.m[3][3] = 1.0;
   1.115 +
   1.116 +	ray.dir = ray.dir.transformed(mat);
   1.117 +	return ray;
   1.118 +}
   1.119 +
   1.120 +TargetCamera::TargetCamera() {}
   1.121 +
   1.122 +TargetCamera::TargetCamera(const Vector3 &pos, const Vector3 &targ)
   1.123 +	: Camera(pos), target(targ)
   1.124 +{
   1.125 +}
   1.126 +
   1.127 +void TargetCamera::set_target(const Vector3 &targ)
   1.128 +{
   1.129 +	target = targ;
   1.130 +	cached_matrix_valid = false; // invalidate the cached matrix
   1.131 +}
   1.132 +
   1.133 +const Vector3 &TargetCamera::get_target() const
   1.134 +{
   1.135 +	return target;
   1.136 +}
   1.137 +
   1.138 +void TargetCamera::calc_matrix(Matrix4x4 *mat) const
   1.139 +{
   1.140 +	Vector3 up(0, 1, 0);
   1.141 +	Vector3 dir = (target - pos).normalized();
   1.142 +	Vector3 right = cross_product(up, dir);
   1.143 +	up = cross_product(dir, right);
   1.144 +
   1.145 +	*mat = Matrix4x4(
   1.146 +			right.x, up.x, dir.x, pos.x,
   1.147 +			right.y, up.y, dir.y, pos.y,
   1.148 +			right.z, up.z, dir.z, pos.z,
   1.149 +			0.0, 0.0, 0.0, 1.0);
   1.150 +}
   1.151 +
   1.152 +void FlyCamera::input_move(float x, float y, float z)
   1.153 +{
   1.154 +	static const Vector3 vfwd(0, 0, 1), vright(1, 0, 0);
   1.155 +
   1.156 +	Vector3 k = vfwd.transformed(rot);
   1.157 +	Vector3	i = vright.transformed(rot);
   1.158 +	Vector3 j = cross_product(k, i);
   1.159 +
   1.160 +	pos += i * x + j * y + k * z;
   1.161 +	cached_matrix_valid = false;
   1.162 +}
   1.163 +
   1.164 +void FlyCamera::input_rotate(float x, float y, float z)
   1.165 +{
   1.166 +	Vector3 axis(x, y, z);
   1.167 +	float axis_len = axis.length();
   1.168 +	if(fabs(axis_len) < 1e-5) {
   1.169 +		return;
   1.170 +	}
   1.171 +	rot.rotate(axis / axis_len, -axis_len);
   1.172 +	rot.normalize();
   1.173 +
   1.174 +	cached_matrix_valid = false;
   1.175 +}
   1.176 +
   1.177 +void FlyCamera::calc_matrix(Matrix4x4 *mat) const
   1.178 +{
   1.179 +	Matrix3x3 rmat = rot.get_rotation_matrix();
   1.180 +	*mat = rmat;
   1.181 +}
   1.182 +
   1.183 +/* generates a sample position for sample number sidx, in the unit square
   1.184 + * by recursive subdivision and jittering
   1.185 + */
   1.186 +static void calc_sample_pos_rec(int sidx, float xsz, float ysz, float *pos)
   1.187 +{
   1.188 +    static const float subpt[4][2] = {
   1.189 +        {-0.25, -0.25}, {0.25, -0.25}, {-0.25, 0.25}, {0.25, 0.25}
   1.190 +    };
   1.191 +
   1.192 +    if(!sidx) {
   1.193 +        return;
   1.194 +    }
   1.195 +
   1.196 +    /* determine which quadrant to recurse into */
   1.197 +    int quadrant = ((sidx - 1) % 4);
   1.198 +    pos[0] += subpt[quadrant][0] * xsz;
   1.199 +    pos[1] += subpt[quadrant][1] * ysz;
   1.200 +
   1.201 +    calc_sample_pos_rec((sidx - 1) / 4, xsz / 2, ysz / 2, pos);
   1.202 +}