int draw(Scene& myScene) { unsigned char* img; img = (unsigned char*)tga_create(myScene.width, myScene.height, TGA_TRUECOLOR_24); int img_index = 0; for(int m = 0; m<myScene.height*myScene.width*3; m++) img[m]=0; for(int y = 0; y < myScene.height; y++) for(int x = 0; x < myScene.width; x++) { Ray viewRay; viewRay.o.x = x; viewRay.o.y = y; viewRay.o.z = -1000.0; viewRay.d.x = 0.0; viewRay.d.y = 0.0; viewRay.d.z = 1.0; viewRay.reflected = 0; float red = 0, green = 0, blue = 0; float coef = 1.0; int level = 0; int repeatFlag = 0; int lastfrontSphere = -1; int frontSphere = -1; int lastfrontTriangle = -1; int frontTriangle = -1; do{ Point inter; Point frontInter; float t_inter; Matrix iMat; Ray newviewRay; int triangleisFront, sphereisFront; int flag; if(repeatFlag==0) { int ret_val_trngl = 0; flag = 1; float t = 2000.0; frontSphere = -1; frontTriangle = -1; sphereisFront = 0; triangleisFront = 0; for(int i = 0; i<myScene.spheres.size(); i++) { if(myScene.spheres[i].transformed==0) { if(raySphere(viewRay, myScene.spheres[i], t)) { frontSphere = i; t_inter = t; } } else if(myScene.spheres[i].transformed==1) { if(lastfrontSphere!=i) { if(viewRay.reflected == 0) { Matrix temp_iMat = invMat(myScene.spheres[i].mat); Ray temp_newviewRay; temp_newviewRay.o = transformPoint(temp_iMat, viewRay.o); temp_newviewRay.o = subPoint(temp_newviewRay.o, myScene.spheres[i].tlate);// we have to sub since it is a inverse transform temp_newviewRay.d = transformPoint(temp_iMat, viewRay.d); ///////////////*doubt*why???//// if(raySphere(temp_newviewRay, myScene.spheres[i], t)) { frontSphere = i; iMat = temp_iMat; t_inter = t; newviewRay = temp_newviewRay; newviewRay.reflected = 0; } } else { Matrix temp_iMat = invMat(myScene.spheres[i].mat); if(raySphere(viewRay, myScene.spheres[i], t)) { frontSphere = i; iMat = temp_iMat; t_inter = t; newviewRay = viewRay; newviewRay.reflected = 0; } } } } } viewRay.reflected = 0; for(int i = 0; i<myScene.triangles.size(); i++) { ret_val_trngl = rayTriangle(viewRay, myScene.triangles[i], inter); if((ret_val_trngl==1)&&(lastfrontTriangle!=i)) { frontTriangle = i; frontInter = inter; } } if(frontSphere==-1) if(frontTriangle==-1) { flag = 0; triangleisFront = 0; sphereisFront = 0; break; } else { triangleisFront = 1; sphereisFront = 0; } if(frontSphere!=-1) if(frontTriangle==-1) { triangleisFront = 0; sphereisFront = 1; } else { triangleisFront = 1; sphereisFront = 1; } } repeatFlag = 0; if((sphereisFront==1)&&(triangleisFront==0)) { if(myScene.spheres[frontSphere].transformed==0) { Point tempo = multPoint(t_inter, viewRay.d); Point newStart = addPoint(viewRay.o, tempo); Point n = subPoint(newStart, myScene.spheres[frontSphere].c); float temp = multPoint(n, n); if (temp == 0.0f) break; temp = 1.0f / sqrtf(temp); n = multPoint(temp, n); //normal Material currentMat = myScene.materials[myScene.spheres[frontSphere].materialId]; for (int j = 0; j < myScene.lights.size(); j++) { Light light = myScene.lights[j]; Point dist = subPoint(light.pos, newStart); if (multPoint(n, dist) <= 0.0f) continue; float t = sqrtf(multPoint(dist, dist)); if ( t <= 0.0f ) continue; Ray lightRay; lightRay.o = newStart; lightRay.d = multPoint((1/t), dist); bool inShadow = false; for (int k = 0; k < myScene.spheres.size(); k++) { if (raySphere(lightRay, myScene.spheres[k], t)) { inShadow = true; break; } } if (!inShadow) { // lambert float lambert = multPoint(n, lightRay.d) * coef; red += lambert * light.col.r * currentMat.r; green += lambert * light.col.g * currentMat.g; blue += lambert * light.col.b * currentMat.b; } } coef *= currentMat.reflection; float reflet = 2.0f * multPoint(viewRay.d, n); viewRay.o = newStart; Point temp_2 = multPoint(reflet, n); viewRay.d = subPoint(viewRay.d, temp_2); viewRay.reflected = 0; level++; } else if (myScene.spheres[frontSphere].transformed==1) { Point tempo = multPoint(t_inter, newviewRay.d); Point newStart = addPoint(newviewRay.o, tempo); //intersection point in sphere space Point newStart_2 = transformPoint(myScene.spheres[frontSphere].mat, newStart);//intersection point in ellipsoid space newStart_2 = addPoint(newStart_2, myScene.spheres[frontSphere].tlate); Point n = subPoint(newStart, myScene.spheres[frontSphere].c); float temp = multPoint(n, n); if (temp == 0.0f) break; temp = 1.0f / sqrtf(temp); n = multPoint(temp, n); //convert normal to new worldspace Matrix iMat_2 = transMat(iMat); Point n_orig = n; n = transformPoint(iMat_2, n); Material currentMat = myScene.materials[myScene.spheres[frontSphere].materialId]; for (int j = 0; j < myScene.lights.size(); j++) { Light light = myScene.lights[j]; Point dist = subPoint(light.pos, newStart_2); if (multPoint(n, dist) <= 0.0f) continue; float t2 = sqrtf(multPoint(dist, dist)); if ( t2 <= 0.0f ) continue; Ray lightRay; lightRay.o = newStart_2; lightRay.d = multPoint((1/t2), dist); lightRay.reflected = 0; Point dist_temp = subPoint(light.pos, newStart); float t_temp = sqrtf(multPoint(dist_temp, dist_temp)); bool inShadow = false; Ray newlightRay; for (int k = 0; k < myScene.spheres.size(); k++) { newlightRay.o = newStart; newlightRay.d = transformPoint(iMat, lightRay.d); newlightRay.reflected = 0; if((k!=frontSphere) && (k!=lastfrontSphere)) if (raySphere(newlightRay, myScene.spheres[k], t_temp)) { inShadow = true; break; } } if (!inShadow) { // lambert float lambert = multPoint(n, lightRay.d) * coef; red += lambert * light.col.r * currentMat.r; green += lambert * light.col.g * currentMat.g; blue += lambert * light.col.b * currentMat.b; } } lastfrontSphere = frontSphere; coef *= currentMat.reflection; float reflet = 2.0f * multPoint(newviewRay.d, n_orig); viewRay.o = newStart_2; Point temp_2 = multPoint(reflet, n_orig); viewRay.d = subPoint(newviewRay.d, temp_2); viewRay.reflected = 1; level++; } } else if((sphereisFront==0)&&(triangleisFront==1)) { Point u_n = subPoint(myScene.triangles[frontTriangle].v1, frontInter); Point v_n = subPoint(myScene.triangles[frontTriangle].v2, frontInter); Point n = crossProduct(v_n, u_n); //pay attention here float temp = multPoint(n, n); if (temp == 0.0f) flag = 0; temp = 1.0f / sqrtf(temp); n = multPoint(temp, n); //normal Material currentMat = myScene.materials[myScene.triangles[frontTriangle].materialId]; for (int j = 0; j < myScene.lights.size(); j++) { Light light = myScene.lights[j]; Point dist = subPoint(light.pos, frontInter); if (multPoint(n, dist) <= 0.0f) continue; float t = sqrtf(multPoint(dist, dist)); if ( t <= 0.0f ) continue; Ray lightRay; lightRay.o = frontInter; lightRay.d = multPoint((1/t), dist); Point temp_inter; for (int k = 0; k < myScene.triangles.size(); k++) { if((k!=frontTriangle) && (k!=lastfrontTriangle)) if ((rayTriangle(lightRay, myScene.triangles[k], temp_inter)==1)) { flag = 0; break; } } if(flag == 1) { float lambert = multPoint(n, lightRay.d) * coef; red += lambert * light.col.r * currentMat.r; green += lambert * light.col.g * currentMat.g; blue += lambert * light.col.b * currentMat.b; } lastfrontTriangle = frontTriangle; //important } coef *= currentMat.reflection; float reflet = 2.0f * multPoint(viewRay.d, n); viewRay.o = frontInter; Point temp_2 = multPoint(reflet, n); viewRay.d = subPoint(viewRay.d, temp_2); viewRay.reflected = 1; level++; } else if((sphereisFront==1)&&(triangleisFront==1)) { Point tempo = multPoint(t_inter, viewRay.d); Point newStart = addPoint(viewRay.o, tempo); if(newStart.z <= frontInter.z) triangleisFront=0; else sphereisFront = 0; repeatFlag = 1; } }while((coef>0.0f)&&(level<10)); img[img_index] = (unsigned char)(min(red*255.0f, 255.0f)); img[img_index+1] = (unsigned char)(min(green*255.0f, 255.0f)); img[img_index+2] = (unsigned char)(min(blue*255.0f, 255.0f)); img_index = img_index+3; } int ret_value = tga_write_rle( "output3.tga", myScene.width, myScene.height, img, TGA_TRUECOLOR_24); return 1; }
bool btContinuousConvexCollision::calcTimeOfImpact( const btTransform& fromA, const btTransform& toA, const btTransform& fromB, const btTransform& toB, CastResult& result) { m_simplexSolver->reset(); /// compute linear and angular velocity for this interval, to interpolate btVector3 linVelA,angVelA,linVelB,angVelB; btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; btVector3 relLinVel = (linVelB-linVelA); btScalar relLinVelocLength = (linVelB-linVelA).length(); if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f) return false; btScalar radius = btScalar(0.001); btScalar lambda = btScalar(0.); btVector3 v(1,0,0); int maxIter = MAX_ITERATIONS; btVector3 n; n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); bool hasResult = false; btVector3 c; btScalar lastLambda = lambda; //btScalar epsilon = btScalar(0.001); int numIter = 0; //first solution, using GJK btTransform identityTrans; identityTrans.setIdentity(); btSphereShape raySphere(btScalar(0.0)); raySphere.setMargin(btScalar(0.)); // result.drawCoordSystem(sphereTr); btPointCollector pointCollector1; { btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver); btGjkPairDetector::ClosestPointInput input; //we don't use margins during CCD // gjk.setIgnoreMargin(true); input.m_transformA = fromA; input.m_transformB = fromB; gjk.getClosestPoints(input,pointCollector1,0); hasResult = pointCollector1.m_hasResult; c = pointCollector1.m_pointInWorld; } if (hasResult) { btScalar dist; dist = pointCollector1.m_distance; n = pointCollector1.m_normalOnBInWorld; btScalar projectedLinearVelocity = relLinVel.dot(n); //not close enough while (dist > radius) { numIter++; if (numIter > maxIter) { return false; //todo: report a failure } btScalar dLambda = btScalar(0.); projectedLinearVelocity = relLinVel.dot(n); //calculate safe moving fraction from distance / (linear+rotational velocity) //btScalar clippedDist = GEN_min(angularConservativeRadius,dist); //btScalar clippedDist = dist; //don't report time of impact for motion away from the contact normal (or causes minor penetration) if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON) return false; dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); lambda = lambda + dLambda; if (lambda > btScalar(1.)) return false; if (lambda < btScalar(0.)) return false; //todo: next check with relative epsilon if (lambda <= lastLambda) { return false; //n.setValue(0,0,0); break; } lastLambda = lambda; //interpolate to next lambda btTransform interpolatedTransA,interpolatedTransB,relativeTrans; btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA); btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB); relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA); result.DebugDraw( lambda ); btPointCollector pointCollector; btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver); btGjkPairDetector::ClosestPointInput input; input.m_transformA = interpolatedTransA; input.m_transformB = interpolatedTransB; gjk.getClosestPoints(input,pointCollector,0); if (pointCollector.m_hasResult) { if (pointCollector.m_distance < btScalar(0.)) { //degenerate ?! result.m_fraction = lastLambda; n = pointCollector.m_normalOnBInWorld; result.m_normal=n;//.setValue(1,1,1);// = n; result.m_hitPoint = pointCollector.m_pointInWorld; return true; } c = pointCollector.m_pointInWorld; n = pointCollector.m_normalOnBInWorld; dist = pointCollector.m_distance; } else { //?? return false; } } if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON) return false; result.m_fraction = lambda; result.m_normal = n; result.m_hitPoint = c; return true; } return false; /* //todo: //if movement away from normal, discard result btVector3 move = transBLocalTo.getOrigin() - transBLocalFrom.getOrigin(); if (result.m_fraction < btScalar(1.)) { if (move.dot(result.m_normal) <= btScalar(0.)) { } } */ }
int main() { float r[3], s[3]; float radius; return raySphere(r, s, radius); }