bool Grid::intersect(const Ray &r, Hit &h, float tmin) { //Prepare the Material objects Vec3f diffuseColor(1, 1, 1); Vec3f specularColor(0, 0, 0); float exponent = 1; Vec3f reflectiveColor(0, 0, 0); Vec3f transparentColor(0, 0, 0); float indexOfRefraction = 1; PhongMaterial *m = new PhongMaterial(diffuseColor, specularColor, exponent, reflectiveColor, transparentColor, indexOfRefraction); //Start to do DDA MarchingInfo mi; initializeRayMarch(mi, r, tmin); bool hitSomething = false; int i, j, k; do { mi.getIndices(i, j, k); printf("The current point is:%d,%d,%d\n", i, j, k); if (mObjects[offset(i, j, k)].getNumObjects() > 0) { h.set(mi.get_tmin(), m, mi.getNormal(), r); return true; } mi.nextCell(); } while(i < mXSize && j < mYSize && k < mZSize); return false; }
void Grid::initializeRayMarch(MarchingInfo &mi, const Ray &r, float tmin) const { Vec3f rayOrigin = r.getOrigin(); Vec3f rayDir = r.getDirection(); Vec3f boxMin = mpBox->getMin(); Vec3f boxMax = mpBox->getMax(); float rayT; if (mpBox->Inside(rayOrigin)) rayT = 0.0; else if (!mpBox->IntersectP(r, &rayT)) { return; } printf("rayT=%f\n", rayT); Vec3f gridIntersect = r.pointAtParameter(rayT); cout << "gridIntersect=" << gridIntersect << endl; cout << "Box min=" << mpBox->getMin() << endl; printf("mVoxel:%d, %d, %d \n", mVoxel[0], mVoxel[1], mVoxel[2]); //MarchingInfo for indices int pos[3]; int axis; int sign[3]; float delta[3]; float next[3]; int indices[3]; for (axis = 0; axis < 3; axis++) { pos[axis] = posToVoxel(gridIntersect, axis); if (rayDir[axis] != 0) sign[axis] = rayDir[axis] > 0 ? 1 : -1; if (sign[axis] >= 0) { next[axis] = rayT + (voxelToPos(pos[axis]+1, axis) - gridIntersect[axis])/rayDir[axis]; delta[axis] = mVoxel[axis] / rayDir[axis]; } else { next[axis] = rayT + (voxelToPos(pos[axis], axis) - gridIntersect[axis])/rayDir[axis]; delta[axis] = mVoxel[axis] / rayDir[axis]; } } printf("Indices:%d, %d, %d \n", pos[0], pos[1], pos[2]); mi.setIndices(pos[0], pos[1], pos[2]); mi.setSign(sign[0], sign[1], sign[2]); mi.setDelta(delta[0], delta[1], delta[2]); mi.setNext(next[0], next[1], next[2]); mi.set_tmin(rayT); }
bool Grid::shadowIntersect(const Ray &r, Hit &h, float tmin) { MarchingInfo march; initialRayMarch(march,r,tmin); int currentI = march.GetI(); int currentJ = march.GetJ(); int currentK = march.GetK(); float currentT = march.GetT(); int numObjects; Object3DVector isAlreadyIntersect; while(currentI>=0 && currentI<nx && currentJ>=0 && currentJ<ny && currentK>=0 && currentK<nz) { RayTracingStats::IncrementNumGridCellsTraversed(); Object3DVector ¤tVector = isOpaque[currentI][currentJ][currentK]; numObjects = currentVector.getNumObjects(); for(int i=0; i<numObjects; ++i) { if(isAlreadyIntersect.isInside(currentVector.getObject(i))) continue; RayTracingStats::IncrementNumIntersections(); if(currentVector.getObject(i)->intersect(r,h,tmin)) return true; isAlreadyIntersect.addObject(currentVector.getObject(i)); } march.nextCell(); currentI = march.GetI(); currentJ = march.GetJ(); currentK = march.GetK(); currentT = march.GetT(); //折射或反射,shadow时,光线圆点会在grid内 } numObjects = others.getNumObjects(); for(int i=0; i<numObjects; i++) { if(others.getObject(i)->intersect(r,h,tmin)) return true; } return false; }
bool Grid::intersect(const Ray &r, Hit &h, float tmin) { MarchingInfo march; initialRayMarch(march,r,tmin); int currentI = march.GetI(); int currentJ = march.GetJ(); int currentK = march.GetK(); float currentT = march.GetT(); int numObjects; //Object3DVector currentVector; 绝对不能新建一个Object3DVector,然后把isOpaque的值赋给这个Object3DVector,因为当这个函数结束时,会把Object3DVector销毁,对应的指针指向的对象也会被销毁。 //当然还有一种方法是定义一个Object3DVector指针 //printf("i:%d j:%d currentI:%d currentJ:%d currentK:%d\n",i,j,currentI,currentJ,currentK); Object3DVector isAlreadyIntersect; while(currentI>=0 && currentI<nx && currentJ>=0 && currentJ<ny && currentK>=0 && currentK<nz) { RayTracingStats::IncrementNumGridCellsTraversed(); Object3DVector* currentVector = &isOpaque[currentI][currentJ][currentK]; numObjects = currentVector->getNumObjects(); //printf("%d %d %d\n",currentI,currentJ,currentK); for(int i=0; i<numObjects; ++i) { //already intersected object don't need intersect again if(isAlreadyIntersect.isInside(currentVector->getObject(i))) continue; RayTracingStats::IncrementNumIntersections(); currentVector->getObject(i)->intersect(r,h,tmin); isAlreadyIntersect.addObject(currentVector->getObject(i)); } if(h.getMaterial()!=NULL && h.getT()>=currentT && h.getT()<=march.GetNext_x() && h.getT()<=march.GetNext_y() && h.getT()<=march.GetNext_z()) { return true; } march.nextCell(); currentI = march.GetI(); currentJ = march.GetJ(); currentK = march.GetK(); currentT = march.GetT(); //折射或反射,shadow时,光线圆点会在grid内 } numObjects = others.getNumObjects(); for(int i=0; i<numObjects; i++) { others.getObject(i)->intersect(r,h,tmin); } if(h.getMaterial()!=NULL) //这里有问题,因为如果没有和平面相交的话,h的material也有可能不是null return true; return false; }
void Grid::initialRayMarch(MarchingInfo &mi, const Ray &r, float tmin) const { Vec3f rayOri = r.getOrigin(); Vec3f rayDir = r.getDirection(); float tbottom,ttop,tfront,tback,tleft,tright,tc; float dtx,dty,dtz; int celli,cellj,cellk; float tnext_x,tnext_y,tnext_z; int signx,signy,signz; signx = (rayDir.x()>=0) ? 1 : -1; signy = (rayDir.y()>=0) ? 1 : -1; signz = (rayDir.z()>=0) ? 1 : -1; //需要求绝对值 这里rayDir.x()等于0没有处理 dtx = abs(dx / rayDir.x()); dty = abs(dy / rayDir.y()); dtz = abs(dz / rayDir.z()); Vec3f normal; Vec3f rayOriTmin = rayOri + rayDir * tmin; //这里临界值要注意 //inside; if(max.x()>rayOriTmin.x()&&min.x()<rayOriTmin.x()&&max.y()>rayOriTmin.y()&&min.y()<rayOriTmin.y()&&max.z()>rayOriTmin.z()&&min.z()<rayOriTmin.z()) //忽略了tmin的作用 { celli = (int)((rayOriTmin.x()-min.x())/dx); cellj = (int)((rayOriTmin.y()-min.y())/dy); cellk = (int)((rayOriTmin.z()-min.z())/dz); if(Utility::isZero(rayDir.x())) tnext_x = 10000; else if(signx == -1) //如果反方向的话,求tnext不需要加signx 谢谢大师提醒 tnext_x = (min.x()+celli*dx-rayOri.x())/rayDir.x(); else tnext_x = (min.x()+(celli+signx)*dx-rayOri.x())/rayDir.x(); if(Utility::isZero(rayDir.y())) tnext_y = 10000; else if(signy == -1) tnext_y = (min.y()+cellj*dy-rayOri.y())/rayDir.y(); else tnext_y = (min.y()+(cellj+signy)*dy-rayOri.y())/rayDir.y(); if(Utility::isZero(rayDir.z())) tnext_z = 10000; else if(signz == -1) tnext_z = (min.z()+cellk*dz-rayOri.z())/rayDir.z(); else tnext_z = (min.z()+(cellk+signz)*dz-rayOri.z())/rayDir.z(); //这里tmin如何修改 mi.Set(0,celli,cellj,cellk,tnext_x,tnext_y,tnext_z,dtx,dty,dtz,signx,signy,signz,normal); } else //outside { float t1x,t1y,t1z; float t2x,t2y,t2z; float tnear,tfar; if(Utility::isZero(rayDir.x())) { tleft = 0; tright = 10000; } else { tleft = (min.x()-rayOri.x())/rayDir.x(); tright = (max.x()-rayOri.x())/rayDir.x(); } if(Utility::isZero(rayDir.y())) { tbottom = 0; ttop = 10000; } else { tbottom = (min.y()-rayOri.y())/rayDir.y(); ttop = (max.y()-rayOri.y())/rayDir.y(); } if(Utility::isZero(rayDir.z())) { tback = 0; tfront = 10000; } else { tback = (min.z()-rayOri.z())/rayDir.z(); tfront = (max.z()-rayOri.z())/rayDir.z(); } t1x = (signx == 1) ? tleft : tright; t2x = (signx == 1) ? tright : tleft; t1y = (signy == 1) ? tbottom : ttop; t2y = (signy == 1) ? ttop : tbottom; t1z = (signz == 1) ? tback : tfront; t2z = (signz == 1) ? tfront : tback; tnear = Utility::getMax(t1x,t1y,t1z); tfar = Utility::getMin(t2x,t2y,t2z); if(tnear>tfar) //miss {} else if(tfar<tmin) //behind {} else //hit { tc = tnear; //求i,j,k if(rayOri.x()+rayDir.x()*tc+tmin < min.x()) //要加上0.0001 celli = -1; else celli = (int)((rayOri.x()+rayDir.x()*tc-min.x()-tmin)/dx); //减去0.0001是为了使边界也算交 if(rayOri.y()+rayDir.y()*tc+tmin < min.y()) cellj = -1; else cellj = (int)((rayOri.y()+rayDir.y()*tc-min.y()-tmin)/dy); if(rayOri.z()+rayDir.z()*tc+tmin < min.z()) cellk = -1; else cellk = (int)((rayOri.z()+rayDir.z()*tc-min.z()-tmin)/dz); //求tnext if(Utility::isZero(rayDir.x())) tnext_x = 10000; else if(signx == -1) //如果反方向的话,求tnext不需要加signx 谢谢大师提醒 tnext_x = (min.x()+celli*dx-rayOri.x())/rayDir.x(); else tnext_x = (min.x()+(celli+signx)*dx-rayOri.x())/rayDir.x(); if(Utility::isZero(rayDir.y())) tnext_y = 10000; else if(signy == -1) tnext_y = (min.y()+cellj*dy-rayOri.y())/rayDir.y(); else tnext_y = (min.y()+(cellj+signy)*dy-rayOri.y())/rayDir.y(); if(Utility::isZero(rayDir.z())) tnext_z = 10000; else if(signz == -1) tnext_z = (min.z()+cellk*dz-rayOri.z())/rayDir.z(); else tnext_z = (min.z()+(cellk+signz)*dz-rayOri.z())/rayDir.z(); if(Utility::isEqual(tc,tleft)) normal.Set(-1,0,0); else if(Utility::isEqual(tc,tright)) normal.Set(1,0,0); else if(Utility::isEqual(tc,tbottom)) normal.Set(0,-1,0); else if(Utility::isEqual(tc,ttop)) normal.Set(0,1,0); else if(Utility::isEqual(tc,tfront)) normal.Set(0,0,1); else if(Utility::isEqual(tc,tback)) normal.Set(0,0,-1); mi.Set(tc,celli,cellj,cellk,tnext_x,tnext_y,tnext_z,dtx,dty,dtz,signx,signy,signz,normal); //printf("celli: %d cellj: %d cellk: %d \n",celli,cellj,cellk); } } }