Ejemplo n.º 1
0
void
__glcore_transform_vertices (GLcontext *g)
{
    GLrenderstate *r = g->renderstate;
    GL_vertex *verts = r->verts;
    GL_procvert *procverts = r->procverts;
    int i;

    GL_float modelview[4][4];
    GL_float projection[4][4];
    GL_float texture[4][4];
    GL_float composite[4][4];
    GL_float invmodelview[4][4];

    minit(modelview, g->trans.modelview[g->trans.modelviewdepth]);
    minit(projection, g->trans.projection[g->trans.projectiondepth]);
    minit(texture, g->trans.texture[g->trans.texturedepth]);    
    mmult(composite, projection, modelview);
    minvtrans(invmodelview, modelview);

    for (i = 0; i < r->nverts; i++) {
	/* position */
	mmultv(procverts[i].position, composite, verts[i].position);

	/* eye position */
	mmultv(procverts[i].eyeposition, modelview, verts[i].position);

	/* color */
	if (g->lighting.lighting) {
	    GL_float objnormal[4];
	    GL_float normal[4];

	    /* object space normal */
	    vcopy(objnormal, verts[i].normal);
	    objnormal[3] = 0.0f;
	    if (verts[i].position[3] != 0.0f) {
		objnormal[3] = -vdot3(objnormal, verts[i].position);
		objnormal[3] /= verts[i].position[3];
	    }

	    /* eye space normal */
	    mmultv(normal, invmodelview, objnormal);
	    if (g->current.normalize)
		vnorm3(normal, normal);

	    /* front color */
	    compute_lighting(g, procverts[i].frontcolor,
			     procverts[i].eyeposition, normal,
			     &verts[i].frontmaterial);

	    /* back color */
	    if (g->lighting.lightmodeltwoside) {
		vscale(normal, normal, -1.0f);
		compute_lighting(g, procverts[i].backcolor,
				 procverts[i].eyeposition, normal,
				 &verts[i].backmaterial);
	    }
	}
	else {
	    vcopy(procverts[i].frontcolor, verts[i].color);
	    vcopy(procverts[i].backcolor, verts[i].color);
	}
	vclamp(procverts[i].frontcolor, procverts[i].frontcolor, 0.0f, 1.0f);
	vclamp(procverts[i].backcolor, procverts[i].backcolor, 0.0f, 1.0f);

	/* no texture coordinate generation */

	/* texture coords */
	mmultv(procverts[i].texcoord, texture, verts[i].texcoord);
    }
}
color scene_3D::cast_ray(line_3D line, double threshold, unsigned int recursion_depth)
  {
    unsigned int k, l, m;
    triangle_3D triangle;
    color final_color, helper_color, add_color;
    double depth, t;
    double *texture_coords_a, *texture_coords_b, *texture_coords_c;
    double barycentric_a, barycentric_b, barycentric_c;
    point_3D starting_point;
    point_3D normal,normal_a,normal_b,normal_c;
    point_3D reflection_vector, incoming_vector_reverse;
    material mat;
    int color_sum[3];

    line.get_point(0,starting_point);

    depth = 99999999;

    final_color.red = this->background_color.red;
    final_color.green = this->background_color.green;
    final_color.blue = this->background_color.blue;

    for (k = 0; k < this->meshes.size(); k++)
      {
        if (!line.intersects_sphere(this->meshes[k]->bounding_sphere_center,this->meshes[k]->bounding_sphere_radius))
          continue;

        for (l = 0; l < this->meshes[k]->triangle_indices.size(); l += 3)
          {
            triangle.a = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l]].position;
            triangle.b = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l + 1]].position;
            triangle.c = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l + 2]].position;

            texture_coords_a = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l]].texture_coords;
            texture_coords_b = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l + 1]].texture_coords;
            texture_coords_c = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l + 2]].texture_coords;

            if (line.intersects_triangle(triangle,barycentric_a,barycentric_b,barycentric_c,t))
              {
                point_3D intersection;
                line.get_point(t,intersection);
                double distance = point_distance(starting_point,intersection);

                mat = this->meshes[k]->get_material();

                if (distance < depth && distance > threshold)  // depth test
                  {
                    depth = distance;

                    normal_a = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l]].normal;
                    normal_b = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l + 1]].normal;
                    normal_c = this->meshes[k]->vertices[this->meshes[k]->triangle_indices[l + 2]].normal;

                    normal.x = 0;
                    normal.y = 0;
                    normal.z = 0;

                    normal.x = barycentric_a * normal_a.x + barycentric_b * normal_b.x + barycentric_c * normal_c.x;
                    normal.y = barycentric_a * normal_a.y + barycentric_b * normal_b.y + barycentric_c * normal_c.y;
                    normal.z = barycentric_a * normal_a.z + barycentric_b * normal_b.z + barycentric_c * normal_c.z;
                    normalize(normal);  // interpolation breaks normalization

                    if (!this->meshes[k]->use_3D_texture && this->meshes[k]->get_texture() != 0)        // 2d texture
                      {
                        double u,v;

                        u = barycentric_a * texture_coords_a[0] + barycentric_b * texture_coords_b[0] + barycentric_c * texture_coords_c[0];
                        v = barycentric_a * texture_coords_a[1] + barycentric_b * texture_coords_b[1] + barycentric_c * texture_coords_c[1];

                        color_buffer_get_pixel(this->meshes[k]->get_texture(),u * this->meshes[k]->get_texture()->width,v * this->meshes[k]->get_texture()->height,&final_color.red,&final_color.green,&final_color.blue);
                      }
                    else if (this->meshes[k]->use_3D_texture && this->meshes[k]->get_texture_3D() != 0) // 3d texture
                      {
                        final_color = this->meshes[k]->get_texture_3D()->get_color(intersection.x,intersection.y,intersection.z);
                      }
                    else                                                                                // mesh color
                      {
                        final_color.red = 255;
                        final_color.green = 255;
                        final_color.blue = 255;
                      }

                    helper_color = compute_lighting(intersection,mat,normal);
                    final_color = multiply_colors(helper_color,final_color);

                    if (recursion_depth != 0)
                      {
                        incoming_vector_reverse = line.get_vector_to_origin();

                        if (mat.reflection > 0)                         // reflection
                          {
                            color_sum[0] = 0;
                            color_sum[1] = 0;
                            color_sum[2] = 0;

                            for (m = 0; m < this->reflection_rays; m++)
                              {
                                point_3D helper_point;
                                reflection_vector = make_reflection_vector(normal,incoming_vector_reverse);

                                reflection_vector.x *= -1;
                                reflection_vector.y *= -1;
                                reflection_vector.z *= -1;

                                if (m > 0) // alter the ray slightly
                                  alter_vector(reflection_vector,this->reflection_range);

                                helper_point.x = intersection.x + reflection_vector.x;
                                helper_point.y = intersection.y + reflection_vector.y;
                                helper_point.z = intersection.z + reflection_vector.z;

                                line_3D reflection_line(intersection,helper_point);

                                add_color = cast_ray(reflection_line,ERROR_OFFSET,recursion_depth - 1);

                                color_sum[0] += add_color.red;
                                color_sum[1] += add_color.green;
                                color_sum[2] += add_color.blue;
                              }

                            add_color.red = color_sum[0] / this->reflection_rays;
                            add_color.green = color_sum[1] / this->reflection_rays;
                            add_color.blue = color_sum[2] / this->reflection_rays;

                            final_color = interpolate_colors(final_color,add_color,mat.reflection);
                          }

                        if (mat.transparency > 0)                       // refraction
                          {
                            color_sum[0] = 0;
                            color_sum[1] = 0;
                            color_sum[2] = 0;

                            for (m = 0; m < this->refraction_rays; m++)
                              {
                                point_3D helper_point;
                                point_3D refraction_vector;
                                refraction_vector = make_refraction_vector(normal,incoming_vector_reverse,mat.refractive_index);

                                if (m > 0) // alter the ray slightly
                                  alter_vector(refraction_vector,this->refraction_range);

                                helper_point.x = intersection.x + refraction_vector.x;
                                helper_point.y = intersection.y + refraction_vector.y;
                                helper_point.z = intersection.z + refraction_vector.z;

                                line_3D refraction_line(intersection,helper_point);
                                add_color = cast_ray(refraction_line,ERROR_OFFSET,recursion_depth - 1);

                                color_sum[0] += add_color.red;
                                color_sum[1] += add_color.green;
                                color_sum[2] += add_color.blue;
                              }

                            add_color.red = color_sum[0] / this->refraction_rays;
                            add_color.green = color_sum[1] / this->refraction_rays;
                            add_color.blue = color_sum[2] / this->refraction_rays;

                            final_color = interpolate_colors(final_color,add_color,mat.transparency);
                          }
                      }
                  }
                }
              }
            }

    return final_color;
  }