コード例 #1
0
ファイル: R3Model.cpp プロジェクト: cricklet/Path-Tracer
static int
FindMaterialIndex(const RNArray<R3Material *>& materials, const char *name)
{
  // Return material with matching name
  for (int i = 0; i < materials.NEntries(); i++) {
    R3Material *material = materials.Kth(i);
    if (!strcmp(name, material->Name())) return i;
  }

  // No matching material found
  return -1;
}
コード例 #2
0
ファイル: R3Plane.cpp プロジェクト: DarkoBomer/Matterport
R3Plane::
R3Plane(const RNArray<R3Point *>& points, RNBoolean polygon_vertices)
{
    // Initialize plane
    v = R3null_vector;
    d = 0;

    // Check number of points
    int npoints = points.NEntries();
    if (npoints < 3) {
      *this = R3null_plane;
      return;
    }

    // Compute centroid
    R3Point c = R3Centroid(points);

    // Check if points form (counter-clockwise) boundary of polygon
    if (polygon_vertices) {
        // Compute best normal for counter-clockwise array of points using newell's method 
        const R3Point *p1 = points[npoints-1];
        for (int i = 0; i < npoints; i++) {
            const R3Point *p2 = points[i];
            v[0] += (p1->Y() - p2->Y()) * (p1->Z() + p2->Z());
            v[1] += (p1->Z() - p2->Z()) * (p1->X() + p2->X());
            v[2] += (p1->X() - p2->X()) * (p1->Y() + p2->Y());
            p1 = p2;
        }

        // Normalize 
        v.Normalize();
    }
    else {
        // Compute principle axes
        R3Triad triad = R3PrincipleAxes(c, points);

        // Select direction of least variation
        v = triad[2];
    }

    // Compute d from centroid and normal
    d = -(v[0]*c[0] + v[1]*c[1] + v[2]*c[2]);
}
コード例 #3
0
ファイル: kdtview.cpp プロジェクト: cricklet/Path-Tracer
void GLUTRedraw(void)
{
  // Set viewing transformation
  viewer->Camera().Load();

  // Clear window 
  glClearColor(200.0/255.0, 200.0/255.0, 200.0/255.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // Set lights
  static GLfloat light0_position[] = { 3.0, 4.0, 5.0, 0.0 };
  glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
  static GLfloat light1_position[] = { -3.0, -2.0, -3.0, 0.0 };
  glLightfv(GL_LIGHT1, GL_POSITION, light1_position);

  // Show all points
  if (show_points) {
    glEnable(GL_LIGHTING);
    static GLfloat material[4] = { 0, 0, 1, 1 };
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material); 
    for (int i = 0; i < all_points.NEntries(); i++) {
      TestPoint *point = all_points[i];
      R3Sphere(point->position, 0.01).Draw();
    }
  }
    
  // Show nearby points
  if (selected_point && !nearby_points.IsEmpty()) {
    glEnable(GL_LIGHTING);
    static GLfloat material[4] = { 1, 0, 0, 1 };
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material); 
    for (int i = 0; i < nearby_points.NEntries(); i++) {
      TestPoint *point = nearby_points.Kth(i);
      R3Sphere(point->position, 0.02).Draw();
    }
  }

  // Show closest point
  if (selected_point && closest_point) {
    glEnable(GL_LIGHTING);
    static GLfloat material[4] = { 0, 1, 0, 1 };
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material); 
    R3Sphere(closest_point->position, 0.03).Draw();
  }
    
  // Show selected point
  if (selected_point) {
    glEnable(GL_LIGHTING);
    static GLfloat material[4] = { 1, 1, 1, 1 };
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material); 
    R3Sphere(selected_point->position, 0.05).Draw();
  }
    
  // Show constraints
  if (0 && show_constraints) {
    glDisable(GL_LIGHTING);
    glColor3f(0.5, 0, 0);
    R3Sphere(selected_point->position, min_nearby_distance).Outline();
    R3Sphere(selected_point->position, max_nearby_distance).Outline();
  }
    
  // Show KD tree
  if (show_kdtree) {
    glDisable(GL_LIGHTING);
    glColor3f(0, 0, 0);
    kdtree->Outline();
  }
    
  // Swap buffers 
  glutSwapBuffers();
}    
コード例 #4
0
ファイル: kdtview.cpp プロジェクト: cricklet/Path-Tracer
void GLUTMouse(int button, int state, int x, int y)
{
  // Invert y coordinate
  y = GLUTwindow_height - y;
  
  // Process mouse button event
  if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN)) {
    // Check for double click
    static RNTime click_time;
    const RNScalar max_double_click_elapsed = 0.5;
    RNBoolean double_click = (click_time.Elapsed() < max_double_click_elapsed);
    click_time.Read();

    // Select closest point to cursor
    if (double_click) {
      selected_point = NULL;
      RNLength closest_distance = 10;
      R2Point cursor_position(x, y);
      for (int i = 0; i < all_points.NEntries(); i++) {
        TestPoint *point = all_points[i];
        const R3Point& world_position = point->position;
        R2Point screen_position = viewer->ViewportPoint(world_position);
        RNLength distance = R2Distance(screen_position, cursor_position);
        if (distance < closest_distance) {
          selected_point = point;
          closest_distance = distance;
        }
      }

      // Find closest points
      closest_point = NULL;
      nearby_points.Empty();
      if (selected_point) {
        if (max_nearby_points > 0) {
          kdtree->FindClosest(selected_point, min_nearby_distance, max_nearby_distance, max_nearby_points, nearby_points);
          closest_point = (nearby_points.NEntries() > 0) ? nearby_points.Head() : NULL;
          if (print_debug) printf("Found %d points\n", nearby_points.NEntries());
        }
        else {
          kdtree->FindAll(selected_point, min_nearby_distance, max_nearby_distance, nearby_points);
          closest_point = kdtree->FindClosest(selected_point);
          if (print_debug) printf("Found %d points\n", nearby_points.NEntries());
        }
      }
    }
  }

  // Remember button state 
  int b = (button == GLUT_LEFT_BUTTON) ? 0 : ((button == GLUT_MIDDLE_BUTTON) ? 1 : 2);
  GLUTbutton[b] = (state == GLUT_DOWN) ? 1 : 0;

  // Remember modifiers 
  GLUTmodifiers = glutGetModifiers();

  // Remember mouse position 
  GLUTmouse[0] = x;
  GLUTmouse[1] = y;

  // Redraw
  glutPostRedisplay();
}
コード例 #5
0
ファイル: R3Model.cpp プロジェクト: cricklet/Path-Tracer
int R3Model::
ReadObjFile(const char *filename)
{
  // Open file
  FILE *fp = fopen(filename, "r");
  if (!fp) {
    RNFail("Unable to open file %s", filename);
    return 0;
  }

  // Determine directory name (for texture image files)
  char dirname[1024];
  strncpy(dirname, filename, 1024);
  char *endp = strrchr(dirname, '/');
  if (!endp) endp = strrchr(dirname, '\\');
  if (!endp) strcpy(dirname, ".");
  else *endp = '\0';

  // Read body
  char buffer[1024];
  int line_count = 0;
  int material_index =-1;
  RNArray<R2Point *> texture_coords;
  RNArray<R3TriangleVertex *> verts;
  RNArray<R3Triangle *> tris;
  while (fgets(buffer, 1023, fp)) {
    // Increment line counter
    line_count++;

    // Skip white space
    char *bufferp = buffer;
    while (isspace(*bufferp)) bufferp++;

    // Skip blank lines and comments
    if (*bufferp == '#') continue;
    if (*bufferp == '\0') continue;

    // Get keyword
    char keyword[80];
    if (sscanf(bufferp, "%s", keyword) != 1) {
      RNFail("Syntax error on line %d in file %s", line_count, filename);
      return 0;
    }

    // Check keyword
    if (!strcmp(keyword, "v")) {
      // Read vertex coordinates
      double x, y, z;
      if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &x, &y, &z) != 4) {
        RNFail("Syntax error on line %d in file %s", line_count, filename);
        return 0;
      }

      // Create vertex
      R3TriangleVertex *vertex = new R3TriangleVertex(R3Point(x, y, z));
      verts.Insert(vertex);
    }
    else if (!strcmp(keyword, "vt")) {
      // Read texture coordinates
      double u, v;
      if (sscanf(bufferp, "%s%lf%lf", keyword, &u, &v) != 3) {
        RNFail("Syntax error on line %d in file %s", line_count, filename);
        return 0;
      }

      // Create texture coordinates
      R2Point *vt = new R2Point(u, v);
      texture_coords.Insert(vt);
    }
    else if (!strcmp(keyword, "f")) {
      // Read vertex indices
      int quad = 1;
      char s1[128], s2[128], s3[128], s4[128] = { '\0' };
      if (sscanf(bufferp, "%s%s%s%s%s", keyword, s1, s2, s3, s4) != 5) {
        quad = 0;;
        if (sscanf(bufferp, "%s%s%s%s", keyword, s1, s2, s3) != 4) {
          RNFail("Syntax error on line %d in file %s", line_count, filename);
          return 0;
        }
      }

      // Parse vertex indices
      int vi1 = -1, vi2 = -1, vi3 = -1, vi4 = -1;
      int ti1 = -1, ti2 = -1, ti3 = -1, ti4 = -1;
      char *p1 = strchr(s1, '/'); 
      if (p1) { *p1 = 0; vi1 = atoi(s1); p1++; if (*p1) ti1 = atoi(p1); }
      else { vi1 = atoi(s1); ti1 = vi1; }
      char *p2 = strchr(s2, '/'); 
      if (p2) { *p2 = 0; vi2 = atoi(s2); p2++; if (*p2) ti2 = atoi(p2); }
      else { vi2 = atoi(s2); ti2 = vi2; }
      char *p3 = strchr(s3, '/'); 
      if (p3) { *p3 = 0; vi3 = atoi(s3); p3++; if (*p3) ti3 = atoi(p3); }
      else { vi3 = atoi(s3); ti3 = vi3; }
      if (quad) {
        char *p4 = strchr(s4, '/'); 
        if (p4) { *p4 = 0; vi4 = atoi(s4); p4++; if (*p4) ti4 = atoi(p4); }
        else { vi4 = atoi(s4); ti4 = vi4; }
      }

      // Get vertices
      R3TriangleVertex *v1 = verts.Kth(vi1-1);
      R3TriangleVertex *v2 = verts.Kth(vi2-1);
      R3TriangleVertex *v3 = verts.Kth(vi3-1);
      R3TriangleVertex *v4 = (quad) ? verts.Kth(vi4-1) : NULL;
      
      // Assign texture coordinates
      if ((ti1 >= 0) && (ti1 < texture_coords.NEntries())) v1->SetTextureCoords(*(texture_coords.Kth(ti1-1)));
      if ((ti2 >= 0) && (ti2 < texture_coords.NEntries())) v2->SetTextureCoords(*(texture_coords.Kth(ti2-1)));
      if ((ti3 >= 0) && (ti3 < texture_coords.NEntries())) v3->SetTextureCoords(*(texture_coords.Kth(ti3-1)));
      if (quad) {
        if ((ti4 >= 0) && (ti4 < texture_coords.NEntries())) v4->SetTextureCoords(*(texture_coords.Kth(ti4-1)));
      }

      // Check vertices
      if ((v1 == v2) || (v2 == v3) || (v1 == v3)) continue;
      if ((quad) && ((v4 == v1) || (v4 == v2) || (v4 == v3))) quad = 0;

      // Create default material, if needed
      if (material_index == -1) {
        R3Brdf *brdf = new R3Brdf(RNRgb(0.2, 0.2, 0.2), RNRgb(0.8, 0.8, 0.8), 
          RNRgb(0.0, 0.0, 0.0), RNRgb(0.0, 0.0, 0.0), 0.2, 1.0, 1.0);
        R3Material *material = new R3Material(brdf, "Default");
        materials.Insert(material);
        RNArray<R3Triangle *> *mat_tris = new RNArray<R3Triangle *>();
        material_triangles.Insert(mat_tris);
        material_index = 0;
      }

      // Get material
      assert(material_index >= 0);
      R3Material *material = materials.Kth(material_index);

      // Create first triangle
      R3Triangle *triangle = new R3Triangle(v1, v2, v3);
      tris.Insert(triangle);
      triangle_materials.Insert(material);
      material_triangles[material_index]->Insert(triangle);

      // Create second triangle
      if (quad) {
        R3Triangle *triangle = new R3Triangle(v1, v3, v4);
        tris.Insert(triangle);
        triangle_materials.Insert(material);
        material_triangles[material_index]->Insert(triangle);
      }
    }
    else if (!strcmp(keyword, "mtllib")) {
      // Read fields
      char mtlname[1024];
      if (sscanf(bufferp, "%s%s", keyword, mtlname) != 2) {
        RNFail("Syntax error on line %d in file %s", line_count, filename);
        return 0;
      }

      // Read materials
      if (!ReadObjMtlFile(dirname, mtlname)) return 0;
    }
    else if (!strcmp(keyword, "usemtl")) {
      // Read fields
      char mtlname[1024];
      if (sscanf(bufferp, "%s%s", keyword, mtlname) != 2) {
        RNFail("Syntax error on line %d in file %s", line_count, filename);
        return 0;
      }

      // Find material
      material_index = FindMaterialIndex(materials, mtlname);
      if (material_index == -1) {
        fprintf(stderr, "Unable to find material %s at on line %d in file %s", mtlname, line_count, filename);
        return 0;
      }
    }
  }

  // Create triangle array
  triangles = new R3TriangleArray(verts, tris);

  // Delete texture coordinates
  for (int i = 0; i < texture_coords.NEntries(); i++) {
    R2Point *vt = texture_coords.Kth(i);
    delete vt;
  }

  // Close file
  fclose(fp);

  // Return success
  return 1;
}
コード例 #6
0
ファイル: R3MeshSearchTree.cpp プロジェクト: kyzyx/empty-room
void R3MeshSearchTree::
FindAll(const R3Point& query_position, const R3Vector& query_normal, RNArray<R3MeshIntersection *>& hits,
  RNScalar min_distance_squared, RNScalar max_distance_squared,
  int (*IsCompatible)(const R3Point&, const R3Vector&, R3Mesh *, R3MeshFace *, void *), void *compatible_data,
  R3MeshFace *face) const
{
  // Check distance to plane
  const R3Plane& plane = mesh->FacePlane(face);
  RNScalar plane_signed_distance = R3SignedDistance(plane, query_position);
  RNScalar plane_distance_squared = plane_signed_distance * plane_signed_distance;
  if (plane_distance_squared >= max_distance_squared) return;

  // Check distance to bounding box
  RNScalar bbox_distance_squared = DistanceSquared(query_position, mesh->FaceBBox(face), max_distance_squared);
  if (bbox_distance_squared >= max_distance_squared) return;

  // Check compatibility
  if (IsCompatible) {
    if (!(*IsCompatible)(query_position, query_normal, mesh, face, compatible_data)) return;
  }

  // Get face vertices
  R3MeshVertex *v0 = mesh->VertexOnFace(face, 0);
  R3MeshVertex *v1 = mesh->VertexOnFace(face, 1);
  R3MeshVertex *v2 = mesh->VertexOnFace(face, 2);

  // Get vertex positions
  const R3Point& p0 = mesh->VertexPosition(v0);
  const R3Point& p1 = mesh->VertexPosition(v1);
  const R3Point& p2 = mesh->VertexPosition(v2);

  // Project query point onto face plane
  const R3Vector& face_normal = mesh->FaceNormal(face);
  R3Point plane_point = query_position - plane_signed_distance * face_normal;

  // Check sides of edges
  R3Vector e0 = p1 - p0;
  e0.Normalize();
  R3Vector n0 = mesh->FaceNormal(face) % e0;
  R3Plane s0(p0, n0);
  RNScalar b0 = R3SignedDistance(s0, plane_point);
  R3Vector e1 = p2 - p1;
  e1.Normalize();
  R3Vector n1 = mesh->FaceNormal(face) % e1;
  R3Plane s1(p1, n1);
  RNScalar b1 = R3SignedDistance(s1, plane_point);
  R3Vector e2 = p0 - p2;
  e2.Normalize();
  R3Vector n2 = mesh->FaceNormal(face) % e2;
  R3Plane s2(p2, n2);
  RNScalar b2 = R3SignedDistance(s2, plane_point);

  // Initialize hit info
  R3MeshIntersection hit;
  hit.type = R3_MESH_NULL_TYPE;

  // Consider plane_point's position in relation to edges of the triangle
  if ((b0 >= 0) && (b1 >= 0) && (b2 >= 0)) {
    // Point is inside face
    if (plane_distance_squared >= min_distance_squared) {
      hit.type = R3_MESH_FACE_TYPE;
      hit.vertex = NULL;
      hit.edge = NULL;
      hit.face = face;
      hit.point = plane_point;
      hit.t = sqrt(plane_distance_squared);
    }
  }
  else {
    // Point is outside face -- check each edge
    if (b0 < 0) {
      // Outside edge0
      R3Vector edge_vector = p1 - p0;
      RNScalar edge_length = edge_vector.Length();
      if (edge_length > 0) {
        edge_vector /= edge_length;
        R3Vector point_vector = plane_point - p0;
        RNScalar t = edge_vector.Dot(point_vector);
        if (t <= 0) {
          RNScalar distance_squared = DistanceSquared(query_position, p0);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v0;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p0;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else if (t >= edge_length) {
          RNScalar distance_squared = DistanceSquared(query_position, p1);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v1;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p1;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else {
          R3Point point = p0 + t * edge_vector;
          RNScalar distance_squared = DistanceSquared(query_position, point);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_EDGE_TYPE;
            hit.vertex = NULL;
            hit.edge = mesh->EdgeOnFace(face, 0);
            hit.face = face;
            hit.point = point;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
      }
    }
    if (b1 < 0) {
      // Outside edge1
      R3Vector edge_vector = p2 - p1;
      RNScalar edge_length = edge_vector.Length();
      if (edge_length > 0) {
        edge_vector /= edge_length;
        R3Vector point_vector = plane_point - p1;
        RNScalar t = edge_vector.Dot(point_vector);
        if (t <= 0) {
          RNScalar distance_squared = DistanceSquared(query_position, p1);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v1;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p1;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else if (t >= edge_length) {
          RNScalar distance_squared = DistanceSquared(query_position, p2);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v2;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p2;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else {
          R3Point point = p1 + t * edge_vector;
          RNScalar distance_squared = DistanceSquared(query_position, point);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_EDGE_TYPE;
            hit.vertex = NULL;
            hit.edge = mesh->EdgeOnFace(face, 1);
            hit.face = face;
            hit.point = point;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
      }
    }
    if (b2 < 0) {
      // Outside edge2
      R3Vector edge_vector = p0 - p2;
      RNScalar edge_length = edge_vector.Length();
      if (edge_length > 0) {
        edge_vector /= edge_length;
        R3Vector point_vector = plane_point - p2;
        RNScalar t = edge_vector.Dot(point_vector);
        if (t <= 0) {
          RNScalar distance_squared = DistanceSquared(query_position, p2);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v2;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p2;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else if (t >= edge_length) {
          RNScalar distance_squared = DistanceSquared(query_position, p0);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v0;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p0;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else {
          R3Point point = p2 + t * edge_vector;
          RNScalar distance_squared = DistanceSquared(query_position, point);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_EDGE_TYPE;
            hit.vertex = NULL;
            hit.edge = mesh->EdgeOnFace(face, 2);
            hit.face = face;
            hit.point = point;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
      }
    }
  }

  // Insert hit
  if (hit.type != R3_MESH_NULL_TYPE) {
    hits.Insert(new R3MeshIntersection(hit));
  }
}