VectorFloatPoint cropPolygon(FloatPoint* _baseVerticiesPos, size_t _size, const IntCoord& _cropRectangle)
		{
			VectorFloatPoint resultVerticiesPos;
			resultVerticiesPos.resize(_size);
			for (size_t i = 0; i < _size; ++i)
			{
				resultVerticiesPos[i] = _baseVerticiesPos[i];
			}

			cropPolygonSide(resultVerticiesPos, _cropRectangle.left, Left);
			cropPolygonSide(resultVerticiesPos, _cropRectangle.right(), Right);
			cropPolygonSide(resultVerticiesPos, _cropRectangle.top, Top);
			cropPolygonSide(resultVerticiesPos, _cropRectangle.bottom(), Bottom);

			return resultVerticiesPos;
		}
Esempio n. 2
0
	void PolygonalSkin::setPoints(const std::vector<FloatPoint>& _points)
	{
		if (_points.size() < 2)
		{
			mVertexCount = 0;
			mResultVerticiesPos.clear();
			mResultVerticiesUV.clear();
			mLinePoints = _points;
			return;
		}

		VectorFloatPoint finalPoints;
		finalPoints.reserve(_points.size());

		mLineLength = 0.0f;
		FloatPoint point = _points[0];
		finalPoints.push_back(point);
		// ignore repeating points
		for (std::vector<FloatPoint>::const_iterator iter = _points.begin() + 1; iter != _points.end(); ++iter)
		{
			if (point != *iter)
			{
				finalPoints.push_back(*iter);
				mLineLength += len(iter->left - point.left, iter->top - point.top);
				point = *iter;
			}
		}

		mLinePoints = finalPoints;

#ifdef MYGUI_NO_POLYGONAL_SKIN_CROPPING
		size_t count = (mLinePoints.size() - 1) * VertexQuad::VertexCount * 2;
#else
		// it's too hard to calculate maximum possible verticies count and worst
		// approximation gives 7 times more verticies than in not cropped geometry
		// so we multiply count by 2, because this looks enough
		size_t count = (mLinePoints.size() - 1) * VertexQuad::VertexCount * 2 * 2;
#endif
		if (count > mVertexCount)
		{
			mVertexCount = count;
			if (nullptr != mRenderItem) mRenderItem->reallockDrawItem(this, mVertexCount);
		}

		_updateView();
	}
Esempio n. 3
0
void RotatingSkin::_rebuildGeometry()
{
    /*
    	0 1
    	3 2
    */
#ifndef M_PI
    const float M_PI = 3.141593f;
#endif

    float width_base = (float)mCurrentCoord.width;
    float height_base = (float)mCurrentCoord.height;

    // calculate original unrotated angles of uncropped rectangle verticies: between axis and line from center of rotation to vertex)
    float baseAngles[RECT_VERTICIES_COUNT];
    baseAngles[0] = atan2(                (float)mCenterPos.left,                 (float)mCenterPos.top) + M_PI / 2;
    baseAngles[1] = atan2( - width_base + (float)mCenterPos.left,                 (float)mCenterPos.top) + M_PI / 2;
    baseAngles[2] = atan2( - width_base + (float)mCenterPos.left, - height_base + (float)mCenterPos.top) + M_PI / 2;
    baseAngles[3] = atan2(                (float)mCenterPos.left, - height_base + (float)mCenterPos.top) + M_PI / 2;

    // calculate original unrotated distances of uncropped rectangle verticies: between center of rotation and vertex)
    float baseDistances[RECT_VERTICIES_COUNT];
    baseDistances[0] = len(                (float)mCenterPos.left,                 (float)mCenterPos.top);
    baseDistances[1] = len( - width_base + (float)mCenterPos.left,                 (float)mCenterPos.top);
    baseDistances[2] = len( - width_base + (float)mCenterPos.left, - height_base + (float)mCenterPos.top);
    baseDistances[3] = len(                (float)mCenterPos.left, - height_base + (float)mCenterPos.top);


    // calculate rotated positions of uncropped rectangle verticies (relative to parent)
    FloatPoint baseVerticiesPos[RECT_VERTICIES_COUNT];

    int offsetX = /*mCurrentCoord.left +*/ mCenterPos.left;
    int offsetY = /*mCurrentCoord.top +*/ mCenterPos.top;

    for (int i = 0; i < RECT_VERTICIES_COUNT; ++i)
    {
        baseVerticiesPos[i].left = offsetX + cos(-mAngle + baseAngles[i]) * baseDistances[i];
        baseVerticiesPos[i].top = offsetY - sin(-mAngle + baseAngles[i]) * baseDistances[i];
    }

    // base texture coordinates
    FloatPoint baseVerticiesUV[RECT_VERTICIES_COUNT] =
    {
        FloatPoint(mCurrentTexture.left, mCurrentTexture.top),
        FloatPoint(mCurrentTexture.right, mCurrentTexture.top),
        FloatPoint(mCurrentTexture.right, mCurrentTexture.bottom),
        FloatPoint(mCurrentTexture.left, mCurrentTexture.bottom)
    };

    // now we have rotated uncropped rectangle verticies coordinates

    // --------- here the cropping starts ---------

    // now we are going to calculate verticies of resulting figure

    // no parent - no cropping
    size_t size = RECT_VERTICIES_COUNT;
    if (nullptr == mCroppedParent->getCroppedParent())
    {
        for (int i = 0; i < RECT_VERTICIES_COUNT; ++i)
        {
            mResultVerticiesPos[i] = baseVerticiesPos[i];
            mResultVerticiesUV[i] = baseVerticiesUV[i];
        }
    }
    else
    {
        ICroppedRectangle* parent = mCroppedParent->getCroppedParent();

        VectorFloatPoint resultVerticiesPos = geometry_utility::cropPolygon(
                baseVerticiesPos,
                RECT_VERTICIES_COUNT,
                IntCoord(
                    parent->_getMarginLeft() - mCroppedParent->getLeft(),
                    parent->_getMarginTop() - mCroppedParent->getTop(),
                    parent->_getViewWidth(),
                    parent->_getViewHeight()
                )
                                              );

        for (size_t i = 0; i < resultVerticiesPos.size(); ++i)
        {
            mResultVerticiesPos[i] = resultVerticiesPos[i];
        }

        size = resultVerticiesPos.size();

        // calculate texture coordinates
        FloatPoint v0 = baseVerticiesUV[3] - baseVerticiesUV[0];
        FloatPoint v1 = baseVerticiesUV[1] - baseVerticiesUV[0];
        for (size_t i = 0; i < GEOMETRY_VERTICIES_TOTAL_COUNT; ++i)
        {
            if (i < size)
            {
                FloatPoint point = geometry_utility::getPositionInsideRect(mResultVerticiesPos[i], baseVerticiesPos[0], baseVerticiesPos[1], baseVerticiesPos[3]);
                mResultVerticiesUV[i] = geometry_utility::getUVFromPositionInsideRect(point, v0, v1, baseVerticiesUV[0]);
            }
            else
            {
                // all unused verticies is equal to last used
                mResultVerticiesUV[i] = mResultVerticiesUV[size - 1];
            }
        }
    }


    // now calculate widget base offset and then resulting position in screen coordinates
    const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
    float vertex_left_base = ((info.pixScaleX * (float)(mCroppedParent->getAbsoluteLeft()) + info.hOffset) * 2) - 1;
    float vertex_top_base = -(((info.pixScaleY * (float)(mCroppedParent->getAbsoluteTop()) + info.vOffset) * 2) - 1);

    for (size_t i = 0; i < GEOMETRY_VERTICIES_TOTAL_COUNT; ++i)
    {
        if (i < size)
        {
            mResultVerticiesPos[i].left = vertex_left_base + mResultVerticiesPos[i].left * info.pixScaleX * 2;
            mResultVerticiesPos[i].top = vertex_top_base + mResultVerticiesPos[i].top * info.pixScaleY * -2;
        }
        else
        {
            // all unused verticies is equal to last used
            mResultVerticiesPos[i] = mResultVerticiesPos[size - 1];
        }
    }
}
Esempio n. 4
0
	void PolygonalSkin::_rebuildGeometry()
	{
		if (mLinePoints.size() < 2) return;
		if (!mRenderItem || !mRenderItem->getRenderTarget()) return;

		mGeometryOutdated = false;

		// using mCurrentCoord as rectangle where we draw polygons

		// base texture coordinates
		FloatPoint baseVerticiesUV[4] =
		{
			FloatPoint(mCurrentTexture.left, mCurrentTexture.top),
			FloatPoint(mCurrentTexture.right, mCurrentTexture.top),
			FloatPoint(mCurrentTexture.right, mCurrentTexture.bottom),
			FloatPoint(mCurrentTexture.left, mCurrentTexture.bottom)
		};

		// UV vectors
		FloatPoint vectorU = baseVerticiesUV[1] - baseVerticiesUV[0];
		FloatPoint vectorV = baseVerticiesUV[3] - baseVerticiesUV[0];

		FloatPoint vertex1;
		FloatPoint vertex2;
		mResultVerticiesPos.clear();
		mResultVerticiesUV.clear();
		// add first two verticies
		FloatPoint normal = _getPerpendicular(mLinePoints[0], mLinePoints[1]);

		FloatPoint points[2] = {mLinePoints[0] + normal, mLinePoints[0] - normal};
		FloatPoint pointsUV[2] = {baseVerticiesUV[0], baseVerticiesUV[3]};
		// add other verticies
		float currentLength = 0.0f;
		for (size_t i = 1; i < mLinePoints.size(); ++i)
		{
			currentLength += len(mLinePoints[i - 1].left - mLinePoints[i].left,  mLinePoints[i - 1].top - mLinePoints[i].top);

			// getting normal between previous and next point
			if (i != mLinePoints.size() - 1)
				normal = _getMiddleLine(mLinePoints[i - 1], mLinePoints[i + 1], mLinePoints[i]);
			else
				normal = _getPerpendicular(mLinePoints[i - 1], mLinePoints[i]);

			bool edge = false;
			bool sharp = false;
			if (normal == FloatPoint() /*|| len(normal.left, normal.top) > mLineWidth * 2*/)
			{
				edge = true;
				normal = _getPerpendicular(mLinePoints[i - 1], mLinePoints[i]);
			}
			else if (len(normal.left, normal.top) > mLineWidth * 1.5)
			{
				sharp = true;
				normal = _getPerpendicular(mLinePoints[i - 1], mLinePoints[i]);
			}

			// check orientation
			FloatPoint lineDir = mLinePoints[i] - mLinePoints[i - 1];
			if (lineDir.left * normal.top - lineDir.top * normal.left < 0)
			{
				normal.left = -normal.left;
				normal.top = -normal.top;
			}

			FloatPoint UVoffset(currentLength / mLineLength * vectorU.left, currentLength / mLineLength * vectorU.top);

			mResultVerticiesPos.push_back(points[0]);
			mResultVerticiesPos.push_back(points[1]);
			mResultVerticiesPos.push_back(mLinePoints[i] + normal);
			mResultVerticiesUV.push_back(pointsUV[0]);
			mResultVerticiesUV.push_back(pointsUV[1]);
			mResultVerticiesUV.push_back(baseVerticiesUV[0] + UVoffset);

			mResultVerticiesPos.push_back(points[1]);
			mResultVerticiesPos.push_back(mLinePoints[i] - normal);
			mResultVerticiesPos.push_back(mLinePoints[i] + normal);
			mResultVerticiesUV.push_back(pointsUV[1]);
			mResultVerticiesUV.push_back(baseVerticiesUV[3] + UVoffset);
			mResultVerticiesUV.push_back(baseVerticiesUV[0] + UVoffset);

			points[edge ? 1 : 0] = mLinePoints[i] + normal;
			points[edge ? 0 : 1] = mLinePoints[i] - normal;
			pointsUV[0] = baseVerticiesUV[0] + UVoffset;
			pointsUV[1] = baseVerticiesUV[3] + UVoffset;

			if (sharp)
			{
				normal =  _getMiddleLine(mLinePoints[i - 1], mLinePoints[i + 1], mLinePoints[i]);

				float sharpness = len(normal.left, normal.top) / mLineWidth;

				float length = len(normal.left, normal.top);
				normal.left *= 2 * mLineWidth / length / (sharpness - 0.5f);
				normal.top *= 2 * mLineWidth / length / (sharpness - 0.5f);

				// check orientation
				lineDir = mLinePoints[i] - mLinePoints[i - 1];
				if (lineDir.left * normal.top - lineDir.top * normal.left < 0)
				{
					normal.left = -normal.left;
					normal.top = -normal.top;
				}
				FloatPoint lineDir1 = mLinePoints[i] - mLinePoints[i - 1];
				FloatPoint lineDir2 = mLinePoints[i + 1] - mLinePoints[i];
				if (lineDir1.left * lineDir2.top - lineDir1.top * lineDir2.left > 0)
				{
					normal.left = -normal.left;
					normal.top = -normal.top;
				}

				// check orientation
				FloatPoint normal2 = _getPerpendicular(mLinePoints[i], mLinePoints[i + 1]);
				lineDir = mLinePoints[i - 1] - mLinePoints[i];
				if ((lineDir.left * normal2.top - lineDir.top * normal2.left < 0))
				{
					normal2.left = -normal2.left;
					normal2.top = -normal2.top;
				}

				FloatPoint UVcenter((baseVerticiesUV[0].left + baseVerticiesUV[3].left) / 2, (baseVerticiesUV[0].top + baseVerticiesUV[3].top) / 2);
				mResultVerticiesPos.push_back(points[0]);
				mResultVerticiesPos.push_back(mLinePoints[i] + normal);
				mResultVerticiesPos.push_back(mLinePoints[i]);
				mResultVerticiesUV.push_back(pointsUV[0]);
				mResultVerticiesUV.push_back(baseVerticiesUV[0] + UVoffset);
				mResultVerticiesUV.push_back(UVcenter + UVoffset);

				mResultVerticiesPos.push_back(mLinePoints[i] + normal);
				mResultVerticiesPos.push_back(mLinePoints[i] + normal2);
				mResultVerticiesPos.push_back(mLinePoints[i]);
				mResultVerticiesUV.push_back(baseVerticiesUV[0] + UVoffset);
				mResultVerticiesUV.push_back(baseVerticiesUV[0] + UVoffset);
				mResultVerticiesUV.push_back(UVcenter + UVoffset);

				points[0] = mLinePoints[i] + normal2;
				points[1] = mLinePoints[i] - normal2;
				pointsUV[0] = baseVerticiesUV[0] + UVoffset;
				pointsUV[1] = baseVerticiesUV[3] + UVoffset;
			}
		}


#ifndef MYGUI_NO_POLYGONAL_SKIN_CROPPING
		// crop triangles
		IntCoord cropRectangle(
			mCurrentCoord.left,
			mCurrentCoord.top,
			mCurrentCoord.width,
			mCurrentCoord.height
			);

		VectorFloatPoint newResultVerticiesPos;
		VectorFloatPoint newResultVerticiesUV;
		newResultVerticiesPos.reserve(mResultVerticiesPos.size());
		newResultVerticiesUV.reserve(mResultVerticiesPos.size());
		for (size_t i = 0; i < mResultVerticiesPos.size(); i += 3)
		{
			VectorFloatPoint croppedTriangle =
				geometry_utility::cropPolygon(&mResultVerticiesPos[i], 3, cropRectangle);
			if (!croppedTriangle.empty())
			{
				FloatPoint v0 = mResultVerticiesUV[i + 2] - mResultVerticiesUV[i];
				FloatPoint v1 = mResultVerticiesUV[i + 1] - mResultVerticiesUV[i];

				for (size_t j = 1; j < croppedTriangle.size() - 1; ++j)
				{
					newResultVerticiesPos.push_back(croppedTriangle[0]);
					newResultVerticiesPos.push_back(croppedTriangle[j]);
					newResultVerticiesPos.push_back(croppedTriangle[j + 1]);

					// calculate UV
					FloatPoint point;
					point = geometry_utility::getPositionInsideRect(croppedTriangle[0], mResultVerticiesPos[i], mResultVerticiesPos[i + 1], mResultVerticiesPos[i + 2]);
					newResultVerticiesUV.push_back(geometry_utility::getUVFromPositionInsideRect(point, v0, v1, mResultVerticiesUV[i]));
					point = geometry_utility::getPositionInsideRect(croppedTriangle[j], mResultVerticiesPos[i], mResultVerticiesPos[i + 1], mResultVerticiesPos[i + 2]);
					newResultVerticiesUV.push_back(geometry_utility::getUVFromPositionInsideRect(point, v0, v1, mResultVerticiesUV[i]));
					point = geometry_utility::getPositionInsideRect(croppedTriangle[j + 1], mResultVerticiesPos[i], mResultVerticiesPos[i + 1], mResultVerticiesPos[i + 2]);
					newResultVerticiesUV.push_back(geometry_utility::getUVFromPositionInsideRect(point, v0, v1, mResultVerticiesUV[i]));
				}
			}
		}
		std::swap(mResultVerticiesPos, newResultVerticiesPos);
		std::swap(mResultVerticiesUV, newResultVerticiesUV);
#endif


		// now calculate widget base offset and then resulting position in screen coordinates
		const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
		float vertex_left_base = ((info.pixScaleX * (float)(mCroppedParent->getAbsoluteLeft()) + info.hOffset) * 2) - 1;
		float vertex_top_base = -(((info.pixScaleY * (float)(mCroppedParent->getAbsoluteTop()) + info.vOffset) * 2) - 1);

		for (size_t i = 0; i < mResultVerticiesPos.size(); ++i)
		{
			mResultVerticiesPos[i].left = vertex_left_base + mResultVerticiesPos[i].left * info.pixScaleX * 2;
			mResultVerticiesPos[i].top = vertex_top_base + mResultVerticiesPos[i].top * info.pixScaleY * -2;
		}
	}
		void cropPolygonSide(VectorFloatPoint& _verticies, int _sideCoord, Side _side)
		{
			VectorFloatPoint newVerticies;
			int invert = (_side == Right || _side == Bottom) ? -1 : 1;
			for (size_t i = 0; i < _verticies.size(); ++i)
			{
				FloatPoint& v0 = _verticies[i];
				FloatPoint& v1 = _verticies[(i+1)%_verticies.size()];
				switch (_side)
				{
				case Left:
				case Right:
					// both inside
					if (invert* v0.left >= invert* _sideCoord && invert* v1.left >= invert * _sideCoord)
						newVerticies.push_back(v0);
					// intersect side (1st vertex in)
					else if (invert* v0.left >= invert * _sideCoord && invert * v1.left < invert * _sideCoord)
					{
						newVerticies.push_back(v0);
						float c = (v0.left - _sideCoord) / (_sideCoord - v1.left);
						newVerticies.push_back(FloatPoint((float)_sideCoord, (v0.top + c * v1.top) / (c + 1)));
					}
					// intersect side (2nd vertex in)
					else if (invert* v0.left <= invert * _sideCoord && invert * v1.left > invert * _sideCoord)
					{
						float c = (v0.left - _sideCoord) / (_sideCoord - v1.left);
						newVerticies.push_back(FloatPoint((float)_sideCoord, (v0.top + c * v1.top) / (c + 1)));
					}
					// else don't add any verticies
					break;
				case Top:
				case Bottom:
					// both inside
					if (invert* v0.top >= invert* _sideCoord && invert* v1.top >= invert * _sideCoord)
						newVerticies.push_back(v0);
					// intersect side (1st vertex in)
					else if (invert* v0.top >= invert * _sideCoord && invert * v1.top < invert * _sideCoord)
					{
						newVerticies.push_back(v0);
						float c = (v0.top - _sideCoord) / (_sideCoord - v1.top);
						newVerticies.push_back(FloatPoint((v0.left + c * v1.left) / (c + 1), (float)_sideCoord));
					}
					// intersect side (2nd vertex in)
					else if (invert* v0.top <= invert * _sideCoord && invert * v1.top > invert * _sideCoord)
					{
						float c = (v0.top - _sideCoord) / (_sideCoord - v1.top);
						newVerticies.push_back(FloatPoint((v0.left + c * v1.left) / (c + 1), (float)_sideCoord));
					}
					// else don't add any verticies
					break;
				}
			}

			_verticies = newVerticies;
		}