Schnittpunkte für Zylinder im Raytracer



  • Hallo, ich hab folgendes Problem: Ich soll einen Raytracer implementieren der unter anderem Zylinder darstellen kann. Allerdings fehlen mir als Algebra Looser dazu die nötigen mathematischen Kenntnisse. Eine Box und ein Sphere hab ich schon rein bringen können. Um mal darzustellen wie meine Intersect Methode funktioniert hier mal die für die Sphere:

    Shape* Kugel::intersect(point3d const& rayUrsprung, vector3d const& rayRichtung, point3d& result)
    {
    	vector3d normRichtung = normalize(rayRichtung);
    	vector3d const p(mittelpunkt_, rayUrsprung);
    	  double const   b = 2 * dot(p, normRichtung);
    	  double const   c = dot(p, p) - radius_ * radius_;
    	  double const   d = b * b - 4 * c;
    
    	  if (epsilon > d) {
    	    return NULL;
    	  }
    
    	  double ray_length;
    	  double t0;
    	  double t1;
    
    	  if (epsilon < (t0 = 0.5 * (-b - std::sqrt(d)))) {
    	    ray_length = t0;
    	  } else if (epsilon < (t1 = 0.5 * (-b + std::sqrt(d)))) {
    	    ray_length = t1;
    	  } else {
    	    return NULL;
    	  }
    
    	  if (ray_length < distance(rayUrsprung, result)) {
    	    result = get_intersection(rayUrsprung, normRichtung, ray_length);
    	    return this;
    	  }
    	  return NULL;	
    }
    

    Die Normale für den Zylinder kann ich auch bereits berechnen, aber dann ist auch Schluss. Kann mir wer helfen? Wäre dringend!
    Vielen Dank schonmal 🙂


  • Mod

    mach die berechnungen wie bei der sphere aber ohne eine achse. dann pruef ob der schnittpunkt innerhalb der des bereiches auf der ignorierten achse liegt, in dem der zylinder ist.



  • Also soll ich die Operation nur für die meinetwegen x und y Koordinaten der vektoren durchführen? Und dann?
    (Stehe gerade auf dem Schlauch^^)


  • Mod

    phantomlord schrieb:

    Also soll ich die Operation nur für die meinetwegen x und y Koordinaten der vektoren durchführen? Und dann?
    (Stehe gerade auf dem Schlauch^^)

    dann pruefst du ob der schnittpunkt (denn du dann ja in 3d ausrechnen kannst) in bezug auf z innerhalb von zmin zmax vom cylinder ist.



  • Also Problem ist erstmal das mein Konstruktor für den Zylinder so aussieht:

    Zylinder::Zylinder(std::string name, point3d const& minPunkt, point3d const& maxPunkt, double const& r, Material mat)
    

    Statt des Mittelpunktes der Kugel nehm ich den minPunkt des Vektors *edit* quatsch des Zylinders^^.
    Nur den maxPunkt verwende ich doch jetzt gar nicht mehr?
    Und die z Koordinate meines result soll ich jetzt mit der z Koordinate vergleichen die sich aus dem minPunkt und dem Radius ergibt?

    Shape* Zylinder::intersect(point3d const& rayUrsprung, vector3d const& rayRichtung, point3d& result)
    {
    	vector3d normRichtung = normalize(rayRichtung);
    	vector3d const p(minPunkt_, rayUrsprung);
    	  double const   b = 2 * (p[0] * normRichtung[0] +  p[1] * normRichtung[1]);
    	  double const   c = (p[0]*p[0]+p[0]*p[0]) - r_ * r_;
    	  double const   d = b * b - 4 * c;
    
    	  if (epsilon > d) {
    	    return NULL;
    	  }
    
    	  double ray_length;
    	  double t0;
    	  double t1;
    
    	  if (epsilon < (t0 = 0.5 * (-b - std::sqrt(d)))) {
    	    ray_length = t0;
    	  } else if (epsilon > (t1 = 0.5 * (-b + std::sqrt(d)))) {
    	    ray_length = t1;
    	  } else {
    	    return NULL;
    	  }
    
    	  if (ray_length < distance(rayUrsprung, result)) {
    	    result = get_intersection(rayUrsprung, normRichtung, ray_length);
    		if(result == .....)??? 	
    	    return this;
    	  }
    	  return NULL;	
    }
    


  • rapso schrieb:

    mach die berechnungen wie bei der sphere aber ohne eine achse. dann pruef ob der schnittpunkt innerhalb der des bereiches auf der ignorierten achse liegt, in dem der zylinder ist.

    Das klappt aber nicht, wenn der Strahl durch die Zylinder-"Kappen" geht.
    Am besten schaut man sich z.B. die Schnitt-Tests von ODE an.



  • Am besten schaut man sich z.B. die Schnitt-Tests von ODE an.

    Ähm, was ist das? Wo find ich das?^^



  • www.ode.org?

    Das hilft mir leider nicht weiter!



  • phantomlord schrieb:

    Das hilft mir leider nicht weiter!

    Warum nicht?
    Du solltest dir schon den Quelltext runterladen und dann schauen, wie die es machen.



  • Hab ich schon, aber da blick ich mal gar nicht durch.
    Ich hab mir jetzt mal was mit Hilfe dieser Seite gebaut:

    http://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node1.html

    Damit habe ich bisher folgendes:

    Shape* Zylinder::intersect(point3d const& rayUrsprung, vector3d const& rayRichtung, point3d& result)
    {
    	vector3d normRichtung = normalize(rayRichtung);
    	vector3d const p(minPunkt_, rayUrsprung);
    
    	  double const   a = ((normRichtung[0] * normRichtung[0]) + (normRichtung[1] * normRichtung[1]));
    	  double const   b = ((2 * rayUrsprung[0] * normRichtung[0]) + (2 * rayUrsprung[1] * normRichtung[1])); 
    	  double const   c = ((rayUrsprung[0] * rayUrsprung[0]) + (rayUrsprung[1] * rayUrsprung[1]) -1);
    	  double ray_length;
    	  double t0, t1, z0, z1;
    
    	t0= (- b + std::sqrt((b*b) - (4*a*c))) / (2 * a);
    	t1= (- b - std::sqrt((b*b) - (4*a*c))) / (2 * a);
    
    	z0= (rayUrsprung[2] + t0 * normRichtung[2]);
    	z1= (rayUrsprung[2] + t1 * normRichtung[2]);  
    
    	  if (epsilon < z0) 
    	    ray_length = z0;
    	   else if (epsilon > z1)
    	    ray_length = z1;
    	   else {
    	    return NULL;
    	  }
    
    	  if (ray_length < distance(rayUrsprung, result)) {
    	    result = get_intersection(rayUrsprung, normRichtung, ray_length);
    
    	   return this;
    
    	  }
    	  return NULL;	
    }
    

    Wobei nach den z alles noch mehr oder minder von der Kugel stammt. Jetzt geht es wieder um die min und max z Vergleiche. Ich blicke gerade nicht mehr durch.....wann, was wie....ahh, wenn das morgen nicht raus müsste, wäre schlaf angebracht! Also wenn ihr mir nochmal nen Schupser geben könntet?^^

    P.S.: Diese ominöse Epsilon:

    double const epsilon = std::numeric_limits<double>::epsilon() *96;
    

Anmelden zum Antworten