예제 #1
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();
	}
예제 #2
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;
		}
	}