예제 #1
0
bool Polygon::DiagonalExists(int i, int j) const
{
	assume(p.size() >= 3);
	assume(i >= 0);
	assume(j >= 0);
	assume(i < (int)p.size());
	assume(j < (int)p.size());
#ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS
	if (p.size() < 3 || i < 0 || j < 0 || i >= (int)p.size() || j >= (int)p.size())
		return false;
#endif
	assume(IsPlanar());
	assume(i != j);
	if (i == j) // Degenerate if i == j.
		return false;
	if (i > j)
		Swap(i, j);
	assume(i+1 != j);
	if (i+1 == j) // Is this LineSegment an edge of this polygon?
		return false;

	Plane polygonPlane = PlaneCCW();
	LineSegment diagonal = polygonPlane.Project(LineSegment(p[i], p[j]));

	// First check that this diagonal line is not intersected by an edge of this polygon.
	for(int k = 0; k < (int)p.size(); ++k)
		if (!(k == i || k+1 == i || k == j))
			if (polygonPlane.Project(LineSegment(p[k], p[k+1])).Intersects(diagonal))
				return false;

	return IsConvex();
}
예제 #2
0
파일: Polygon.cpp 프로젝트: katik/naali
/** Implementation based on Graphics Gems 2, p. 170: "IV.1. Area of Planar Polygons and Volume of Polyhedra." */
float Polygon::Area() const
{
    assume(IsPlanar());
    float3 area = float3::zero;

    int i = NumEdges()-1;
    for(int j = 0; j < NumEdges(); ++j)
    {
        area += Vertex(i).Cross(Vertex(j));
        i = j;
    }
    return 0.5f * Abs(NormalCCW().Dot(area));
}
예제 #3
0
bool Polygon::IsSimple() const
{
	assume(IsPlanar());
	Plane plane = PlaneCCW();
	for(int i = 0; i < (int)p.size(); ++i)
	{
		LineSegment si = plane.Project(Edge(i));
		for(int j = i+2; j < (int)p.size(); ++j)
		{
			if (i == 0 && j == (int)p.size() - 1)
				continue; // These two edges are consecutive and share a vertex. Don't check that pair.
			LineSegment sj = plane.Project(Edge(j));
			if (si.Intersects(sj))
				return false;
		}
	}
	return true;
}
예제 #4
0
cairo_surface_t *
GLSurface::Cairo ()
{
	int stride = size[0] * 4;

	if (!data) {
		data = (unsigned char *) g_malloc0 (stride * size[1]);

		// derived class should implement read back of texture image
		g_assert (texture == 0 && !IsPlanar ());
	}

	return cairo_image_surface_create_for_data (data,
						    CAIRO_FORMAT_ARGB32,
						    size[0],
						    size[1],
						    stride);
}
예제 #5
0
//-------------------------------------------------------------------------------------
// Decompression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image )
{
    if ( !IsCompressed(cImage.format) || IsCompressed(format) )
        return E_INVALIDARG;

    if ( format == DXGI_FORMAT_UNKNOWN )
    {
        // Pick a default decompressed format based on BC input format
        format = _DefaultDecompress( cImage.format );
        if ( format == DXGI_FORMAT_UNKNOWN )
        {
            // Input is not a compressed format
            return E_INVALIDARG;
        }
    }
    else
    {
        if ( !IsValid(format) )
            return E_INVALIDARG;

        if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
            return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
    }

    // Create decompressed image
    HRESULT hr = image.Initialize2D( format, cImage.width, cImage.height, 1, 1 );
    if ( FAILED(hr) )
        return hr;

    const Image *img = image.GetImage( 0, 0, 0 );
    if ( !img )
    {
        image.Release();
        return E_POINTER;
    }

    // Decompress single image
    hr = _DecompressBC( cImage, *img );
    if ( FAILED(hr) )
        image.Release();

    return hr;
}
예제 #6
0
float3 Polygon::ClosestPoint(const float3 &point) const
{
	assume(IsPlanar());

	std::vector<Triangle> tris = Triangulate();
	float3 closestPt = float3::nan;
	float closestDist = FLT_MAX;
	for(size_t i = 0; i < tris.size(); ++i)
	{
		float3 pt = tris[i].ClosestPoint(point);
		float d = pt.DistanceSq(point);
		if (d < closestDist)
		{
			closestPt = pt;
			closestDist = d;
		}
	}
	return closestPt;
}
예제 #7
0
vec Polygon::ClosestPoint(const vec &point) const
{
	assume(IsPlanar());

	TriangleArray tris = Triangulate();
	vec closestPt = vec::nan;
	float closestDist = FLT_MAX;
	for(size_t i = 0; i < tris.size(); ++i)
	{
		vec pt = TRIANGLE(tris[i]).ClosestPoint(point);
		float d = pt.DistanceSq(point);
		if (d < closestDist)
		{
			closestPt = pt;
			closestDist = d;
		}
	}
	return closestPt;
}
예제 #8
0
//-------------------------------------------------------------------------------------
// Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& image )
{
    if ( IsCompressed(srcImage.format) || !IsCompressed(format) )
        return E_INVALIDARG;

    if ( IsTypeless(format)
         || IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
        return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );

    // Create compressed image
    HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
    if ( FAILED(hr) )
        return hr;

    const Image *img = image.GetImage( 0, 0, 0 );
    if ( !img )
    {
        image.Release();
        return E_POINTER;
    }

    // Compress single image
    if (compress & TEX_COMPRESS_PARALLEL)
    {
#ifndef _OPENMP
        return E_NOTIMPL;
#else
        hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
#endif // _OPENMP
    }
    else
    {
        hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
    }

    if ( FAILED(hr) )
        image.Release();

    return hr;
}
예제 #9
0
파일: Polygon.cpp 프로젝트: katik/naali
float3 Polygon::ClosestPoint(const float3 &point) const
{
    assume(IsPlanar());

    float3 ptOnPlane = PlaneCCW().Project(point);
    if (Contains(ptOnPlane))
        return ptOnPlane;

    float3 closestPt;
    float closestDist = FLOAT_MAX;
    for(int i = 0; i < NumEdges(); ++i)
    {
        float3 pt = Edge(i).ClosestPoint(point);
        float d = pt.DistanceSq(point);
        if (d < closestDist)
        {
            closestPt = pt;
            closestDist = d;
        }
    }
    return ptOnPlane;
}
예제 #10
0
bool Polygon::IsConvex() const
{
	assume(IsPlanar());
	if (p.empty())
		return false;
	if (p.size() <= 3)
		return true;
	int i = (int)p.size()-2;
	int j = (int)p.size()-1;
	int k = 0;

	while(k < (int)p.size())
	{
		float2 a = MapTo2D(i);
		float2 b = MapTo2D(j);
		float2 c = MapTo2D(k);
		if (!float2::OrientedCCW(a, b, c))
			return false;
		i = j;
		j = k;
		++k;
	}
	return true;
}
예제 #11
0
/** The implementation of this function is based on the paper
	"Kong, Everett, Toussant. The Graham Scan Triangulates Simple Polygons."
	See also p. 772-775 of Geometric Tools for Computer Graphics.
	The running time of this function is O(n^2). */
std::vector<Triangle> Polygon::Triangulate() const
{
	assume(IsPlanar());

	std::vector<Triangle> t;
	// Handle degenerate cases.
	if (NumVertices() < 3)
		return t;
	if (NumVertices() == 3)
	{
		t.push_back(Triangle(Vertex(0), Vertex(1), Vertex(2)));
		return t;
	}
	std::vector<float2> p2d;
	std::vector<int> polyIndices;
	for(int v = 0; v < NumVertices(); ++v)
	{
		p2d.push_back(MapTo2D(v));
		polyIndices.push_back(v);
	}

	// Clip ears of the polygon until it has been reduced to a triangle.
	int i = 0;
	int j = 1;
	int k = 2;
	size_t numTries = 0; // Avoid creating an infinite loop.
	while(p2d.size() > 3 && numTries < p2d.size())
	{
		if (float2::OrientedCCW(p2d[i], p2d[j], p2d[k]) && IsAnEar(p2d, i, k))
		{
			// The vertex j is an ear. Clip it off.
			t.push_back(Triangle(p[polyIndices[i]], p[polyIndices[j]], p[polyIndices[k]]));
			p2d.erase(p2d.begin() + j);
			polyIndices.erase(polyIndices.begin() + j);

			// The previous index might now have become an ear. Move back one index to see if so.
			if (i > 0)
			{
				i = (i + (int)p2d.size() - 1) % p2d.size();
				j = (j + (int)p2d.size() - 1) % p2d.size();
				k = (k + (int)p2d.size() - 1) % p2d.size();
			}
			numTries = 0;
		}
		else
		{
			// The vertex at j is not an ear. Move to test next vertex.
			i = j;
			j = k;
			k = (k+1) % p2d.size();
			++numTries;
		}
	}

	assume(p2d.size() == 3);
	if (p2d.size() > 3) // If this occurs, then the polygon is NOT counter-clockwise oriented.
		return t;
/*
	{
		// For conveniency, create a copy that has the winding order fixed, and triangulate that instead.
		// (Causes a large performance hit!)
		Polygon p2 = *this;
		for(size_t i = 0; i < p2.p.size()/2; ++i)
			std::swap(p2.p[i], p2.p[p2.p.size()-1-i]);
		return p2.Triangulate();
	}
*/
	// Add the last poly.
	t.push_back(Triangle(p[polyIndices[0]], p[polyIndices[1]], p[polyIndices[2]]));

	return t;
}
예제 #12
0
_Use_decl_annotations_
HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& metadata,
                    DXGI_FORMAT format, ScratchImage& images )
{
    if ( !cImages || !nimages )
        return E_INVALIDARG;

    if ( !IsCompressed(metadata.format) || IsCompressed(format) )
        return E_INVALIDARG;

    if ( format == DXGI_FORMAT_UNKNOWN )
    {
        // Pick a default decompressed format based on BC input format
        format = _DefaultDecompress( cImages[0].format );
        if ( format == DXGI_FORMAT_UNKNOWN )
        {
            // Input is not a compressed format
            return E_FAIL;
        }
    }
    else
    {
        if ( !IsValid(format) )
            return E_INVALIDARG;

        if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
            HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
    }

    images.Release();

    TexMetadata mdata2 = metadata;
    mdata2.format = format;
    HRESULT hr = images.Initialize( mdata2 );
    if ( FAILED(hr) )
        return hr;

    if ( nimages != images.GetImageCount() )
    {
        images.Release();
        return E_FAIL;
    }

    const Image* dest = images.GetImages();
    if ( !dest )
    {
        images.Release();
        return E_POINTER;
    }

    for( size_t index=0; index < nimages; ++index )
    {
        assert( dest[ index ].format == format );

        const Image& src = cImages[ index ];
        if ( !IsCompressed( src.format ) )
        {
            images.Release();
            return E_FAIL;
        }

        if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
        {
            images.Release();
            return E_FAIL;
        }

        hr = _DecompressBC( src, dest[ index ] );
        if ( FAILED(hr) )
        {
            images.Release();
            return hr;
        }
    }

    return S_OK;
}
예제 #13
0
_Use_decl_annotations_
HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
                  DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages )
{
    if ( !srcImages || !nimages )
        return E_INVALIDARG;

    if ( IsCompressed(metadata.format) || !IsCompressed(format) )
        return E_INVALIDARG;

    if ( IsTypeless(format)
         || IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
        return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );

    cImages.Release();

    TexMetadata mdata2 = metadata;
    mdata2.format = format;
    HRESULT hr = cImages.Initialize( mdata2 );
    if ( FAILED(hr) )
        return hr;

    if ( nimages != cImages.GetImageCount() )
    {
        cImages.Release();
        return E_FAIL;
    }

    const Image* dest = cImages.GetImages();
    if ( !dest  )
    {
        cImages.Release();
        return E_POINTER;
    }

    for( size_t index=0; index < nimages; ++index )
    {
        assert( dest[ index ].format == format );

        const Image& src = srcImages[ index ];

        if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
        {
            cImages.Release();
            return E_FAIL;
        }

        if ( (compress & TEX_COMPRESS_PARALLEL) )
        {
#ifndef _OPENMP
            return E_NOTIMPL;
#else
            if ( compress & TEX_COMPRESS_PARALLEL )
            {
                hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
                if ( FAILED(hr) )
                {
                    cImages.Release();
                    return  hr;
                }
            }
#endif // _OPENMP
        }
        else
        {
            hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
            if ( FAILED(hr) )
            {
                cImages.Release();
                return hr;
            }
        }
    }

    return S_OK;
}
예제 #14
0
bool
OpenGLSurface::HasTexture ()
{
	return texture != 0 || IsPlanar ();
}
예제 #15
0
std::string Format::Name() const
{
    static const std::string funcName = "Format::Name";

    if (IsPlanar())
    {
        std::string name;

        switch (type)
        {
        case Gray:
            name += "Gray";
            break;
        case RGB:
            name += "RGB";
            break;
        case RGBA:
            name += "RGBA";
            break;
        case YUV:
            name += "YUV";
            if (subsample_w == 0 && subsample_h == 0)
            {
                name += "444P";
            }
            else if (subsample_w == 1 && subsample_h == 0)
            {
                name += "422P";
            }
            else if (subsample_w == 1 && subsample_h == 1)
            {
                name += "420P";
            }
            else if (subsample_w == 2 && subsample_h == 0)
            {
                name += "411P";
            }
            else if (subsample_w == 2 && subsample_h == 1)
            {
                name += "410P";
            }
            else
            {
                name += "ssw" + std::to_string(subsample_w) + "ssh" + std::to_string(subsample_h) + "P";
            }
            break;
        default:
            throw std::invalid_argument(funcName + ": unrecognized Planar type!");
        }

        name += std::to_string(bps);

        switch (sample)
        {
        case UInteger:
            name += "U";
            break;
        case Integer:
            name += "I";
            break;
        case Float:
            name += "F";
            break;
        case Complex:
            name += "C";
            break;
        default:
            throw std::invalid_argument(funcName + ": unrecognized sample!");
        }

        return name;
    }
    else if (IsPacked())
    {
        switch (type)
        {
        case RGB24:
            return "RGB24";
        case RGB32:
            return "RGB32";
        case RGBA32:
            return "RGBA32";
        case GBR24:
            return "GBR24";
        case GBR32:
            return "GBR32";
        case GBRA32:
            return "GBRA32";
        case BGR24:
            return "BGR24";
        case BGR32:
            return "BGR32";
        case BGRA32:
            return "BGRA32";
        case YUYV:
            return "YUYV";
        case YVYU:
            return "YVYU";
        case UYVY:
            return "UYVY";
        case VYUY:
            return "VYUY";
        case AYUV:
            return "AYUV";
        default:
            throw std::invalid_argument(funcName + ": unrecognized Packed type!");
        }
    }
    else if (type == Undef)
    {
        return "Undefined";
    }
    else
    {
        throw std::invalid_argument(funcName + ": unrecognized type!");
    }

    return std::string();
}