/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #include "OdaCommon.h" #include "Gs/GsBaseVectorizer.h" #include "Gi/GiEnvironmentTraitsData.h" #include "GsGradientBackgroundImpl.h" // OdGsGradientBackgroundImpl OdGsGradientBackgroundImpl::OdGsGradientBackgroundImpl(const OdGsBackgroundModule *pModule) : OdGsBackgroundImpl(pModule) { } static inline OdCmEntityColor GradientPercentCalc(const OdCmEntityColor &clr1, const OdCmEntityColor &clr2, double perc) { return OdCmEntityColor(OdUInt8(double(clr1.red()) * (1.0 - perc) + double(clr2.red() * perc)), OdUInt8(double(clr1.green()) * (1.0 - perc) + double(clr2.green() * perc)), OdUInt8(double(clr1.blue()) * (1.0 - perc) + double(clr2.blue() * perc))); } void OdGsGradientBackgroundImpl::display(OdGsBaseVectorizer& view, const OdGiDrawable* /*pDrawable*/, OdGiBackgroundTraitsData* pBackgroundTraits, OdGsPropertiesDirectRenderOutput *pdro) { #ifdef OD_GSBACKGROUND_VERBOSE_ON ODA_TRACE(L"OdGsGradientBackgroundImpl::display\n"); #endif int i; OdGiGradientBackgroundTraitsData *bgt = reinterpret_cast(pBackgroundTraits); RenderingModeHolder holder; OdGePoint3d rect[5]; OdGeMatrix3d m3d; m3d = view.eyeToOutputTransform(); fillBackgroundRect(view.view(), rect); for (i = 0; i < 5; i++) { rect[i].transformBy(m3d); } view.subEntityTraits().setTrueColor(bgt->colorMiddle()); holder = setRenderingMode(view); { // Two colors render double diag_length = (rect[0] - rect[2]).length(); OdGeVector3d grad_dir = (rect[3] - rect[0]); double height_real = grad_dir.normalizeGetLength(); double height_quart = height_real * 2; OdGeVector3d grad_side = (rect[1] - rect[0]); double grad_side_length = grad_side.normalizeGetLength(); if (bgt->rotation() != 0.0) { // Rotate direction on specified angle OdGeVector3d grad_normal = OdGePlane(rect[1], rect[0], rect[3]).normal(); OdGeMatrix3d mx; mx.setCoordSystem(OdGePoint3d::kOrigin, grad_side, grad_dir, grad_normal); mx *= OdGeMatrix3d::rotation(bgt->rotation() * OdaPI / 180, OdGeVector3d::kZAxis); grad_dir = mx.getCsYAxis(); grad_side = mx.getCsXAxis(); } OdGePoint3d origin(rect[0] + grad_side * (grad_side_length * 0.5) + grad_dir * (height_real * 0.5)); // Offset if (bgt->horizon() != 0.5) { // Find horizon length first over direction double level = 0.0; for (i = 0; i < 4; i++) { double ul = grad_dir.dotProduct(rect[i] - origin); if (ul > level) { level = ul; } } level *= 2; origin += grad_dir * (level * (bgt->horizon() - 0.5)); } if (bgt->height() != 0.0) { height_quart *= bgt->height(); } // Compute length to append top-side double up_level = 0.0; for (i = 0; i < 4; i++) { double ul = grad_dir.dotProduct(rect[i] - (origin + grad_dir * (height_quart * 0.5))); if (ul > up_level) { up_level = ul; } } double down_level = 0.0; for (i = 0; i < 4; i++) { double ul = (-grad_dir).dotProduct(rect[i] - (origin - grad_dir * (height_quart * 0.5))); if (ul > down_level) { down_level = ul; } } // Construct basic output rectangle OdGePoint3d grad_rect[4] = { origin - grad_side * (diag_length / 2) - grad_dir * (height_quart / 2), origin + grad_side * (diag_length / 2) - grad_dir * (height_quart / 2), origin + grad_side * (diag_length / 2) + grad_dir * (height_quart / 2), origin - grad_side * (diag_length / 2) + grad_dir * (height_quart / 2) }; OdGiVertexData vdata; VertexColorResolver colors[4]; colors[1].setColor(colors[0].setColor(bgt->colorBottom(), view), view);//GradientPercentCalc(bgt->colorBottom(), bgt->colorTop(), 0.25); colors[3].setColor(colors[2].setColor(bgt->colorTop(), view), view);//GradientPercentCalc(bgt->colorBottom(), bgt->colorTop(), 0.75); vdata.setTrueColors(colors); OdInt32 faces[5] = { 4, 0, 1, 2, 3 }; if (OdZero(bgt->height())) { if (pdro != NULL && GETBIT(pdro->directRenderOutputFlags(), OdGsPropertiesDirectRenderOutput::DirectRender_PolygoneGouraud)) { pdro->directRenderOutputPolygoneGouraud(4, grad_rect, colors); } else { view.shell(4, grad_rect, 5, faces, NULL, NULL, &vdata); } } else { // Three colors gradient OdGePoint3d pt_tmp[2]; // Bottom part pt_tmp[0] = grad_rect[2]; pt_tmp[1] = grad_rect[3]; grad_rect[2] = origin + grad_side * (diag_length / 2); grad_rect[3] = origin - grad_side * (diag_length / 2); colors[3].setColor(colors[2].setColor(bgt->colorMiddle(), view), view); if (pdro != NULL && GETBIT(pdro->directRenderOutputFlags(), OdGsPropertiesDirectRenderOutput::DirectRender_PolygoneGouraud)) { pdro->directRenderOutputPolygoneGouraud(4, grad_rect, colors); } else { view.shell(4, grad_rect, 5, faces, NULL, NULL, &vdata); } // Top part grad_rect[2] = pt_tmp[0]; grad_rect[3] = pt_tmp[1]; grad_rect[0] = origin - grad_side * (diag_length / 2); grad_rect[1] = origin + grad_side * (diag_length / 2); colors[0] = colors[2]; colors[1] = colors[3]; colors[3].setColor(colors[2].setColor(bgt->colorTop(), view), view); if (pdro != NULL && GETBIT(pdro->directRenderOutputFlags(), OdGsPropertiesDirectRenderOutput::DirectRender_PolygoneGouraud)) { pdro->directRenderOutputPolygoneGouraud(4, grad_rect, colors); } else { view.shell(4, grad_rect, 5, faces, NULL, NULL, &vdata); } } // // Construct output for upper limit if (up_level > 0.0) { grad_rect[0] = origin - grad_side * (diag_length / 2) + grad_dir * (height_quart * 0.5); grad_rect[1] = origin + grad_side * (diag_length / 2) + grad_dir * (height_quart * 0.5); grad_rect[2] = origin + grad_side * (diag_length / 2) + grad_dir * (height_quart * 0.5) + grad_dir * up_level; grad_rect[3] = origin - grad_side * (diag_length / 2) + grad_dir * (height_quart * 0.5) + grad_dir * up_level; colors[0].setColor(colors[1].setColor(colors[2].setColor(colors[3].setColor(bgt->colorTop(), view), view), view), view); if (pdro != NULL && GETBIT(pdro->directRenderOutputFlags(), OdGsPropertiesDirectRenderOutput::DirectRender_PolygoneFlat)) { pdro->directRenderOutputPolygoneFlat(4, grad_rect, colors[0]); } else { view.shell(4, grad_rect, 5, faces, NULL, NULL, &vdata); } } // Construct output for lower limit if (down_level > 0.0) { grad_rect[0] = origin - grad_side * (diag_length / 2) - grad_dir * (height_quart * 0.5) - grad_dir * down_level; grad_rect[1] = origin + grad_side * (diag_length / 2) - grad_dir * (height_quart * 0.5) - grad_dir * down_level; grad_rect[2] = origin + grad_side * (diag_length / 2) - grad_dir * (height_quart * 0.5); grad_rect[3] = origin - grad_side * (diag_length / 2) - grad_dir * (height_quart * 0.5); colors[0].setColor(colors[1].setColor(colors[2].setColor(colors[3].setColor(bgt->colorBottom(), view), view), view), view); if (pdro != NULL && GETBIT(pdro->directRenderOutputFlags(), OdGsPropertiesDirectRenderOutput::DirectRender_PolygoneFlat)) { pdro->directRenderOutputPolygoneFlat(4, grad_rect, colors[0]); } else { view.shell(4, grad_rect, 5, faces, NULL, NULL, &vdata); } } } restoreRenderingMode(view, holder); } //