extern "C" DLLEXPORT miBoolean MYMR_AmbientOcclusion( miColor *result , miState *state, struct MYMR_AmbientOcclusion_p *paras) { miUint samples = * mi_eval_integer(¶s->samples); miVector trace_direction; miUshort dimension = 2; int instance = 0, found=0; double amb_exp; double sample[dimension]; //Try to get samples to random places monte carlo style while (mi_sample(sample,&instance,state,dimension,&samples)){ // get the direction of the ray given the sample mi_reflection_dir_diffuse_x(&trace_direction,state,sample); if (mi_trace_probe(state, &trace_direction, &state->point)){ found++; } } printf("%d %d\n",found,samples); amb_exp = 1.0 - ((double)found/(double)samples); printf("%f\n",amb_exp); result->r = result->g = result->b = amb_exp; return miTRUE; }
static miBoolean miao_trace_the_ray( miState *state, miVector *dir, miVector *point, miao_trace_info *ti) { int label = 0, childlabel = 0; miVector base_point = *point; miScalar base_dist = 0; miBoolean result = miFALSE; play_it_again: /* Trace the ray */ result = mi_trace_probe(state, dir, &base_point); /* If a miss, or compatible mode - then simply return */ if (!result || ti->compatible) return result; childlabel = miao_get_label(state->child->instance); /* Test non-self-occlusion. A hit on this object id that originates on the same object id is considered a total miss, i.e. the environment */ if (ti->id_nonself > 0) { int label = miao_get_label(state->instance); /* Compare parent AND child labels */ if (label == ti->id_nonself && childlabel == ti->id_nonself) return miFALSE; } /* Test the include/exclude. However, a miss here causes the ray to continue to be traced, in case of a hit */ /* Positive inclexcl == include */ if (ti->id_inclexcl > 0 && childlabel != ti->id_inclexcl) result = miFALSE; /* Negative inclexcl == exclude */ if (ti->id_inclexcl < 0 && childlabel == -ti->id_inclexcl) result = miFALSE; /* Was this hit rejected? */ if (!result) { /* Remember distance traced so far */ base_dist += state->child->dist; /* Advance the point */ base_point.x += base_dist * dir->x; base_point.y += base_dist * dir->y; base_point.z += base_dist * dir->z; /* Keep tracing ray */ goto play_it_again; } /* Plug originals back, if necessary */ /* state->child->dist += base_dist; */ return result; }