void Grid::rasterizeSphere(Vec3f center, float radius) { Vec3f coord; for (int i = 0; i < num_x; ++i) { for (int j = 0; j < num_y; ++j) { for (int k = 0; k < num_z; ++k) { coord.Set ( min_coor[0] + (i + 0.5f) * del_x, min_coor[1] + (j + 0.5f) * del_y, min_coor[2] + (k + 0.5f) * del_z ); if ( (coord - center).Length() <= radius ) { voxels[num_y * num_z * i + num_z * j + k] = true; } else { voxels[num_y * num_z * i + num_z * j + k] = false; } } } } return; }
bool Draw::QtpickColor(Vec3f& col) { QColor qcol = QColorDialog::getColor(getCurrColor()); if (!qcol.isValid()) return false; col.Set(float(qcol.red())/255., float(qcol.green())/255., float(qcol.blue())/255.); return true; }
Vec3f scene::rayTrace(Vec3f eye, Vec3f dir, int recurseDepth) { //start with black, add color as we go Vec3f answer(0,0,0); //test for intersection against all our objects float dist = myObjGroup->testIntersections(eye, dir); //if we saw nothing, return the background color of our scene if (dist==9999999) return bgColor; Vec3f textureColor; //get the material index and normal vector(at the point we saw) of the object we saw int matIndex = myObjGroup->getClosest()->getMatIndex(); Vec3f normal = myObjGroup->getClosest()->getNormal(eye, dir * dist); //determine texture color if (myMaterials.at(matIndex).texture==NULL) //this is multiplicative, rather than additive //so if there is no texture, just use ones textureColor.Set(1,1,1); else { //if there is a texture image, ask the object for the image coordinates (between 0 and 1) Vec3f coords = myObjGroup->getClosest()->getTextureCoords(eye, dir * dist); //get the color from that image location textureColor.Set( PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),0), PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),1), PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),2)); textureColor = textureColor*(1/255.0); } // add ambient light/color to our answer answer += multiplyColorVectors(ambLight, myMaterials.at(matIndex).diffuseCol); // set point slightly above the actual surface, prevents // issues with that point intersecting itself Vec3f point = eye + (dir * dist) + (normal * .0001); Vec3f real_point = eye + (dir * dist); // get the diffuse color of our material Vec3f diffuseColor = myMaterials.at(matIndex).diffuseCol; // iterate through lights for (int iter = 0; iter < myLights.size(); iter++) { Vec3f lightPos = myLights.at(iter).position; Vec3f direction= lightPos - point; direction.Normalize(); float distance = myObjGroup->testIntersections(point, direction); // if nothing between point and light if (distance == 9999999) { Vec3f color = multiplyColorVectors(diffuseColor, myLights.at(iter).color); float nl = abs(direction.Dot3(normal)); answer += (color * nl); // now do the specular // we need vector that goes from point to eye Vec3f backDir = dir * -1.0f; Vec3f h = (backDir + direction); h.Normalize(); Vec3f Cp = myMaterials.at(matIndex).specularCol; float p = myMaterials.at(matIndex).shininess; float nh = abs(normal.Dot3(h)); nh = pow(nh, p); answer += multiplyColorVectors(myLights.at(iter).color, Cp) * nh; } } //if the light can see the surface point, //add its diffuse color to a total diffuse for the point (using our illumination model) //use testIntersection to help decide this //add the diffuse light times the accumulated diffuse light to our answer if (recurseDepth < 3) { Vec3f e = dir * -1.0f; e.Normalize(); Vec3f r = dir + normal * 2.0f * e.Dot3(normal); r.Normalize(); Vec3f bounced = rayTrace(point, r, recurseDepth + 1); answer += (multiplyColorVectors(bounced, myMaterials.at(matIndex).reflectiveCol)); // refraction Vec3f transparentColor = myMaterials.at(matIndex).transparentCol; float transpar = transparentColor.Dot3(transparentColor); if (transpar > 0.0f) { float exitAngle, entryAngle; if (dir.Dot3(normal) < 0.0f) { entryAngle = acos(dir.Dot3(normal * -1.0f)); exitAngle = entryAngle * myMaterials.at(matIndex).refractionIndex; } else { entryAngle = acos(dir.Dot3(normal)); exitAngle = entryAngle / myMaterials.at(matIndex).refractionIndex; } Vec3f b = (dir + (normal * cos(entryAngle))) * (1.0f /sin(entryAngle)); b.Normalize(); Vec3f refracted = (b * sin(exitAngle)) - (normal * cos(exitAngle)); refracted.Normalize(); answer += multiplyColorVectors(rayTrace(real_point, refracted, recurseDepth + 1), myMaterials.at(matIndex).transparentCol); } } //put a limit on the depth of recursion //if (recurseDepth<3) //{ //reflect our view across the normal //recusively raytrace from the surface point along the reflected view //add the color seen times the reflective color //if going into material (dot prod of dir and normal is negative), bend toward normal //find entry angle using inverse cos of dot product of dir and -normal //multiply entry angle by index of refraction to get exit angle //else, bend away //find entry angle using inverse cos of dot product of dir and normal //divide entry angle by index of refraction to get exit angle //recursively raytrace from the other side of the object along the new direction //add the color seen times the transparent color //} //multiply whatever color we have found by the texture color answer=multiplyColorVectors(answer,textureColor); return answer; }
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); } } }