DLLEXPORT miBoolean domeAFL_FOV_Stereo(
	miColor	*result,
	miState	*state,
	struct dsDomeAFL_FOV_Stereo *params)
{
	miScalar	cameras_separation_multiplier = *mi_eval_scalar(&params->Cameras_Separation_Map);
	miScalar	head_turn_multiplier = *mi_eval_scalar(&params->Head_Turn_Map);
	miScalar	head_tilt = *mi_eval_scalar(&params->Head_Tilt_Map);

	miVector	org, ray, target, htarget;
	miMatrix	tilt;
	double		x, y, r, phi, theta, rot, tmp, tmpY, tmpZ;
	double		sinP, cosP, sinT, cosT, sinR, cosR;

   	// normalize image coordinates btwn [-1,1]...
	// [rz] swap X-Y to match camera view and apply a vertical symmetry
	// [rz] basically, we rotate the cartesian axis 90deg CW
	x = -2.0*state->raster_y/state->camera->y_resolution+1.0;
	y = 2.0*state->raster_x/state->camera->x_resolution-1.0;

	// Calculate the radius value
	r = MI_SQRT((x*x)+(y*y));

	if (r < 1.0) {

		// Calculate phi...
		if ((r > -EPSILON) && (r < EPSILON) ) {
			phi = 0.0;
		} else {
			phi = atan2(y,x);
		}
		// Calculate theta...
		theta = r*(fov_angle/2.0);

		// start by matching camera (center camera)
		// mi_point_to_camera(state, &org, &state->org);
		org.x = org.y = org.z = 0.0;

		// saves common used values for performance reasons
		sinP = sin(phi); cosP = cos(phi);
		sinT = sin(theta); cosT = cos(theta);

		// center camera target vector (normalized)
		target.x = (miScalar)(sinP*sinT);
		target.y = (miScalar)(-cosP*sinT);
		target.z = (miScalar)(-cosT);

		if (camera != CENTERCAM) {
			// camera selection and initial position
			// @@@ use switch?
			if (camera == LEFTCAM) {
				org.x = (miScalar)(-cameras_separation*cameras_separation_multiplier/2);
			}
			if (camera == RIGHTCAM) {
				org.x = (miScalar)(cameras_separation*cameras_separation_multiplier/2);
			}

			if (dome_tilt_compensation) {		// tilted dome mode

				// head rotation
				// @@@ need to check atan2 params for 0 values?
				// @@@ save values of sin/cos
				tmpY = target.y*cos(-dome_tilt)-target.z*sin(-dome_tilt);
				tmpZ = target.z*cos(-dome_tilt)+target.y*sin(-dome_tilt);
				rot = atan2(target.x,-tmpY)*head_turn_multiplier;
				if (vertical_mode)
					rot *= fabs(sinP);
				sinR = sin(rot); cosR = cos(rot);

				// rotate camera
				tmp = org.x*cosR-org.y*sinR;
				org.y = (miScalar)(org.y*cosR+org.x*sinR);
				org.x = (miScalar)tmp;

				// compensate for dome tilt
				// @@@ save values of sin/cos
				tmp = org.y*cos(dome_tilt)-org.z*sin(dome_tilt);
				org.z = (miScalar)(org.z*cos(dome_tilt)+org.y*sin(dome_tilt));
				org.y = (miScalar)tmp;

				// calculate head target
				tmp = sqrt(target.x*target.x+tmpY*tmpY);
				htarget.x = (miScalar)(sin(rot)*tmp);
				htarget.y = (miScalar)(-cos(rot)*tmp);
				htarget.z = (miScalar)tmpZ;

				// dome rotation again on head target
				tmp = htarget.y*cos(dome_tilt)-htarget.z*sin(dome_tilt);
				htarget.z = (miScalar)(htarget.z*cos(dome_tilt)+htarget.y*sin(dome_tilt));
				htarget.y = (miScalar)tmp;

			} else {

				if (vertical_mode) {			// vertical mode

					// head rotation
					// @@@ need to check atan2 params for 0 values?
					rot = atan2(target.x,-target.z)*head_turn_multiplier*fabs(sinP);
					sinR = sin(rot); cosR = cos(rot);

					// rotate camera
					tmp = org.x*cosR-org.z*sinR;
					org.z = (miScalar)(org.z*cosR+org.x*sinR);
					org.x = (miScalar)tmp;

					// calculate head target
					tmp = sqrt(target.x*target.x+target.z*target.z);
					htarget.x = (miScalar)(sin(rot)*tmp);
					htarget.y = (miScalar)target.y;
					htarget.z = (miScalar)(-cos(rot)*tmp);

				} else {						// horizontal mode

					// head rotation
					rot = phi*head_turn_multiplier;
					sinR = sin(rot); cosR = cos(rot);

					// rotate camera
					tmp = org.x*cosR-org.y*sinR;
					org.y = (miScalar)(org.y*cosR+org.x*sinR);
					org.x = (miScalar)tmp;

					// calculate head target
					htarget.x = (miScalar)(sin(rot)*sinT);
					htarget.y = (miScalar)(-cos(rot)*sinT);
					htarget.z = (miScalar)target.z;

				}
			}

			// head tilt
			head_tilt = (miScalar)((head_tilt-0.5)*M_PI);
			mi_matrix_ident(tilt);
			mi_matrix_rotate_axis(tilt, &htarget, head_tilt);
			mi_vector_transform(&org, &org, tilt);

			// calculate ray from camera to target
			target.x *= dome_radius;
			target.y *= dome_radius;
			target.z *= dome_radius;
			ray.x = target.x-org.x;
			ray.y = target.y-org.y;
			ray.z = target.z-org.z;
			mi_vector_normalize(&ray);

		} else {		// center camera

			ray = target;

		}


		// Account for view offset...
   		// Offset is added to y & z components because they are negative values...
		// @@@ ray.x = ray.x - viewport_offset.x;
		// @@@ ray.y = ray.y + viewport_offset.y;
		// @@@ ray.z = ray.z + viewport_offset.z;

//mi_debug("II->,Phi=%f,Theta=%f,rot=%f,camx=%f,camy=%f", (miScalar)phi, (miScalar)theta, (miScalar)rot, (miScalar)org.x, (miScalar)org.y);

		// Flip the ray direction about the y-axis
		// @@@ if(*mi_eval_boolean(&params->Flip_Ray_X)) { 
		// @@@ 	ray.x = (-ray.x);
		// @@@ }
       	// Flip the ray direction about the x-axis
		// @@@ if(*mi_eval_boolean(&params->Flip_Ray_Y)) {
		// @@@ 	ray.y = (-ray.y);		
		// @@@ }


		// Convert ray from camera space
		mi_vector_from_camera(state, &ray, &ray);
		mi_point_from_camera(state, &org, &org);

		// Trace new ray...
		return(mi_trace_eye(result, state, &org, &ray));

	} else {

		// Set the return colors to Black
		result->r = result->g = result->b = result->a = 0;
		return(miFALSE);
	}

}
Example #2
0
extern "C" DLLEXPORT miBoolean mib_bent_normal_env(
	miColor     *result,
	miState     *state,
	struct mib_bent_normal_env_p *paras)
{
	miTag  original_env = state->environment;
	miTag  environment  = *mi_eval_tag(&paras->environment);
	miColor   normal    = *mi_eval_color(&paras->bent_normals);
	miColor   occlus    = *mi_eval_color(&paras->occlusion);
	miScalar  strength  = *mi_eval_scalar(&paras->strength);
	miColor   color;      /* Work color */
	miVector  bent;       /* Bent normals */
	miVector  bent_i;     /* Bent normals in internal space */
	miUint	  samples;    /* # of samples */

	/* Displace or light - makes no sense */
	if (state->type == miRAY_DISPLACE || state->type == miRAY_LIGHT)
	    return miFALSE;

	if (strength == 0.0) {
	    result->r = result->g = result->b = 0.0;
	    result->a = 1.0;
	    return miTRUE;
	}

	color.r = color.b = color.g = 0.0;

	/* Does occlusion live in "alpha" component of bn data? */
	if (*mi_eval_boolean(&paras->occlusion_in_alpha))
	    strength *= normal.a;
    
	bent.x = (normal.r * 2.0) - 1.0;
	bent.y = (normal.g * 2.0) - 1.0;
	bent.z = (normal.b * 2.0) - 1.0;

	mi_vector_normalize(&bent);

	/* The different coordinate spaces */
	switch(*mi_eval_integer(&paras->coordinate_space)) {
		case 0: /* No change */
			bent_i = bent;
			break;
		case 1: /* By matrix */
			mi_vector_transform(&bent_i,
				&bent,
				mi_eval_transform(&paras->matrix));
			break;
		case 2: /* World */
			mi_normal_from_world(state, &bent_i, &bent);
			break;
		case 3: /* Camera */
			mi_normal_from_camera(state, &bent_i, &bent);
			break;
		case 4: /* Object */
			mi_normal_from_object(state, &bent_i, &bent);
			break;
	}
    
	samples = *mi_eval_integer(&paras->env_samples);

	/* Temporarily override the environment */
	if (environment)
	    state->environment = environment;

	if (samples <= 1) {
		/* Single sampling */		      
		mi_trace_environment(&color, state, &bent_i);
	} else {
		/* Multisampling */
		double	 sample[3];
		int	 counter = 0;
		miScalar spread  = *mi_eval_scalar(&paras->samples_spread);
		miColor  work_color;

		/* Clear color */
		color.r = color.g = color.b = 0.0;
			
		while (mi_sample(sample, &counter, state, 3, &samples)) {
			miVector trace_dir;
			trace_dir.x = bent_i.x + (sample[0] - 0.5) * spread;
			trace_dir.y = bent_i.y + (sample[1] - 0.5) * spread;
			trace_dir.z = bent_i.z + (sample[2] - 0.5) * spread;
			
			mi_vector_normalize(&trace_dir);

			mi_trace_environment(&work_color, state, &trace_dir);
			color.r += work_color.r;
			color.g += work_color.g;
			color.b += work_color.b;
		}

		color.r /= samples;
		color.g /= samples;
		color.b /= samples;
	}

	/* Reset original environment */
	state->environment = original_env;

	result->r = color.r * occlus.r * strength;
	result->g = color.g * occlus.g * strength;
	result->b = color.b * occlus.b * strength;
	result->a = 1.0;

	return miTRUE;
}
DLLEXPORT miBoolean LatLong_Stereo(
	miColor	*result,
	miState	*state,
	struct dsLatLong_Stereo *params)
{
	miScalar	cameras_separation_multiplier = *mi_eval_scalar(&params->Cameras_Separation_Map);
	miScalar	head_tilt = *mi_eval_scalar(&params->Head_Tilt_Map);

	miVector	org, ray, target, htarget;
	miMatrix	tilt;
	double		x, y, phi, theta, tmp;
	double		sinP, cosP, sinT, cosT;

	miBoolean	zenithMode = *mi_eval_boolean(&params->Zenith_Mode);

	// Normalize image coordinates btwn [-1,-1] and [1,1]...
	x = 2.0*state->raster_x/state->camera->x_resolution-1.0;
	y = 2.0*state->raster_y/state->camera->y_resolution-1.0;

	// Calculate phi and theta...
	phi = x*(fov_horiz_angle/2.0);
	if (zenithMode)
		theta = M_PI_2-y*(fov_vert_angle/2.0);
	else
		theta = y*(fov_vert_angle/2.0);

	// Start by matching camera (center camera)
	// mi_point_to_camera(state, &org, &state->org);
	org.x = org.y = org.z = 0.0;

	// Saves common used values for performance reasons
	sinP = sin(phi); cosP = cos(phi);
	sinT = sin(theta); cosT = cos(theta);

	// Center camera target vector (normalized)
	if (zenithMode) {
		target.x = (miScalar)(sinP*sinT);
		target.y = (miScalar)(-cosP*sinT);
		target.z = (miScalar)(-cosT);
	} else {
		target.x = (miScalar)(sinP*cosT);
		target.y = (miScalar)(sinT);
		target.z = (miScalar)(-cosP*cosT);
	}

	if (camera != CENTERCAM) {
		// Camera selection and initial position
		if (camera == LEFTCAM) {
			org.x = (miScalar)(-cameras_separation*cameras_separation_multiplier/2);
		} else if (camera == RIGHTCAM) {
			org.x = (miScalar)(cameras_separation*cameras_separation_multiplier/2);
		}

		// Head rotation = phi
		// Rotate camera
		if (zenithMode) {
			tmp = org.x*cosP-org.y*sinP;
			org.y = (miScalar)(org.y*cosP+org.x*sinP);
			org.x = (miScalar)tmp;
		} else {
			tmp = org.x*cosP-org.z*sinP;
			org.z = (miScalar)(org.z*cosP+org.x*sinP);
			org.x = (miScalar)tmp;
		}

		// Calculate head target
		htarget.x = (miScalar)(sinP*sinT);
		htarget.y = (miScalar)(-cosP*sinT);
		htarget.z = (miScalar)target.z;

		// Head tilt
		head_tilt = (miScalar)((head_tilt-0.5)*M_PI);
		mi_matrix_ident(tilt);
		mi_matrix_rotate_axis(tilt, &htarget, head_tilt);
		mi_vector_transform(&org, &org, tilt);

		// Calculate ray from camera to target
		target.x *= parallax_distance;
		target.y *= parallax_distance;
		target.z *= parallax_distance;
		ray.x = target.x-org.x;
		ray.y = target.y-org.y;
		ray.z = target.z-org.z;
		mi_vector_normalize(&ray);
	} else{		
    // Center camera
    ray = target;
	}

//mi_debug("II->,Phi=%f,Theta=%f,rot=%f,camx=%f,camy=%f", (miScalar)phi, (miScalar)theta, (miScalar)rot, (miScalar)org.x, (miScalar)org.y);

	// Flip the X ray direction about the Y-axis
	if(*mi_eval_boolean(&params->Flip_Ray_X)) { 
		org.x = (-org.x);
		ray.x = (-ray.x);
	}
	// Flip the Y ray direction about the X-axis
	if(*mi_eval_boolean(&params->Flip_Ray_Y)) {
		if(zenithMode) {
			org.z = (-org.z);
			ray.z = (-ray.z);
		} else {
			org.y = (-org.y);
			ray.y = (-ray.y);
		}
	}

  #if 1
    /* Adjust the ray differentials */
    rotate_ray_differentials(state, ray);
  #endif
  
	// Convert ray from camera space
	mi_vector_from_camera(state, &ray, &ray);
	mi_point_from_camera(state, &org, &org);

	// Trace new ray...
	return(mi_trace_eye(result, state, &org, &ray));

}
miTag createMeshParticles(miState *state, mrParticleGeoShader_paras *paras, PartioContainer& pc)
{
	mi_info("Creating mesh particles for cache file: %s", pc.cacheFileName.c_str());
	if( ! pc.good())
	{
		mi_error("Invalid PartioContainer.");
		return miNULLTAG;
	}

	Partio::ParticleAttribute posAttr;
	if(!pc.assertAttribute("position", posAttr))
		return miNULLTAG;

	Partio::ParticleAttribute idAttr;
	bool hasId = true;
	if(!pc.assertAttribute("id", idAttr))
		hasId = false;

	Partio::ParticleAttribute radiusPPAttr;
	bool hasRadiusPP = true;
	if(!pc.assertAttribute("radiusPP", radiusPPAttr))
		hasRadiusPP = false;

	Partio::ParticleAttribute velocityAttr;
	bool hasVelocity = true;
	if(!pc.assertAttribute("velocity", velocityAttr))
		hasVelocity = false;
	
	miObject *obj = beginObject();

	float *fpos;
	srand(123345);
	int numParticles = pc.data->numParticles();
	float sizeMultiplier = *mi_eval_scalar(&paras->sizeMultiplier);
	float density = *mi_eval_scalar(&paras->density);
	float size = *mi_eval_scalar(&paras->size);
	float sizeVariation = *mi_eval_scalar(&paras->sizeVariation);

	// particle number can vary because of density value
	int numWrittenParticles = 0;

	// define vectors
	for(int vtxId = 0; vtxId < numParticles; vtxId++)
	{
		miVector pos;
		fpos = (float *)pc.data->data<float>(posAttr, vtxId);

		int id = vtxId;
		if( hasId)
			id = *pc.data->data<int>(idAttr, vtxId);

		float radiusPP = 1.0f;
		if( hasRadiusPP )
			radiusPP = *pc.data->data<float>(radiusPPAttr, vtxId);

		miVector vel = {0.0, 0.0, 0.0};
		if(hasVelocity)
		{
			float *v;
			v = (float *)pc.data->data<float>(velocityAttr, vtxId);
			vel.x = v[0];
			vel.y = v[1];
			vel.z = v[2];
			// velocity ist distance/sekunde, eine velocity von 24 legt also eine Distanz von 1 Einheit pro frame bei 24fps zurück
			// zusätzlich muss man noch den shutter angle beachten, bei 140° sind das -.2 -> 0.2 also 0.4 * 1 und damit grob .4 Einheiten
			float factor = 1.0f/24.0f * 0.4f;
			mi_vector_mul(&vel, factor);
		}

		pos.x = fpos[0];
		pos.y = fpos[1];
		pos.z = fpos[2];

		miVector camPos = pos;

		// ich transformiere das particle in camera space und gehe dann einfach size/2 nach rechts und oben
		miMatrix matrix;
		mi_matrix_ident(matrix);
		miInstance *inst = (miInstance *)mi_db_access(state->instance);
		mi_matrix_copy(matrix, inst->tf.global_to_local);
		mi_db_unpin(state->instance);
		
		mi_point_from_world(state, &camPos, &pos);
		mi_point_from_world(state, &camPos, &camPos);
		mi_point_to_camera(state, &camPos, &camPos);

		float psize = radiusPP * sizeMultiplier;
		int pId = vtxId;
		double rndVal = rnd(id * state->camera->frame + 5);
		if( rndVal > density)
			continue;
		
		float srndVal = (rndVal - 0.5f) * 2.0f;
		psize *= size + (size * srndVal * sizeVariation * 0.5f);
		psize = fabs(psize);
		if(psize == 0.0f)
			continue;

		miVector upRight, bottomLeft;
		upRight = camPos;
		upRight.x += psize/2.0f;
		upRight.y += psize/2.0f;
		bottomLeft = camPos;
		bottomLeft.x -= psize/2.0f;
		bottomLeft.y -= psize/2.0f;

		// checkScreenSpace in Screenspace und testet auf minPixelSize. 
		if(!checkScreenSpace(state, paras, camPos, bottomLeft, upRight) )
			continue;
		numWrittenParticles++;

		miVector v0, v1, v2, v3;
		v0 = bottomLeft;
		v2 = upRight;
		v1 = bottomLeft;
		v1.y = upRight.y;
		v3 = upRight;
		v3.y = bottomLeft.y;

		mi_point_from_camera(state, &v0, &v0);
		mi_point_from_camera(state, &v1, &v1);
		mi_point_from_camera(state, &v2, &v2);
		mi_point_from_camera(state, &v3, &v3);

		mi_point_to_world(state, &v0, &v0);
		mi_point_to_world(state, &v1, &v1);
		mi_point_to_world(state, &v2, &v2);
		mi_point_to_world(state, &v3, &v3);

		miVector v01, v02, v03;
		mi_vector_sub(&v01, &v0, &v1);
		mi_vector_sub(&v02, &v0, &v2);
		mi_vector_sub(&v03, &v0, &v3);
		mi_vector_transform(&v01, &v01, matrix);
		mi_vector_transform(&v02, &v02, matrix);
		mi_vector_transform(&v03, &v03, matrix);
		mi_vector_add(&v1, &v0, &v01);
		mi_vector_add(&v2, &v0, &v02);
		mi_vector_add(&v3, &v0, &v03);

		// add geometry vectors 
		// e.g. -0.5 -0.5 0.5
		add_vector(v0.x, v0.y, v0.z);
		add_vector(v1.x, v1.y, v1.z);
		add_vector(v2.x, v2.y, v2.z);
		add_vector(v3.x, v3.y, v3.z);

		// single motion vector per particle
		add_vector(vel.x, vel.y, vel.z);

	}

	// uv coordinates
	miVector uvw;
	uvw.x = uvw.y = uvw.z = 0.0f;
	uvw.z = 123.0f;
	mi_api_vector_xyz_add( &uvw );
	uvw.x = 1.0;
	mi_api_vector_xyz_add( &uvw );
	uvw.y = 1.0;
	mi_api_vector_xyz_add( &uvw );
	uvw.x = 0.0;
	mi_api_vector_xyz_add( &uvw );


	// define vertices
	// depending on the attributes we have x vectors per vertex:
	// 0: pos1
	// 1: pos2
	// 2: pos3
	// 3: pos4
	// 4: vel
	// tex0 = numWrittenParticles * 5 - 4

	// num done particles für rnd density
	int texIndex = numWrittenParticles * 5;
	for(int vtxId = 0; vtxId < numWrittenParticles; vtxId++)
	{
		int vertexIndex = vtxId * 5;
		int mvIndex = vtxId * 5 + 4;
		// add vertex definitions
		// e.g. v 0 n 8 t 32 m 46
		mi_api_vertex_add(vertexIndex);
		mi_api_vertex_tex_add( texIndex, -1, -1);
		mi_api_vertex_motion_add(mvIndex);

		mi_api_vertex_add(vertexIndex + 1);
		mi_api_vertex_tex_add( texIndex + 1, -1, -1);
		mi_api_vertex_motion_add(mvIndex);

		mi_api_vertex_add(vertexIndex + 2);
		mi_api_vertex_tex_add( texIndex + 2, -1, -1);
		mi_api_vertex_motion_add(mvIndex);

		mi_api_vertex_add(vertexIndex + 3);
		mi_api_vertex_tex_add( texIndex + 3, -1, -1);
		mi_api_vertex_motion_add(mvIndex);
	}


	// add poly for every particle

	for( int pId = 0; pId < numWrittenParticles; pId++)
	{
		int vtxId = pId * 4;
		mi_api_poly_begin_tag(1, miNULLTAG);

		mi_api_poly_index_add(vtxId);
		mi_api_poly_index_add(vtxId + 1);
		mi_api_poly_index_add(vtxId + 2);
		mi_api_poly_index_add(vtxId + 3);

		mi_api_poly_end();

	}
	miTag objTag = finishObject();
	return objTag;
   
}