每次运行我的程序时,都会遇到此错误,但我似乎无法弄清楚导致它的原因。该程序假设从文本文件&中获取输入。然后创建一个光线跟踪器的输出ppm文件。谢谢!
/** genRay **/
vector_t genRay(scene_t *scene, int column, int row)
{
vector_t direction;
entity_t *ent;
window_t *window;
assert(scene->magic == SCENE_T);
ent = scene->window;
window = ent->entDerived;
assert(window->magic == WINDOW_T);
/* Computer the pixel's real scene coordinates */
direction.x = ((double)(column)/
(double)(scene->picture->columns-1))*window->windowWidth;
direction.x -= window->windowWidth/2.0;
direction.y = ((double)(row)/
(double)(scene->picture->rows-1))*window->windowHeight;
direction.y -= window->windowHeight/2.0;
direction.z = 0;
/* And now construct a unit vector from the view point to the pixel */
direction = ray(window->viewPoint, direction);
direction = unitize(direction);
return(direction);
} /* End genRay */
/**
* The raytrace() function traces a single ray and returns
* the composite
* intensity of the light it encounters. It is recursive and
* so the start of the ray cannot be assumed to be the viewpt
* Recursion won't be involved until we take on specular light
**/
intensity_t rayTrace(scene_t *scene, point_t base, vector_t unitDir,
double total_dist, entity_t *self) {
intensity_t intensity = ((intensity_t){0, 0, 0});
entity_t * closestEnt;
hitinfo_t * hit = malloc(sizeof(hitinfo_t));
closestEnt = closest(scene, base, unitDir, self, hit);
if (closestEnt == NULL) {
free(hit);
return (intensity);
}
total_dist += hit->distance;
window_t * window = ((window_t *)(scene->window->entDerived));
sobj_t * sobj = ((sobj_t *)(closestEnt->entDerived));
intensity = ((tuple_t){window->ambient.x * sobj->color.r,
window->ambient.y * sobj->color.g,
window->ambient.z * sobj->color.b});
sobj_t * closestSobj = closestEnt->entDerived;
if (length(((tuple_t)(closestSobj->reflective))) != 0) {
vector_t U = scale(unitDir, -1);
vector_t N = hit->normal;
vector_t V = unitize(add(scale(N, (2 * dot(U, N))), unitDir));
intensity_t reflection;
reflection = rayTrace(scene, hit->hitpoint, V, total_dist, closestEnt);
intensity = add(intensity, reflection);
}
free(hit);
return (intensity);
} /* End rayTrace */
/**
* The closest() function processes each scene object in the scene
* objects list (sobjList) and uses the "hits" functions to determine
* if the ray hits the scene object. If the ray hits one or more
* scene objects, the function determines the closest object hit
* and updates the fields of the hitinfo_t pointed. The function
* returns the pointer to the closest entity, or NULL if the ray
* doesn't hit anything.
**/
entity_t *closest(scene_t *scene, point_t base, vector_t unitDir,
entity_t *self, hitinfo_t *hit) {
int flag_closest = 0;
entity_t * ent; //Shortcut to entity in list
sobj_t * sobj; //Shortcut to ent->entDerived
entity_t * closest = NULL; //Will be returned at end of function
hitinfo_t hit_closest;
iterator_t * iter = newIterator(scene->sobjList);
l_begin(iter);
while((ent = l_next(iter)) != NULL) {
/** Run Hit Checks and stores closest Entity **/
if (ent != self) {
sobj = ent->entDerived;
if (sobj->hits(ent, base, unitDir, &hit_closest) == 1) {
if (flag_closest == 1) {
if (hit->distance > hit_closest.distance) {
hit->distance = hit_closest.distance;
hit->normal = hit_closest.normal;
hit->hitpoint = hit_closest.hitpoint;
closest = ent;
}
}
else { //first time there has been a "hit"
hit->distance = hit_closest.distance;
hit->normal = hit_closest.normal;
hit->hitpoint = hit_closest.hitpoint;
flag_closest = 1;
closest = ent;
}
}
}
}
free(iter);
return closest;
} /* End closest */
#include "ray.h"
/** newPlane **/
entity_t *newPlane(char *enttype, int code)
{
entity_t *ent;
plane_t *plane;
vector_t zero = {0, 0, 0};
ent = newSceneObj(enttype, code);
plane = malloc(sizeof(plane_t));
assert(plane != NULL);
((sobj_t *)(ent->entDerived))->sobjDerived = plane; // create new plane
plane->point = zero;
plane->orient1 = (vector_t){1, 0, 0}; // setting default values for plane
plane->orient2 = (vector_t){0, 1, 0};
plane->magic = PLANE_T;
return(ent);
}
/** loadPlane **/
void loadPlane(FILE *inFP, entity_t *ent)
{
char *attributes[] = {"point", "orient1", "orient2", NULL};
char attribute[25];
int ndx;
assert(ent->magic == ENTITY_T);
sobj_t *obj = ent->entDerived;
assert(obj->magic == SCENEOBJ_T);
plane_t *plane = obj->sobjDerived;
assert(plane->magic == PLANE_T);
loadSceneObj(inFP, ent);
fscanf(inFP, "%s", attribute);
while(attribute[0] != ';')
{
ndx = getindex(attribute, attributes);
switch (ndx) {
case 0:
/* point */
plane->point = readTuple(inFP, "Could not read plane point");
break;
case 1:
/* orient1 */
plane->orient1 = readTuple(inFP, "Could not read plane orient1");
break;
case 2:
/* orient1 */
plane->orient2 = readTuple(inFP, "Could not read plane orient2");
break;
default:
fprintf(stderr, "bad plane attribute; exiting\n");
exit(1);
}
fscanf(inFP, "%s", attribute);
}
}
/** completePlane **/
void completePlane(scene_t *scene, entity_t *ent)
{
sobj_t *sobj;
plane_t *plane;
assert(scene->magic == SCENE_T);
assert(ent->magic == ENTITY_T);
sobj = ent->entDerived;
assert(sobj->magic == SCENEOBJ_T);
plane = sobj->sobjDerived;
assert(plane->magic == PLANE_T);
plane->normal = unitize(cross(plane->orient1, plane->orient2));
completeSceneObj(scene, ent);
}
/** dumpPlane **/
void dumpPlane(FILE *outFP, entity_t *ent)
{
assert(ent->magic == ENTITY_T);
sobj_t *sobj = ent->entDerived;
assert(sobj->magic == SCENEOBJ_T);
plane_t *plane = sobj->sobjDerived;
assert(plane->magic == PLANE_T);
dumpSceneObj(outFP, ent);
printTuple(outFP, " point: ", plane->point);
printTuple(outFP, " normal: ", plane->normal);
}
int hitPlane(entity_t *ent, point_t base, vector_t dir, hitinfo_t *hit) {
assert(ent->magic == ENTITY_T);
sobj_t *sobj = ent->entDerived;
assert(sobj->magic == SCENEOBJ_T);
plane_t *planePtr = sobj->sobjDerived;
assert(planePtr->magic == PLANE_T);
point_t Q = planePtr->point; // Point data
vector_t N = planePtr->normal; // Normal data
vector_t D = dir; // Direction vector
point_t V = base; // Base coordinates
point_t H; // Hit point
double t; // Distance
if (dot(N, D) == 0)
return 0; // parallel
t = (dot(N, Q) - dot(N, V))/
dot(N, D);
if (t < 0)
return 0; // behind me
H = scale(D, t);
H = add(H, V);
if (H.z > 0) {
return 0; // between me & the screen
}
hit->hitpoint = H;
hit->normal = unitize(N);
hit->distance = t;
if (dot(D, hit->normal) > 0) { // adjust normal depending on which side the ray hit
hit->normal = scale(hit->normal, -1);
}
return 0;
}
#include "ray.h"
/** newSphere **/
entity_t *newSphere(char *enttype, int code)
{
entity_t *ent;
sphere_t *sphere;
vector_t zero = {0, 0, 0};
ent = newSceneObj(enttype, code);
sphere = malloc(sizeof(sphere_t));
assert(sphere != NULL);
((sobj_t *)(ent->entDerived))->sobjDerived = sphere; // create sphere
sphere->center = zero;
sphere->radius = 1;
sphere->magic = SPHERE_T; // set default values
return(ent);
}
/** loadSphere **/
void loadSphere(FILE *inFP, entity_t *ent)
{
char *attributes[] = {"center", "radius", NULL};
char attribute[25];
int ndx;
assert(ent->magic == ENTITY_T);
sobj_t *obj = ent->entDerived;
assert(obj->magic == SCENEOBJ_T);
sphere_t *sphere = obj->sobjDerived;
assert(sphere->magic == SPHERE_T);
loadSceneObj(inFP, ent);
fscanf(inFP, "%s", attribute);
while(attribute[0] != ';')
{
ndx = getindex(attribute, attributes);
switch (ndx)
{
case 0:
/** center **/
sphere->center = readTuple(inFP,
"Could not read sphere center coordinates");
break;
case 1:
/** radius **/
sphere->radius = readDouble(inFP, "Could not read sphere radius");
break;
default:
fprintf(stderr, "bad sphere attribute; exiting\n");
exit(1);
}
fscanf(inFP, "%s", attribute);
}
}
/** completeShere **/
void completeSphere(scene_t *scene, entity_t *ent) {
assert(scene->magic == SCENE_T);
assert(ent->magic == ENTITY_T);
completeSceneObj(scene, ent);
}
/** dumpSphere **/
void dumpSphere(FILE *out, entity_t *ent) {
assert(ent->magic == ENTITY_T);
sobj_t *obj = ent->entDerived;
assert(obj->magic == SCENEOBJ_T);
sphere_t *sphere = obj->sobjDerived;
assert(sphere->magic == SPHERE_T);
dumpSceneObj(out, ent);
printTuple(out, " center: ", sphere->center);
fprintf(out, " radius: %8.4lf\n",
sphere->radius);
}
/** hitSphere **/
int hitSphere(entity_t *ent, point_t base, vector_t dir, hitinfo_t *hit)
{
/** asserts **/
assert(ent->magic == ENTITY_T);
sobj_t * sobj = ent->entDerived;
assert(sobj->magic == SCENEOBJ_T);
sphere_t * sphere = sobj->sobjDerived;
assert(sphere->magic == SPHERE_T);
point_t V = base; //View/Starting point
vector_t D = dir; //Unit vector in direction of travel
point_t C = sphere->center; //Center of the sphere
double r = sphere->radius; //Radius of the sphere
point_t Cp = add(C, scale(C, (-1))); //Adjusted center of sphere (0,0,0)
point_t Vp = add(V, scale(C, (-1))); //Adjust viewpoint of sphere
double t;
if (length(Cp) != 0) fprintf(stderr, "Cp does not equal (0,0,0)\n");
//Quadratic formula to determine distance and if a hit occured
double a = dot(D, D);
double b = (dot(Vp, D) * 2.0);
double c = (dot(Vp, Vp) - pow(r, 2));
t = (pow(b, 2) - (4 * a * c)); //dscriminant
if (t <= 0) return 0; //miss
t = ((b*(-1) - pow(t, 1.0/2))/(2 * a)); //quadratic equation
if (t < 0) return 0; //behind us
hit->hitpoint = add(V, scale(D, t));
if (hit->hitpoint.z > 0) return 0;
hit->normal = add(hit->hitpoint, scale(C, (-1)));
hit->normal = unitize(hit->normal);
hit->distance = t;
return 1;
}
#include "ray.h"
/** render **/
/* The render() function invokes makePixel() to set the color of each
* pixel in the window
*
* input parameter:
* a pointer to the scene
* return value:
* none
*
* method/effect:
* the color of each pixel is set for each pixel in the window
*
* typical calling sequence:
* render(scene)
*
* local variables:
* picture - a pointer to the image
* currPix - a pointer to the current pixel beign painted.
* row - a lcv for processing each row (the height) of the image
* col - a lcv for processing each column (the width) of the image
*/
void render(scene_t *scene)
{
/* Get pointer to picture data */
assert(scene->magic == SCENE_T);
image_t *picture = scene->picture;
/* Work directly with an increasing pointer */
pixel_t *currPix = picture->image;
int row, col;
for(row = picture->rows - 1; row >= 0; row--) /* Bottom row of */
for(col = 0; col < picture->columns; col++) /* image is row 0 */
*currPix++ = makePixel(scene, col, row); /* Left column */
/* of image is */
/* column 0 */
} /* End render */
/** makePixel **/
pixel_t makePixel(scene_t *scene, int colndx, int rowndx)
{
intensity_t intensity;
vector_t dir;
window_t * windowPtr;
dir = genRay(scene, colndx, rowndx);
windowPtr = scene->window->entDerived;
intensity = rayTrace(scene, windowPtr->viewPoint, dir, 0.0, NULL);
if (intensity.x > 1.0) intensity.x = 1.0;
if (intensity.y > 1.0) intensity.y = 1.0;
if (intensity.z > 1.0) intensity.z = 1.0;
return((pixel_t){(255 * intensity.x),
(255 * intensity.y),
(255 * intensity.z)});
} /* End makePixel */
答案 0 :(得分:2)
Valgrind和GDB非常有用。
我之前使用的最前一个是GDB-我喜欢它,因为它向我显示了Segmentation Fault所在的确切行号。
以下是一些可以指导您使用GDB的资源:
如果你仍然无法弄清楚如何在这些教程中使用GDB,那么谷歌就有很多!只需使用GDB搜索调试分段错误!
祝你好运:)