Exemple #1
0
void ogl::mesh::cache_verts(const ogl::mesh *that, const mat4& M,
                                                   const mat4& I, int id)
{
    const size_t n = that->vv.size();

    // Cache that mesh's transformed vertices here.  Update bounding volume.

    vv.resize(n);
    nv.resize(n);
    tv.resize(n);
    uv.resize(n);

    bound = aabb();

    for (size_t i = 0; i < n; ++i)
    {
        transform_vertex(vv[i].v,           M,  that->vv[i].v);
        transform_normal(nv[i].v, transpose(I), that->nv[i].v);
        transform_normal(tv[i].v, transpose(I), that->tv[i].v);

        bound.merge(vec3(double(vv[i].v[0]),
                         double(vv[i].v[1]),
                         double(vv[i].v[2])));

        // Handy trick: Store the unit ID in the texture coordinate.

        uv[i].v[0] = that->uv[i].v[0];
        uv[i].v[1] = that->uv[i].v[1];
        uv[i].v[2] = GLfloat(id);
    }

    dirty_verts = true;
}
void RunFloat2Or3Tests(std::string const& typeName)
{
    RunCommonVectorTests<T>(typeName);

    RunPerfTest<T, T>(typeName + " reflect", [](T* value, T const& param)
    {
        *value = reflect(*value, param);
    });

    RunPerfTest<T, float4x4>(typeName + " transform_normal (float4x4)", [](T* value, float4x4 const& param)
    {
        *value = transform_normal(*value, param);
    });

    RunPerfTest<T, float4x4>(typeName + " transform4 (float4x4)", [](T* value, float4x4 const& param)
    {
        float4 t = transform4(*value, param);
        value->x = t.x + t.y + t.z + t.w;
    });

    RunPerfTest<T, quaternion>(typeName + " transform4 (quaternion)", [](T* value, quaternion const& param)
    {
        float4 t = transform4(*value, param);
        value->x = t.x + t.y + t.z + t.w;
    });
}
void RunFloat2Tests()
{
    RunFloat2Or3Tests<float2>("float2");

    RunPerfTest<float2, float3x2>("float2 transform (float3x2)", [](float2* value, float3x2 const& param)
    {
        *value = transform(*value, param);
    });

    RunPerfTest<float2, float3x2>("float2 transform_normal (float3x2)", [](float2* value, float3x2 const& param)
    {
        *value = transform_normal(*value, param);
    });
}
Exemple #4
0
// \en Calculates intersections. Stores intersection info to intersections and returns the number of intersections.\enden \ja 交点計算を行う。交点の情報はintersectionsに格納し、交点の数を返す。 \endja 
// \en The ray is defined as the starting point o and the normalized direction vector d as in o + td, 0.0 <= t.\enden \ja レイは始点位置ベクトルo、単位方向ベクトルdから成る、o + td, 0.0 <= t として指定される。 \endja 
int attribute_component::ray_intersection (const sxsdk::custom_element_info_base_class *info, sxsdk::shape_class &shape, const sxsdk::mat4 &lw, const sxsdk::mat4 &wl, int i, const sx::vec<float,3> &o, const sx::vec<float,3> &d, sxsdk::intersection_class intersections[], sxsdk::custom_element_info_base_class *per_thread, void *) {
	{	custom_element_info__class *info = dynamic_cast<custom_element_info__class *>(per_thread);
		if (info) {
			for (int i = 0; i < 100; i++) info->data[i] = i;
		}
	}
	int n = 0;
	sxsdk::sphere_class &sphere = shape.get_sphere();
	if (info) {

		// \en Fetch the data created in the new_custom_element_info function.\enden \ja new_custom_element_infoで作成したデータを取得する。 \endja 
		const float size = dynamic_cast<const custom_size_class &>(*info).size;

		sxsdk::mat4 t = sphere.get_matrix();
		for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) t[i][j] *= size;
		t *= lw;
		sxsdk::mat4 itrans = inv(t);
		sx::vec<float,3> p2 = o * itrans; // \en Transform the starting point of the ray to the sphere primitive coordinates.\enden \ja レイの始点位置ベクトルを球プリミティブ座標系に変換する。 \endja 
		sx::vec<float,3> d2 = transform_direction(d, itrans); // \en Transform the normalized direction vector of the ray to the sphere primitive coordinates.\enden \ja レイの単位方向ベクトルを球プリミティブ座標系に変換する。 \endja 
		
		// \en Calculate the intersections between the sphere and the ray.\enden \ja 球とレイの交点計算。 \endja 
		float a = d2.x * d2.x + d2.y * d2.y + d2.z * d2.z;
		float b = p2.x * d2.x + p2.y * d2.y + p2.z * d2.z;
		float c = p2.x * p2.x + p2.y * p2.y + p2.z * p2.z - 1.0f;
		float k = b*b - a*c;
		if (k <= 0.0f) ;
		else {
			k = sqrt(k);
			float t1 = (-b + k) / a;
			float t0 = (-b - k) / a;
			//sxassert(t0 <= t1);
			if (0.0f <= t0) {
				intersections[n].t = t0;
				sx::vec<float,3> normal = p2 + d2 * t0;
				intersections[n].normal = normalize(transform_normal(itrans, normal));
				intersections[n].point = o + d * t0;
				
				// \en Merge Info.\enden \ja 融合情報 \endja 
				if (shape.has_sis()) {
					intersections[n].number_of_shapes = 2;
					//sxassert(intersections[n].shape_mixes);
					intersections[n].shape_mixes[1] = sxsdk::shape_mix_class(0.5f, shape.get_sis());
					intersections[n].shape_mixes[0] = sxsdk::shape_mix_class(0.5f, &shape);
				}
				n++;
			}
			if (0.0f <= t1) {
				intersections[n].t = t1;
				sx::vec<float,3> normal = p2 + d2 * t1;
				intersections[n].normal = normalize(transform_normal(itrans, normal));
				intersections[n].point = o + d * t1;
				
				// \en Merge Info.\enden \ja 融合情報 \endja 
				if (shape.has_sis()) {
					intersections[n].number_of_shapes = 2;
					//sxassert(intersections[n].shape_mixes);
					intersections[n].shape_mixes[1] = sxsdk::shape_mix_class(0.5f, shape.get_sis());
					intersections[n].shape_mixes[0] = sxsdk::shape_mix_class(0.5f, &shape);
				}
				n++;
			}
		}
	}
	return n;
}
Exemple #5
0
// intersects the scene and return the first intrerseciton
intersection3f intersect(Scene* scene, ray3f ray) {
    // create a default intersection record to be returned
    auto intersection = intersection3f();
    // foreach surface
    for(auto surface : scene->surfaces) {
        // if it is a quad
        if(surface->isquad) {
            // compute ray intersection (and ray parameter), continue if not hit
            auto tray = transform_ray_inverse(surface->frame,ray);
            
            // intersect quad
            auto t = 0.0f; auto p = zero3f;
            auto hit = intersect_quad(tray, surface->radius, t, p);
            
            // skip if not hit
            if(not hit) continue;
            
            // check if this is the closest intersection, continue if not
            if(t > intersection.ray_t and intersection.hit) continue;
            
            // if hit, set intersection record values
            intersection.hit = true;
            intersection.ray_t = t;
            intersection.pos = transform_point(surface->frame,p);
            intersection.norm = transform_normal(surface->frame,z3f);
            intersection.texcoord = {0.5f*p.x/surface->radius+0.5f,0.5f*p.y/surface->radius+0.5f};
            intersection.mat = surface->mat;
        } else {
            // compute ray intersection (and ray parameter), continue if not hit
            auto tray = transform_ray_inverse(surface->frame,ray);
            
            // intersect sphere
            auto t = 0.0f;
            auto hit = intersect_sphere(tray, surface->radius, t);
            
            // skip if not hit
            if(not hit) continue;
            
            // check if this is the closest intersection, continue if not
            if(t > intersection.ray_t and intersection.hit) continue;
            
            // compute local point and normal
            auto p = tray.eval(t);
            auto n = normalize(p);
            
            // if hit, set intersection record values
            intersection.hit = true;
            intersection.ray_t = t;
            intersection.pos = transform_point(surface->frame,p);
            intersection.norm = transform_normal(surface->frame,n);
            intersection.texcoord = {(pif+(float)atan2(n.y, n.x))/(2*pif),(float)acos(n.z)/pif};
            intersection.mat = surface->mat;
        }
    }
    // foreach mesh
    for(auto mesh : scene->meshes) {
        // quads are not supported: check for error
        error_if_not(mesh->quad.empty(), "quad intersection is not supported");
        // tranform the ray
        auto tray = transform_ray_inverse(mesh->frame, ray);
        // save auto mesh intersection
        auto sintersection = intersection3f();
        // if it is accelerated
        if(mesh->bvh) {
            sintersection = intersect(mesh->bvh, 0, tray,
               [mesh](int tid, ray3f tray){
                   // grab triangle
                   auto triangle = mesh->triangle[tid];
                   
                   // grab vertices
                   auto v0 = mesh->pos[triangle.x];
                   auto v1 = mesh->pos[triangle.y];
                   auto v2 = mesh->pos[triangle.z];
                   
                   // intersect triangle
                   auto t = 0.0f, u = 0.0f, v = 0.0f;
                   auto hit = intersect_triangle(tray, v0, v1, v2, t, u, v);
                   
                   // skip if not hit
                   if(not hit) return intersection3f();
                   
                   // if hit, set up intersection, trasforming hit data to world space
                   auto sintersection = intersection3f();
                   sintersection.hit = true;
                   sintersection.ray_t = t;
                   sintersection.pos = tray.eval(t);
                   sintersection.norm = normalize(mesh->norm[triangle.x]*u+
                                                  mesh->norm[triangle.y]*v+
                                                  mesh->norm[triangle.z]*(1-u-v));
                   if(mesh->texcoord.empty()) sintersection.texcoord = zero2f;
                   else {
                       sintersection.texcoord = mesh->texcoord[triangle.x]*u+
                                                mesh->texcoord[triangle.y]*v+
                                                mesh->texcoord[triangle.z]*(1-u-v);
                   }
                   sintersection.mat = mesh->mat;
                   return sintersection;
               });
        } else {
            // clear intersection
            sintersection = intersection3f();
            // foreach triangle
            for(auto triangle : mesh->triangle) {
                // grab vertices
                auto v0 = mesh->pos[triangle.x];
                auto v1 = mesh->pos[triangle.y];
                auto v2 = mesh->pos[triangle.z];
                
                // intersect triangle
                auto t = 0.0f, u = 0.0f, v = 0.0f;
                auto hit = intersect_triangle(tray, v0, v1, v2, t, u, v);
                
                // skip if not hit
                if(not hit) continue;
                
                // check if closer then the found hit
                if(t > sintersection.ray_t and sintersection.hit) continue;
                
                // if hit, set up intersection, trasforming hit data to world space
                sintersection.hit = true;
                sintersection.ray_t = t;
                sintersection.pos = tray.eval(t);
                sintersection.norm = normalize(mesh->norm[triangle.x]*u+
                                               mesh->norm[triangle.y]*v+
                                               mesh->norm[triangle.z]*(1-u-v));
                if(mesh->texcoord.empty()) sintersection.texcoord = zero2f;
                else {
                    sintersection.texcoord = mesh->texcoord[triangle.x]*u+
                                             mesh->texcoord[triangle.y]*v+
                                             mesh->texcoord[triangle.z]*(1-u-v);
                }
                sintersection.mat = mesh->mat;
            }
        }
        // if did not hit the mesh, skip
        if(not sintersection.hit) continue;
        // check not first intersection, skip
        if(sintersection.ray_t > intersection.ray_t and intersection.hit) continue;
        // set interserction
        intersection = sintersection;
        // transform by mesh frame
        intersection.pos = transform_point(mesh->frame,sintersection.pos);
        intersection.norm = transform_normal(mesh->frame,sintersection.norm);
        // set material
        intersection.mat = sintersection.mat;
    }
    
    // record closest intersection
    return intersection;
}
Exemple #6
0
normal transform::inverse_transform(const normal &n) const
{
  // note we send the transform itself, not its inverse
  return transform_normal(m_xfrm, n);
} // end transform::inverse_transform()
Exemple #7
0
normal transform::operator()(const normal &n) const
{
  // note we send the inverse of the transform
  return transform_normal(m_inv, n);
} // end transform::operator()()