Exemple #1
0
static void mikk_get_normal(const SMikkTSpaceContext *context,
                            float N[3],
                            const int face_num,
                            const int vert_num)
{
  const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
  const Mesh *mesh = userdata->mesh;
  float3 vN;
  if (mesh->subd_faces.size()) {
    const Mesh::SubdFace &face = mesh->subd_faces[face_num];
    if (face.smooth) {
      const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
      vN = userdata->vertex_normal[vertex_index];
    }
    else {
      vN = face.normal(mesh);
    }
  }
  else {
    if (mesh->smooth[face_num]) {
      const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
      vN = userdata->vertex_normal[vertex_index];
    }
    else {
      const Mesh::Triangle tri = mesh->get_triangle(face_num);
      vN = tri.compute_normal(&mesh->verts[0]);
    }
  }
  N[0] = vN.x;
  N[1] = vN.y;
  N[2] = vN.z;
}
Exemple #2
0
void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
{
	Attribute *attr_mP = NULL;
	
	if(mesh->has_motion_blur())
		attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

	for(uint j = 0; j < mesh->triangles.size(); j++) {
		Mesh::Triangle t = mesh->triangles[j];
		BoundBox bounds = BoundBox::empty;
		PrimitiveType type = PRIMITIVE_TRIANGLE;

		t.bounds_grow(&mesh->verts[0], bounds);

		/* motion triangles */
		if(attr_mP) {
			size_t mesh_size = mesh->verts.size();
			size_t steps = mesh->motion_steps - 1;
			float3 *vert_steps = attr_mP->data_float3();

			for(size_t i = 0; i < steps; i++)
				t.bounds_grow(vert_steps + i*mesh_size, bounds);

			type = PRIMITIVE_MOTION_TRIANGLE;
		}

		if(bounds.valid()) {
			references.push_back(BVHReference(bounds, j, i, type));
			root.grow(bounds);
			center.grow(bounds.center2());
		}
	}

	Attribute *curve_attr_mP = NULL;

	if(mesh->has_motion_blur())
		curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

	for(uint j = 0; j < mesh->curves.size(); j++) {
		Mesh::Curve curve = mesh->curves[j];
		PrimitiveType type = PRIMITIVE_CURVE;

		for(int k = 0; k < curve.num_keys - 1; k++) {
			BoundBox bounds = BoundBox::empty;
			curve.bounds_grow(k, &mesh->curve_keys[0], bounds);

			/* motion curve */
			if(curve_attr_mP) {
				size_t mesh_size = mesh->curve_keys.size();
				size_t steps = mesh->motion_steps - 1;
				float4 *key_steps = curve_attr_mP->data_float4();

				for(size_t i = 0; i < steps; i++)
					curve.bounds_grow(k, key_steps + i*mesh_size, bounds);

				type = PRIMITIVE_MOTION_CURVE;
			}

			if(bounds.valid()) {
				int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
				
				references.push_back(BVHReference(bounds, j, i, packed_type));
				root.grow(bounds);
				center.grow(bounds.center2());
			}
		}
	}
}
Exemple #3
0
void BVH4::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
{
	if(leaf) {
		int4 *data = &pack.leaf_nodes[idx];
		int4 c = data[0];
		/* Refit leaf node. */
		for(int prim = c.x; prim < c.y; prim++) {
			int pidx = pack.prim_index[prim];
			int tob = pack.prim_object[prim];
			Object *ob = objects[tob];

			if(pidx == -1) {
				/* Object instance. */
				bbox.grow(ob->bounds);
			}
			else {
				/* Primitives. */
				const Mesh *mesh = ob->mesh;

				if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
					/* Curves. */
					int str_offset = (params.top_level)? mesh->curve_offset: 0;
					Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
					int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);

					curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);

					visibility |= PATH_RAY_CURVE;

					/* Motion curves. */
					if(mesh->use_motion_blur) {
						Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

						if(attr) {
							size_t mesh_size = mesh->curve_keys.size();
							size_t steps = mesh->motion_steps - 1;
							float3 *key_steps = attr->data_float3();

							for(size_t i = 0; i < steps; i++)
								curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox);
						}
					}
				}
				else {
					/* Triangles. */
					int tri_offset = (params.top_level)? mesh->tri_offset: 0;
					Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
					const float3 *vpos = &mesh->verts[0];

					triangle.bounds_grow(vpos, bbox);

					/* Motion triangles. */
					if(mesh->use_motion_blur) {
						Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

						if(attr) {
							size_t mesh_size = mesh->verts.size();
							size_t steps = mesh->motion_steps - 1;
							float3 *vert_steps = attr->data_float3();

							for(size_t i = 0; i < steps; i++)
								triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
						}
					}
				}
			}
			visibility |= ob->visibility_for_tracing();
		}
		/* TODO(sergey): This is actually a copy of pack_leaf(),
		 * but this chunk of code only knows actual data and has
		 * no idea about BVHNode.
		 *
		 * Would be nice to de-duplicate code, but trying to make
		 * making code more general ends up in much nastier code
		 * in my opinion so far.
		 *
		 * Same applies to the inner nodes case below.
		 */
		float4 leaf_data[BVH_QNODE_LEAF_SIZE];
		leaf_data[0].x = __int_as_float(c.x);
		leaf_data[0].y = __int_as_float(c.y);
		leaf_data[0].z = __uint_as_float(visibility);
		leaf_data[0].w = __uint_as_float(c.w);
		memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
	}
	else {
		int4 *data = &pack.nodes[idx];
		bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0;
		int4 c;
		if(is_unaligned) {
			c = data[13];
		}
		else {
			c = data[7];
		}
		/* Refit inner node, set bbox from children. */
		BoundBox child_bbox[4] = {BoundBox::empty,
		                          BoundBox::empty,
		                          BoundBox::empty,
		                          BoundBox::empty};
		uint child_visibility[4] = {0};
		int num_nodes = 0;

		for(int i = 0; i < 4; ++i) {
			if(c[i] != 0) {
				refit_node((c[i] < 0)? -c[i]-1: c[i], (c[i] < 0),
				           child_bbox[i], child_visibility[i]);
				++num_nodes;
				bbox.grow(child_bbox[i]);
				visibility |= child_visibility[i];
			}
		}

		if(is_unaligned) {
			Transform aligned_space[4] = {transform_identity(),
			                              transform_identity(),
			                              transform_identity(),
			                              transform_identity()};
			pack_unaligned_node(idx,
			                    aligned_space,
			                    child_bbox,
			                    &c[0],
			                    visibility,
			                    0.0f,
			                    1.0f,
			                    4);
		}
		else {
			pack_aligned_node(idx,
			                  child_bbox,
			                  &c[0],
			                  visibility,
			                  0.0f,
			                  1.0f,
			                  4);
		}
	}
}
Exemple #4
0
void BVH8::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
{
  if (leaf) {
    int4 *data = &pack.leaf_nodes[idx];
    int4 c = data[0];
    /* Refit leaf node. */
    for (int prim = c.x; prim < c.y; prim++) {
      int pidx = pack.prim_index[prim];
      int tob = pack.prim_object[prim];
      Object *ob = objects[tob];

      if (pidx == -1) {
        /* Object instance. */
        bbox.grow(ob->bounds);
      }
      else {
        /* Primitives. */
        const Mesh *mesh = ob->mesh;

        if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
          /* Curves. */
          int str_offset = (params.top_level) ? mesh->curve_offset : 0;
          Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
          int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);

          curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);

          visibility |= PATH_RAY_CURVE;

          /* Motion curves. */
          if (mesh->use_motion_blur) {
            Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

            if (attr) {
              size_t mesh_size = mesh->curve_keys.size();
              size_t steps = mesh->motion_steps - 1;
              float3 *key_steps = attr->data_float3();

              for (size_t i = 0; i < steps; i++) {
                curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox);
              }
            }
          }
        }
        else {
          /* Triangles. */
          int tri_offset = (params.top_level) ? mesh->tri_offset : 0;
          Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
          const float3 *vpos = &mesh->verts[0];

          triangle.bounds_grow(vpos, bbox);

          /* Motion triangles. */
          if (mesh->use_motion_blur) {
            Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

            if (attr) {
              size_t mesh_size = mesh->verts.size();
              size_t steps = mesh->motion_steps - 1;
              float3 *vert_steps = attr->data_float3();

              for (size_t i = 0; i < steps; i++) {
                triangle.bounds_grow(vert_steps + i * mesh_size, bbox);
              }
            }
          }
        }
      }

      visibility |= ob->visibility;
    }

    float4 leaf_data[BVH_ONODE_LEAF_SIZE];
    leaf_data[0].x = __int_as_float(c.x);
    leaf_data[0].y = __int_as_float(c.y);
    leaf_data[0].z = __uint_as_float(visibility);
    leaf_data[0].w = __uint_as_float(c.w);
    memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_ONODE_LEAF_SIZE);
  }
  else {
    float8 *data = (float8 *)&pack.nodes[idx];
    bool is_unaligned = (__float_as_uint(data[0].a) & PATH_RAY_NODE_UNALIGNED) != 0;
    /* Refit inner node, set bbox from children. */
    BoundBox child_bbox[8] = {BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty};
    int child[8];
    uint child_visibility[8] = {0};
    int num_nodes = 0;

    for (int i = 0; i < 8; ++i) {
      child[i] = __float_as_int(data[(is_unaligned) ? 13 : 7][i]);

      if (child[i] != 0) {
        refit_node((child[i] < 0) ? -child[i] - 1 : child[i],
                   (child[i] < 0),
                   child_bbox[i],
                   child_visibility[i]);
        ++num_nodes;
        bbox.grow(child_bbox[i]);
        visibility |= child_visibility[i];
      }
    }

    if (is_unaligned) {
      Transform aligned_space[8] = {transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity()};
      pack_unaligned_node(
          idx, aligned_space, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes);
    }
    else {
      pack_aligned_node(idx, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes);
    }
  }
}
void FindClosestTriangle:: find
(
  mesh::Triangle& triangle )
{
  typedef utils::GeometryComputations GeoComp;
  using utils::Vector2D; using utils::Vector3D;
  using namespace tarch::la;

  Vector3D barycentricCoords;
  Vector3D projected;

  // Methodology of book "Computational Geometry", Joseph O' Rourke, Chapter 7.3
  // with the barycentric coordinates method and real projection into 2D, instead
  // of outprojecting one coordinate

  // Parametric representation for triangle plane:
  // (x, y, z) * normal = d
  Vector3D a = triangle.vertex(0).getCoords();
  Vector3D normal = triangle.getNormal();
  double d = dot(normal, a);

  // Parametric description of line from searchpoint orthogonal to triangle:
  // _searchPoint + t * normal = x     (where t is parameter)
  // Determine t such that x lies on triangle plane:
  double t = d - dot(_searchPoint, normal) / dot(normal, normal);

  // Compute projected point with parameter t:
  projected = normal;
  projected *= t;
  projected += _searchPoint;

  // Project everything to 2D
  Vector3D normalAbs;
  int iMax = indexMax(abs(normal, normalAbs));
  int indices[2];
  if (iMax == 0){
    indices[0] = 1;
    indices[1] = 2;
  }
  else if (iMax == 1){
    indices[0] = 0;
    indices[1] = 2;
  }
  else {
    assertion1(iMax == 2, iMax);
    indices[0] = 0;
    indices[1] = 1;
  }
  Vector2D a2D(triangle.vertex(0).getCoords()[indices[0]],
               triangle.vertex(0).getCoords()[indices[1]]);
  Vector2D b2D(triangle.vertex(1).getCoords()[indices[0]],
               triangle.vertex(1).getCoords()[indices[1]]);
  Vector2D c2D(triangle.vertex(2).getCoords()[indices[0]],
               triangle.vertex(2).getCoords()[indices[1]]);
  Vector2D projected2D(projected[indices[0]], projected[indices[1]]);
  // Compute barycentric coordinates by solving linear 3x3 system
  Vector3D rhs (projected2D(0), projected2D(1), 1);
  Matrix<3,3,double> A;
  assignList(A) = a2D(0), b2D(0), c2D(0),
    a2D(1), b2D(1), c2D(1),
    1,      1,      1;
  solveSystem3x3(A, rhs, barycentricCoords);

  // Determine from barycentric coordinates, if point is inside triangle
  bool inside = true;
  for (int i=0; i < 3; i++){
    if (barycentricCoords(i) < - NUMERICAL_ZERO_DIFFERENCE){
      inside = false;
    }
  }

  // if inside, compute distance to triangle and evtl. store distance
  if (inside){
    Vector3D distanceVector = projected - _searchPoint;
    double distance = norm2(distanceVector);
    if (_shortestDistance > distance){
      _shortestDistance = distance;
      _vectorToProjectionPoint = distanceVector;
      _parametersProjectionPoint[0] = barycentricCoords(0);
      _parametersProjectionPoint[1] = barycentricCoords(1);
      _parametersProjectionPoint[2] = barycentricCoords(2);
      _closestTriangle = &triangle;
    }
  }
}
Exemple #6
0
void BVH::refit_primitives(int start, int end, BoundBox& bbox, uint& visibility)
{
	/* Refit range of primitives. */
	for(int prim = start; prim < end; prim++) {
		int pidx = pack.prim_index[prim];
		int tob = pack.prim_object[prim];
		Object *ob = objects[tob];

		if(pidx == -1) {
			/* Object instance. */
			bbox.grow(ob->bounds);
		}
		else {
			/* Primitives. */
			const Mesh *mesh = ob->mesh;

			if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
				/* Curves. */
				int str_offset = (params.top_level)? mesh->curve_offset: 0;
				Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
				int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);

				curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);

				visibility |= PATH_RAY_CURVE;

				/* Motion curves. */
				if(mesh->use_motion_blur) {
					Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

					if(attr) {
						size_t mesh_size = mesh->curve_keys.size();
						size_t steps = mesh->motion_steps - 1;
						float3 *key_steps = attr->data_float3();

						for(size_t i = 0; i < steps; i++)
							curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox);
					}
				}
			}
			else {
				/* Triangles. */
				int tri_offset = (params.top_level)? mesh->tri_offset: 0;
				Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
				const float3 *vpos = &mesh->verts[0];

				triangle.bounds_grow(vpos, bbox);

				/* Motion triangles. */
				if(mesh->use_motion_blur) {
					Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

					if(attr) {
						size_t mesh_size = mesh->verts.size();
						size_t steps = mesh->motion_steps - 1;
						float3 *vert_steps = attr->data_float3();

						for(size_t i = 0; i < steps; i++)
							triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
					}
				}
			}
		}
		visibility |= ob->visibility_for_tracing();
	}
}