示例#1
0
文件: union.cpp 项目: maq14/RayTrace
Color Union::rayTrace(CRay ray, int depth, CObject* &_object,IntersectResult*& res)
{
    if(depth>max_depth)  return Color::white();
    int size = (int)CVector.size();
    float distance = 100000000.0f;
    CObject* primitive_near = NULL;
    bool visible = true;
    Color totalColor = Color::black();
    CObject* pLight;
    int num=0;
    IntersectResult s = IntersectResult::noHit();
    for(int i=0;i<size;i++){
        CObject* primitive = CVector.at(i);
        IntersectResult result = primitive->isIntersected(ray);
        if(result.isHit){
            if(result.distance < distance){
                s = result;
                distance = result.distance;
                primitive_near = result.object;
                num = i;
            }
        }
    }
    _object = primitive_near;
    res = &s;
    if(primitive_near == NULL) {

        return Color::black();
    }
    else if(primitive_near->isLight()){

        return Color::white();
    }
    else if(!s.front){
        cout<<depth<<" "<<s.object->code<<endl;
        GVector3 v = ray.getDirection();
        v = v.normalize();
        GVector3 normal = s.normal.normalize();
        double cosA = v.dotMul(normal);
        double sinA = sqrt(1-cosA*cosA);
        double n = 1.000 / 1.500;
        //cout<<sinA<<endl;
        if(sinA >= n){
            //cout<<"zhixingle"<<endl;
            CRay newray;
            newray.setDirection(normal*(-cosA) + (ray.getDirection() - normal*cosA).normalize()*sinA);
            newray.setOrigin(s.position + ray.getDirection()*1e-3);
            CObject* no_use = NULL;
            IntersectResult* n0=NULL;
            Color refraction_second = rayTrace(newray,depth+1,no_use,n0);
            //cout<<refraction_second.r<<" "<<refraction_second.g<<" "<<refraction_second.b<<endl;
            Color absorbance(0,0,0);
            if(n0){
                Color absorbance = primitive_near->getMaterial()->getColor().multiply(0.15f * ((-1)*n0->distance));
            }
            Color transparancy = Color(exp(absorbance.r),exp(absorbance.g),exp(absorbance.b));
            return refraction_second.moderate(transparancy);
        }
        else{

            double sinB = sinA / n;

            double cosB = sqrt(1 - sinB*sinB);

            CRay newray;
            newray.setDirection(normal*cosB + (v-normal*cosA).normalize()*sinB);
            newray.setOrigin(s.position + newray.getDirection()*1e-3);
            //cout<<"Origin:"<<newray.getOrigin().getX()<<" "<<newray.getOrigin().getY()<<" "<<newray.getOrigin().getZ()<<endl;
            //cout<<"Direction:"<<newray.getDirection().getX()<<" "<<newray.getDirection().getY()<<" "<<newray.getDirection().getZ()<<endl;
            CObject* no_use = NULL;
            IntersectResult* n0=NULL;
            Color refraction_second = rayTrace(newray,depth+1,no_use,n0);
            //cout<<refraction_second.r<<" "<<refraction_second.g<<" "<<refraction_second.b<<endl;
            Color absorbance(0,0,0);
            if(n0){
                Color absorbance = primitive_near->getMaterial()->getColor().multiply(0.15f * ((-1)*n0->distance));
            }
            Color transparancy = Color(exp(absorbance.r),exp(absorbance.g),exp(absorbance.b));
            return refraction_second.moderate(transparancy);
        }
    }
    else{
        GVector3 point;
        point = ray.getPoint(distance);
        for(int i=0;i<size;i++){
            CObject* primitive = CVector.at(i);
            if(primitive->isLight()){
                pLight = primitive;
                GVector3 inDir = ((Lamp*) primitive)->getCenter() - point;
                inDir = inDir.normalize();
                CRay line(point+inDir*0.001,inDir);
                for(int j=0;j<size;j++){
                    CObject* ano_primitive = CVector.at(j);
                    if(!ano_primitive->isLight() && j!=num){
                        IntersectResult result = ano_primitive->isIntersected(line);
                        if(result.isHit && result.distance < inDir.getLength()){
                            visible = false;
                            break;
                        }
                    }
                }
                break;
            }
        }
    }
    GVector3 point;
    point = ray.getPoint(distance);

    if(visible){
        GVector3 lig = ((Lamp*)pLight)->getCenter() - point;
        lig = lig.normalize();
        primitive_near->getMaterial()->setLightDir(lig);
        totalColor = totalColor.add( primitive_near->getMaterial()->sample(ray, point, primitive_near->getNormal(point)) );
    }
    float reflection = primitive_near->getMaterial()->getRef();
    if( (reflection>0.0f) && (depth<max_depth) ){
        GVector3 normal_point = primitive_near->getNormal(point);
        normal_point = normal_point.normalize();
        float s0 = ray.getDirection().dotMul(normal_point) * (-2.0f);
        CRay newRay;
        newRay.setDirection(normal_point * s0 + ray.getDirection());
        newRay.setOrigin(point + newRay.getDirection()*1e-3);
        CObject* no_use = NULL;
        IntersectResult* n0=NULL;
        Color reflectionColor = rayTrace(newRay,depth+1,no_use,n0);
        reflectionColor = reflectionColor.multiply(reflection);
        //reflectionColor = reflectionColor.moderate(primitive_near->getMaterial()->getColor());
        totalColor = totalColor.add(reflectionColor.moderate(primitive_near->getMaterial()->getColor()));
    }
    float refraction = primitive_near->getMaterial()->getRefr();
    //cout<<refraction<<endl;
    if((refraction>0.0f) && (depth<max_depth)){

        GVector3 normal_point = primitive_near->getNormal(point);
        GVector3 Direction = ray.getDirection().normalize();
        normal_point = normal_point.normalize();
        float cosA = -Direction.dotMul(normal_point);
        float sinA = sqrt(1-cosA*cosA);
        float sinB = sinA / 1.5;
        float cosB = sqrt(1 - sinB*sinB);
        //cout<<sinA<<" "<<cosA<<" "<<sinB<<" "<<cosB<<endl;
        CRay newray;
        newray.setDirection(normal_point*(-cosB) + (Direction + normal_point*cosA).normalize()*sinB);
        newray.setOrigin(point + newray.getDirection() * 1e-3);
        CObject* no_use = NULL;
        IntersectResult* n0=NULL;
        Color refractionColor = rayTrace(newray,depth+1,no_use,n0);
        refractionColor = refractionColor.multiply(refraction);
        //refractionColor = refractionColor.moderate(primitive_near->getMaterial()->getColor());
        totalColor = totalColor.add(refractionColor);
    }
    return totalColor;
}
示例#2
0
文件: Cone.cpp 项目: Exapuppy/cg_lab
bool  CCone::trace(CRay ray, float& t)
{
  static float  R = r1,//max(r1,r2),
    r = r2;//min(r1,r2);
  CRay Ray = TransferToCanonical(ray);
  SavedEyeRay = ray;
  float Dirx = Ray._2.m[0], Diry = Ray._2.m[2], Dirz = Ray._2.m[1],
    Eyex = Ray._1.m[0], Eyey = Ray._1.m[2], Eyez = Ray._1.m[1],

    s = r / R, k = s - 1, d = k*Dirz, f = 1 + k*Eyez,

    A = Dirx*Dirx + Diry*Diry - d*d,
    B = (Eyex*Dirx + Eyey*Diry - f*d) * 2,
    C = Eyex*Eyex + Eyey*Eyey - f*f;

  float D = B*B - 4.0f*A*C;

  if (D >= 0) //бокова¤ поверхность
  {
    t = (-B - sqrtf(D)) / (2.0f*A);
    fl3 P = Ray.getPoint(t);

    if (t < 0) return false;

    fl3 Vscale = fl3(R, h, R),

      P1 = (Ray._1) ^ Vscale,
      P2 = P ^ Vscale;

    float norm1 = norm(P1 - P2);
    float norm2 = norm(ray._2);
    t = norm1 / norm2;

    SavedPoint = TransferToCanonical(ray.getPoint(t));

    SavedNormal = normalize(fl3(SavedPoint.m[0], (R - r) / h, SavedPoint.m[2]));

    if (P.m[1] <= 1 && P.m[1] >= 0) return true;
  }

  float t1 = -Eyez / Dirz,    //нижнее основание 
    t2 = t1 + 1.0f / Dirz; //верхнее
  t = min(t1, t2);
  fl3   P = Ray.getPoint(t);

  if (t < 0) return false;

  fl3 Vscale = fl3(R, h, R),
    P1 = (Ray._1) ^ Vscale,
    P2 = P ^ Vscale;
  float norm1 = norm(P1 - P2);
  float norm2 = norm(ray._2);
  t = norm1 / norm2;

  SavedPoint = TransferToCanonical(ray.getPoint(t));

  float px = P.m[0],
    py = P.m[2];
  if (t1 < t2)
  {
    SavedNormal = fl3(0, -1, 0);
    return (px*px + py*py <= 1);
  }
  else
  {
    SavedNormal = fl3(0, 1, 0);
    return (px*px + py*py <= s*s);
  }
}