DLLEXPORT void domeAFL_FOV_Stereo_init(
	miState	*state,
	struct dsDomeAFL_FOV_Stereo *params,
	miBoolean *inst_init_req)
{
	if (!params) {
		// version output
		mi_info(_VER_);
		*inst_init_req = miTRUE;
	} else {
		fov_angle = *mi_eval_scalar(&params->FOV_Angle);
		viewport_offset = *mi_eval_vector(&params->View_Offset);
		camera = *mi_eval_integer(&params->Camera);
		dome_radius = *mi_eval_scalar(&params->Dome_Radius);
		dome_tilt = *mi_eval_scalar(&params->Dome_Tilt);
		cameras_separation = *mi_eval_scalar(&params->Cameras_Separation);
		dome_tilt_compensation = *mi_eval_boolean(&params->Dome_Tilt_Compensation);
		vertical_mode = *mi_eval_boolean(&params->Vertical_Mode);
//mi_info("II-> fov=%f,cam=%i,rad=%f,tilt=%f,sep=%f,comp=%i,vert=%i",fov_angle,camera,dome_radius,dome_tilt,cameras_separation,dome_tilt_compensation,vertical_mode);

		// Convert input angles from degrees to radians...
		fov_angle = (miScalar)(fov_angle*M_PI/180.0);
		dome_tilt = (miScalar)(dome_tilt*M_PI/180.0);
	}
}
extern "C" DLLEXPORT miBoolean mrParticleGeoShader(
	miTag             *result,
	miState                 *state,
	mrParticleGeoShader_paras   *paras)
{
	
	mi_info("mrParticleGeoShader: Version %s", VERSION);

	int			geometryType = *mi_eval_integer(&paras->geometryType);
	miScalar	minPixelSize = *mi_eval_scalar(&paras->minPixelSize);
	miScalar	maxPixelSize = *mi_eval_scalar(&paras->maxPixelSize);
	int i_m = *mi_eval_integer(&paras->i_particleFiles);
	int n_m = *mi_eval_integer(&paras->n_particleFiles);
	miTag *particleFiles = mi_eval_tag(paras->particleFiles) + i_m;

	for(int i = 0; i < n_m; i++)
	{
		if (particleFiles[i])
		{
			std::string fileName = tag_to_string(particleFiles[i]);
			std::string correctedFileName = getCorrectFileName(state, paras, fileName);
			mi_info("reading cacheFile %s", correctedFileName.c_str());
			PartioContainer pc(correctedFileName);
			if( geometryType == 0)
			{
				miTag particleTag = createMeshParticles(state, paras, pc);
				if( particleTag != miNULLTAG)
					miBoolean done = mi_geoshader_add_result( result, particleTag);
			}else{
				miTag particleTag = createNativeParticles(state, paras, pc);
				if( particleTag != miNULLTAG)
					miBoolean done = mi_geoshader_add_result( result, particleTag);
			}
		}
	}
	return miTRUE;
}
DLLEXPORT void LatLong_Stereo_init(
	miState	*state,
	struct dsLatLong_Stereo *params,
	miBoolean *inst_init_req)
{
	if (!params) {
		// Version output
		mi_info(_VER_);
		*inst_init_req = miTRUE;
	} else {
		fov_vert_angle = *mi_eval_scalar(&params->FOV_Vert_Angle);
		fov_horiz_angle = *mi_eval_scalar(&params->FOV_Horiz_Angle);
		camera = *mi_eval_integer(&params->Camera);
		parallax_distance = *mi_eval_scalar(&params->Parallax_Distance);
		cameras_separation = *mi_eval_scalar(&params->Cameras_Separation);
//mi_info("II-> fovV=%f,fovH=%f,cam=%i,rad=%f,sep=%f",fov_vert_angle,fov_horiz_angle,camera,parallax_distance,cameras_separation);

		// Convert input angles from degrees to radians...
		fov_vert_angle = (miScalar)(fov_vert_angle*M_PI/180.0);
		fov_horiz_angle = (miScalar)(fov_horiz_angle*M_PI/180.0);
	}
}
Beispiel #4
0
DLLEXPORT miBoolean Glare(miOutstate *state,
		    struct Glare_param *paras)
{
  miColor *image_in;
  miColor *image_out;
  float *glare_box;
  int box_size;            /* size of the effect box */
  double min;              /* threshold for affecting distant pixels */
  double threshold;        /* limit at which a pixel contributes */
  double scaling;          /* make glare resolution independent */

  lic(NULL, NAME, PROD);


  if ((paras->rays_on) && (paras->rays_image == NULL))
    mi_fatal("[Glare] Streaks image invalid.\n");


  /* set quality */
  if (paras->quality_fastest_on)
    {
      min       = 0.00031;
      threshold = 3.0;
    }
  if (paras->quality_faster_on)
    {
      min       = 0.0001;
      threshold = 2.0;
    }
  if (paras->quality_average_on)
    {
      min       = 0.000031;
      threshold = 1.1;
    }
  if (paras->quality_better_on)
    {
      min       = 0.00001;
      threshold = 0.9;
    }
  if (paras->quality_best_on)
    {
      min       = 0.00001;
      threshold = 0.5;
    }

  /* Determine scaling for resolution independence */
  /* scaling = sqrt(state->xres * state->xres + state->yres * state->yres) / 
    720.0; */
  scaling = 1;


  /* allocate out frame buffers */

  if (paras->verbose_on)
    mi_info("[Glare] Allocating image buffers.\n");
  image_in  = mi_mem_allocate(sizeof(miColor) * state->xres * state->yres);
  image_out = mi_mem_allocate(sizeof(miColor) * state->xres * state->yres);


  { /* copy the image into our buffer,
     also, set the copy the alpha channel directly to the 
     outgoing image */

    int x,y;
    miColor color;
    for (x=0; x<state->xres; x++)
      for (y=0; y<state->yres; y++)
	{
	  mi_img_get_color(state->frame_rgba, &color, x,y);
	  image_in[x+y*state->xres] = color;
	  image_out[x+y*state->xres].a = color.a;
	}
  }

  { /* Determine the size of the glare-box */

    int x,y;
    float M,m;
    miColor color;

    M = threshold;

    for (x=0; x<state->xres; x++)
      for (y=0; y<state->yres; y++)
	{
	  color = image_in[x+y*state->xres];

	  m = max3(color.r, color.g, color.b);

	  if (m != m)  /* is NaN */
	    {
	      mi_warning(NAN_WARN,x,y);
	      m = 0;
	    }

	  if ((m + 1) == m) /* is Infinity */
	    {
	      mi_warning(INF_WARN,x,y);
	      m = 0;
	    }
	  


	  if (m > M)
	    {
	      if ((m > threshold) &&
		  (glare_object(state, paras, x,y)))
		{
		  M = m;


		  box_size = (int)(paras->spread * scaling *
				   pow(autogamma_inverse_scalar(min)
				       /m/K_B,1/FALL_POW));
		}

	    }

	}

    if (box_size > state->xres)
      box_size = state->xres;

    if (box_size > state->yres)
      box_size = state->yres;

    if (box_size == 0)
      {
	mi_info("[Glare] Nothing to glare.\n");
	mi_mem_release(image_in);
	mi_mem_release(image_out);

	return miTRUE;
      }

  }


  if (paras->verbose_on)
    mi_info("[Glare] Allocating glare buffer (%dx%d).\n", 
	    box_size, box_size);
  glare_box = mi_mem_allocate(sizeof(float) * box_size * box_size * 4);



  { /* compute the glare_box */
    int x,y;

    for (x = -box_size; x < box_size; x++)
      for (y = -box_size; y < box_size; y ++)
	{
	  double f,d;
	  miColor p;
		    
	  d = sqrt(x*x + y*y);

	  if (( 0 == x )&&( 0 == y))
	    {
	      if (paras->overlay_on)
		f = 0;
	      else
		f = 1;
	    }

	  
	  else
	    {
	      f = autogamma_scalar(K_B * pow(d/paras->spread/scaling,
					     FALL_POW));
	      if (paras->rays_on)
		{
		  miColor c;
		  miVector p;
		
		  p.x = 0.5 + (double) x / state->xres;
		  p.y = 0.5 + (double) y / state->yres;

		  mi_lookup_color_texture(&c, NULL, paras->rays_image,
					  &p);

		  f *= ((c.r + c.g + c.b)/3 * paras->rays_contrast +
			1.0 - paras->rays_contrast);
		}
	    }
	  glare_box[(x+box_size) + (y+box_size)*box_size*2] = f;
	}

  }

  


  { /* Do glare */
    int x,y;
    int maxb = 0;
    int verbose_count;
    miColor color;

    verbose_count = 10;

    for (x=0; x < state->xres; x++)
      for (y=0; y < state->yres; y++)
	{
	  int bx, by;
	  int b;
	  miScalar c;


	  if ((x%verbose_count == 0) && 
	      (y == 0) && (paras->verbose_on))
	    {
	      mi_info("[Glare]  %.1f%% complete.\n",
		      (float) x/state->xres * 100.0);
	    }
			    

	  
	  color = image_in[x+y*state->xres];

	  c = max3(color.r, color.g, color.b);

	  if (c <= threshold)
	    b = 0;
	  else if ((c != c) || (c == c +1))
	    b = 0;
	  else if (!glare_object(state, paras, x, y))
	    b = 0;
	  else
	    {
	      b = (int)(paras->spread * scaling *
			pow(autogamma_inverse_scalar(min)/c/K_B,1/FALL_POW));
	      if (b > box_size - 1)
		b = box_size -1;
	    }


	  
	  for (by = -b ; by < b+1; by++)
	    {
	      float *gp;
	      miColor *iop;

	      gp  = &glare_box[(-b+box_size) + (by+box_size)*box_size*2];
	      iop = &image_out[(x-b)+(y+by)*state->xres];

	  for (bx = -b ; bx < b+1; bx++, gp++, iop++)
		{
		  int px, py;
		  px = x + bx;
		  py = y + by;
		  
		  if ((px >= 0) &&
		      (px < state->xres) &&
		      (py >= 0 ) &&
		      (py < state->yres))
		    {
		      float f;
		    
		      f = *gp;

		      iop->r += f * color.r;
		      iop->g += f * color.g;
		      iop->b += f * color.b;
		    }
		}
	    }
	}
  }


  
  { /* copy the image out to mi */
    int x,y;
    miColor color;
    for (x=0; x<state->xres; x++)
      for (y=0; y<state->yres; y++)
	{
	  miColor color;
	  miScalar new_alpha;

	  color = image_out[x+y*state->xres];

	  new_alpha = max3(color.r, color.b, color.g);

	  if (new_alpha > color.a)
	    color.a = new_alpha;

	  mi_img_put_color(state->frame_rgba, &color, 
			   x,y);
	}
  }

  mi_mem_release(image_in);
  mi_mem_release(image_out);
  mi_mem_release(glare_box);

  lic_end(PROD);

  return miTRUE;
}
miTag createNativeParticles(miState *state, mrParticleGeoShader_paras *paras, PartioContainer& pc)
{
	miBoolean useAllAttributes = *mi_eval_boolean(&paras->useAllAttributes);
	int i_a = *mi_eval_integer(&paras->i_attributeNames);
	int n_a = *mi_eval_integer(&paras->n_attributeNames);
	miTag *attributeNames = mi_eval_tag(paras->attributeNames) + i_a;

	if( !pc.good())
	{
		mi_info("createNativeParticles: Invalid patioContainer");
		return miNULLTAG;
	}

	Partio::ParticleAttribute posAttr;
	if(!pc.assertAttribute("position", posAttr))
	{
		mi_info("createNativeParticles: partioContainer: no position.");
		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 radiusRGBPPAttr;
	bool hasRgbPP = true;
	if(!pc.assertAttribute("rgbPP", radiusRGBPPAttr))
		hasRgbPP = false;

	mi_info("Creating native particles for cache file: %s", pc.cacheFileName.c_str());

	// declare the map as a 3-dimensional map
	mi_api_map_decl_dim ( 3 );

	// the 'mi_api_map_field_decl' function takes four arguments:
	//
	// miParam_type type: basic type of the field (miTYPE_SCALAR or miTYPE_INTEGER)
	// char *name : field name
	// int dimension : dimension of the field, 0 for single values, > 0 for arrays
	// miBoolean global : miTRUE if it's a global field, miFALSE otherwise

	// add the "extension" field as a single float
	miParameter *extension_field = mi_api_map_field_decl (
	miTYPE_SCALAR , mi_mem_strdup("extension") , 0 , miFALSE );

	// add the "color" field as an array of 1 color
	miParameter *color_field = mi_api_map_field_decl (
	miTYPE_SCALAR , mi_mem_strdup("color") , 3 , miFALSE );

	// append the color to the extension for the declaration
	// (this also frees the 'color_field' miParameter)
	miParameter *fields_list = mi_api_map_field_append ( extension_field , color_field );

	// create a declaration called "particles" with the given fields list
	// (this also frees the 'fields_list' miParameter)
	miMap_decl *decl = mi_api_map_decl_begin ( mi_mem_strdup("particles") , fields_list );

	// ends the declaration
	mi_api_map_decl_end ();

//	Then you begin the object definition, by calling 'mi_api_object_begin' and possibly setting the object flags as needed, then you begin the definition of the particle object as a set of spheres:
	miObject *obj = mi_api_object_begin(mi_mem_strdup("TestParticleObject"));
	obj->visible = miTRUE;

	// begin the definition of the particle object as spheres
	mi_api_map_obj_type ( mi_mem_strdup("spheres") );

	// the 'mi_api_map_obj_field' function takes 2 arguments:
	//
	// char *field_name : name of the field to map ("radius" in this case)
	// char *mapped_name : name of the mapped field ("extension" in this case)

	// maps the "radius" field to the "extension" field of this map
	mi_api_map_obj_field( mi_mem_strdup("radius") , mi_mem_strdup("extension") );	

	// begins the definition of the map, taking "particles" as the declaration name
	mi_api_map_begin ( mi_mem_strdup("particles") );

	int num_elements = pc.data->numParticles();

	for ( int i = 0 ; i < num_elements ; ++i ) 
	{
		
		float pos[3];
		pc.getPosition(i, pos);

		// define the position of this element
		mi_api_map_value ( miTYPE_SCALAR , &pos[0] );
		mi_api_map_value ( miTYPE_SCALAR , &pos[1] );
		mi_api_map_value ( miTYPE_SCALAR , &pos[2] );
		mi_api_map_field_end ();

		float radiusPP = 1.0f;
		if( hasRadiusPP )
			radiusPP = *pc.data->data<float>(radiusPPAttr, i);
		radiusPP = rnd() * 0.3;
		// define the radius of this element
		mi_api_map_value ( miTYPE_SCALAR , &radiusPP );
		mi_api_map_field_end ();

		//
		// compute the color in r, g and b
		//
		miScalar r = rnd();
		miScalar g = rnd();
		miScalar b = rnd();
		miColor col;
		col.r = r;
		col.g = g;
		col.b = b;
		// define the color of this element
		//mi_api_map_value ( miTYPE_COLOR , &col );
		mi_api_map_value ( miTYPE_SCALAR , &r );
		mi_api_map_value ( miTYPE_SCALAR , &g );
		mi_api_map_value ( miTYPE_SCALAR , &b );
		mi_api_map_field_end();

		// end the definition of this element
		mi_api_map_element_end ();
	}

	// terminates the map definition and stores it in the DB
	miTag map_tag = mi_api_map_end ( 0 );

	miTag particleObjTag = mi_api_object_end();

	miEchoOptions options;
	memset(&options, 0, sizeof(options));
	options.ascii_output = true;
	options.compressed_output = false;
	options.dont_echo = false;
	
	mi_info("Writing to geodump.mi file.");
	const char *mode = "w";
	FILE *fh = fopen("C:/daten/3dprojects/Maya2013/scenes/geodump.mi", mode);
	//mi_geoshader_echo_tag(fh, particleObjTag, &options);
	fclose(fh);

	mi::shader::Access_map  map(map_tag);
	mi::shader::Map_status	    status;
	mi::shader::Map_declaration map_declaration(map, &status);
	mi::shader::Map_field_id field_id = map_declaration->get_field_id(mi_mem_strdup("color"), &status);
	if (!status.is_ok())
	{
		mi_error("problems getting field_id for color");
		return particleObjTag;
	}
	mi_info("Field id %d", field_id);
	mi::shader::Map_field_type f_type;
	miUint f_dimension;
	bool f_is_global;
	status = map_declaration->get_field_info(field_id, f_type, f_dimension, f_is_global);
	if (!status.is_ok())
	{
		mi_error("problems get_field_info");
		return particleObjTag;
	}
	mi_info("Field type %d is global %d", f_type.type(), f_is_global);
	return particleObjTag;
}
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;
   
}