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(¶ms->FOV_Angle); viewport_offset = *mi_eval_vector(¶ms->View_Offset); camera = *mi_eval_integer(¶ms->Camera); dome_radius = *mi_eval_scalar(¶ms->Dome_Radius); dome_tilt = *mi_eval_scalar(¶ms->Dome_Tilt); cameras_separation = *mi_eval_scalar(¶ms->Cameras_Separation); dome_tilt_compensation = *mi_eval_boolean(¶ms->Dome_Tilt_Compensation); vertical_mode = *mi_eval_boolean(¶ms->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(¶s->geometryType); miScalar minPixelSize = *mi_eval_scalar(¶s->minPixelSize); miScalar maxPixelSize = *mi_eval_scalar(¶s->maxPixelSize); int i_m = *mi_eval_integer(¶s->i_particleFiles); int n_m = *mi_eval_integer(¶s->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(¶ms->FOV_Vert_Angle); fov_horiz_angle = *mi_eval_scalar(¶ms->FOV_Horiz_Angle); camera = *mi_eval_integer(¶ms->Camera); parallax_distance = *mi_eval_scalar(¶ms->Parallax_Distance); cameras_separation = *mi_eval_scalar(¶ms->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); } }
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(¶s->useAllAttributes); int i_a = *mi_eval_integer(¶s->i_attributeNames); int n_a = *mi_eval_integer(¶s->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(¶s->sizeMultiplier); float density = *mi_eval_scalar(¶s->density); float size = *mi_eval_scalar(¶s->size); float sizeVariation = *mi_eval_scalar(¶s->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; }