public class Surface{ double[] origCoeff; double[] coefficients; Matrix3D tf; Vector currentNormalIn;//normal of entry for the point being observed Vector currentNormalOut; int objInd; material m; final int INFTY=10500; final static Vector e0=new Vector(new double[]{0,0,1}); void setMaterial(material ms){ m=new material(); m.copy(ms); } void setInd(int i){ objInd=i; } void setTransfo(Matrix3D tfs){ tf=new Matrix3D(); tf.copy(tfs); tf.invert(); tf.transpose(); tf.transform(origCoeff, coefficients); } void cube(material ms){ } double[] intersections(double[] v, double[] w){ //yields t where the ray enters and leaves the surface, // adding 0 (or -infty?) or +infty if necessary return new double[]{0}; } Vector getNormal(double[] position){ return new Vector(new double[]{0}); } public double[] shade(Surface[] obj, Light[] lights, Ray ray, double t, int flagIn){ //NB: the refraction part is full of bugs Vector w0=new Vector(ray.w); w0.normalize(); double[] w=w0.v; double[] v=ray.v.v; double[] res = new double[] {0,0,0}; double[] currPt=new double[3]; double[] shadowCoeff=new double[] {1,1,1}; for (int i=0; i<3; ++i){ currPt[i]=v[i]+t*w[i]; res[i]=m.ambient[i]; } Vector normV; if (flagIn<2){ normV=new Vector(currentNormalIn); } else{ normV=currentNormalIn.scalMult(-1); } if (lights!=null){ for (int i=0; i=tTmpOut) continue; if (tTmp>0 & tTmp<9995){ if (obj[ii].m.translucent==0){ shadowed=1; break; } else{ shadowCoeff[0]*=obj[ii].m.refractive[0]; shadowCoeff[1]*=obj[ii].m.refractive[1]; shadowCoeff[2]*=obj[ii].m.refractive[2]; } } } if (shadowed==1){ continue; } for (int j=0;j<3;j++){ double vald=lights[i].dir.dotP(normV); if (vald>0) res[j]+=lights[i].rgb[j]*m.diffuse[j]*vald;// diffuse tmp=normV.scalMult(2*vald); double vals=e0.dotP(tmp.diff(lights[i].dir)); if (vals>0) res[j]+=lights[i].rgb[j]*m.specular[j]*Math.pow(vals,m.p); } } } //now reflection if (ray.howManyRefl>0){ Vector newW=new Vector(w); newW=newW.diff(normV.scalMult(2*normV.dotP(w))); newW.normalize(); Vector newV=new Vector(currPt); newV=newV.add(newW.scalMult(0.001)); Ray newRay=new Ray(newV, newW, ray.n1); newRay.setRefl(ray.howManyRefl -1); double[] tmpRef; if (flagIn==0){ tmpRef=newRay.rayTraceSurf(obj, lights); } else{ newRay.setIndex(ray.index); tmpRef=newRay.rayIn(obj,lights); } tmpRef[0]*=m.specular[0]; tmpRef[1]*=m.specular[1]; tmpRef[2]*=m.specular[2]; res[0]+=tmpRef[0]; res[1]+=tmpRef[1]; res[2]+=tmpRef[2]; //res=add(res,calling.rayTrace(newV, newW, howManyRefl-1)); //res=diff(add(res,calling.rayTrace(newV, newW, howManyRefl-1)), m.ambient); } //...and refraction if (m.translucent!=0){ double cosT1=-normV.dotP(w); double n1=ray.n1; if (flagIn==0){//assuming you don't have transparent objects //inside transparent objects (i.e. if you get here, flagIn=0). double n2=m.refrInd; if ((1-cosT1*cosT1)<=(n2*n2/(n1*n1))){ double cosT2=Math.sqrt(1-n1*n1/(n2*n2)*(1-cosT1*cosT1)); Vector newW=new Vector(normV.scalMult(- cosT2)); Vector tmpW=new Vector(w); tmpW=tmpW.add(normV.scalMult(cosT1)); tmpW=tmpW.scalMult(n1/n2); newW=newW.add(tmpW); newW.normalize(); Vector newV=new Vector(currPt); newV=newV.add(newW.scalMult(0.001)); Ray newRay=new Ray(newV, newW, n2); newRay.setRefl(ray.howManyRefl); newRay.setIndex(objInd); double[] tmpRef=newRay.rayIn(obj, lights); tmpRef[0]*=m.refractive[0]; tmpRef[1]*=m.refractive[1]; tmpRef[2]*=m.refractive[2]; res[0]+=tmpRef[0]; res[1]+=tmpRef[1]; res[2]+=tmpRef[2]; } } if (flagIn==2){ double n2=1; if ((1-cosT1*cosT1)<=(n2*n2/(n1*n1))){ double cosT2=Math.sqrt(1-n1*n1/(n2*n2)*(1-cosT1*cosT1)); Vector newW=new Vector(normV.scalMult(- cosT2)); Vector tmpW=new Vector(w); tmpW=tmpW.add(normV.scalMult(cosT1)); tmpW=tmpW.scalMult(n1/n2); newW=newW.add(tmpW); newW.normalize(); Vector newV=new Vector(currPt); newV=newV.add(newW.scalMult(0.001)); Ray newRay=new Ray(newV, newW, n2); newRay.setRefl(ray.howManyRefl); double[] tmpRef=newRay.rayTraceSurf(obj, lights); res[0]+=tmpRef[0]; res[1]+=tmpRef[1]; res[2]+=tmpRef[2]; } } } /* res[0]*=shadowCoeff[0]; res[1]*=shadowCoeff[1]; res[2]*=shadowCoeff[2];*/ return res; } public double[] shadeSimple(Surface[] obj, Light[] lights, Ray ray, double t){ Vector w0=new Vector(ray.w); w0.normalize(); double[] w=w0.v; double[] v=ray.v.v; double[] res = new double[] {0,0,0}; double[] currPt=new double[3]; double[] currPt2=new double[3]; double[] shadowCoeff=new double[] {1,1,1}; for (int i=0; i<3; ++i){ currPt[i]=v[i]+t*w[i]; res[i]=m.ambient[i]; } Vector normV=new Vector(currentNormalIn);// Beware!! if no new vector, might //change in the recursive calculations of intersctions... if (lights!=null){ for (int i=0; i=tTmpOut) continue; if (tTmp>0 & tTmp<9995){ if (obj[ii].m.translucent==0){ shadowed=1; break; } else{ shadowCoeff[0]*=obj[ii].m.refractive[0]; shadowCoeff[1]*=obj[ii].m.refractive[1]; shadowCoeff[2]*=obj[ii].m.refractive[2]; } } } if (shadowed==1){ continue; } for (int j=0;j<3;j++){ double vald=lights[i].dir.dotP(normV); if (vald>0) res[j]+=lights[i].rgb[j]*m.diffuse[j]*vald;// diffuse tmp=normV.scalMult(2*vald); double vals=e0.dotP(tmp.diff(lights[i].dir)); if (vals>0) res[j]+=lights[i].rgb[j]*m.specular[j]*Math.pow(vals,m.p); } } } //now reflection if (ray.howManyRefl>0){ Vector newW=new Vector(w); newW=newW.diff(normV.scalMult(2*normV.dotP(w))); newW.normalize(); Vector newV=new Vector(currPt); newV=newV.add(newW.scalMult(0.001)); Ray newRay=new Ray(newV, newW, ray.n1); newRay.setRefl(ray.howManyRefl -1); double[] tmpRef; tmpRef=newRay.rayTraceSurf(obj, lights); tmpRef[0]*=m.specular[0]; tmpRef[1]*=m.specular[1]; tmpRef[2]*=m.specular[2]; res[0]+=tmpRef[0]; res[1]+=tmpRef[1]; res[2]+=tmpRef[2]; //res=add(res,calling.rayTrace(newV, newW, howManyRefl-1)); //res=diff(add(res,calling.rayTrace(newV, newW, howManyRefl-1)), m.ambient); } //...and refraction if (m.translucent!=0){ double cosT1=-normV.dotP(w); double n1=ray.n1; double n2=m.refrInd; if ((1-cosT1*cosT1)<=(n2*n2/(n1*n1))){ double cosT2=Math.sqrt(1-n1*n1/(n2*n2)*(1-cosT1*cosT1)); Vector newW=new Vector(normV.scalMult(- cosT2)); Vector tmpW=new Vector(w); tmpW=tmpW.add(normV.scalMult(cosT1)); tmpW=tmpW.scalMult(n1/n2); newW=newW.add(tmpW); newW.normalize(); Vector newV=new Vector(currPt); newV=newV.add(newW.scalMult(0.001)); double[] tmpInters=intersections(newV.v,newW.v); Vector normVOut=new Vector(currentNormalOut); double newCosT1=normVOut.dotP(newW.v); currPt2[0]=newV.v[0]+tmpInters[1]*newW.v[0]; currPt2[1]=newV.v[1]+tmpInters[1]*newW.v[1]; currPt2[2]=newV.v[2]+tmpInters[1]*newW.v[2]; if ((1-newCosT1*newCosT1)<=(n1*n1/(n2*n2))){ double newCosT2=Math.sqrt(1-n2*n2/(n1*n1)*(1-newCosT1*newCosT1)); Vector newW2=new Vector(normVOut.scalMult(newCosT2)); Vector tmpW2=new Vector(newW.v); tmpW2=tmpW2.diff(normVOut.scalMult(newCosT2)); tmpW2=tmpW2.scalMult(n2/n1); newW2=newW2.add(tmpW2); newW2.normalize(); Vector newV2=new Vector(currPt2); newV2=newV2.add(newW2.scalMult(0.001)); Ray newRay=new Ray(newV2, newW2, n1); newRay.setRefl(ray.howManyRefl); /* if (cosT1>0){ System.out.println("orig ray: "+ w[0] +" "+w[1]+" "+w[2]+"; new ray:"+ newW.v[0]+" "+newW.v[1]+" "+newW.v[2]+"\n cosT1:"+ cosT1+"normV:"+ normV.v[0]+" "+normV.v[1]+" "+normV.v[2]+"\n"); } System.out.println("casting a ray out\n");*/ double[] tmpRef=newRay.rayTraceSurf(obj, lights); tmpRef[0]*=m.refractive[0]; tmpRef[1]*=m.refractive[1]; tmpRef[2]*=m.refractive[2]; res[0]+=tmpRef[0]; res[1]+=tmpRef[1]; res[2]+=tmpRef[2]; } } } /* res[0]*=shadowCoeff[0]; res[1]*=shadowCoeff[1]; res[2]*=shadowCoeff[2];*/ return res; } void setCenter(double[] c){ } }