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; }
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]; } } }
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; } }