bool checkScreenSpace(miState *state, mrParticleGeoShader_paras *paras, miVector pos, miVector& bottomLeft, miVector& topRight) { miScalar minPixelSize = *mi_eval_scalar(¶s->minPixelSize); miScalar maxPixelSize = *mi_eval_scalar(¶s->maxPixelSize); int minSizeBehaviour = *mi_eval_integer(¶s->minSizeBehaviour); // 0 = delete, 1 = resize if(maxPixelSize <= 0.0f ) maxPixelSize = 100000000.0f; miVector screenBottomLeft = bottomLeft; miVector screenTopRight = topRight; mi_point_from_camera(state, &screenBottomLeft, &screenBottomLeft); mi_point_from_camera(state, &screenTopRight, &screenTopRight); mi_point_to_raster(state, &screenBottomLeft, &screenBottomLeft); mi_point_to_raster(state, &screenTopRight, &screenTopRight); miScalar screenDist = mi_vector_dist(&screenBottomLeft, &screenTopRight); miScalar dist = mi_vector_dist(&bottomLeft, &topRight); //mi_info("screenDist %f minPixelSize %f", screenDist, minPixelSize); // nonsense no check will be done if(minPixelSize > maxPixelSize) return true; float minClip = 0.001f; if( screenDist < minPixelSize ) { if( minSizeBehaviour == 0) return false; //mi_info("screenDist %f < minPixelSize %f", screenDist, minPixelSize); float resizeFactor = minPixelSize/screenDist; float resizeDist = dist * resizeFactor/2.0f; topRight = pos; bottomLeft = pos; topRight.x += resizeDist; topRight.y += resizeDist; bottomLeft.x -= resizeDist; bottomLeft.y -= resizeDist; return true; } if( screenDist > maxPixelSize ) { float resizeFactor = maxPixelSize/screenDist; float resizeDist = dist * resizeFactor/2.0f; topRight = pos; bottomLeft = pos; topRight.x += resizeDist; topRight.y += resizeDist; bottomLeft.x -= resizeDist; bottomLeft.y -= resizeDist; return true; } return true; }
DLLEXPORT miBoolean domeAFL_FOV_Stereo( miColor *result, miState *state, struct dsDomeAFL_FOV_Stereo *params) { miScalar cameras_separation_multiplier = *mi_eval_scalar(¶ms->Cameras_Separation_Map); miScalar head_turn_multiplier = *mi_eval_scalar(¶ms->Head_Turn_Map); miScalar head_tilt = *mi_eval_scalar(¶ms->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(¶ms->Flip_Ray_X)) { // @@@ ray.x = (-ray.x); // @@@ } // Flip the ray direction about the x-axis // @@@ if(*mi_eval_boolean(¶ms->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); } }
DLLEXPORT miBoolean LatLong_Stereo( miColor *result, miState *state, struct dsLatLong_Stereo *params) { miScalar cameras_separation_multiplier = *mi_eval_scalar(¶ms->Cameras_Separation_Map); miScalar head_tilt = *mi_eval_scalar(¶ms->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(¶ms->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(¶ms->Flip_Ray_X)) { org.x = (-org.x); ray.x = (-ray.x); } // Flip the Y ray direction about the X-axis if(*mi_eval_boolean(¶ms->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(¶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; }