Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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 &currentVector = 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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
		}
	}
}