/*! SLRay::diffuseMC scatters a ray around hit normal (cosine distribution). This is only used for photonmapping(russian roulette). The random direction lies around z-Axis and is then transformed by a rotation matrix to lie along the normal. The direction is calculated according to MCCABE */ void SLRay::diffuseMC(SLRay* scattered) { SLVec3f randVec; SLfloat eta1,eta2,eta1sqrt; scattered->setDir(hitNormal); scattered->origin = hitPoint; scattered->depth = depth+1; depthReached = scattered->depth; // for reflectance the start material stays the same scattered->originMat = hitMat; scattered->originNode = hitNode; scattered->originMesh = hitMesh; scattered->type = REFLECTED; //calculate rotation matrix SLMat3f rotMat; SLVec3f rotAxis((SLVec3f(0.0,0.0,1.0) ^ scattered->dir).normalize()); SLfloat rotAngle=acos(scattered->dir.z); //z*scattered.dir() rotMat.rotation(rotAngle*180.0f/SL_PI, rotAxis); //cosine distribution eta1 = rnd01(); eta2 = SL_2PI*rnd01(); eta1sqrt = sqrt(1-eta1); //transform to cartesian randVec.set(eta1sqrt * cos(eta2), eta1sqrt * sin(eta2), sqrt(eta1)); scattered->setDir(rotMat*randVec); }
/*! SLRay::refractMC scatters a ray around perfect transmissive direction according to translucency (for higher translucency the ray is less scattered). This is used for path tracing and distributed ray tracing as well as for photon scattering. The direction is calculated the same as with specular scattering (see reflectMC). The created direction is along z-axis and then transformed to lie along transmissive direction with rotationMatrix rotMat. The rotation matrix must be precalculated (stays the same for each ray sample, needs to be be calculated only once) */ void SLRay::refractMC(SLRay* refracted,SLMat3f rotMat) { SLfloat eta1, eta2; SLVec3f randVec; SLfloat translucency = hitMat->translucency(); //scatter within transmissive lobe eta1 = rnd01(); eta2 = SL_2PI*rnd01(); SLfloat f1=sqrt(1.0f-pow(eta1,2.0f/(translucency+1.0f))); //transform to cartesian randVec.set(f1*cos(eta2), f1*sin(eta2), pow(eta1,1.0f/(translucency+1.0f))); //ray needs to be reset if already hit a scene node if(refracted->hitNode) { refracted->length = FLT_MAX; refracted->hitNode = 0; refracted->hitMesh = 0; refracted->hitPoint = SLVec3f::ZERO; refracted->hitNormal = SLVec3f::ZERO; } refracted->setDir(rotMat*randVec); }
/*! SLRay::reflectMC scatters a ray around perfect specular direction according to shininess (for higher shininess the ray is less scattered). This is used for path tracing and distributed ray tracing as well as for photon scattering. The direction is calculated according to MCCABE. The created direction is along z-axis and then transformed to lie along specular direction with rotationMatrix rotMat. The rotation matrix must be precalculated (stays the same for each ray sample, needs to be be calculated only once) */ bool SLRay::reflectMC(SLRay* reflected,SLMat3f rotMat) { SLfloat eta1, eta2; SLVec3f randVec; SLfloat shininess = hitMat->shininess(); //scatter within specular lobe eta1 = rnd01(); eta2 = SL_2PI*rnd01(); SLfloat f1 = sqrt(1.0f-pow(eta1, 2.0f/(shininess+1.0f))); //tranform to cartesian randVec.set(f1 * cos(eta2), f1 * sin(eta2), pow(eta1, 1.0f/(shininess+1.0f))); //ray needs to be reset if already hit a scene node if(reflected->hitNode) { reflected->length = FLT_MAX; reflected->hitNode = 0; reflected->hitMesh = 0; reflected->hitPoint = SLVec3f::ZERO; reflected->hitNormal = SLVec3f::ZERO; } //apply rotation reflected->setDir(rotMat*randVec); //true if in direction of normal return (hitNormal * reflected->dir >= 0.0f); }
static void randomize(cube21_conf *cp) { int i, j, s; int matches[12]; for(i = 0; i<SHUFFLE; i++) { s = rnd01(); find_matches(cp->pieces, matches, s); j = matches[0]-1; j = random()%j; j = matches[j+1]; rot_face(cp->pieces, cp->cind, s, j); s = rnd01(); rot_halves(cp->pieces, cp->cind, cp->hf, s); } }
SLfloat SLLightRect::shadowTestMC(SLRay* ray, // ray of hit point const SLVec3f& L, // vector from hit point to light const SLfloat lightDist) // distance to light { SLVec3f SP; // vector hit point to sample point in world coords SLfloat randX = rnd01(); SLfloat randY = rnd01(); // choose random point on rect as sample SP.set(updateAndGetWM().multVec(SLVec3f((randX*_width)-(_width*0.5f), (randY*_height)-(_height*0.5f), 0)) - ray->hitPoint); SLfloat SPDist = SP.length(); SP.normalize(); SLRay shadowRay(SPDist, SP, ray); SLScene::current->root3D()->hitRec(&shadowRay); if (shadowRay.length >= SPDist - FLT_EPSILON) return 1.0f; else return 0.0f; }
static void finish(cube21_conf *cp) { int j, s; int matches[12]; switch(cp->state) { case CUBE21_PAUSE1: s = rnd01(); find_matches(cp->pieces, matches, s); j = matches[0]-1; j = random()%j; j = matches[j+1]; if(j==6 && rnd01()) j = -6; cp->state = CUBE21_ROT_BASE+s; cp->tmax = 30.0*abs(j); cp->fr[0] = cp->fr[1] = 0; cp->rface = s; cp->ramount = j; break; case CUBE21_ROT_TOP: case CUBE21_ROT_BOTTOM: rot_face(cp->pieces, cp->cind, s = cp->rface, cp->ramount); cp->fr[s] = 1; s ^= 1; if(!cp->fr[s] && rnd01()) { find_matches(cp->pieces, matches, s); j = matches[0]-1; j = random()%j; j = matches[j+1]; if(j==6 && rnd01()) j = -6; cp->state = CUBE21_ROT_BASE+s; cp->tmax = 30.0*abs(j); cp->rface = s; cp->ramount = j; break; } else { cp->state = CUBE21_PAUSE2; cp->tmax = twait; break; } case CUBE21_PAUSE2: s = rnd01(); cp->ramount = -rnd01(); /* 0 or -1, only sign is significant in this case */ cp->state = CUBE21_HALF_BASE+s; cp->tmax = 180.0; cp->rface = s; break; case CUBE21_HALF1: case CUBE21_HALF2: rot_halves(cp->pieces, cp->cind, cp->hf, cp->rface); cp->state = CUBE21_PAUSE1; cp->tmax = twait; break; } cp->t = 0; }
static void randomize(rubikblocks_conf *cp) { int axis, side; int i, j; for(i = 0; i < SHUFFLE; i++) { axis = (random()%3)+1; side = rnd01()*2-1; flag_pieces(cp->pieces, axis, side); for(j = 1; j < 4; j++) cp->qfram[j] = 0; cp->qfram[0] = M_SQRT1_2; cp->qfram[axis] = M_SQRT1_2; for(j = 0; j < 27; j++) { if(cp->pieces[j].act) mult_quat(cp->qfram, cp->pieces[j].qr); } } }
static void finish(rubikblocks_conf *cp) { static int axis = 1; int side, angle; int i, j; if(cp->pause) { switch(axis) { case 1: axis = rnd01()+2; break; case 2: axis = 2*rnd01()+1; break; default: axis = rnd01()+1; } side = rnd01()*2-1; angle = rnd01()+1; flag_pieces(cp->pieces, axis, side); cp->pause = False; cp->tmax = 90.0*angle; for(i = 1; i < 4; i++) cp->qfram[i] = 0; cp->qfram[0] = cos(tspeed*M_PI/360); cp->qfram[axis] = sin((rnd01()*2-1)*tspeed*M_PI/360); } else { for(i = 0; i < 27; i++) { for(j = 0; j < 4; j++) { cp->pieces[i].qr[j] = settle_value(cp->pieces[i].qr[j]); } } cp->pause = True; cp->tmax = twait; } cp->t = 0; }