📄 scene.cpp
字号:
string inp;
name = nexttoken();
if ( whichtoken(name) != IDENT ) {
cout << "Error: Identifier expected." << endl;
return NULL;
}
if ( def_stack->search(name) ) {
cout << line << ": " << name;
cout << ": attempt to redefine. " << endl;
return NULL;
}
lb = nexttoken();
if ( whichtoken(lb) != LFTCURLY ) {
cout << "Error: { expected." << endl;
return NULL;
}
while ( whichtoken( temp = nexttoken()) != RGHTCURLY ) {
//cout << temp << endl;
inp = inp + temp + " ";
if (!f_in) {
cout << "Error: end of file detected." << endl;
return NULL;
}
}
// Push the contents of the string on the stack.
def_stack->push(name, inp);
break;} // end of case: DEF
case USE:
{
string name;
name = nexttoken();
if ( whichtoken(name) != IDENT ) {
cout << line << ": " << name;
cout << ": identifier expected.";
return NULL;
}
if (! def_stack->search(name) ) {
cout << line << ": " << name;
cout << ": not defined.";
return NULL;
}
// cout << def_stack->contents(name) << endl;
temp_fin = new strstream;
*temp_fin << def_stack->contents(name);
char *c = new char[temp_fin->pcount()];
int n = temp_fin->pcount() ;
int i = n - 1;
while(temp_fin->get(c[i])){
i--;
}
i++;
while(i< n)
f_in->putback(c[i++]);
delete(c);
}
break; // end of case: USE
// Camera Definitions
case EYE:
eye.x = getFloat();
eye.y = getFloat();
eye.z = getFloat();
break;
case LOOKAT:
lookAt.x = getFloat();
lookAt.y = getFloat();
lookAt.z = getFloat();
break;
case UP:
up.x = getFloat();
up.y = getFloat();
up.z = getFloat();
break;
case NEARPLANE:
nearPlane = getFloat();
break;
case FARPLANE:
farPlane = getFloat();
break;
case VIEWANGLE:
angle = getFloat();
break;
default: { // inner switch for Shapes
switch(typ)
{
case SQUARE: newShape = new Square;
break;
case CUBE: newShape = new Cube;
newShape->drawOpenGL();
break;
case SPHERE: newShape = new Sphere;
break;
case TORUS: newShape = new Torus;break;
case PLANE: newShape = new Plane;break;
case CHECKERBOARD: newShape = new Checkerboard(getFloat(), getFloat()); break;
case TAPEREDCYLINDER: newShape = new TaperedCylinder;
((TaperedCylinder*)newShape)->smallRadius = getFloat(); break;
case CONE: newShape = new Cone; break;
case CYLINDER: newShape = new Cylinder; break;
case OCTAHEDRON: newShape = new Octahedron; break;
case TETRAHEDRON: newShape = new Tetrahedron; break;
case DODECAHEDRON: newShape = new Dodecahedron; break;
case ICOSAHEDRON: newShape = new Icosahedron; break;
case BUCKYBALL: newShape = new BuckyBall; break;
case DIAMOND: newShape = new Diamond; break;
case TEAPOT: newShape = new Teapot; break;
case MESH: {// get a filename (with extension) for this mesh
string fname = nexttoken(); // get file name for mesh
newShape = new Mesh(fname); break;
}// end of case: MESH
default: {
cerr << "Line " << nextline << ": unknown keyword " << s << endl;
return NULL;
}
} // end of inner switch
// common things to do to all Shapes
((Shape*)newShape)->mtrl.set(currMtrl);
// load transform and its inverse
((Shape*)newShape)->transf.set(*(affStk.tos->affn));
((Shape*)newShape)->invTransf.set(*(affStk.tos->invAffn));
return newShape;
}// end of default: block
} // end of outer switch
} // end of while
return NULL;
}
void Scene::makeLightsOpenGL(void)
{
if(light == NULL)
return;
GLfloat light_position[] = { light->pos.x, light->pos.y, light->pos.z, 0};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
return;
}
void Scene::drawSceneOpenGL(void)
{
for(GeomObj *p = obj; p; p=p->next)
p->drawOpenGL();
return;
}
void Scene::drawSceneCanvas(void)
{
for(GeomObj *p = obj; p; p=p->next)
p->drawCanvas();
return;
}
void Scene::printScene(void)
{
for(GeomObj *p=obj; p; p=p->next)
p->print();
return;
}
void Scene::xfrmNormal(Vector3 &N2, Affine4 transf, Vector3 &N1)
{
float v[4];
N1.build4tuple(v);
Affine4 t;
transf.transpose(t);
t.applyTransform(v);
N2.set(v[0],v[1],v[2]);
return;
}
Color3 Scene::shade(Ray &ray)
{
Color3 color(0, 0, 0);
Intersection best;
// Retrieve the first object intersection
getFirstHit(ray, best);
// If not intersection then return background color
if(best.numHits == 0) {
return background;
}
// The point of intersection
Point3 p = ray.calculatePointOnRay(best.hit[0].hitTime);
// Retrieve pointer to object hit
Shape *myObj = (Shape*)best.hit[0].hitObject;
// The surfact normal at the point of intersection
Vector3 N;
xfrmNormal(N, myObj->invTransf, best.hit[0].hitNormal);
N.normalize();
// Only compute surface properties when entering (not when exiting)
// Calculate the local intensity
color = phongLighting(myObj->mtrl, p, N, ray);
// Calculate color contribution from reflections and refractions
if(ray.getRecurseLevel() == maxRecursionDepth) return color;
if(myObj->mtrl.reflectivity > 0) spawnReflectedRay(myObj->mtrl, p, N, ray, color);
return color;
}
void Scene::spawnReflectedRay(Material mtrl, Point3 p, Vector3 N, Ray ray, Color3 &color)
{
// Increment counter
reflRays++;
// Calculate the reflection direction
Vector3 newDir(ray.getDir());
newDir.normalize();
float f = 2 * newDir.dot(N);
Vector3 temp;
temp.set(N);
temp.scale(f);
temp.flip();
newDir.add(temp);
newDir.normalize();
// Create the reflection ray
Ray reflected(p, newDir);
reflected.nudgeForward(mtrl.nudgeValue);
reflected.setRecurseLevel(ray.getRecurseLevel() + 1);
// Add the color contribution
Color3 reflectColor;
reflectColor = shade(reflected);
reflectColor.scale(mtrl.reflectivity);
// Set the resulting color
color.add(reflectColor);
}
Color3 Scene::phongLighting(Material mtrl, Point3 p, Vector3 N, Ray ray)
{
// Add emissive component and ambient component
Color3 result;
result.set(mtrl.emissive);
result.add(ambient, mtrl.ambient);
// View vector is always back along the ray (even when reflecting or refracting)
Vector3 V(ray.getDir());
V.flip();
// Loop through the lights to calculate specular and diffuse
for(Light *l = light; l != NULL; l=l->next)
{
// Increment the counter
shadowRays++;
// Check if the object is in shadow for this light
Ray feeler(p); feeler.setDir(l);
feeler.nudgeForward(mtrl.nudgeValue);
if(isInShadow(feeler)) continue;
// Calculate the diffuse component according to Lambert equation
Vector3 L;
L.setDiff(l->pos, p);
L.normalize();
float lambert = L.dot(N);
if(lambert > 0.0f)
{
Color3 diffuseColor;
diffuseColor.add(l->color, mtrl.diffuse);
diffuseColor.scale(lambert);
result.add(diffuseColor);
}
// Calculate the Specular component according to Blinn-Phong equation
Vector3 H(L); H.add(V);
if(!CLOSE(H.x*H.x + H.y*H.y + H.z*H.z, 0))
H.normalize();
float phong = H.dot(N);
if(phong > 0.0f)
{
phong = pow(phong, mtrl.specularExponent);
Color3 specularColor;
specularColor.add(l->color, mtrl.specular);
specularColor.scale(phong);
result.add(specularColor);
}
// Add distance attenuation
result.scale(feeler.getAttenuation());
}
return result;
}
void Scene::getFirstHit(Ray &ray, Intersection &best)
{
Intersection inter;
best.numHits = 0;
for(GeomObj *pObj=obj; pObj != NULL; pObj = pObj->next)
{
if(!pObj->hit(ray, inter))
continue;
if(best.numHits == 0 || inter.hit[0].hitTime < best.hit[0].hitTime)
best.set(inter);
}
}
bool Scene::isInShadow(Ray &feeler)
{
Intersection i;
float attenuate = 1.0;
for(GeomObj* p = obj; p; p= p->next)
{
if(p->hit(feeler, i))
{
if(((Shape*)p)->mtrl.transparency == 0.0)
return true;
else attenuate *= ((Shape*)p)->mtrl.transparency;
}
}
feeler.setAttenuation(attenuate);
return false;
}
void Scene::bindTexture(int TextureType)
{
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, TextureType);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -