Exemple #1
0
bool Ray::InsideGeometry(const void* vertexData, unsigned vertexSize, unsigned vertexStart, unsigned vertexCount) const
{
    float currentFrontFace = M_INFINITY;
    float currentBackFace = M_INFINITY;
    const unsigned char* vertices = ((const unsigned char*)vertexData) + vertexStart * vertexSize;
    unsigned index = 0;
    
    while (index + 2 < vertexCount)
    {
        const Vector3& v0 = *((const Vector3*)(&vertices[index * vertexSize]));
        const Vector3& v1 = *((const Vector3*)(&vertices[(index + 1) * vertexSize]));
        const Vector3& v2 = *((const Vector3*)(&vertices[(index + 2) * vertexSize]));
        float frontFaceDistance = HitDistance(v0, v1, v2);
        float backFaceDistance = HitDistance(v2, v1, v0);
        currentFrontFace = Min(frontFaceDistance > 0.0f ? frontFaceDistance : M_INFINITY, currentFrontFace);
        // A backwards face is just a regular one, with the vertices in the opposite order. This essentially checks backfaces by
        // checking reversed frontfaces
        currentBackFace = Min(backFaceDistance > 0.0f ? backFaceDistance : M_INFINITY, currentBackFace);
        index += 3;
    }
    
    // If the closest face is a backface, that means that the ray originates from the inside of the geometry
    // NOTE: there may be cases where both are equal, as in, no collision to either. This is prevented in the most likely case
    // (ray doesnt hit either) by this conditional
    if (currentFrontFace != M_INFINITY || currentBackFace != M_INFINITY)
        return currentBackFace < currentFrontFace;
    
    // It is still possible for two triangles to be equally distant from the triangle, however, this is extremely unlikely.
    // As such, it is safe to assume they are not
    return false;
}
Exemple #2
0
bool ORay::InsideGeometry(const void* vertexData, unsigned vertexSize, const void* indexData, unsigned indexSize,
						 unsigned indexStart, unsigned indexCount) const
{
	float currentFrontFace = INFINITY;
	float currentBackFace = INFINITY;
	const unsigned char* vertices = (const unsigned char*)vertexData;

	// 16-bit indices
	if (indexSize == sizeof(unsigned short))
	{
		const unsigned short* indices = ((const unsigned short*)indexData) + indexStart;
		const unsigned short* indicesEnd = indices + indexCount;

		while (indices < indicesEnd)
		{
			const OVector3& v0 = *((const OVector3*)(&vertices[indices[0] * vertexSize]));
			const OVector3& v1 = *((const OVector3*)(&vertices[indices[1] * vertexSize]));
			const OVector3& v2 = *((const OVector3*)(&vertices[indices[2] * vertexSize]));
			float frontFaceDistance = HitDistance(v0, v1, v2);
			float backFaceDistance = HitDistance(v2, v1, v0);
			currentFrontFace = OMin2<float32>(frontFaceDistance > 0.0f ? frontFaceDistance : INFINITY, currentFrontFace);
			// A backwards face is just a regular one, with the vertices in the opposite order. This essentially checks backfaces by
			// checking reversed frontfaces
			currentBackFace = OMin2<float32>(backFaceDistance > 0.0f ? backFaceDistance : INFINITY, currentBackFace);
			indices += 3;
		}
	}
	// 32-bit indices
	else
	{
		const unsigned* indices = ((const unsigned*)indexData) + indexStart;
		const unsigned* indicesEnd = indices + indexCount;

		while (indices < indicesEnd)
		{
			const OVector3& v0 = *((const OVector3*)(&vertices[indices[0] * vertexSize]));
			const OVector3& v1 = *((const OVector3*)(&vertices[indices[1] * vertexSize]));
			const OVector3& v2 = *((const OVector3*)(&vertices[indices[2] * vertexSize]));
			float32 frontFaceDistance = HitDistance(v0, v1, v2);
			float32 backFaceDistance = HitDistance(v2, v1, v0);
			currentFrontFace = OMin2<float32>(frontFaceDistance > 0.0f ? frontFaceDistance : INFINITY, currentFrontFace);
			// A backwards face is just a regular one, with the vertices in the opposite order. This essentially checks backfaces by
			// checking reversed frontfaces
			currentBackFace = OMin2<float32>(backFaceDistance > 0.0f ? backFaceDistance : INFINITY, currentBackFace);
			indices += 3; 
		}
	}

	// If the closest face is a backface, that means that the ORay originates from the inside of the geometry
	// NOTE: there may be cases where both are equal, as in, no collision to either. This is prevented in the most likely case
	// (ORay doesnt hit either) by this conditional
	if (currentFrontFace != INFINITY || currentBackFace != INFINITY)
		return currentBackFace < currentFrontFace;

	// It is still possible for two triangles to be equally distant from the triangle, however, this is extremely unlikely.
	// As such, it is safe to assume they are not
	return false;
}
Exemple #3
0
float Ray::HitDistance(const Frustum& frustum, bool solidInside) const
{
    float maxOutside = 0.0f;
    float minInside = M_INFINITY;
    bool allInside = true;
    
    for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
    {
        const Plane& plane = frustum.planes_[i];
        float distance = HitDistance(frustum.planes_[i]);
        
        if (plane.Distance(origin_) < 0.0f)
        {
            maxOutside = Max(maxOutside, distance);
            allInside = false;
        }
        else
            minInside = Min(minInside, distance);
    }
    
    if (allInside)
        return solidInside ? 0.0f : minInside;
    else if (maxOutside <= minInside)
        return maxOutside;
    else
        return M_INFINITY;
}
Exemple #4
0
float ORay::HitDistance(const OFrustum& frustum, bool solidInside) const
{
	float maxOutside = 0.0f;
	float minInside = INFINITY;
	bool allInside = true;

	for (unsigned i = 0; i < ONLY_FRUSTUM_PLANES_NUM; ++i)
	{
		const OPlane& plane = frustum.planes[i];
		float distance = HitDistance(frustum.planes[i]);

		if (plane.Distance(m_origin) < 0.0f)
		{
			maxOutside = OMax2<float32>(maxOutside, distance);
			allInside = false;
		}
		else
			minInside = OMin2<float32>(minInside, distance);
	}

	if (allInside)
		return solidInside ? 0.0f : minInside;
	else if (maxOutside <= minInside)
		return maxOutside;
	else
		return INFINITY;
}
Exemple #5
0
float Ray::HitDistance(const Frustum& frustum, bool solidInside) const
{
    float maxOutside = 0.0f;
    float minInside = M_INFINITY;
    bool allInside = true;

    for (const auto& plane : frustum.planes_)
    {
        float distance = HitDistance(plane);

        if (plane.Distance(origin_) < 0.0f)
        {
            maxOutside = Max(maxOutside, distance);
            allInside = false;
        }
        else
            minInside = Min(minInside, distance);
    }

    if (allInside)
        return solidInside ? 0.0f : minInside;
    else if (maxOutside <= minInside)
        return maxOutside;
    else
        return M_INFINITY;
}
Exemple #6
0
float Ray::HitDistance(const void* vertexData, unsigned vertexSize, const void* indexData, unsigned indexSize,
    unsigned indexStart, unsigned indexCount, Vector3* outNormal) const
{
    float nearest = M_INFINITY;
    const unsigned char* vertices = (const unsigned char*)vertexData;
    
    // 16-bit indices
    if (indexSize == sizeof(unsigned short))
    {
        const unsigned short* indices = ((const unsigned short*)indexData) + indexStart;
        const unsigned short* indicesEnd = indices + indexCount;
        
        while (indices < indicesEnd)
        {
            const Vector3& v0 = *((const Vector3*)(&vertices[indices[0] * vertexSize]));
            const Vector3& v1 = *((const Vector3*)(&vertices[indices[1] * vertexSize]));
            const Vector3& v2 = *((const Vector3*)(&vertices[indices[2] * vertexSize]));
            nearest = Min(nearest, HitDistance(v0, v1, v2, outNormal));
            indices += 3;
        }
    }
    // 32-bit indices
    else
    {
        const unsigned* indices = ((const unsigned*)indexData) + indexStart;
        const unsigned* indicesEnd = indices + indexCount;
        
        while (indices < indicesEnd)
        {
            const Vector3& v0 = *((const Vector3*)(&vertices[indices[0] * vertexSize]));
            const Vector3& v1 = *((const Vector3*)(&vertices[indices[1] * vertexSize]));
            const Vector3& v2 = *((const Vector3*)(&vertices[indices[2] * vertexSize]));
            nearest = Min(nearest, HitDistance(v0, v1, v2, outNormal));
            indices += 3;
        }
    }
    
    return nearest;
}
Exemple #7
0
float Ray::HitDistance(const void* vertexData, unsigned vertexSize, unsigned vertexStart, unsigned vertexCount, Vector3* outNormal) const
{
    float nearest = M_INFINITY;
    const unsigned char* vertices = ((const unsigned char*)vertexData) + vertexStart * vertexSize;
    unsigned index = 0;
    
    while (index + 2 < vertexCount)
    {
        const Vector3& v0 = *((const Vector3*)(&vertices[index * vertexSize]));
        const Vector3& v1 = *((const Vector3*)(&vertices[(index + 1) * vertexSize]));
        const Vector3& v2 = *((const Vector3*)(&vertices[(index + 2) * vertexSize]));
        nearest = Min(nearest, HitDistance(v0, v1, v2, outNormal));
        index += 3;
    }
    
    return nearest;
}
Exemple #8
0
float Ray::HitDistance(const void* vertexData, unsigned vertexStride, unsigned vertexStart, unsigned vertexCount,
    Vector3* outNormal, Vector2* outUV, unsigned uvOffset) const
{
    float nearest = M_INFINITY;
    const unsigned char* vertices = ((const unsigned char*)vertexData) + vertexStart * vertexStride;
    unsigned index = 0, nearestIdx = M_MAX_UNSIGNED;
    Vector3 barycentric;
    Vector3* outBary = outUV ? &barycentric : 0;

    while (index + 2 < vertexCount)
    {
        const Vector3& v0 = *((const Vector3*)(&vertices[index * vertexStride]));
        const Vector3& v1 = *((const Vector3*)(&vertices[(index + 1) * vertexStride]));
        const Vector3& v2 = *((const Vector3*)(&vertices[(index + 2) * vertexStride]));
        float distance = HitDistance(v0, v1, v2, outNormal, outBary);
        if (distance < nearest)
        {
            nearestIdx = index;
            nearest = distance;
        }
        index += 3;
    }

    if (outUV)
    {
        if (nearestIdx == M_MAX_UNSIGNED)
            *outUV = Vector2::ZERO;
        else
        {
            // Interpolate the UV coordinate using barycentric coordinate
            const Vector2& uv0 = *((const Vector2*)(&vertices[uvOffset + nearestIdx * vertexStride]));
            const Vector2& uv1 = *((const Vector2*)(&vertices[uvOffset + (nearestIdx + 1) * vertexStride]));
            const Vector2& uv2 = *((const Vector2*)(&vertices[uvOffset + (nearestIdx + 2) * vertexStride]));
            *outUV = Vector2(uv0.x_ * barycentric.x_ + uv1.x_ * barycentric.y_ + uv2.x_ * barycentric.z_,
                uv0.y_ * barycentric.x_ + uv1.y_ * barycentric.y_ + uv2.y_ * barycentric.z_);
        }
    }

    return nearest;
}
Exemple #9
0
float Ray::HitDistance(const Vector3& v0, const Vector3& v1, const Vector3& v2) const
{
    return HitDistance(v0, v1, v2, 0);
}
Exemple #10
0
float Ray::HitDistance(const void* vertexData, unsigned vertexStride, const void* indexData, unsigned indexSize,
    unsigned indexStart, unsigned indexCount, Vector3* outNormal, Vector2* outUV, unsigned uvOffset) const
{
    float nearest = M_INFINITY;
    const unsigned char* vertices = (const unsigned char*)vertexData;
    Vector3 barycentric;
    Vector3* outBary = outUV ? &barycentric : 0;

    // 16-bit indices
    if (indexSize == sizeof(unsigned short))
    {
        const unsigned short* indices = ((const unsigned short*)indexData) + indexStart;
        const unsigned short* indicesEnd = indices + indexCount;
        const unsigned short* nearestIndices = 0;

        while (indices < indicesEnd)
        {
            const Vector3& v0 = *((const Vector3*)(&vertices[indices[0] * vertexStride]));
            const Vector3& v1 = *((const Vector3*)(&vertices[indices[1] * vertexStride]));
            const Vector3& v2 = *((const Vector3*)(&vertices[indices[2] * vertexStride]));
            float distance = HitDistance(v0, v1, v2, outNormal, outBary);
            if (distance < nearest)
            {
                nearestIndices = indices;
                nearest = distance;
            }
            indices += 3;
        }

        if (outUV)
        {
            if (nearestIndices == 0)
                *outUV = Vector2::ZERO;
            else
            {
                // Interpolate the UV coordinate using barycentric coordinate
                const Vector2& uv0 = *((const Vector2*)(&vertices[uvOffset + nearestIndices[0] * vertexStride]));
                const Vector2& uv1 = *((const Vector2*)(&vertices[uvOffset + nearestIndices[1] * vertexStride]));
                const Vector2& uv2 = *((const Vector2*)(&vertices[uvOffset + nearestIndices[2] * vertexStride]));
                *outUV = Vector2(uv0.x_ * barycentric.x_ + uv1.x_ * barycentric.y_ + uv2.x_ * barycentric.z_,
                    uv0.y_ * barycentric.x_ + uv1.y_ * barycentric.y_ + uv2.y_ * barycentric.z_);
            }
        }
    }
    // 32-bit indices
    else
    {
        const unsigned* indices = ((const unsigned*)indexData) + indexStart;
        const unsigned* indicesEnd = indices + indexCount;
        const unsigned* nearestIndices = 0;

        while (indices < indicesEnd)
        {
            const Vector3& v0 = *((const Vector3*)(&vertices[indices[0] * vertexStride]));
            const Vector3& v1 = *((const Vector3*)(&vertices[indices[1] * vertexStride]));
            const Vector3& v2 = *((const Vector3*)(&vertices[indices[2] * vertexStride]));
            float distance = HitDistance(v0, v1, v2, outNormal, outBary);
            if (distance < nearest)
            {
                nearestIndices = indices;
                nearest = distance;
            }
            indices += 3;
        }

        if (outUV)
        {
            if (nearestIndices == 0)
                *outUV = Vector2::ZERO;
            else
            {
                // Interpolate the UV coordinate using barycentric coordinate
                const Vector2& uv0 = *((const Vector2*)(&vertices[uvOffset + nearestIndices[0] * vertexStride]));
                const Vector2& uv1 = *((const Vector2*)(&vertices[uvOffset + nearestIndices[1] * vertexStride]));
                const Vector2& uv2 = *((const Vector2*)(&vertices[uvOffset + nearestIndices[2] * vertexStride]));
                *outUV = Vector2(uv0.x_ * barycentric.x_ + uv1.x_ * barycentric.y_ + uv2.x_ * barycentric.z_,
                    uv0.y_ * barycentric.x_ + uv1.y_ * barycentric.y_ + uv2.y_ * barycentric.z_);
            }
        }
    }

    return nearest;
}