From 65ab0cd7aa3e99741f28a16fb43bf598473f4b89 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sun, 30 Jul 2023 11:43:13 +0200 Subject: [PATCH 01/42] Blender addon - option to show or hide new addon version message --- common/lc_blenderpreferences.cpp | 60 ++++++++++++++++++++++++-------- common/lc_profile.cpp | 1 + common/lc_profile.h | 1 + 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index 4a111bae..10d4c468 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -441,31 +441,40 @@ lcBlenderPreferences::lcBlenderPreferences(int Width, int Height, double Scale, mAddonGridLayout = new QGridLayout(BlenderAddonVersionBox); BlenderAddonVersionBox->setLayout(mAddonGridLayout); + QCheckBox* AddonVersionCheck = new QCheckBox(tr("Prompt to download new addon version when available"), BlenderAddonVersionBox); + AddonVersionCheck->setChecked(lcGetProfileInt(LC_PROFILE_BLENDER_ADDON_VERSION_CHECK)); + QObject::connect(AddonVersionCheck, &QCheckBox::stateChanged, [](int State) + { + const bool VersionCheck = static_cast(State) == Qt::CheckState::Checked; + lcSetProfileInt(LC_PROFILE_BLENDER_ADDON_VERSION_CHECK, (int)VersionCheck); + }); + mAddonGridLayout->addWidget(AddonVersionCheck,0,0,1,4); + mAddonVersionLabel = new QLabel(BlenderAddonVersionBox); - mAddonGridLayout->addWidget(mAddonVersionLabel,0,0); + mAddonGridLayout->addWidget(mAddonVersionLabel,1,0); mAddonVersionEdit = new QLineEdit(BlenderAddonVersionBox); mAddonVersionEdit->setToolTip(tr("%1 Blender LDraw import and image renderer addon").arg(LC_PRODUCTNAME_STR)); mAddonVersionEdit->setPalette(ReadOnlyPalette); mAddonVersionEdit->setReadOnly(true); - mAddonGridLayout->addWidget(mAddonVersionEdit,0,1); + mAddonGridLayout->addWidget(mAddonVersionEdit,1,1); mAddonGridLayout->setColumnStretch(1,1/*1 is greater than 0 (default)*/); mAddonUpdateButton = new QPushButton(tr("Update"), BlenderAddonVersionBox); mAddonUpdateButton->setToolTip(tr("Update %1 Blender LDraw addon").arg(LC_PRODUCTNAME_STR)); - mAddonGridLayout->addWidget(mAddonUpdateButton,0,2); + mAddonGridLayout->addWidget(mAddonUpdateButton,1,2); connect(mAddonUpdateButton, SIGNAL(clicked(bool)), this, SLOT(UpdateBlenderAddon())); mAddonStdOutButton = new QPushButton(tr("Output..."), BlenderAddonVersionBox); mAddonStdOutButton->setToolTip(tr("Open the standrd output log")); mAddonStdOutButton->setEnabled(false); - mAddonGridLayout->addWidget(mAddonStdOutButton,0,3); + mAddonGridLayout->addWidget(mAddonStdOutButton,1,3); connect(mAddonStdOutButton, SIGNAL(clicked(bool)), this, SLOT(GetStandardOutput())); mModulesBox = new QGroupBox(tr("Enabled Addon Modules"),mContent); QHBoxLayout* ModulesLayout = new QHBoxLayout(mModulesBox); mModulesBox->setLayout(ModulesLayout); - mAddonGridLayout->addWidget(mModulesBox,1,0,1,4); + mAddonGridLayout->addWidget(mModulesBox,2,0,1,4); mImportActBox = new QCheckBox(tr("LDraw Import TN"),mModulesBox); mImportActBox->setToolTip(tr("Enable addon import module (adapted from LDraw Import by Toby Nelson) in Blender")); @@ -1440,18 +1449,25 @@ bool lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) } else if (gMainWindow) { - if (LocalVersion.isEmpty()) - LocalVersion = gAddonPreferences->mAddonVersion; - const QString& Title = tr ("%1 Blender LDraw Addon").arg(LC_PRODUCTNAME_STR); - const QString& Header = tr ("Detected %1 Blender LDraw addon %2. A newer version %3 exists.").arg(LC_PRODUCTNAME_STR).arg(LocalVersion).arg(OnlineVersion); - const QString& Body = tr ("Do you want to download version %1 ?").arg(OnlineVersion); - int Exec = ShowMessage(Header, Title, Body, QString(), MBB_YES, QMessageBox::NoIcon); - if (Exec == QMessageBox::Cancel) + if (lcGetProfileInt(LC_PROFILE_BLENDER_ADDON_VERSION_CHECK)) { - AddonStatus = tr("Blender addon setup cancelled"); - AddonAction = ADDON_CANCEL; + if (LocalVersion.isEmpty()) + LocalVersion = gAddonPreferences->mAddonVersion; + const QString& Title = tr ("%1 Blender LDraw Addon").arg(LC_PRODUCTNAME_STR); + const QString& Header = tr ("Detected %1 Blender LDraw addon %2. A newer version %3 exists.").arg(LC_PRODUCTNAME_STR).arg(LocalVersion).arg(OnlineVersion); + const QString& Body = tr ("Do you want to download version %1 ?").arg(OnlineVersion); + int Exec = ShowMessage(Header, Title, Body, QString(), MBB_YES, QMessageBox::NoIcon); + if (Exec == QMessageBox::Cancel) + { + AddonStatus = tr("Blender addon setup cancelled"); + AddonAction = ADDON_CANCEL; + } + else if (Exec == QMessageBox::No) + { + AddonAction = ADDON_RELOAD; + } } - else if (Exec == QMessageBox::No) + else { AddonAction = ADDON_RELOAD; } @@ -3462,6 +3478,20 @@ int lcBlenderPreferences::ShowMessage(const QString& Header, const QString& Tit } } + const bool DownloadRequest = Body.startsWith(tr("Do you want to download version ")); + + if (DownloadRequest){ + QCheckBox* AddonVersionCheck = new QCheckBox(tr("Do not show download new addon version message again.")); + Box.setCheckBox(AddonVersionCheck); + QObject::connect(AddonVersionCheck, &QCheckBox::stateChanged, [](int State) + { + bool VersionCheck = true; + if (static_cast(State) == Qt::CheckState::Checked) + VersionCheck = false; + lcSetProfileInt(LC_PROFILE_BLENDER_ADDON_VERSION_CHECK, (int)VersionCheck); + }); + } + return Box.exec(); } diff --git a/common/lc_profile.cpp b/common/lc_profile.cpp index f1cc0c7f..bf975088 100644 --- a/common/lc_profile.cpp +++ b/common/lc_profile.cpp @@ -148,6 +148,7 @@ static lcProfileEntry gProfileEntries[LC_NUM_PROFILE_KEYS] = lcProfileEntry("Blender", "LDrawConfigPath", ""), // LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH lcProfileEntry("Blender", "Version", ""), // LC_PROFILE_BLENDER_VERSION lcProfileEntry("Blender", "AddonVersion", ""), // LC_PROFILE_BLENDER_ADDON_VERSION + lcProfileEntry("Blender", "AddonVersionCheck", 1), // LC_PROFILE_BLENDER_ADDON_VERSION_CHECK lcProfileEntry("Blender", "ImportModule", ""), // LC_PROFILE_BLENDER_IMPORT_MODULE lcProfileEntry("Settgins", "PreviewViewSphereEnabled", 0), // LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED diff --git a/common/lc_profile.h b/common/lc_profile.h index 16508434..b91df8ea 100644 --- a/common/lc_profile.h +++ b/common/lc_profile.h @@ -94,6 +94,7 @@ enum LC_PROFILE_KEY LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH, LC_PROFILE_BLENDER_VERSION, LC_PROFILE_BLENDER_ADDON_VERSION, + LC_PROFILE_BLENDER_ADDON_VERSION_CHECK, LC_PROFILE_BLENDER_IMPORT_MODULE, LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED, From c7aecad3535e79141c1e53ba1085ef2e967a4956 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sun, 30 Jul 2023 21:22:19 +0200 Subject: [PATCH 02/42] Blender addon - only save settings that exist in config file --- common/lc_blenderpreferences.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index 10d4c468..2a9b0703 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -2602,7 +2602,9 @@ void lcBlenderPreferences::SaveSettings() continue; Key = mBlenderPaths[LblIdx].key; Value = QDir::toNativeSeparators(mBlenderPaths[LblIdx].value); - Settings.setValue(Key, QVariant(Value)); + + if (Settings.contains(Key)) + Settings.setValue(Key, QVariant(Value)); } for (int LblIdx = 0; LblIdx < NumSettings(); LblIdx++) @@ -2624,7 +2626,9 @@ void lcBlenderPreferences::SaveSettings() } Key = mBlenderSettings[LblIdx].key; - Settings.setValue(Key, QVariant(Value)); + + if (Settings.contains(Key)) + Settings.setValue(Key, QVariant(Value)); } Settings.setValue(parameterFileKey, QVariant(QDir::toNativeSeparators(ParameterFile))); @@ -2641,7 +2645,9 @@ void lcBlenderPreferences::SaveSettings() continue; Key = mBlenderPaths[LblIdx].key_mm; Value = QDir::toNativeSeparators(mBlenderPaths[LblIdx].value); - Settings.setValue(Key, QVariant(Value)); + + if (Settings.contains(Key)) + Settings.setValue(Key, QVariant(Value)); } for (int LblIdx = 0; LblIdx < NumSettingsMM(); LblIdx++) @@ -2660,7 +2666,9 @@ void lcBlenderPreferences::SaveSettings() } Key = mBlenderSettingsMM[LblIdx].key; - Settings.setValue(Key, QVariant(Value)); + + if (Settings.contains(Key)) + Settings.setValue(Key, QVariant(Value)); } searchDirectoriesKey = QLatin1String("additionalSearchPaths"); From 74eb11299292335dd78f2996cc6ecf74eeea8ba5 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Fri, 11 Aug 2023 05:36:51 +0200 Subject: [PATCH 03/42] Blender addon - update settings to addon 1.5 --- common/lc_blenderpreferences.cpp | 119 ++++++++++---------- common/lc_blenderpreferences.h | 182 +++++++++++++++---------------- 2 files changed, 153 insertions(+), 148 deletions(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index 2a9b0703..a9426a7e 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -123,7 +123,7 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettings [N /* 2 LBL_BEVEL_EDGES */ {"beveledges", "1", QObject::tr("Bevel Edges"), QObject::tr("Adds a Bevel modifier for rounding off sharp edges")}, /* 3 LBL_BLENDFILE_TRUSTED */ {"blendfiletrusted", "0", QObject::tr("Trusted Blend File"), QObject::tr("Specify whether to treat the .blend file as being loaded from a trusted source")}, /* 4 LBL_CROP_IMAGE */ {"cropimage", "0", QObject::tr("Crop Image"), QObject::tr("Crop the image border at opaque content. Requires transparent background set to True")}, - /* 5 LBL_CURVED_WALLS */ {"curvedwalls", "1", QObject::tr("Curved Walls"), QObject::tr("Makes surfaces look slightly concave")}, + /* 5 LBL_CURVED_WALLS */ {"curvedwalls", "1", QObject::tr("Curved Walls"), QObject::tr("Makes surfaces look slightly concave, for interesting reflections")}, /* 6 LBL_FLATTEN_HIERARCHY */ {"flattenhierarchy", "0", QObject::tr("Flatten Hierarchy"), QObject::tr("In Scene Outline, all parts are placed directly below the root - there's no tree of submodels")}, /* 7 LBL_IMPORT_CAMERAS */ {"importcameras", "1", QObject::tr("Import Cameras"), QObject::tr("%1 can specify camera definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, /* 8 LBL_IMPORT_LIGHTS */ {"importlights", "1", QObject::tr("Import Lights"), QObject::tr("%1 can specify point and sunlight definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, @@ -147,12 +147,12 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettings [N /*26 LBL_VERBOSE */ {"verbose", "1", QObject::tr("Verbose output"), QObject::tr("Output all messages while working, else only show warnings and errors")}, /*27/0 LBL_BEVEL_WIDTH */ {"bevelwidth", "0.5", QObject::tr("Bevel Width"), QObject::tr("Width of the bevelled edges")}, - /*28/1 LBL_CAMERA_BORDER_PERCENT */ {"cameraborderpercentage", "5.0", QObject::tr("Camera Border Percent"), QObject::tr("When positioning the camera, include a (percentage) border around the model in the render")}, + /*28/1 LBL_CAMERA_BORDER_PERCENT */ {"cameraborderpercentage", "5.0", QObject::tr("Camera Border Percent"), QObject::tr("When positioning the camera, include a (percentage) border leeway around the model in the rendered image")}, /*29/2 LBL_DEFAULT_COLOUR */ {"defaultcolour", "16", QObject::tr("Default Colour"), QObject::tr("Sets the default part colour using LDraw colour code")}, - /*20/3 LBL_GAPS_SIZE */ {"gapwidth", "0.01", QObject::tr("Gap Width"), QObject::tr("Amount of gap space between each part")}, + /*20/3 LBL_GAPS_SIZE */ {"realgapwidth", "0.0002", QObject::tr("Gap Width"), QObject::tr("Amount of space between each part (default 0.2mm)")}, /*31/4 LBL_IMAGE_WIDTH */ {"resolutionwidth", "800", QObject::tr("Image Width"), QObject::tr("Sets the rendered image width in pixels - from current step image, label shows config setting.")}, /*32/5 LBL_IMAGE_HEIGHT */ {"resolutionheight", "600", QObject::tr("Image Height"), QObject::tr("Sets the rendered image height in pixels - from current step image, label shows config setting.")}, - /*33/6 LBL_IMAGE_SCALE */ {"scale", "0.02", QObject::tr("Image Scale"), QObject::tr("Sets the imported model scale (between .01 and 1.0). Scale is 1.0 and is huge and unwieldy in the viewport")}, + /*33/6 LBL_IMAGE_SCALE */ {"realscale", "1.0", QObject::tr("Image Scale"), QObject::tr("Sets a scale for the model (1.0 = real life scale)")}, /*34/6 LBL_RENDER_PERCENTAGE */ {"renderpercentage", "100", QObject::tr("Render Percentage"), QObject::tr("Sets the rendered image percentage scale for its pixel resolution - updated from current step, label shows config setting.")}, /*35/0 LBL_COLOUR_SCHEME */ {"usecolourscheme", "lgeo", QObject::tr("Colour Scheme"), QObject::tr("Colour scheme options - Realistic (lgeo), Original (LDConfig), Alternate (LDCfgalt), Custom (User Defined)")}, @@ -183,29 +183,33 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM /* 00 LBL_ADD_ENVIRONMENT_MM */ {"addenvironment", "1", QObject::tr("Add Environment"), QObject::tr("Adds a ground plane and environment texture")}, /* 01 LBL_BEVEL_EDGES_MM */ {"beveledges", "0", QObject::tr("Bevel Edgest"), QObject::tr("Bevel edges. Can cause some parts to render incorrectly")}, /* 02 LBL_BLEND_FILE_TRUSTED_MM */ {"blendfiletrusted", "0", QObject::tr("Trusted Blend File"), QObject::tr("Specify whether to treat the .blend file as being loaded from a trusted source")}, - /* 03 LBL_CROP_IMAGE_MM */ {"cropimage", "0", QObject::tr("Crop Image"), QObject::tr("Crop the image border at opaque content. Requires transparent background set to True")}, - /* 04 LBL_DISPLAY_LOGO */ {"displaylogo", "1", QObject::tr("Display Logo"), QObject::tr("Display the logo on the stud")}, - /* 05 LBL_IMPORT_CAMERAS_MM */ {"importcameras", "1", QObject::tr("Import Cameras"), QObject::tr("%1 can specify camera definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, - /* 06 LBL_IMPORT_EDGES */ {"importedges", "0", QObject::tr("Import Edges"), QObject::tr("Import LDraw edges as edges")}, - /* 07 LBL_IMPORT_LIGHTS_MM */ {"importlights", "0", QObject::tr("Import Lights"), QObject::tr("%1 can specify point and sunlight definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, - /* 08 LBL_KEEP_ASPECT_RATIO_MM */ {"keepaspectratio", "1", QObject::tr("Keep Aspect Ratio"), QObject::tr("Maintain the aspect ratio when resizing the output image - this attribute is not passed to Blender")}, - /* 09 LBL_MAKE_GAPS */ {"makegaps", "1", QObject::tr("Make Gaps"), QObject::tr("Make small gaps between bricks. A small gap is more realistic")}, - /* 10 LBL_META_BFC */ {"metabfc", "1", QObject::tr("BFC"), QObject::tr("Process LDraw Back Face Culling meta commands")}, - /* 11 LBL_META_CLEAR */ {"metaclear", "0", QObject::tr("CLEAR Command"), QObject::tr("Hides all parts in the timeline up to where this command is encountered")}, - /* 12 LBL_META_GROUP */ {"metagroup", "1", QObject::tr("GROUP Command"), QObject::tr("Process GROUP meta commands")}, - /* 13 LBL_META_PAUSE */ {"metapause", "0", QObject::tr("PAUSE Command"), QObject::tr("Not implemented")}, - /* 14 LBL_META_PRINT_WRITE */ {"metaprintwrite", "0", QObject::tr("PRINT/WRITE Command"), QObject::tr("Prints PRINT/WRITE META commands to the system console.")}, - /* 15 LBL_META_SAVE */ {"metasave", "0", QObject::tr("SAVE Command"), QObject::tr("Not implemented")}, - /* 16 LBL_META_STEP */ {"metastep", "0", QObject::tr("STEP Command"), QObject::tr("Adds a keyframe that shows the part at the moment in the timeline")}, - /* 17 LBL_META_STEP_GROUPS */ {"metastepgroups", "0", QObject::tr("STEP Groups"), QObject::tr("Create collection for individual steps")}, - /* 18 LBL_META_TEXMAP */ {"metatexmap", "1", QObject::tr("TEXMAP and DATA Command"), QObject::tr("Process TEXMAP and DATA meta commands")}, - /* 19 LBL_NO_STUDS */ {"nostuds", "0", QObject::tr("No Studs"), QObject::tr("Don't import studs")}, - /* 20 LBL_OVERWRITE_IMAGE_MM */ {"overwriteimage", "1", QObject::tr("Overwrite Image"), QObject::tr("Specify whether to overwrite an existing rendered image file")}, - /* 21 LBL_POSITION_CAMERA_MM */ {"positioncamera", "1", QObject::tr("Position Camera"), QObject::tr("Position the camera to show the whole model")}, - /* 22 LBL_PARENT_TO_EMPTY */ {"parenttoempty", "1", QObject::tr("Parent To Empty"), QObject::tr("Parent the model to an empty")}, - /* 23 LBL_PREFER_STUDIO */ {"preferstudio", "0", QObject::tr("Prefer Stud.io Library"), QObject::tr("Search for parts in Stud.io library first")}, - /* 24 LBL_PREFER_UNOFFICIAL */ {"preferunofficial", "0", QObject::tr("Prefer Unofficial Parts"), QObject::tr("Search for unofficial parts first")}, - /* 25 LBL_PRESERVE_HIERARCHY */ {"preservehierarchy", "0", QObject::tr("Preserve File Structure"), QObject::tr("Don't merge the constituent subparts and primitives into the top level part. Some parts may not render properly")}, +#ifdef Q_OS_LINUX + /* 03 LBL_CASE_SENSITIVE_FILESYSTEM */ {"casesensitivefilesystem", "1", QObject::tr("Case-sensitive Filesystem"),QObject::tr("Filesystem is case sensitive. Defaults to true on Linux.")}, +#else + /* 03 LBL_CASE_SENSITIVE_FILESYSTEM */ {"casesensitivefilesystem", "0", QObject::tr("Case-sensitive Filesystem"),QObject::tr("Filesystem case sensitive defaults to false Windows and MacOS. Set true if LDraw path set to case-sensitive on case-insensitive filesystem.")}, +#endif + /* 04 LBL_CROP_IMAGE_MM */ {"cropimage", "0", QObject::tr("Crop Image"), QObject::tr("Crop the image border at opaque content. Requires transparent background set to True")}, + /* 05 LBL_DISPLAY_LOGO */ {"displaylogo", "1", QObject::tr("Display Logo"), QObject::tr("Display the logo on the stud")}, + /* 06 LBL_IMPORT_CAMERAS_MM */ {"importcameras", "1", QObject::tr("Import Cameras"), QObject::tr("%1 can specify camera definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, + /* 07 LBL_IMPORT_EDGES */ {"importedges", "0", QObject::tr("Import Edges"), QObject::tr("Import LDraw edges as edges")}, + /* 08 LBL_IMPORT_LIGHTS_MM */ {"importlights", "0", QObject::tr("Import Lights"), QObject::tr("%1 can specify point and sunlight definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, + /* 09 LBL_KEEP_ASPECT_RATIO_MM */ {"keepaspectratio", "1", QObject::tr("Keep Aspect Ratio"), QObject::tr("Maintain the aspect ratio when resizing the output image - this attribute is not passed to Blender")}, + /* 10 LBL_MAKE_GAPS */ {"makegaps", "1", QObject::tr("Make Gaps"), QObject::tr("Make small gaps between bricks. A small gap is more realistic")}, + /* 11 LBL_META_BFC */ {"metabfc", "1", QObject::tr("BFC"), QObject::tr("Process LDraw Back Face Culling meta commands")}, + /* 12 LBL_META_CLEAR */ {"metaclear", "0", QObject::tr("CLEAR Command"), QObject::tr("Hides all parts in the timeline up to where this command is encountered")}, + /* 13 LBL_META_GROUP */ {"metagroup", "1", QObject::tr("GROUP Command"), QObject::tr("Process GROUP meta commands")}, + /* 14 LBL_META_PAUSE */ {"metapause", "0", QObject::tr("PAUSE Command"), QObject::tr("Not implemented")}, + /* 15 LBL_META_PRINT_WRITE */ {"metaprintwrite", "0", QObject::tr("PRINT/WRITE Command"), QObject::tr("Prints PRINT/WRITE META commands to the system console.")}, + /* 16 LBL_META_SAVE */ {"metasave", "0", QObject::tr("SAVE Command"), QObject::tr("Not implemented")}, + /* 17 LBL_META_STEP */ {"metastep", "0", QObject::tr("STEP Command"), QObject::tr("Adds a keyframe that shows the part at the moment in the timeline")}, + /* 18 LBL_META_STEP_GROUPS */ {"metastepgroups", "0", QObject::tr("STEP Groups"), QObject::tr("Create collection for individual steps")}, + /* 19 LBL_META_TEXMAP */ {"metatexmap", "1", QObject::tr("TEXMAP and DATA Command"), QObject::tr("Process TEXMAP and DATA meta commands")}, + /* 20 LBL_NO_STUDS */ {"nostuds", "0", QObject::tr("No Studs"), QObject::tr("Don't import studs")}, + /* 21 LBL_OVERWRITE_IMAGE_MM */ {"overwriteimage", "1", QObject::tr("Overwrite Image"), QObject::tr("Specify whether to overwrite an existing rendered image file")}, + /* 22 LBL_POSITION_CAMERA_MM */ {"positioncamera", "1", QObject::tr("Position Camera"), QObject::tr("Position the camera to show the whole model")}, + /* 23 LBL_PARENT_TO_EMPTY */ {"parenttoempty", "1", QObject::tr("Parent To Empty"), QObject::tr("Parent the model to an empty")}, + /* 24 LBL_PREFER_STUDIO */ {"preferstudio", "0", QObject::tr("Prefer Stud.io Library"), QObject::tr("Search for parts in Stud.io library first")}, + /* 25 LBL_PREFER_UNOFFICIAL */ {"preferunofficial", "0", QObject::tr("Prefer Unofficial Parts"), QObject::tr("Search for unofficial parts first")}, /* 26 LBL_PROFILE */ {"profile", "0", QObject::tr("Profile"), QObject::tr("Profile import performance")}, /* 27 LBL_RECALCULATE_NORMALS */ {"recalculatenormals", "0", QObject::tr("Recalculate Normals"), QObject::tr("Recalculate normals. Not recommended if BFC processing is active")}, /* 28 LBL_REMOVE_DOUBLES_MM */ {"removedoubles", "1", QObject::tr("No Duplicate Vertices"), QObject::tr("Merge vertices that are within a certain distance.")}, @@ -215,32 +219,32 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM /* 32 LBL_SET_TIMELINE_MARKERS */ {"settimelinemarkers", "0", QObject::tr("Set Timeline Markers"), QObject::tr("Set timeline markers for meta commands")}, /* 33 LBL_SHADE_SMOOTH */ {"shadesmooth", "1", QObject::tr("Shade Smooth"), QObject::tr("Use flat or smooth shading for part faces")}, /* 34 LBL_TRANSPARENT_BACKGROUND_MM */ {"transparentbackground", "0", QObject::tr("Transparent Background"), QObject::tr("Specify whether to render a background")}, - /* 35 LBL_TREAT_MODELS_WITH_SUBPARTS_AS_PARTS */ {"treatmodelswithsubpartsasparts","1", QObject::tr("Treat Subparts As Parts"), QObject::tr("Treat subpart like a part by merging its constituent parts into one object")}, - /* 36 LBL_TREAT_SHORTCUT_AS_MODEL */ {"treatshortcutasmodel", "0", QObject::tr("Treat Shortcuts As Models"),QObject::tr("Split shortcut parts into their constituent pieces as if they were models")}, - /* 37 LBL_TRIANGULATE */ {"triangulate", "0", QObject::tr("Triangulate Faces"), QObject::tr("Triangulate all faces")}, - /* 38 LBL_USE_ARCHIVE_LIBRARY_MM */ {"usearchivelibrary", "0", QObject::tr("Use Archive Libraries"), QObject::tr("Add any archive (zip) libraries in the LDraw file path to the library search list")}, - /* 39 LBL_USE_FREESTYLE_EDGES */ {"usefreestyleedges", "0", QObject::tr("Use Freestyle Edges"), QObject::tr("Render LDraw edges using freestyle")}, - /* 40 LBL_VERBOSE_MM */ {"verbose", "1", QObject::tr("Verbose output"), QObject::tr("Output all messages while working, else only show warnings and errors")}, - - /* 41/00 LBL_BEVEL_SEGMENTS */ {"bevelsegments", "4", QObject::tr("Bevel Segments"), QObject::tr("Bevel segments")}, - /* 42/01 LBL_BEVEL_WEIGHT */ {"bevelweight", "0.3", QObject::tr("Bevel Weight"), QObject::tr("Bevel weight")}, - /* 43/02 LBL_BEVEL_WIDTH_MM */ {"bevelwidth", "0.3", QObject::tr("Bevel Width"), QObject::tr("Width of the bevelled edges")}, - /* 44/03 LBL_CAMERA_BORDER_PERCENT_MM */ {"cameraborderpercent", "5", QObject::tr("Camera Border Percent"), QObject::tr("When positioning the camera, include a (percentage) border around the model in the render")}, - /* 45/04 LBL_FRAMES_PER_STEP */ {"framesperstep", "3", QObject::tr("Frames Per Step"), QObject::tr("Frames per step")}, - /* 46/05 LBL_GAP_SCALE */ {"gapscale", "0.997", QObject::tr("Gap Scale"), QObject::tr("Scale individual parts by this much to create the gap")}, - /* 47/06 LBL_IMPORT_SCALE */ {"importscale", "0.02", QObject::tr("Import Scale"), QObject::tr("What scale to import at. Full scale is 1.0 and is so huge that it is unwieldy in the viewport")}, - /* 48/07 LBL_MERGE_DISTANCE */ {"mergedistance", "0.05", QObject::tr("Merge Distance"), QObject::tr("Maximum distance between elements to merge")}, - /* 49/08 LBL_RENDER_PERCENTAGE_MM */ {"renderpercentage", "100", QObject::tr("Render Percentage"), QObject::tr("Sets the rendered image percentage scale for its pixel resolution - updated from current step, label shows config setting.")}, - /* 50/09 LBL_RESOLUTION_WIDTH */ {"resolutionwidth", "800", QObject::tr("Image Width"), QObject::tr("Sets the rendered image width in pixels - from current step image, label shows config setting.")}, - /* 51/10 LBL_RESOLUTION_HEIGHT */ {"resolutionheight", "600", QObject::tr("Image Height"), QObject::tr("Sets the rendered image height in pixels - from current step image, label shows config setting.")}, - /* 52/11 LBL_STARTING_STEP_FRAME */ {"startingstepframe", "1", QObject::tr("Starting Step Frame"), QObject::tr("Frame to add the first STEP meta command")}, - - /* 53/00 LBL_CHOSEN_LOGO */ {"chosenlogo", "logo3", QObject::tr("Chosen Logo"), QObject::tr("Which logo to display. logo and logo2 aren't used and are only included for completeness")}, - /* 54/01 LBL_COLOUR_SCHEME_MM */ {"usecolourscheme", "lgeo", QObject::tr("Colour Scheme"), QObject::tr("Colour scheme options - Realistic (lgeo), Original (LDConfig), Alternate (LDCfgalt), Custom (User Defined)")}, - /* 55/02 LBL_GAP_SCALE_STRATEGY */ {"gapscalestrategy", "constraint", QObject::tr("Gap Strategy"), QObject::tr("Apply gap to object directly or scale and empty to adjust to gaps between parts")}, - /* 56/03 LBL_GAP_TARGET */ {"gaptarget", "object", QObject::tr("Gap Target"), QObject::tr("Whether to scale the object data or mesh data")}, - /* 57/04 LBL_RESOLUTION_MM */ {"resolution", "Standard", QObject::tr("Resolution"), QObject::tr("Resolution of part primitives, ie. how much geometry they have")}, - /* 58/05 LBL_SMOOTH_TYPE */ {"smoothtype", "edge_split", QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")} + /* 35 LBL_TREAT_SHORTCUT_AS_MODEL */ {"treatshortcutasmodel", "0", QObject::tr("Treat Shortcuts As Models"),QObject::tr("Split shortcut parts into their constituent pieces as if they were models")}, + /* 36 LBL_TRIANGULATE */ {"triangulate", "0", QObject::tr("Triangulate Faces"), QObject::tr("Triangulate all faces")}, + /* 37 LBL_USE_ARCHIVE_LIBRARY_MM */ {"usearchivelibrary", "0", QObject::tr("Use Archive Libraries"), QObject::tr("Add any archive (zip) libraries in the LDraw file path to the library search list")}, + /* 38 LBL_USE_FREESTYLE_EDGES */ {"usefreestyleedges", "0", QObject::tr("Use Freestyle Edges"), QObject::tr("Render LDraw edges using freestyle")}, + /* 39 LBL_VERBOSE_MM */ {"verbose", "1", QObject::tr("Verbose output"), QObject::tr("Output all messages while working, else only show warnings and errors")}, + + /* 40/00 LBL_BEVEL_SEGMENTS */ {"bevelsegments", "4", QObject::tr("Bevel Segments"), QObject::tr("Bevel segments")}, + /* 41/01 LBL_BEVEL_WEIGHT */ {"bevelweight", "0.3", QObject::tr("Bevel Weight"), QObject::tr("Bevel weight")}, + /* 42/02 LBL_BEVEL_WIDTH_MM */ {"bevelwidth", "0.3", QObject::tr("Bevel Width"), QObject::tr("Width of the bevelled edges")}, + /* 43/03 LBL_CAMERA_BORDER_PERCENT_MM */ {"cameraborderpercent", "5", QObject::tr("Camera Border Percent"), QObject::tr("When positioning the camera, include a (percentage) border around the model in the render")}, + /* 44/04 LBL_FRAMES_PER_STEP */ {"framesperstep", "3", QObject::tr("Frames Per Step"), QObject::tr("Frames per step")}, + /* 45/05 LBL_GAP_SCALE */ {"gapscale", "0.997", QObject::tr("Gap Scale"), QObject::tr("Scale individual parts by this much to create the gap")}, + /* 46/06 LBL_IMPORT_SCALE */ {"importscale", "0.02", QObject::tr("Import Scale"), QObject::tr("What scale to import at. Full scale is 1.0 and is so huge that it is unwieldy in the viewport")}, + /* 47/07 LBL_MERGE_DISTANCE */ {"mergedistance", "0.05", QObject::tr("Merge Distance"), QObject::tr("Maximum distance between elements to merge")}, + /* 48/08 LBL_RENDER_PERCENTAGE_MM */ {"renderpercentage", "100", QObject::tr("Render Percentage"), QObject::tr("Sets the rendered image percentage scale for its pixel resolution - updated from current step, label shows config setting.")}, + /* 49/09 LBL_RESOLUTION_WIDTH */ {"resolutionwidth", "800", QObject::tr("Image Width"), QObject::tr("Sets the rendered image width in pixels - from current step image, label shows config setting.")}, + /* 50/10 LBL_RESOLUTION_HEIGHT */ {"resolutionheight", "600", QObject::tr("Image Height"), QObject::tr("Sets the rendered image height in pixels - from current step image, label shows config setting.")}, + /* 51/11 LBL_STARTING_STEP_FRAME */ {"startingstepframe", "1", QObject::tr("Starting Step Frame"), QObject::tr("Frame to add the first STEP meta command")}, + + /* 52/00 LBL_CHOSEN_LOGO */ {"chosenlogo", "logo3", QObject::tr("Chosen Logo"), QObject::tr("Which logo to display. logo and logo2 aren't used and are only included for completeness")}, + /* 53/01 LBL_COLOUR_SCHEME_MM */ {"usecolourscheme", "lgeo", QObject::tr("Colour Scheme"), QObject::tr("Colour scheme options - Realistic (lgeo), Original (LDConfig), Alternate (LDCfgalt), Custom (User Defined)")}, + /* 54/02 LBL_COLOUR_STRATEGY */ {"colorstrategy", "material", QObject::tr("How To Color Parts"), QObject::tr("Colour strategy options - Material (Default - use if exporting), Vertex colors (slightly quicker to import)")}, + /* 55/03 LBL_GAP_SCALE_STRATEGY */ {"gapscalestrategy", "constraint", QObject::tr("Gap Strategy"), QObject::tr("Apply gap to object directly or scale and empty to adjust to gaps between parts")}, + /* 56/04 LBL_GAP_TARGET */ {"gaptarget", "object", QObject::tr("Gap Target"), QObject::tr("Whether to scale the object data or mesh data")}, + /* 57/05 LBL_RESOLUTION_MM */ {"resolution", "Standard", QObject::tr("Resolution"), QObject::tr("Resolution of part primitives, ie. how much geometry they have")}, + /* 58/06 LBL_SMOOTH_TYPE */ {"smoothtype", "edge_split", QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")} }; lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO_ITEMS_MM] = @@ -248,10 +252,11 @@ lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO /* FIRST item set as default Data Item: */ /* 00 LBL_CHOSEN_LOGO */ {"logo|logo2|logo3", QObject::tr("Logo (Not Used)|Logo2 (Not Used)|Flattened(3)")}, /* 01 LBL_COLOUR_SCHEME_MM */ {"lgeo|ldraw|alt|custom", QObject::tr("Realistic Colours|Original LDraw Colours|Alternate LDraw Colours|Custom Colours")}, - /* 02 LBL_GAP_SCALE_STRATEGY */ {"object|constraint", QObject::tr("Gap applied directly to object|Gap scaled to adjust to gaps between parts")}, - /* 03 LBL_GAP_TARGET */ {"object|mesh", QObject::tr("Scale object data|Scale mesh data")}, - /* 04 LBL_RESOLUTION_MM */ {"Low|Standard|High", QObject::tr("Low Resolution Primitives|Standard Primitives|High Resolution Primitives")}, - /* 05 LBL_SMOOTH_TYPE */ {"edge_split|auto_smooth|bmesh_split", QObject::tr("Smooth part faces with edge split modifier|Auto-smooth part faces|Split during initial mesh processing")} + /* 02 LBL_COLOUR_STRATEGY */ {"material|vertex_colors", QObject::tr("Material|Vertex Colors")}, + /* 03 LBL_GAP_SCALE_STRATEGY */ {"object|constraint", QObject::tr("Gap applied directly to object|Gap scaled to adjust to gaps between parts")}, + /* 04 LBL_GAP_TARGET */ {"object|mesh", QObject::tr("Scale object data|Scale mesh data")}, + /* 05 LBL_RESOLUTION_MM */ {"Low|Standard|High", QObject::tr("Low Resolution Primitives|Standard Primitives|High Resolution Primitives")}, + /* 06 LBL_SMOOTH_TYPE */ {"edge_split|auto_smooth|bmesh_split", QObject::tr("Smooth part faces with edge split modifier|Auto-smooth part faces|Split during initial mesh processing")} }; lcBlenderPreferences* gAddonPreferences; diff --git a/common/lc_blenderpreferences.h b/common/lc_blenderpreferences.h index 5c1f9bd6..c034b7bb 100644 --- a/common/lc_blenderpreferences.h +++ b/common/lc_blenderpreferences.h @@ -237,30 +237,30 @@ private slots: LBL_ADD_ENVIRONMENT_MM, // 0 QCheckBox LBL_BEVEL_EDGES_MM, // 1 QCheckBox LBL_BLEND_FILE_TRUSTED_MM, // 2 QCheckBox - LBL_CROP_IMAGE_MM, // 3 QCheckBox - LBL_DISPLAY_LOGO, // 4 QCheckBox - LBL_IMPORT_CAMERAS_MM, // 5 QCheckBox - LBL_IMPORT_EDGES, // 6 QCheckBox + LBL_CASE_SENSITIVE_FILESYSTEM, // 3 QCheckBox + LBL_CROP_IMAGE_MM, // 4 QCheckBox + LBL_DISPLAY_LOGO, // 5 QCheckBox + LBL_IMPORT_CAMERAS_MM, // 6 QCheckBox NUM_COMBO_ITEMS_MM, // 7 - LBL_IMPORT_LIGHTS_MM = NUM_COMBO_ITEMS_MM, // 7 QCheckBox - LBL_KEEP_ASPECT_RATIO_MM, // 8 QCheckBox - LBL_MAKE_GAPS, // 9 QCheckBox - LBL_META_BFC, // 10 QCheckBox - LBL_META_CLEAR, // 11 QCheckBox - LBL_META_GROUP, // 12 QCheckBox - LBL_META_PAUSE, // 13 QCheckBox - LBL_META_PRINT_WRITE, // 14 QCheckBox - LBL_META_SAVE, // 15 QCheckBox - LBL_META_STEP, // 16 QCheckBox - LBL_META_STEP_GROUPS, // 17 QCheckBox - LBL_META_TEXMAP, // 18 QCheckBox - LBL_NO_STUDS, // 19 QCheckBox - LBL_OVERWRITE_IMAGE_MM, // 20 QCheckBox - LBL_POSITION_CAMERA_MM, // 21 QCheckBox - LBL_PARENT_TO_EMPTY, // 22 QCheckBox - LBL_PREFER_STUDIO, // 23 QCheckBox - LBL_PREFER_UNOFFICIAL, // 24 QCheckBox - LBL_PRESERVE_HIERARCHY, // 25 QCheckBox + LBL_IMPORT_EDGES = NUM_COMBO_ITEMS_MM, // 7 QCheckBox + LBL_IMPORT_LIGHTS_MM, // 8 QCheckBox + LBL_KEEP_ASPECT_RATIO_MM, // 9 QCheckBox + LBL_MAKE_GAPS, // 10 QCheckBox + LBL_META_BFC, // 11 QCheckBox + LBL_META_CLEAR, // 12 QCheckBox + LBL_META_GROUP, // 13 QCheckBox + LBL_META_PAUSE, // 14 QCheckBox + LBL_META_PRINT_WRITE, // 15 QCheckBox + LBL_META_SAVE, // 16 QCheckBox + LBL_META_STEP, // 17 QCheckBox + LBL_META_STEP_GROUPS, // 18 QCheckBox + LBL_META_TEXMAP, // 19 QCheckBox + LBL_NO_STUDS, // 20 QCheckBox + LBL_OVERWRITE_IMAGE_MM, // 21 QCheckBox + LBL_POSITION_CAMERA_MM, // 22 QCheckBox + LBL_PARENT_TO_EMPTY, // 23 QCheckBox + LBL_PREFER_STUDIO, // 24 QCheckBox + LBL_PREFER_UNOFFICIAL, // 25 QCheckBox LBL_PROFILE, // 26 QCheckBox LBL_RECALCULATE_NORMALS, // 27 QCheckBox LBL_REMOVE_DOUBLES_MM, // 28 QCheckBox @@ -270,32 +270,32 @@ private slots: LBL_SET_TIMELINE_MARKERS, // 32 QCheckBox LBL_SHADE_SMOOTH, // 33 QCheckBox LBL_TRANSPARENT_BACKGROUND_MM, // 34 QCheckBox - LBL_TREAT_MODELS_WITH_SUBPARTS_AS_PARTS, // 35 QCheckBox - LBL_TREAT_SHORTCUT_AS_MODEL, // 36 QCheckBox - LBL_TRIANGULATE, // 37 QCheckBox - LBL_USE_ARCHIVE_LIBRARY_MM, // 38 QCheckBox - LBL_USE_FREESTYLE_EDGES, // 39 QCheckBox - LBL_VERBOSE_MM, // 40 QCheckBox - - LBL_BEVEL_SEGMENTS, // 41/ 0 QLineEdit - LBL_BEVEL_WEIGHT, // 42/ 1 QLineEdit - LBL_BEVEL_WIDTH_MM, // 43/ 2 QLineEdit - LBL_CAMERA_BORDER_PERCENT_MM, // 44/ 3 QLineEdit - LBL_FRAMES_PER_STEP, // 45/ 4 QLineEdit - LBL_GAP_SCALE, // 46/ 5 QLineEdit - LBL_IMPORT_SCALE, // 47/ 6 QLineEdit - LBL_MERGE_DISTANCE, // 48/ 7 QLineEdit - LBL_RENDER_PERCENTAGE_MM, // 49/ 8 QLineEdit - LBL_RESOLUTION_WIDTH, // 50/ 9 QLineEdit - LBL_RESOLUTION_HEIGHT, // 51/10 QLineEdit - LBL_STARTING_STEP_FRAME, // 52/11 QLineEdit - - LBL_CHOSEN_LOGO, // 53/ 0 QComboBox - LBL_COLOUR_SCHEME_MM, // 54/ 1 QComboBox - LBL_GAP_SCALE_STRATEGY, // 55/ 2 QComboBox - LBL_GAP_TARGET, // 56/ 3 QComboBox - LBL_RESOLUTION_MM, // 57/ 4 QComboBox - LBL_SMOOTH_TYPE, // 58/ 5 QComboBox + LBL_TREAT_SHORTCUT_AS_MODEL, // 35 QCheckBox + LBL_TRIANGULATE, // 36 QCheckBox + LBL_USE_ARCHIVE_LIBRARY_MM, // 37 QCheckBox + LBL_USE_FREESTYLE_EDGES, // 38 QCheckBox + LBL_VERBOSE_MM, // 39 QCheckBox + + LBL_BEVEL_SEGMENTS, // 40/ 0 QLineEdit + LBL_BEVEL_WEIGHT, // 41/ 1 QLineEdit + LBL_BEVEL_WIDTH_MM, // 42/ 2 QLineEdit + LBL_CAMERA_BORDER_PERCENT_MM, // 43/ 3 QLineEdit + LBL_FRAMES_PER_STEP, // 44/ 4 QLineEdit + LBL_GAP_SCALE, // 45/ 5 QLineEdit + LBL_IMPORT_SCALE, // 46/ 6 QLineEdit + LBL_MERGE_DISTANCE, // 47/ 7 QLineEdit + LBL_RENDER_PERCENTAGE_MM, // 48/ 8 QLineEdit + LBL_RESOLUTION_WIDTH, // 49/ 9 QLineEdit + LBL_RESOLUTION_HEIGHT, // 50/10 QLineEdit + LBL_STARTING_STEP_FRAME, // 51/11 QLineEdit + + LBL_CHOSEN_LOGO, // 52/ 0 QComboBox + LBL_COLOUR_SCHEME_MM, // 53/ 1 QComboBox + LBL_COLOUR_STRATEGY, // 54/ 2 QComboBox + LBL_GAP_SCALE_STRATEGY, // 55/ 3 QComboBox + LBL_GAP_TARGET, // 56/ 4 QComboBox + LBL_RESOLUTION_MM, // 57/ 5 QComboBox + LBL_SMOOTH_TYPE, // 58/ 6 QComboBox NUM_SETTINGS_MM }; @@ -311,42 +311,43 @@ private slots: CTL_COLOUR_SCHEME_COMBO_MM = CTL_BEVEL_EDGES_BOX_MM, // 1 CTL_BLEND_FILE_TRUSTED_BOX_MM, // 2 CTL_BEVEL_WIDTH_EDIT_MM = CTL_BLEND_FILE_TRUSTED_BOX_MM,// 2 - CTL_GAP_SCALE_STRATEGY_COMBO = CTL_BLEND_FILE_TRUSTED_BOX_MM,// 2 - CTL_CROP_IMAGE_BOX_MM, // 3 - CTL_CAMERA_BORDER_PERCENT_EDIT_MM = CTL_CROP_IMAGE_BOX_MM, // 3 - CTL_GAP_TARGET_COMBO = CTL_CROP_IMAGE_BOX_MM, // 3 - CTL_DISPLAY_LOGO_BOX, // 4 - CTL_FRAMES_PER_STEP_EDIT = CTL_DISPLAY_LOGO_BOX, // 4 - CTL_RESOLUTION_COMBO_MM = CTL_DISPLAY_LOGO_BOX, // 4 - CTL_IMPORT_CAMERAS_BOX_MM, // 5 - CTL_GAP_SCALE_EDIT = CTL_IMPORT_CAMERAS_BOX_MM, // 5 - CTL_SMOOTH_TYPE_COMBO = CTL_IMPORT_CAMERAS_BOX_MM, // 5 - CTL_IMPORT_EDGES_BOX, // 6 - CTL_IMPORT_SCALE_EDIT = CTL_IMPORT_EDGES_BOX, // 6 - CTL_IMPORT_LIGHTS_BOX_MM, // 7 - CTL_MERGE_DISTANCE_EDIT = CTL_IMPORT_LIGHTS_BOX_MM, // 7 - CTL_KEEP_ASPECT_RATIO_BOX_MM, // 8 - CTL_RENDER_PERCENTAGE_EDIT_MM = CTL_KEEP_ASPECT_RATIO_BOX_MM, // 8 - CTL_MAKE_GAPS_BOX, // 9 - CTL_RESOLUTION_WIDTH_EDIT = CTL_MAKE_GAPS_BOX, // 9 - CTL_META_BFC_BOX, // 10 - CTL_RESOLUTION_HEIGHT_EDIT = CTL_META_BFC_BOX, // 10 - CTL_META_CLEAR_BOX, // 11 - CTL_STARTING_STEP_FRAME_EDIT = CTL_META_CLEAR_BOX, // 11 - CTL_META_GROUP_BOX, // 12 - CTL_META_PAUSE_BOX, // 13 - CTL_META_PRINT_WRITE_BOX, // 14 - CTL_META_SAVE_BOX, // 15 - CTL_META_STEP_BOX, // 16 - CTL_META_STEP_GROUPS_BOX, // 17 - CTL_META_TEXMAP_BOX, // 18 - CTL_NO_STUDS_BOX, // 19 - CTL_POSITION_CAMERA_BOX_MM, // 10 - CTL_OVERWRITE_IMAGE_BOX_MM, // 21 - CTL_PARENT_TO_EMPTY_BOX, // 22 - CTL_PREFER_STUDIO_BOX, // 23 - CTL_PREFER_UNOFFICIAL_BOX, // 24 - CTL_PRESERVE_HIERARCHY_BOX, // 25 + CTL_COLOUR_STRATEGY_COMBO = CTL_BLEND_FILE_TRUSTED_BOX_MM,// 2 + CTL_CASE_SENSITIVE_FILESYSTEM_BOX, // 3 + CTL_CAMERA_BORDER_PERCENT_EDIT_MM = CTL_CASE_SENSITIVE_FILESYSTEM_BOX,// 3 + CTL_GAP_SCALE_STRATEGY_COMBO = CTL_CASE_SENSITIVE_FILESYSTEM_BOX,// 3 + CTL_CROP_IMAGE_BOX_MM, // 4 + CTL_FRAMES_PER_STEP_EDIT = CTL_CROP_IMAGE_BOX_MM, // 4 + CTL_GAP_TARGET_COMBO = CTL_CROP_IMAGE_BOX_MM, // 4 + CTL_DISPLAY_LOGO_BOX, // 5 + CTL_GAP_SCALE_EDIT = CTL_DISPLAY_LOGO_BOX, // 5 + CTL_RESOLUTION_COMBO_MM = CTL_DISPLAY_LOGO_BOX, // 5 + CTL_IMPORT_CAMERAS_BOX_MM, // 6 + CTL_IMPORT_SCALE_EDIT = CTL_IMPORT_CAMERAS_BOX_MM, // 6 + CTL_SMOOTH_TYPE_COMBO = CTL_IMPORT_CAMERAS_BOX_MM, // 6 + CTL_IMPORT_EDGES_BOX, // 7 + CTL_MERGE_DISTANCE_EDIT = CTL_IMPORT_EDGES_BOX, // 7 + CTL_IMPORT_LIGHTS_BOX_MM, // 8 + CTL_RENDER_PERCENTAGE_EDIT_MM = CTL_IMPORT_LIGHTS_BOX_MM, // 8 + CTL_KEEP_ASPECT_RATIO_BOX_MM, // 9 + CTL_RESOLUTION_WIDTH_EDIT = CTL_KEEP_ASPECT_RATIO_BOX_MM, // 9 + CTL_MAKE_GAPS_BOX, // 10 + CTL_RESOLUTION_HEIGHT_EDIT = CTL_MAKE_GAPS_BOX, // 10 + CTL_META_BFC_BOX, // 11 + CTL_STARTING_STEP_FRAME_EDIT = CTL_META_BFC_BOX, // 11 + CTL_META_CLEAR_BOX, // 12 + CTL_META_GROUP_BOX, // 13 + CTL_META_PAUSE_BOX, // 14 + CTL_META_PRINT_WRITE_BOX, // 15 + CTL_META_SAVE_BOX, // 16 + CTL_META_STEP_BOX, // 17 + CTL_META_STEP_GROUPS_BOX, // 18 + CTL_META_TEXMAP_BOX, // 19 + CTL_NO_STUDS_BOX, // 20 + CTL_POSITION_CAMERA_BOX_MM, // 21 + CTL_OVERWRITE_IMAGE_BOX_MM, // 22 + CTL_PARENT_TO_EMPTY_BOX, // 23 + CTL_PREFER_STUDIO_BOX, // 24 + CTL_PREFER_UNOFFICIAL_BOX, // 25 CTL_PROFILE_BOX, // 26 CTL_RECALCULATE_NORMALS_BOX, // 27 CTL_REMOVE_DOUBLES_BOX_MM, // 28 @@ -356,12 +357,11 @@ private slots: CTL_SET_TIMELINE_MARKERS_BOX, // 32 CTL_SHADE_SMOOTH_BOX, // 33 CTL_TRANSPARENT_BACKGROUND_BOX_MM, // 34 - CTL_TREAT_MODELS_WITH_SUBPARTS_AS_PARTS_BOX, // 35 - CTL_TREAT_SHORTCUT_AS_MODEL_BOX, // 36 - CTL_TRIANGULATE_BOX, // 37 - CTL_USE_ARCHIVE_LIBRARY_BOX_MM, // 38 - CTL_USE_FREESTYLE_EDGES_BOX, // 39 - CTL_VERBOSE_BOX_MM // 40 + CTL_TREAT_SHORTCUT_AS_MODEL_BOX, // 35 + CTL_TRIANGULATE_BOX, // 36 + CTL_USE_ARCHIVE_LIBRARY_BOX_MM, // 37 + CTL_USE_FREESTYLE_EDGES_BOX, // 38 + CTL_VERBOSE_BOX_MM // 39 }; enum BlenderBrickType From bf004ae0cbf7c5e5d189c64e68b5dcec91e326d8 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Tue, 8 Aug 2023 19:18:48 +0200 Subject: [PATCH 04/42] Blender addon - use StdErrFile for POVRay output display --- qt/lc_renderdialog.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/qt/lc_renderdialog.cpp b/qt/lc_renderdialog.cpp index 57ccf787..2b1c20c9 100644 --- a/qt/lc_renderdialog.cpp +++ b/qt/lc_renderdialog.cpp @@ -882,11 +882,16 @@ void lcRenderDialog::on_OutputBrowseButton_clicked() void lcRenderDialog::on_RenderOutputButton_clicked() { - const QString RenderType = mCommand == POVRAY_RENDER ? QLatin1String("POV-Ray") : QLatin1String("Blender"); - QFileInfo FileInfo(GetStdOutFileName()); + QFileInfo FileInfo(GetStdErrFileName()); + QString Message = tr("POV-Ray standard error file not found: %1.").arg(FileInfo.absoluteFilePath()); + if (mCommand == BLENDER_RENDER) + { + FileInfo.setFile(GetStdOutFileName()); + Message = tr("Blender standard output file not found: %1.").arg(FileInfo.absoluteFilePath()); + } if (!FileInfo.exists()) { - QMessageBox::warning(this, tr("Error"), tr("%1 Standard output file not found: %2.").arg(RenderType).arg(FileInfo.absoluteFilePath())); + QMessageBox::warning(this, tr("Error"), Message); return; } From 1dd08401d747a6eba9ef4f29ebab456f98afbea0 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sat, 8 Jul 2023 00:52:04 +0200 Subject: [PATCH 05/42] Blender lights - images --- leocad.qrc | 6 ++++++ resources/action_arealight.png | Bin 0 -> 1530 bytes resources/action_arealight_16.png | Bin 0 -> 877 bytes resources/action_sunlight.png | Bin 0 -> 1548 bytes resources/action_sunlight_16.png | Bin 0 -> 720 bytes resources/cursor_arealight.png | Bin 0 -> 417 bytes resources/cursor_sunlight.png | Bin 0 -> 428 bytes 7 files changed, 6 insertions(+) create mode 100644 resources/action_arealight.png create mode 100644 resources/action_arealight_16.png create mode 100644 resources/action_sunlight.png create mode 100644 resources/action_sunlight_16.png create mode 100644 resources/cursor_arealight.png create mode 100644 resources/cursor_sunlight.png diff --git a/leocad.qrc b/leocad.qrc index 13b59431..b510eba2 100644 --- a/leocad.qrc +++ b/leocad.qrc @@ -1,5 +1,6 @@ + resources/action_arealight_16.png resources/action_delete_16.png resources/action_insert_16.png resources/action_light_16.png @@ -9,6 +10,7 @@ resources/action_rotate_16.png resources/action_select_16.png resources/action_spotlight_16.png + resources/action_sunlight_16.png resources/action_zoom_16.png resources/edit_copy_16.png resources/edit_cut_16.png @@ -23,6 +25,7 @@ resources/file_render_open_in_blender_16.png resources/file_render_povray_16.png resources/file_save_16.png + resources/action_arealight.png resources/action_camera.png resources/action_color_picker.png resources/action_color_picker_16.png @@ -41,9 +44,11 @@ resources/action_rotate_view.png resources/action_select.png resources/action_spotlight.png + resources/action_sunlight.png resources/action_zoom.png resources/action_zoom_extents.png resources/action_zoom_region.png + resources/cursor_arealight.png resources/cursor_camera.png resources/cursor_color_picker.png resources/cursor_delete.png @@ -61,6 +66,7 @@ resources/cursor_select_add.png resources/cursor_select_remove.png resources/cursor_spotlight.png + resources/cursor_sunlight.png resources/cursor_zoom.png resources/cursor_zoom_region.png resources/edit_copy.png diff --git a/resources/action_arealight.png b/resources/action_arealight.png new file mode 100644 index 0000000000000000000000000000000000000000..68198467cdf9d060553dfb06f93d8e47b2f6a2fa GIT binary patch literal 1530 zcmbtS2~d+q6kdTKqF8MOMT&q_g)q=G3f0uMz<>l03J4Yj6%Z6f2Sh~eP%Bg&@Bo2I zDHQ}n4pA@yNs%+$AOsJt0Fsl0B!BLUoc2ejooQ#<=}c$7x9{zH-}iQR_GJYH`k0w+ zGz9>d`C`37U~ju*CWi3pRdKx!c1FiN0z3e~<*d|3BbJIsu^|Bfe76;V%U1wU!>P*) z0GvYsz>NX`QwYHNq`S|8cLQK>BWQ1^_uIE`VNTAyhX0AYvc}wZxLwxxw^nfJJqoLv z-*YM(x@Tx?n7KqQeTV;cf$TqMe+KW*$}WBa2iYY!IREd+EpIBUYOcT$ajiq`{jY~# z&(2U;u(q(WxvajUme7YMl88g&BV%vKlzA3cAd@R~dc9Jm5z7~OA~};Q*6MVn^&Qns zJsoV)Fcap~A3B+>6 zqF%2T%N8NAoXwZgIilHl!32#rLFG-+Au=73D;Eh}B%xHv;EE}1!88LJr*Nkk{22zH z!V-22jLkCnV-(ITQ}AXUhLE`c^^cM#VL6RA#}ZQ5A~s+4a*8UItH=yKl`Wzzh+a%m zgc2p02F)-90*UfY1!11UXYwTTJP8Yuw)DO%dDJG7$QPELtFCJ7)@Zf!kdz~kafR~x zI3k@R=8F|AJug&htw5p>NtL}LQw**|s!&PfDw$F}OJl1vT7^=@fkYyia#5{;=PJLv zskpXHtJ8N6Pc(Lp=yZBq+fWU@cXVP-qtlhucg`_5MKvvak@Tku0{ky~v@u!mEC#29 z1nz@J-UhuVA~~~c)kepi*aIiivdal0Os$=NLPlOg?-b7P z7J${=OSY^(u{st`E>H0d@LtX|vRLP`*{EgHYgnW9_3{Ya`TS^Fv%6cB&iha){Au6ALyUrQmPbzAQB6b;m5 zM>rKg?#m2{vb>A8erS%2Xtck#)^{13bZBPn(})|X(A>U+tB>4M6KU;XwRTS(zeqhl zHX*2w_6mtQ-4OqEC_dh&zhv5Q`O5rLx#m-38^3D<8Loy8KCp@Q+E1lkkZqWXFJ~vh#cTO{(V=J*W``SQ`wk}*8iPV%Oe9r*5u8qpJ#p;fKMVZB{H$OB@bwP#s`HG>_#M6= BQ7Qlc literal 0 HcmV?d00001 diff --git a/resources/action_arealight_16.png b/resources/action_arealight_16.png new file mode 100644 index 0000000000000000000000000000000000000000..2a5b5c315c64c53feece608a31e5acd637951767 GIT binary patch literal 877 zcmZ{hdrVVz6vuyMG=M0>%*RBTD){#nufOU+-ll{%CGdE&!UV$+1IRwqIFMP+A1Q$#noo z&jJu(k#qup6FdM=5di!)02bG^Kijhn08Uj&VVQs(xY*GryQRIR>X9jRtt#EGoxN9- z+ABA;S5>o6+5P<9r+UMv;U8<$?H+aS;KTmmS0;r1nBJf-16FZDvzH_Hj`{%gLEtea0dZWqgkVqsi4FA41 zS+8~U8b__BahDUpSZ;A34iAQ4BuX%_m$D&**@eA#ct1G2Bpvz)F(+nrV&g9S zBO9>K=J9#3fCcth-NYvkVMF|O#1EsCW5Vy8Bw>`ay1d3wixZ{nv&8R0NjF9zcwmyC z$3D3yeYDrl;N+Cu?R8@T1gE_OgOO82AV@J`Iv7EHl#iP7)1d$pWn*_x9nR}g=h!(e%+BpsUxrc zdh>^2Xk_4ZS63~71IdYLX-jUjU6&u&|3eaodsfh0)BV$Z3|qcT(Jns~SJ;u+kdjjT z;AdaD^6<(vgKK|(v8;B*!Rd7kjrE$H2-C(U)uwPtxNLx?m$EZIf%WM3jg$o8lqNlZoK zjk46SHXiEbB<=N7^yuML=EV2?yuaT2<9*M)pYQj6zW4LJ_uTV6H^;+$4_0B50)ik| zmb0TL>b2J7#Z26{EbL0A9Ll!`uSx#MP(iUHXibP( z{bB5CE^a=H@GYM>mqkRGj$qtB86<4C{AxY{jUOlC7jj7@K3E?!%mp88=P~8p2$h+1 z;>x+TTm9Q+Gl}9@{74*rwLrDuDDGVvss6}XwV++{c6#eQOxLc_8LEQvP)CIVJQNaO zt^*1PAYj46RN&JfTMnj5VXg_@T!QXESn7hsPWYV<6S*+o4x>z%Yln#(7>k54SC~qG z50~N7Eg16#u>(vb!LS_+qQeHnt}tW|!%S$l1<^hjI|WlkFcAg)wlKhe0ecv5fc{XJ zu7NidFqI7tyrIt)`WR574?}LyV+lQ0&}$9%Y~Y?P zrWrIEf?x-aH6~FPb%wSz7TJfOgLgiDmtdzgY9!DfwR>K)x$i=eUm~!vdsS-_f)^%z= zLYsOQ%aP%2`GCvT#%wH-BAA;Ka*?fvq!f({+1#&Rrr9#o{eEL4L6jsiYVor~vb?;w z5E-)^d9%*&)mt1!NkJ7OkHr!&8x)jYy?5}^HXv%MsFO4ZWU`tTNnOQMH@m@ZzwQ<@ zLo2Dzq;^${rXk==%eQ)r_=?nWo{~Xe+;LX{W>tktDOfVOrHP zIO14XW2;wTmWZ+UYWwxOcV%STgu-?sLwnL^gKM$zahFqC+(|smY-!r#nipNG^1-#; z$NdY8$j(y5Px(V$4epia);G9SQ@Q6i5j;`^60zT{_u@VzCUCU!s;QD^ZJkwe?>**5 z_UqK;icQ+Gt_PmdMQ6*lGi6**#%~CWBn}uP^3QB@g7i%cw-zp`>`>yvR*L-Id zd!&ciBTwUI$9qKWp-OBiUI*uG!^pwg5f0J^g<&t+qSCfl(DL)#Tt~#hc{}N;kr7w7 zy!_f5A)F9iIJYxK4gVx0lpD?qk;-?Y*)TXRozHhA%uRO6W4_Ey{t_dst`}%)k)zMw zdMP{!>$7C!aGH@%1j%1*PI8tUXHN_cP4>mze|?{P=x|l_2CGZk4%qyVfYWo?J-T&| z^1mIt!)4R literal 0 HcmV?d00001 diff --git a/resources/action_sunlight_16.png b/resources/action_sunlight_16.png new file mode 100644 index 0000000000000000000000000000000000000000..ae352ef96e517108ccab1fea7bc4317669050a1f GIT binary patch literal 720 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>H^x6ORN*EyA13IAGb3Y2=>BJs3d@cV3??=v-j zPLa*E;dt9C@v>dK-d^~~``N03TD*m7G_Hk5y{|9XT?{oRT$MXM? z$p1Sm{%l#~t zS{ReO-CbOMZkcfq$l)yTh%9Dc;5!V$jK}j=qyPokOFVsD*`Kh8iRdY@?3TL>6x!zL z;us=v*|-0?P*VU8tESTuPBRuA6G2x^CbJ`L|Nr~PJ+Ru9fAh?fCju_qoBEq7qjbZl;mWHvvKK8e9r?i#O<(oAhb0W^9U;b5S zur~Z_UAX?~mT#3CWXpG!$V%^fYQq|)9bofny<0QkwZt`|BqgyV z)hf9t6-Y4{85kMp8kp!B8HE@bSeckv8JlPu7+Dz@SaEz>j-nwqKP5A*61N8LP%lsl OVDNPHb6Mw<&;$UpV;9l@ literal 0 HcmV?d00001 diff --git a/resources/cursor_arealight.png b/resources/cursor_arealight.png new file mode 100644 index 0000000000000000000000000000000000000000..732746b375ad017a34670f0716ff93a6c67bd9a1 GIT binary patch literal 417 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-G$+Qd;gjJKptm- zM`SSr1K%MKW)#)%Y5)qdmw5WRvOi%F6VX#**)4Y&C^W^>#WBR=_}eKPg&GVvoQ2nS z|NpxowW*u}q<9%zDh>h#xWdh4?C0K0WZ?hJfr{O%Wg8${wS=)DhjcT}_ z=&a$loU>tnqb5Uh<)X#{MuDf=31w`DSQgBa*Hb*jE;aYx%#sEBJEvLtnKR~};hM1N z=d}e%?;2J`GV07`{41Gy_gd$2yXPAYc1@H1(;)wW^8w4*`7$A!ot(IV?o%ysjVMV; zEJ?LWE=mPb3`Pb<2D%0&x<*DJMg~?UW>&@~+6G2e1_o9fpO&L&$jwj5OsmAL!8_DT Q8mNK6)78&qol`;+0P@*~9{>OV literal 0 HcmV?d00001 diff --git a/resources/cursor_sunlight.png b/resources/cursor_sunlight.png new file mode 100644 index 0000000000000000000000000000000000000000..48b2eafc10ac0e9f574ee41a914b8c44d0ae0f5b GIT binary patch literal 428 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-G$+Qd;gjJKptm- zM`SSr1K&XqX529``z=tAy~NYkmHi2en24Sd%Wk>LK%x1bE{-7{$KM8@=4(*kiSGRW z|Mb@f&63{^bR2BnyWvFG^}fbSOe#x+U8i3SK5jVe_5AIVnHGy2>S^$uqOF+5Z0;*k5IHINVAGVd^Y+}C?euZI$)7ntgBhlpul3wod? dXvob^$xN%nt-(9gOB$$w!PC{xWt~$(695CDl^Os5 literal 0 HcmV?d00001 From 07a268ed3289673f75dace51f949f11f6a90022e Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Mon, 7 Aug 2023 11:31:33 +0200 Subject: [PATCH 06/42] Blender lights - lcLight --- common/lc_global.h | 1 + common/light.cpp | 570 +++++++++++++++++++++++++++++++++++++++++++-- common/light.h | 89 ++++++- common/object.cpp | 14 ++ 4 files changed, 655 insertions(+), 19 deletions(-) diff --git a/common/lc_global.h b/common/lc_global.h index 2452f103..f079df05 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -105,6 +105,7 @@ struct lcMeshSection; struct lcRenderMesh; struct lcObjectSection; struct lcPieceInfoRayTest; +struct lcLightProperties; class lcTexture; class lcScene; class lcViewManipulator; diff --git a/common/light.cpp b/common/light.cpp index 12f01c7d..fbf11ec2 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -11,36 +11,81 @@ #define LC_LIGHT_POSITION_EDGE 7.5f #define LC_LIGHT_TARGET_EDGE 5.0f #define LC_LIGHT_SPHERE_RADIUS 5.0f +#define LC_LIGHT_BASEFACE_EDGE 12.5f // New omni light. lcLight::lcLight(float px, float py, float pz) : lcObject(lcObjectType::Light) { - Initialize(lcVector3(px, py, pz), lcVector3(0.0f, 0.0f, 0.0f)); + Initialize(lcVector3(px, py, pz), lcVector3(0.0f, 0.0f, 0.0f), LC_POINTLIGHT); UpdatePosition(1); } // New directional or spot light. -lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz) +lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType) : lcObject(lcObjectType::Light) { - Initialize(lcVector3(px, py, pz), lcVector3(tx, ty, tz)); - mState |= LC_LIGHT_SPOT; + Initialize(lcVector3(px, py, pz), lcVector3(tx, ty, tz), LightType); + if (LightType == LC_SPOTLIGHT) + mState |= LC_LIGHT_SPOT; + else + mState |= LC_LIGHT_DIRECTIONAL; UpdatePosition(1); } -void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosition) +void lcLight::SetLightState(int LightType) { mState = 0; - mPositionKeys.ChangeKey(Position, 1, true); - mTargetPositionKeys.ChangeKey(TargetPosition, 1, true); - mAmbientColorKeys.ChangeKey(lcVector4(0.0f, 0.0f, 0.0f, 1.0f), 1, true); - mDiffuseColorKeys.ChangeKey(lcVector4(0.8f, 0.8f, 0.8f, 1.0f), 1, true); - mSpecularColorKeys.ChangeKey(lcVector4(1.0f, 1.0f, 1.0f, 1.0f), 1, true); - mAttenuationKeys.ChangeKey(lcVector3(1.0f, 0.0f, 0.0f), 1, true); - mSpotCutoffKeys.ChangeKey(30.0f, 1, true); - mSpotExponentKeys.ChangeKey(0.0f, 1, true); + switch (LightType) + { + case LC_AREALIGHT: + case LC_SUNLIGHT: + mState |= LC_LIGHT_DIRECTIONAL; + break; + case LC_SPOTLIGHT: + mState |= LC_LIGHT_SPOT; + break; + default: + break; + } +} + +void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType) +{ + SetLightState(LightType); + + mEnableCutoff = false; + mPosition = Position; + mTargetPosition = TargetPosition; + mAmbientColor = lcVector4(0.0f, 0.0f, 0.0f, 1.0f); + mDiffuseColor = lcVector4(0.8f, 0.8f, 0.8f, 1.0f); + mSpecularColor = lcVector4(1.0f, 1.0f, 1.0f, 1.0f); + mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); + mLightColor = lcVector3(1.0f, 1.0f, 1.0f); //RGB - White + mLightType = LightType ? LightType : int(LC_POINTLIGHT); + mLightFactor[0] = LightType ? LightType == LC_SUNLIGHT ? 11.4f : 0.25f : 0.0f; + mLightFactor[1] = LightType == LC_AREALIGHT ? 0.25f : LightType == LC_SPOTLIGHT ? 0.150f : 0.0f; + mLightSpecular = 1.0f; + mSpotSize = 75.0f; + mLightShape = 0 /*Square*/; + mSpotCutoff = LightType ? LightType != LC_SUNLIGHT ? 40.0f : 0.0f : 30.0f; + mSpotExponent = 10.0f; /*Energy/Power*/ + + mPositionKeys.ChangeKey(mPosition, 1, true); + mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); + mAmbientColorKeys.ChangeKey(mAmbientColor, 1, true); + mDiffuseColorKeys.ChangeKey(mDiffuseColor, 1, true); + mSpecularColorKeys.ChangeKey(mSpecularColor, 1, true); + mAttenuationKeys.ChangeKey(mAttenuation, 1, true); + mLightShapeKeys.ChangeKey(mLightShape, 1, true); + mLightColorKeys.ChangeKey(mLightColor, 1, true); + mLightTypeKeys.ChangeKey(mLightType, 1, true); + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); + mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); + mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); + mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, true); } lcLight::~lcLight() @@ -49,7 +94,139 @@ lcLight::~lcLight() void lcLight::SaveLDraw(QTextStream& Stream) const { - Q_UNUSED(Stream); + const QLatin1String LineEnding("\r\n"); + + if (mPositionKeys.GetSize() > 1) + mPositionKeys.SaveKeysLDraw(Stream, "LIGHT POSITION_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding; + + if (mTargetPositionKeys.GetSize() > 1) + mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding; + + if (mLightColorKeys.GetSize() > 1) + mLightColorKeys.SaveKeysLDraw(Stream, "LIGHT COLOR_RGB_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT COLOR_RGB ") << mLightColor[0] << ' ' << mLightColor[1] << ' ' << mLightColor[2] << LineEnding; + + if (mLightSpecularKeys.GetSize() > 1) + mLightSpecularKeys.SaveKeysLDraw(Stream, "LIGHT SPECULAR_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPECULAR ") << mLightSpecular << LineEnding; + + if (mLightType == LC_SUNLIGHT) + { + if (mSpotExponentKeys.GetSize() > 1) + mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT STRENGTH_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << mSpotExponent << LineEnding; + + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT ANGLE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT ANGLE ") << mLightFactor[0] << LineEnding; + } + else + { + if (mSpotExponentKeys.GetSize() > 1) + mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT POWER_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT POWER ") << mSpotExponent << LineEnding; + + if (mEnableCutoff) + { + if (mSpotCutoffKeys.GetSize() > 1) + mSpotCutoffKeys.SaveKeysLDraw(Stream, "LIGHT CUTOFF_DISTANCE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT CUTOFF_DISTANCE ") << mSpotCutoff << LineEnding; + } + + switch (mLightType) + { + case LC_POINTLIGHT: + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + break; + case LC_SPOTLIGHT: + if (mLightFactorKeys.GetSize() > 1) { + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); + } else { + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; + } + if (mLightSpotSizeKeys.GetSize() > 1) + mLightSpotSizeKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_SIZE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; + break; + case LC_AREALIGHT: + if (mLightFactorKeys.GetSize() > 1) { + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); + } else { + if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE) + Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding; + else + Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding; + } + if (mLightShapeKeys.GetSize() > 1) { + mLightShapeKeys.SaveKeysLDraw(Stream, "LIGHT SHAPE_KEY "); + } else { + Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE "); + + QString Shape = QLatin1String("Undefined "); + switch(mLightShape) + { + case LC_LIGHT_SHAPE_SQUARE: + Shape = QLatin1String("Square "); + break; + case LC_LIGHT_SHAPE_DISK: + Shape = QLatin1String("Disk "); + break; + case LC_LIGHT_SHAPE_RECTANGLE: + Shape = QLatin1String("Rectangle "); + break; + case LC_LIGHT_SHAPE_ELLIPSE: + Shape = QLatin1String("Ellipse "); + break; + default: + break; + } + Stream << QLatin1String(Shape.toLatin1()) << LineEnding; + } + + break; + } + } + + if (mLightTypeKeys.GetSize() > 1) + { + mLightTypeKeys.SaveKeysLDraw(Stream, "LIGHT TYPE_KEY "); + } + else + { + Stream << QLatin1String("0 !LEOCAD LIGHT TYPE "); + + QString Type = QLatin1String("Undefined "); + switch(mLightType){ + case LC_POINTLIGHT: + Type = QLatin1String("Point "); + break; + case LC_SUNLIGHT: + Type = QLatin1String("Sun "); + break; + case LC_AREALIGHT: + Type = QLatin1String("Area "); + break; + case LC_SPOTLIGHT: + Type = QLatin1String("Spot "); + break; + } + Stream << QLatin1String(Type.toLatin1()) << QLatin1String("NAME ") << mName << LineEnding; + } } void lcLight::CreateName(const lcArray& Lights) @@ -72,7 +249,8 @@ void lcLight::CreateName(const lcArray& Lights) } int MaxLightNumber = 0; - const QLatin1String Prefix("Light "); + + const QLatin1String Prefix(mLightType == LC_POINTLIGHT ? "Pointlight " : mLightType == LC_AREALIGHT ? "Arealight " : mLightType == LC_SUNLIGHT ? "Sunlight " : "Spotlight "); for (const lcLight* Light : Lights) { @@ -91,6 +269,142 @@ void lcLight::CreateName(const lcArray& Lights) mName = Prefix + QString::number(MaxLightNumber + 1); } +bool lcLight::ParseLDrawLine(QTextStream& Stream) +{ + while (!Stream.atEnd()) + { + QString Token; + Stream >> Token; + if (Token == QLatin1String("COLOR_RGB")) + { + Stream >> mLightColor[0] >> mLightColor[1] >> mLightColor[2]; + mLightColorKeys.ChangeKey(mLightColor, 1, true); + } + else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) + { + Stream >> mSpotExponent; + mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); + } + else if (Token == QLatin1String("RADIUS") || Token == QLatin1String("SIZE") || Token == QLatin1String("WIDTH") || (mHeightSet = Token == QLatin1String("HEIGHT")) || (mSpotBlendSet = Token == QLatin1String("SPOT_BLEND")) || (mAngleSet = Token == QLatin1String("ANGLE"))) + { + if(Token == QLatin1String("HEIGHT") || Token == QLatin1String("SPOT_BLEND")) + Stream >> mLightFactor[1]; + else + Stream >> mLightFactor[0]; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + else if (Token == QLatin1String("SPOT_SIZE")) + { + Stream >> mSpotSize; + mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, true); + } + else if (Token == QLatin1String("SHAPE")) + { + QString Shape; + Stream >> Shape; + Shape = Shape.replace("\"", "").toLower(); + if (Shape == QLatin1String("square")) + mLightShape = LC_LIGHT_SHAPE_SQUARE; + else if (Shape == QLatin1String("disk") || Shape == QLatin1String("circle")) + mLightShape = LC_LIGHT_SHAPE_DISK; + else if (Shape == QLatin1String("rectangle")) + mLightShape = LC_LIGHT_SHAPE_RECTANGLE; + else if (Shape == QLatin1String("ellipse")) + mLightShape = LC_LIGHT_SHAPE_ELLIPSE; + mLightShapeKeys.ChangeKey(mLightShape, 1, true); + } + else if (Token == QLatin1String("SPECULAR")) + { + Stream >>mLightSpecular; + mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); + } + else if ((mSpotCutoffSet = Token == QLatin1String("CUTOFF_DISTANCE"))) + { + mEnableCutoff = true; + Stream >> mSpotCutoff; + mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); + } + else if (Token == QLatin1String("TYPE")) + { + QString Type; + Stream >> Type; + Type = Type.replace("\"", "").toLower(); + if (Type == QLatin1String("point")) + mLightType = LC_POINTLIGHT; + else if (Type == QLatin1String("sun")) + mLightType = LC_SUNLIGHT; + else if (Type == QLatin1String("spot")) + mLightType = LC_SPOTLIGHT; + else if (Type == QLatin1String("area")) + mLightType = LC_AREALIGHT; + SetLightState(mLightType); + mLightTypeKeys.ChangeKey(mLightType, 1, true); + } + else if (Token == QLatin1String("POSITION")) + { + Stream >> mPosition[0] >> mPosition[1] >> mPosition[2]; + mPositionKeys.ChangeKey(mPosition, 1, true); + } + else if (Token == QLatin1String("TARGET_POSITION")) + { + Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; + mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); + } + else if (Token == QLatin1String("COLOR_RGB_KEY")) + mLightColorKeys.LoadKeysLDraw(Stream); + else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) + mSpotExponentKeys.LoadKeysLDraw(Stream); + else if ((Token == QLatin1String("ANGLE_KEY")) || (Token == QLatin1String("RADIUS_KEY")) || (Token == QLatin1String("SIZE_KEY")) || (Token == QLatin1String("RADIUS_AND_SPOT_BLEND_KEY"))) + mLightFactorKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPOT_SIZE_KEY")) + mLightSpotSizeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SHAPE_KEY")) + mLightShapeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPECULAR_KEY")) + mLightSpecularKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("CUTOFF_DISTANCE_KEY")) + mSpotCutoffKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("TYPE_KEY")) + mLightTypeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("POSITION_KEY")) + mPositionKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("TARGET_POSITION_KEY")) + mTargetPositionKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("NAME")) + { + mName = Stream.readAll().trimmed(); + mName.replace("\"", ""); + + // Set default settings per light type + if (mLightType == LC_SPOTLIGHT) { + if (!mSpotBlendSet) { + mLightFactor[1] = 0.15f; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + } + if (mLightType == LC_AREALIGHT && (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE)) { + if (!mHeightSet) { + mLightFactor[1] = 0.25f; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + } + if (mLightType == LC_SUNLIGHT) { + if (!mAngleSet) { + mLightFactor[0] = 11.4f; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + if (!mSpotCutoffSet) { + mSpotCutoff = 0.0f; + mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); + } + } + return true; + } + } + + return false; +} + void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max) { const lcVector3 Points[2] = @@ -109,6 +423,44 @@ void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max) } } +void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) +{ + switch(Property){ + case LC_LIGHT_SHAPE: + mLightShape = Props.mLightShape; + mLightShapeKeys.ChangeKey(mLightShape, Step, false); + break; + case LC_LIGHT_COLOR: + mLightColor = Props.mLightColor; + mLightColorKeys.ChangeKey(mLightColor, Step, false); + break; + case LC_LIGHT_FACTOR: + mLightFactor = Props.mLightFactor; + mLightFactorKeys.ChangeKey(mLightFactor, Step, false); + break; + case LC_LIGHT_SPECULAR: + mLightSpecular = Props.mLightSpecular; + mLightSpecularKeys.ChangeKey(mLightSpecular, Step, false); + break; + case LC_LIGHT_EXPONENT: + mSpotExponent = Props.mSpotExponent; + mSpotExponentKeys.ChangeKey(mSpotExponent, Step, false); + break; + case LC_LIGHT_SPOT_SIZE: + mSpotSize = Props.mSpotSize; + mLightSpotSizeKeys.ChangeKey(mSpotSize, Step, false); + break; + case LC_LIGHT_CUTOFF: + mSpotCutoff = Props.mSpotCutoff; + mSpotCutoffKeys.ChangeKey(mSpotCutoff, Step, false); + break; + case LC_LIGHT_USE_CUTOFF: + mEnableCutoff = Props.mEnableCutoff; + break; + } + UpdatePosition(Step); +} + void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const { if (IsPointLight()) @@ -231,6 +583,12 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mDiffuseColorKeys.InsertTime(Start, Time); mSpecularColorKeys.InsertTime(Start, Time); mAttenuationKeys.InsertTime(Start, Time); + mLightShapeKeys.InsertTime(Start, Time); + mLightColorKeys.InsertTime(Start, Time); + mLightTypeKeys.InsertTime(Start, Time); + mLightFactorKeys.InsertTime(Start, Time); + mLightSpecularKeys.InsertTime(Start, Time); + mLightSpotSizeKeys.InsertTime(Start, Time); mSpotCutoffKeys.InsertTime(Start, Time); mSpotExponentKeys.InsertTime(Start, Time); } @@ -243,6 +601,12 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mDiffuseColorKeys.RemoveTime(Start, Time); mSpecularColorKeys.RemoveTime(Start, Time); mAttenuationKeys.RemoveTime(Start, Time); + mLightShapeKeys.RemoveTime(Start, Time); + mLightColorKeys.RemoveTime(Start, Time); + mLightTypeKeys.RemoveTime(Start, Time); + mLightFactorKeys.RemoveTime(Start, Time); + mLightSpecularKeys.RemoveTime(Start, Time); + mLightSpotSizeKeys.RemoveTime(Start, Time); mSpotCutoffKeys.RemoveTime(Start, Time); mSpotExponentKeys.RemoveTime(Start, Time); } @@ -255,6 +619,12 @@ void lcLight::UpdatePosition(lcStep Step) mDiffuseColor = mDiffuseColorKeys.CalculateKey(Step); mSpecularColor = mSpecularColorKeys.CalculateKey(Step); mAttenuation = mAttenuationKeys.CalculateKey(Step); + mLightShape = mLightShapeKeys.CalculateKey(Step); + mLightColor = mLightColorKeys.CalculateKey(Step); + mLightType = mLightTypeKeys.CalculateKey(Step); + mLightFactor = mLightFactorKeys.CalculateKey(Step); + mLightSpecular = mLightSpecularKeys.CalculateKey(Step); + mSpotSize = mLightSpotSizeKeys.CalculateKey(Step); mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); mSpotExponent = mSpotExponentKeys.CalculateKey(Step); @@ -294,10 +664,160 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const if (IsPointLight()) DrawPointLight(Context); + else if (IsDirectionalLight()) + DrawDirectionalLight(Context); else DrawSpotLight(Context); } +void lcLight::DrawDirectionalLight(lcContext* Context) const +{ + lcVector3 FrontVector(mTargetPosition - mPosition); + lcVector3 UpVector(1, 1, 1); + + if (fabs(FrontVector[0]) < fabs(FrontVector[1])) + { + if (fabs(FrontVector[0]) < fabs(FrontVector[2])) + UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); + else + UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + } + else + { + if (fabs(FrontVector[1]) < fabs(FrontVector[2])) + UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); + else + UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + } + + lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); + LightMatrix = lcMatrix44AffineInverse(LightMatrix); + LightMatrix.SetTranslation(lcVector3(0, 0, 0)); + + lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); + Context->SetWorldMatrix(LightViewMatrix); + + float Verts[(20 + 8 + 2 + 16) * 3]; + float* CurVert = Verts; + + for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) + { + float c = cosf(float(EdgeIdx) / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; + float s = sinf(float(EdgeIdx) / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; + + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } + + if (mLightType == LC_SUNLIGHT) { + + // set base face to same size (LC_LIGHT_TARGET_EDGE) as body - was 12.5f + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + + } else { + + *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } + + + float Length = FrontVector.Length(); + + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; + + const GLushort Indices[56 + 24 + 2 + 40] = + { + // base body + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, + 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1, + // base face + 16, 17, 17, 18, 18, 19, 19, 16, + // targe box + 20, 21, 21, 22, 22, 23, 23, 20, + 24, 25, 25, 26, 26, 27, 27, 24, + 20, 24, 21, 25, 22, 26, 23, 27, + // target line - from base to target + 28, 29, + }; + + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); + Context->SetIndexBufferPointer(Indices); + + const lcPreferences& Preferences = lcGetPreferences(); + const float LineWidth = Preferences.mLineWidth; + const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); + const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); + const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); + + if (!IsSelected()) + { + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + + Context->DrawIndexedPrimitives(GL_LINES, 56 + 24 + 2, GL_UNSIGNED_SHORT, 0); + } + else + { + if (IsSelected(LC_LIGHT_SECTION_POSITION)) + { + Context->SetLineWidth(2.0f * LineWidth); + if (IsFocused(LC_LIGHT_SECTION_POSITION)) + Context->SetColor(FocusedColor); + else + Context->SetColor(SelectedColor); + } + else + { + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + } + + Context->DrawIndexedPrimitives(GL_LINES, 56, GL_UNSIGNED_SHORT, 0); + + if (IsSelected(LC_LIGHT_SECTION_TARGET)) + { + Context->SetLineWidth(2.0f * LineWidth); + if (IsFocused(LC_LIGHT_SECTION_TARGET)) + Context->SetColor(FocusedColor); + else + Context->SetColor(SelectedColor); + } + else + { + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + } + + Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 56 * 2); + + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + + Context->DrawIndexedPrimitives(GL_LINES, 2 + 40, GL_UNSIGNED_SHORT, (56 + 24) * 2); + } +} + void lcLight::DrawSpotLight(lcContext* Context) const { lcVector3 FrontVector(mTargetPosition - mPosition); @@ -360,7 +880,7 @@ void lcLight::DrawSpotLight(lcContext* Context) const *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; - const GLushort Indices[56 + 24 + 2 + 40] = + const GLushort Indices[56 + 24 + 2 + 40] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, @@ -565,6 +1085,24 @@ void lcLight::RemoveKeyFrames() mAttenuationKeys.RemoveAll(); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); + mLightShapeKeys.RemoveAll(); + mLightShapeKeys.ChangeKey(mLightShape, 1, false); + + mLightColorKeys.RemoveAll(); + mLightColorKeys.ChangeKey(mLightColor, 1, true); + + mLightFactorKeys.RemoveAll(); + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + + mLightTypeKeys.RemoveAll(); + mLightTypeKeys.ChangeKey(mLightType, 1, true); + + mLightSpecularKeys.RemoveAll(); + mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); + + mLightSpotSizeKeys.RemoveAll(); + mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, false); + mSpotCutoffKeys.RemoveAll(); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); diff --git a/common/light.h b/common/light.h index 78a0cd0d..0163d8d2 100644 --- a/common/light.h +++ b/common/light.h @@ -21,11 +21,55 @@ enum lcLightSection LC_LIGHT_SECTION_TARGET }; +enum lcLightType +{ + LC_UNDEFINED_LIGHT, + LC_POINTLIGHT, + LC_AREALIGHT, + LC_SUNLIGHT, + LC_SPOTLIGHT +}; + +enum lcLightShape +{ + LC_LIGHT_SHAPE_UNDEFINED = -1, + LC_LIGHT_SHAPE_SQUARE, + LC_LIGHT_SHAPE_DISK, + LC_LIGHT_SHAPE_RECTANGLE, + LC_LIGHT_SHAPE_ELLIPSE +}; + +enum lcLightProperty +{ + LC_LIGHT_NONE, + LC_LIGHT_SHAPE, + LC_LIGHT_COLOR, + LC_LIGHT_TYPE, + LC_LIGHT_FACTOR, + LC_LIGHT_SPECULAR, + LC_LIGHT_EXPONENT, + LC_LIGHT_SPOT_SIZE, + LC_LIGHT_CUTOFF, + LC_LIGHT_USE_CUTOFF +}; + +struct lcLightProperties +{ + lcVector3 mLightColor; + lcVector2 mLightFactor; + float mLightSpecular; + float mSpotExponent; + float mSpotCutoff; + float mSpotSize; + bool mEnableCutoff; + int mLightShape; +}; + class lcLight : public lcObject { public: lcLight(float px, float py, float pz); - lcLight(float px, float py, float pz, float tx, float ty, float tz); + lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType); ~lcLight(); lcLight(const lcLight&) = delete; @@ -178,6 +222,7 @@ class lcLight : public lcObject } void SaveLDraw(QTextStream& Stream) const; + bool ParseLDrawLine(QTextStream& Stream); public: void RayTest(lcObjectRayTest& ObjectRayTest) const override; @@ -191,6 +236,11 @@ class lcLight : public lcObject bool IsVisible() const { return (mState & LC_LIGHT_HIDDEN) == 0; } + void SetName(const QString& Name) + { + mName = Name; + } + QString GetName() const override { return mName; @@ -201,6 +251,20 @@ class lcLight : public lcObject void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance); bool Setup(int LightIndex); void CreateName(const lcArray& Lights); + void UpdateLight(lcStep Step, lcLightProperties Props, int Property); + lcLightProperties GetLightProperties() const + { + lcLightProperties props; + props.mLightColor = mLightColor; + props.mLightFactor = mLightFactor; + props.mLightSpecular = mLightSpecular; + props.mSpotExponent = mSpotExponent; + props.mSpotCutoff = mSpotCutoff; + props.mSpotSize = mSpotSize; + props.mEnableCutoff = mEnableCutoff; + props.mLightShape = mLightShape; + return props; + } // Temporary parameters lcMatrix44 mWorldLight; @@ -210,8 +274,20 @@ class lcLight : public lcObject lcVector4 mDiffuseColor; lcVector4 mSpecularColor; lcVector3 mAttenuation; + lcVector3 mLightColor; + lcVector2 mLightFactor; + bool mAngleSet; + bool mSpotBlendSet; + bool mSpotCutoffSet; + bool mHeightSet; + bool mEnableCutoff; + int mLightType; + int mLightShape; + float mLightSpecular; + float mSpotSize; float mSpotCutoff; float mSpotExponent; + QString mName; protected: lcObjectKeyArray mPositionKeys; @@ -220,14 +296,21 @@ class lcLight : public lcObject lcObjectKeyArray mDiffuseColorKeys; lcObjectKeyArray mSpecularColorKeys; lcObjectKeyArray mAttenuationKeys; + lcObjectKeyArray mLightColorKeys; + lcObjectKeyArray mLightFactorKeys; + lcObjectKeyArray mLightTypeKeys; + lcObjectKeyArray mLightShapeKeys; + lcObjectKeyArray mLightSpecularKeys; + lcObjectKeyArray mLightSpotSizeKeys; lcObjectKeyArray mSpotCutoffKeys; lcObjectKeyArray mSpotExponentKeys; - void Initialize(const lcVector3& Position, const lcVector3& TargetPosition); + void Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType); + void DrawDirectionalLight(lcContext* Context) const; void DrawPointLight(lcContext* Context) const; void DrawSpotLight(lcContext* Context) const; + void SetLightState(int LightType); - QString mName; quint32 mState; }; diff --git a/common/object.cpp b/common/object.cpp index 42723094..c8eedc93 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -38,6 +38,20 @@ template void lcObjectKeyArray::ChangeKey(const lcMatrix33& Value, l template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); +template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; +template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); +template const int& lcObjectKeyArray::CalculateKey(lcStep Step) const; +template void lcObjectKeyArray::ChangeKey(const int& Value, lcStep Step, bool AddKey); +template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); +template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); + +template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; +template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); +template const lcVector2& lcObjectKeyArray::CalculateKey(lcStep Step) const; +template void lcObjectKeyArray::ChangeKey(const lcVector2& Value, lcStep Step, bool AddKey); +template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); +template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); + template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const { From 3b9ea3ae7948652baa1acbeaf5dacb196445d603 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Fri, 4 Aug 2023 22:26:29 +0200 Subject: [PATCH 07/42] Blender lights - view and control --- common/lc_commands.cpp | 16 ++ common/lc_commands.h | 4 + common/lc_model.cpp | 42 ++- common/lc_model.h | 5 +- common/lc_view.cpp | 30 +- common/lc_view.h | 4 + common/lc_viewmanipulator.cpp | 2 + qt/lc_qpropertiestree.cpp | 501 +++++++++++++++++++++++++++++++++- qt/lc_qpropertiestree.h | 35 +++ 9 files changed, 628 insertions(+), 11 deletions(-) diff --git a/common/lc_commands.cpp b/common/lc_commands.cpp index 3d616a98..79ff61f5 100644 --- a/common/lc_commands.cpp +++ b/common/lc_commands.cpp @@ -648,6 +648,20 @@ const lcCommand gCommands[] = QT_TRANSLATE_NOOP("Status", "Add new omni light sources to the model"), "" }, + // LC_EDIT_ACTION_AREALIGHT + { + QT_TRANSLATE_NOOP("Action", "Edit.Tool.Arealight"), + QT_TRANSLATE_NOOP("Menu", "Arealight"), + QT_TRANSLATE_NOOP("Status", "Add new arealight sources to the model - edit in Properties tab"), + "" + }, + // LC_EDIT_ACTION_SUNLIGHT + { + QT_TRANSLATE_NOOP("Action", "Edit.Tool.Sunlight"), + QT_TRANSLATE_NOOP("Menu", "Sunlight"), + QT_TRANSLATE_NOOP("Status", "Add new omnidirectional sunlight sources to the model - edit in Properties tab"), + "" + }, // LC_EDIT_ACTION_SPOTLIGHT { QT_TRANSLATE_NOOP("Action", "Edit.Tool.Spotlight"), @@ -1860,6 +1874,8 @@ const char* gToolNames[] = { QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::Light + QT_TRANSLATE_NOOP("Mouse", "NewAreaLight"), // lcTool::AreaLight + QT_TRANSLATE_NOOP("Mouse", "NewSunLight"), // lcTool::SunLight QT_TRANSLATE_NOOP("Mouse", "NewSpotLight"), // lcTool::SpotLight QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select diff --git a/common/lc_commands.h b/common/lc_commands.h index f49d28fc..6db95a22 100644 --- a/common/lc_commands.h +++ b/common/lc_commands.h @@ -99,6 +99,8 @@ enum lcCommandId LC_EDIT_ACTION_FIRST, LC_EDIT_ACTION_INSERT = LC_EDIT_ACTION_FIRST, LC_EDIT_ACTION_LIGHT, + LC_EDIT_ACTION_AREALIGHT, + LC_EDIT_ACTION_SUNLIGHT, LC_EDIT_ACTION_SPOTLIGHT, LC_EDIT_ACTION_CAMERA, LC_EDIT_ACTION_SELECT, @@ -299,6 +301,8 @@ enum class lcTool { Insert, Light, + AreaLight, + SunLight, SpotLight, Camera, Select, diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 843119b5..6069cfad 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -571,6 +571,15 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) } else if (Token == QLatin1String("LIGHT")) { + if (!Light) + Light = new lcLight(0.0f, 0.0f, 0.0f); + + if (Light->ParseLDrawLine(LineStream)) + { + Light->CreateName(mLights); + mLights.Add(Light); + Light = nullptr; + } } else if (Token == QLatin1String("GROUP")) { @@ -2949,6 +2958,15 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) } } +void lcModel::UpdateLight(lcLight* Light, const lcLightProperties Props, int Property) +{ + Light->UpdateLight(mCurrentStep, Props, Property); + + SaveCheckpoint(tr("Update Light")); + UpdateAllViews(); + gMainWindow->UpdateSelectedObjects(false); +} + void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) { if (Camera->IsOrtho() == Ortho) @@ -3011,6 +3029,19 @@ void lcModel::SetCameraName(lcCamera* Camera, const QString& Name) gMainWindow->UpdateCameraMenu(); } +void lcModel::SetLightName(lcLight* Light, const QString &Name) +{ + if (Light->GetName() == Name) + return; + + Light->SetName(Name); + + SaveCheckpoint(tr("Renaming Light")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); + gMainWindow->UpdateCameraMenu(); +} + bool lcModel::AnyPiecesSelected() const { for (const lcPiece* Piece : mPieces) @@ -3955,6 +3986,8 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) { case lcTool::Insert: case lcTool::Light: + case lcTool::AreaLight: + case lcTool::SunLight: break; case lcTool::SpotLight: @@ -4034,17 +4067,20 @@ void lcModel::PointLightToolClicked(const lcVector3& Position) SaveCheckpoint(tr("New Light")); } -void lcModel::BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target) +void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, int LightType) { - lcLight* Light = new lcLight(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2]); + lcLight* Light = new lcLight(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2], LightType); + Light->CreateName(mLights); mLights.Add(Light); mMouseToolDistance = Target; ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_TARGET, false); + QString light(LightType == LC_AREALIGHT ? "Arealight " : LightType == LC_SUNLIGHT ? "Sunlight " : "Spotlight "); + SaveCheckpoint(tr("%1").arg(light)); } -void lcModel::UpdateSpotLightTool(const lcVector3& Position) +void lcModel::UpdateDirectionalLightTool(const lcVector3& Position) { lcLight* Light = mLights[mLights.GetSize() - 1]; diff --git a/common/lc_model.h b/common/lc_model.h index 5ce41599..e92b1c03 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -302,8 +302,9 @@ class lcModel void EndMouseTool(lcTool Tool, bool Accept); void InsertPieceToolClicked(const lcMatrix44& WorldMatrix); void PointLightToolClicked(const lcVector3& Position); + void BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, int LightType); + void UpdateDirectionalLightTool(const lcVector3& Position); void BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target); - void UpdateSpotLightTool(const lcVector3& Position); void BeginCameraTool(const lcVector3& Position, const lcVector3& Target); void UpdateCameraTool(const lcVector3& Position); void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag); @@ -341,6 +342,8 @@ class lcModel void SetCameraZNear(lcCamera* Camera, float ZNear); void SetCameraZFar(lcCamera* Camera, float ZFar); void SetCameraName(lcCamera* Camera, const QString& Name); + void SetLightName(lcLight* Light, const QString& Name); + void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); void ShowPropertiesDialog(); void ShowSelectByNameDialog(); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 71d6c93c..370fe84a 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -3,6 +3,7 @@ #include "lc_viewwidget.h" #include #include "lc_mainwindow.h" +#include "light.h" #include "camera.h" #include "texfont.h" #include "lc_texture.h" @@ -1596,6 +1597,8 @@ lcTrackTool lcView::GetOverrideTrackTool(Qt::MouseButton Button) const { lcTrackTool::Insert, // lcTool::Insert lcTrackTool::PointLight, // lcTool::Light + lcTrackTool::AreaLight, // lcTool::AreaLight + lcTrackTool::SunLight, // lcTool::SunLight lcTrackTool::SpotLight, // lcTool::SpotLight lcTrackTool::Camera, // lcTool::Camera lcTrackTool::Select, // lcTool::Select @@ -1867,6 +1870,8 @@ lcCursor lcView::GetCursor() const lcCursor::Select, // lcTrackTool::None lcCursor::Brick, // lcTrackTool::Insert lcCursor::Light, // lcTrackTool::PointLight + lcCursor::Arealight, // lcTrackTool::AreaLight + lcCursor::Sunlight, // lcTrackTool::SunLight lcCursor::Spotlight, // lcTrackTool::SpotLight lcCursor::Camera, // lcTrackTool::Camera lcCursor::Select, // lcTrackTool::Select @@ -1921,6 +1926,8 @@ void lcView::SetCursor(lcCursor CursorType) { 0, 0, "" }, // lcCursor::Default { 8, 3, ":/resources/cursor_insert" }, // lcCursor::Brick { 15, 15, ":/resources/cursor_light" }, // lcCursor::Light + { 15, 15, ":/resources/cursor_arealight" }, // lcCursor::Arealight + { 15, 15, ":/resources/cursor_sunlight" }, // lcCursor::Sunlight { 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::Spotlight { 15, 9, ":/resources/cursor_camera" }, // lcCursor::Camera { 0, 2, ":/resources/cursor_select" }, // lcCursor::Select @@ -1972,6 +1979,8 @@ lcTool lcView::GetCurrentTool() const lcTool::Select, // lcTrackTool::None lcTool::Insert, // lcTrackTool::Insert lcTool::Light, // lcTrackTool::PointLight + lcTool::AreaLight, // lcTrackTool::AreaLight + lcTool::SunLight, // lcTrackTool::SunLight lcTool::SpotLight, // lcTrackTool::SpotLight lcTool::Camera, // lcTrackTool::Camera lcTool::Select, // lcTrackTool::Select @@ -2036,6 +2045,14 @@ void lcView::UpdateTrackTool() NewTrackTool = lcTrackTool::PointLight; break; + case lcTool::AreaLight: + NewTrackTool = lcTrackTool::AreaLight;; + break; + + case lcTool::SunLight: + NewTrackTool = lcTrackTool::SunLight; + break; + case lcTool::SpotLight: NewTrackTool = lcTrackTool::SpotLight; break; @@ -2261,11 +2278,14 @@ void lcView::StartTracking(lcTrackButton TrackButton) case lcTool::Light: break; + case lcTool::AreaLight: + case lcTool::SunLight: case lcTool::SpotLight: { lcVector3 Position = GetCameraLightInsertPosition(); lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f); - ActiveModel->BeginSpotLightTool(Position, Target); + int LightType = Tool == lcTool::AreaLight ? LC_AREALIGHT : Tool == lcTool::SunLight ? LC_SUNLIGHT : LC_SPOTLIGHT; + ActiveModel->BeginDirectionalLightTool(Position, Target, LightType); } break; @@ -2325,6 +2345,8 @@ void lcView::StopTracking(bool Accept) case lcTool::Light: break; + case lcTool::AreaLight: + case lcTool::SunLight: case lcTool::SpotLight: case lcTool::Camera: ActiveModel->EndMouseTool(Tool, Accept); @@ -2452,6 +2474,8 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) } break; + case lcTrackTool::AreaLight: + case lcTrackTool::SunLight: case lcTrackTool::SpotLight: case lcTrackTool::Camera: StartTracking(TrackButton); @@ -2689,8 +2713,10 @@ void lcView::OnMouseMove() case lcTrackTool::PointLight: break; + case lcTrackTool::AreaLight: + case lcTrackTool::SunLight: case lcTrackTool::SpotLight: - ActiveModel->UpdateSpotLightTool(GetCameraLightInsertPosition()); + ActiveModel->UpdateDirectionalLightTool(GetCameraLightInsertPosition()); break; case lcTrackTool::Camera: diff --git a/common/lc_view.h b/common/lc_view.h index e7c8d27f..0227be62 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -18,6 +18,8 @@ enum class lcCursor Default, Brick, Light, + Arealight, + Sunlight, Spotlight, Camera, Select, @@ -51,6 +53,8 @@ enum class lcTrackTool None, Insert, PointLight, + AreaLight, + SunLight, SpotLight, Camera, Select, diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index e26ce898..84ef75db 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -674,6 +674,8 @@ bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 Allowe case lcTrackTool::None: case lcTrackTool::Insert: case lcTrackTool::PointLight: + case lcTrackTool::AreaLight: + case lcTrackTool::SunLight: case lcTrackTool::SpotLight: case lcTrackTool::Camera: case lcTrackTool::Select: diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index a19c3f9b..7c562a1d 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -160,7 +160,7 @@ void lcQPropertiesTreeDelegate::paint(QPainter *painter, const QStyleOptionViewI QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); painter->save(); painter->setPen(QPen(color)); - + if (!m_treeWidget || (!m_treeWidget->lastColumn(index.column()) && hasValue)) { int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left(); @@ -457,6 +457,31 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return editor; } + case PropertyFloatLightSpotSize: + { + QLineEdit *editor = new QLineEdit(parent); + float value = item->data(0, PropertyValueRole).toFloat(); + + editor->setValidator(new QDoubleValidator(1.0, 180.0,1, editor)); + editor->setText(lcFormatValueLocalized(value)); + editor->setToolTip(tr("Angle of the spotlight beam.")); + + connect(editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); + return editor; + } + + case PropertyFloatReadOnly: + { + QLineEdit *editor = new QLineEdit(parent); + float value = item->data(0, PropertyValueRole).toFloat(); + + editor->setText(lcFormatValueLocalized(value)); + editor->setReadOnly(true); + editor->setToolTip(tr("Property is read only")); + + return editor; + } + case PropertyStep: { QLineEdit* Editor = new QLineEdit(parent); @@ -495,6 +520,49 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return editor; } + case PropertyStringLightReadOnly: + { + QLineEdit *editor = new QLineEdit(parent); + const char *value = (const char*)item->data(0, PropertyValueRole).value(); + + editor->setText(value); + editor->setReadOnly(true); + editor->setToolTip(tr("Property is read only")); + + return editor; + } + + case PropertyLightShape: + { + QComboBox *editor = new QComboBox(parent); + + editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); + editor->setMinimumContentsLength(1); + + QStringList shapes = { "Square", "Disk", "Rectangle", "Ellipse"}; + for (int i = 0; i < shapes.size(); i++) + editor->addItem(shapes.at(i), QVariant::fromValue(i)); + + int value = item->data(0, PropertyValueRole).toInt(); + editor->setCurrentIndex(value); + + connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); + + return editor; + } + + case PropertyLightColor: + { + QPushButton *editor = new QPushButton(parent); + QColor value = item->data(0, PropertyValueRole).value(); + + updateLightColorEditor(editor, value); + + connect(editor, SIGNAL(clicked()), this, SLOT(slotColorButtonClicked())); + + return editor; + } + case PropertyColor: { QPushButton *editor = new QPushButton(parent); @@ -567,10 +635,28 @@ void lcQPropertiesTree::updateColorEditor(QPushButton *editor, int value) const editor->setText(color->Name); } +void lcQPropertiesTree::updateLightColorEditor(QPushButton *editor, QColor color) const +{ + QImage img(12, 12, QImage::Format_ARGB32); + img.fill(0); + + QPainter painter(&img); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.setPen(Qt::darkGray); + painter.setBrush(color); + painter.drawRect(0, 0, img.width() - 1, img.height() - 1); + painter.end(); + + editor->setStyleSheet("Text-align:left"); + editor->setIcon(QPixmap::fromImage(img)); + editor->setText(color.name().toUpper()); +} + void lcQPropertiesTree::slotToggled(bool Value) { QTreeWidgetItem* Item = m_delegate->editedItem(); lcModel* Model = gMainWindow->GetActiveModel(); + lcObject* Focus = Model->GetFocusObject(); if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA) { @@ -586,6 +672,30 @@ void lcQPropertiesTree::slotToggled(bool Value) } } } + else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) + { + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; + + if (Light) + { + lcLightProperties Props = Light->GetLightProperties(); + if (Item == lightEnableCutoff) + { + Props.mEnableCutoff = Value; + Model->UpdateLight(Light, Props, LC_LIGHT_USE_CUTOFF); + } + else if (Item == lightPOVRay) + { + Props.mPOVRayLight = Value; + Model->UpdateLight(Light, Props, LC_LIGHT_POVRAY); + } + else if (Item == lightShadowless) + { + Props.mShadowless = Value; + Model->UpdateLight(Light, Props, LC_LIGHT_SHADOWLESS); + } + } + } } void lcQPropertiesTree::slotReturnPressed() @@ -744,6 +854,102 @@ void lcQPropertiesTree::slotReturnPressed() } } } + else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) + { + lcLight* Light = (mFocus && mFocus->IsLight()) ? (lcLight*)mFocus : nullptr; + + if (Light) + { + lcLightProperties Props = Light->GetLightProperties(); + + QString Name = Light->GetName(); + + if (Item == lightPositionX || Item == lightPositionY || Item == lightPositionZ) + { + lcVector3 Center = Light->mPosition; + lcVector3 Position = Center; + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightPositionX) + Position[0] = Value; + else if (Item == lightPositionY) + Position[1] = Value; + else if (Item == lightPositionZ) + Position[2] = Value; + + lcVector3 Distance = Position - Center; + + Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); + } + else if (Item == lightTargetX || Item == lightTargetY || Item == lightTargetZ) + { + lcVector3 Center = Light->mTargetPosition; + lcVector3 Position = Center; + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightTargetX) + Position[0] = Value; + else if (Item == lightTargetY) + Position[1] = Value; + else if (Item == lightTargetZ) + Position[2] = Value; + + lcVector3 Distance = Position - Center; + + Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); + } + else if (Item == lightColorR || Item == lightColorG || Item == lightColorB) + { + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightColorR) + Props.mLightColor[0] = Value; + else if (Item == lightColorG) + Props.mLightColor[2] = Value; + else if (Item == lightColorB) + Props.mLightColor[1] = Value; + + Model->UpdateLight(Light, Props, LC_LIGHT_COLOR); + } + else if (Item == lightFactorA || Item == lightFactorB) + { + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightFactorA) + Props.mLightFactor[0] = Value; + else if (Item == lightFactorB) + Props.mLightFactor[1] = Value; + + Model->UpdateLight(Light, Props, LC_LIGHT_FACTOR); + } + else if (Item == lightSpecular) + { + Props.mLightSpecular = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_SPECULAR); + } + else if (Item == lightExponent) + { + Props.mSpotExponent = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_EXPONENT); + } + else if (Item == lightCutoff) + { + Props.mSpotCutoff = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_CUTOFF); + } + else if (Item == lightSpotSize) + { + Props.mSpotSize = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_SPOT_SIZE); + } + else if (Item == lightName) + { + QString Value = Editor->text(); + + Model->SetLightName(Light, Value.toLocal8Bit().data()); + } + } + } } void lcQPropertiesTree::slotSetValue(int Value) @@ -775,6 +981,37 @@ void lcQPropertiesTree::slotSetValue(int Value) gMainWindow->PreviewPiece(Info->mFileName, ColorCode, false); } } + else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) + { + lcObject* Focus = Model->GetFocusObject(); + + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; + + if (Light && Item == lightShape) + { + lcLightProperties Props = Light->GetLightProperties(); + Props.mLightShape = static_cast(Value); + Model->UpdateLight(Light, Props, LC_LIGHT_SHAPE); + } + } +} + +void lcQPropertiesTree::slotSetColorValue(QColor Value) +{ + lcModel* Model = gMainWindow->GetActiveModel(); + lcObject* Focus = Model->GetFocusObject(); + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; + if (Light) + { + float r = Value.red(); + float g = Value.green(); + float b = Value.blue(); + lcVector3 Color(r/255, g/255, b/255); + + lcLightProperties Props = Light->GetLightProperties(); + Props.mLightColor = Color; + Model->UpdateLight(Light, Props, LC_LIGHT_COLOR); + } } void lcQPropertiesTree::slotColorButtonClicked() @@ -882,6 +1119,31 @@ void lcQPropertiesTree::SetEmpty() cameraFar = nullptr; cameraName = nullptr; + lightPosition = nullptr; + lightPositionX = nullptr; + lightPositionY = nullptr; + lightPositionZ = nullptr; + lightTarget = nullptr; + lightTargetX = nullptr; + lightTargetY = nullptr; + lightTargetZ = nullptr; + lightColor = nullptr; + lightColorIcon = nullptr; + lightColorR = nullptr; + lightColorG = nullptr; + lightColorB = nullptr; + lightProperties = nullptr; + lightSpecular = nullptr; + lightCutoff = nullptr; + lightEnableCutoff = nullptr; + lightExponent = nullptr; + lightType = nullptr; + lightFactorA = nullptr; + lightFactorB = nullptr; + lightName = nullptr; + lightSpotSize = nullptr; + lightShape = nullptr; + mWidgetMode = LC_PROPERTY_WIDGET_EMPTY; mFocus = nullptr; } @@ -1110,12 +1372,241 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus) void lcQPropertiesTree::SetLight(lcObject* Focus) { - Q_UNUSED(Focus); + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; + + QString Name = tr("Light"); + QString FactorALabel = tr("FactorA"); + QString ExponentLabel = tr("Exponent"); + QString Type, Shape, FactorAToolTip, FactorBToolTip; + lcLightType LightIndex = LC_UNDEFINED_LIGHT; + lcLightShape ShapeIndex = LC_LIGHT_SHAPE_UNDEFINED; + float SpotSize = 0.0f; + float Specular = 0.0f; + float Cutoff = 0.0f; + float Exponent = 0.0f; + bool EnableCutoff = false; + PropertyType TargetProperty = PropertyFloat; + lcVector3 Position(0.0f, 0.0f, 0.0f); + lcVector3 Target(0.0f, 0.0f, 0.0f); + lcVector3 Color(0.0f, 0.0f, 0.0f); + lcVector2 Factor(0.0f, 0.0f); - SetEmpty(); - mFocus = nullptr; + if (Light) + { + Name = Light->GetName(); + + Position = Light->mPosition; // normalizeDegrees(Light->mPosition); + Target = Light->mTargetPosition; // normalizeDegrees(Light->mTargetPosition); + Color = Light->mLightColor; + Factor = Light->mLightFactor; + LightIndex = static_cast(Light->mLightType); + + switch(LightIndex) + { + case LC_POINTLIGHT: + Type = QLatin1String("Point"); + FactorALabel = tr("Radius (m)"); + FactorAToolTip = tr("Shadow soft size - Light size for shadow sampling"); + break; + case LC_AREALIGHT: + Type = QLatin1String("Area"); + FactorALabel = tr("Width (X)"); + FactorAToolTip = tr("Size of the area of the area light. X direction size for rectangular shapes"); + FactorBToolTip = tr("Size of the area of the area light. Y direction size for rectangular shapes"); + break; + case LC_SUNLIGHT: + Type = QLatin1String("Sun"); + FactorALabel = tr("Angle (°)"); + FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth"); + break; + case LC_SPOTLIGHT: + Type = QLatin1String("Spot"); + FactorALabel = tr("Radius (m)"); + FactorAToolTip = tr("Shadow soft size - Light size for shadow sampling"); + FactorBToolTip = tr("Shadow blend - The softness of the spotlight edge"); + break; + default: + Type = QLatin1String("Undefined"); + FactorALabel = tr("FactorA"); + break; + } + + ShapeIndex = static_cast(Light->mLightShape); + switch(ShapeIndex) + { + case LC_LIGHT_SHAPE_SQUARE: + Shape = QLatin1String("Square"); + break; + case LC_LIGHT_SHAPE_DISK: + Shape = QLatin1String("Disk"); + break; + case LC_LIGHT_SHAPE_RECTANGLE: + Shape = QLatin1String("Rectangle"); + break; + case LC_LIGHT_SHAPE_ELLIPSE: + Shape = QLatin1String("Ellipse"); + break; + default: + break; + } + + Specular = Light->mLightSpecular; + Exponent = Light->mSpotExponent; + ExponentLabel = LightIndex ? LightIndex == LC_SUNLIGHT ? tr("Strength") : tr("Power") : tr("Exponent"); + Cutoff = Light->mSpotCutoff; + EnableCutoff = Light->mEnableCutoff; + TargetProperty = Light->mLightType > LC_POINTLIGHT ? PropertyFloat : PropertyFloatReadOnly; + SpotSize = Light->mSpotSize; + } + + if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightIndex || mLightShape != ShapeIndex) + { + SetEmpty(); + // Position + lightPosition = addProperty(nullptr, tr("Position"), PropertyGroup); + lightPositionX = addProperty(lightPosition, tr("X"), PropertyFloat); + lightPositionY = addProperty(lightPosition, tr("Y"), PropertyFloat); + lightPositionZ = addProperty(lightPosition, tr("Z"), PropertyFloat); + // Target Position + if (LightIndex != LC_POINTLIGHT) + { + lightTarget = addProperty(nullptr, tr("Target"), PropertyGroup); + lightTargetX = addProperty(lightTarget, tr("X"), TargetProperty); + lightTargetY = addProperty(lightTarget, tr("Y"), TargetProperty); + lightTargetZ = addProperty(lightTarget, tr("Z"), TargetProperty); + } + // Ambient Colour + lightColor = addProperty(nullptr, tr("Color"), PropertyGroup); + lightColorIcon = addProperty(lightColor, tr("Name"), PropertyLightColor); + lightColorR = addProperty(lightColor, tr("Red"), PropertyFloat); + lightColorG = addProperty(lightColor, tr("Green"), PropertyFloat); + lightColorB = addProperty(lightColor, tr("Blue"), PropertyFloat); + // Properties + lightProperties = addProperty(nullptr, tr("Properties"), PropertyGroup); + lightType = addProperty(lightProperties, tr("Type"), PropertyStringLightReadOnly); + lightExponent = addProperty(lightProperties, ExponentLabel, PropertyFloat); + lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); + if (LightIndex == LC_AREALIGHT) + { + if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE) + lightFactorB = addProperty(lightProperties, tr("Height (Y)"), PropertyFloat); + lightShape = addProperty(lightProperties, tr("Shape"), PropertyLightShape); + } + else if (LightIndex == LC_SPOTLIGHT) + { + lightFactorB = addProperty(lightProperties, tr("Spot Blend"), PropertyFloat); + lightSpotSize = addProperty(lightProperties, tr("Spot Size (°)"), PropertyFloatLightSpotSize); + } + if (LightIndex != LC_SUNLIGHT) + { + lightEnableCutoff = addProperty(lightProperties, tr("Cutoff"), PropertyBool); + lightCutoff = addProperty(lightProperties, tr("Cutoff Distance"), PropertyFloat); + } + lightSpecular = addProperty(lightProperties, tr("Specular"), PropertyFloat); + lightName = addProperty(lightProperties, tr("Name"), PropertyString); + + mWidgetMode = LC_PROPERTY_WIDGET_LIGHT; + mLightType = LightIndex; + mLightShape = ShapeIndex; + } + + mFocus = Light; + + lightPositionX->setText(1, lcFormatValueLocalized(Position[0])); + lightPositionX->setData(0, PropertyValueRole, Position[0]); + lightPositionY->setText(1, lcFormatValueLocalized(Position[1])); + lightPositionY->setData(0, PropertyValueRole, Position[1]); + lightPositionZ->setText(1, lcFormatValueLocalized(Position[2])); + lightPositionZ->setData(0, PropertyValueRole, Position[2]); + + if (LightIndex != LC_POINTLIGHT) + { + lightTargetX->setText(1, lcFormatValueLocalized(Target[0])); + lightTargetX->setData(0, PropertyValueRole, Target[0]); + lightTargetY->setText(1, lcFormatValueLocalized(Target[1])); + lightTargetY->setData(0, PropertyValueRole, Target[1]); + lightTargetZ->setText(1, lcFormatValueLocalized(Target[2])); + lightTargetZ->setData(0, PropertyValueRole, Target[2]); + } + + QImage img(16, 16, QImage::Format_ARGB32); + img.fill(0); + + QColor RgbColor = QColor::fromRgb(int(Color[1]*255), int(Color[1]*255), int(Color[2]*255)); + + QPainter painter(&img); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.setPen(Qt::darkGray); + painter.setBrush(RgbColor); + painter.drawRect(0, 0, img.width() - 1, img.height() - 1); + painter.end(); + + lightColorIcon->setIcon(1, QIcon(QPixmap::fromImage(img))); + lightColorIcon->setText(1, RgbColor.name().toUpper()); + lightColorIcon->setData(0, PropertyValueRole, RgbColor); + + lightColorR->setText(1, lcFormatValueLocalized(Color[0])); + lightColorR->setData(0, PropertyValueRole, Color[0]); + lightColorR->setToolTip(1, tr("Red color component - use .0 - 1 format")); + lightColorG->setText(1, lcFormatValueLocalized(Color[1])); + lightColorG->setData(0, PropertyValueRole, Color[1]); + lightColorG->setToolTip(1, tr("Green color component - use .0 - 1 format")); + lightColorB->setText(1, lcFormatValueLocalized(Color[2])); + lightColorB->setData(0, PropertyValueRole, Color[2]); + lightColorB->setToolTip(1, tr("Blue color component - use .0 - 1 format")); + + lightType->setText(1, Type); + lightType->setData(0, PropertyValueRole, Type); + + lightExponent->setText(1, lcFormatValueLocalized(Exponent)); + lightExponent->setData(0, PropertyValueRole, Exponent); + lightExponent->setToolTip(1, tr("Intensity of the light in Watts.")); + + lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); + lightFactorA->setData(0, PropertyValueRole, Factor[0]); + lightFactorA->setToolTip(1, FactorAToolTip); + + if (LightIndex == LC_AREALIGHT) + { + if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE) + { + lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); + lightFactorB->setData(0, PropertyValueRole, Factor[1]); + lightFactorB->setToolTip(1, FactorBToolTip); + } + + lightShape->setText(1, Shape); + lightShape->setData(0, PropertyValueRole, ShapeIndex); + lightShape->setToolTip(1, tr("Shape of the arealight.")); + + } + else if (LightIndex == LC_SPOTLIGHT) + { + lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); + lightFactorB->setData(0, PropertyValueRole, Factor[1]); + lightFactorB->setToolTip(1, FactorBToolTip); + + lightSpotSize->setText(1, lcFormatValueLocalized(SpotSize)); + lightSpotSize->setData(0, PropertyValueRole, SpotSize); + lightSpotSize->setToolTip(1, tr("Angle of the spotlight beam.")); + } + + if (LightIndex != LC_SUNLIGHT) + { + lightEnableCutoff->setText(1, EnableCutoff ? "True" : "False"); + lightEnableCutoff->setData(0, PropertyValueRole, EnableCutoff); + + lightCutoff->setText(1, lcFormatValueLocalized(Cutoff)); + lightCutoff->setData(0, PropertyValueRole, Cutoff); + lightCutoff->setToolTip(1, tr("Distance at which the light influence will be set to 0.")); + } + + lightSpecular->setText(1, lcFormatValueLocalized(Specular)); + lightSpecular->setData(0, PropertyValueRole, Specular); + lightSpecular->setToolTip(1, tr("Specular reflection multiplier factor.")); - // todo: light properties + lightName->setText(1, Name); + lightName->setData(0, PropertyValueRole, QVariant::fromValue(Name)); } void lcQPropertiesTree::SetMultiple() diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 7ea77165..5b06a330 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -44,8 +44,13 @@ class lcQPropertiesTree : public QTreeWidget PropertyGroup, PropertyBool, PropertyFloat, + PropertyFloatReadOnly, + PropertyFloatLightSpotSize, PropertyStep, PropertyString, + PropertyStringLightReadOnly, + PropertyLightShape, + PropertyLightColor, PropertyColor, PropertyPart }; @@ -55,12 +60,14 @@ protected slots: void slotReturnPressed(); void slotSetValue(int value); void slotColorButtonClicked(); + void slotSetColorValue(QColor Value); protected: void keyPressEvent(QKeyEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void updateColorEditor(QPushButton *editor, int value) const; + void updateLightColorEditor(QPushButton *editor, QColor color) const; QTreeWidgetItem *addProperty(QTreeWidgetItem *parent, const QString& label, PropertyType propertyType); @@ -72,6 +79,9 @@ protected slots: void getPartProperties(lcPartProperties *properties); + int mLightType; + int mLightShape; + lcPropertyWidgetMode mWidgetMode; lcObject* mFocus; @@ -113,6 +123,31 @@ protected slots: QTreeWidgetItem *cameraNear; QTreeWidgetItem *cameraFar; QTreeWidgetItem *cameraName; + + QTreeWidgetItem *lightPosition; + QTreeWidgetItem *lightPositionX; + QTreeWidgetItem *lightPositionY; + QTreeWidgetItem *lightPositionZ; + QTreeWidgetItem *lightTarget; + QTreeWidgetItem *lightTargetX; + QTreeWidgetItem *lightTargetY; + QTreeWidgetItem *lightTargetZ; + QTreeWidgetItem *lightColor; + QTreeWidgetItem *lightColorIcon; + QTreeWidgetItem *lightColorR; + QTreeWidgetItem *lightColorG; + QTreeWidgetItem *lightColorB; + QTreeWidgetItem *lightProperties; + QTreeWidgetItem *lightSpecular; + QTreeWidgetItem *lightCutoff; + QTreeWidgetItem *lightEnableCutoff; + QTreeWidgetItem *lightExponent; + QTreeWidgetItem *lightType; + QTreeWidgetItem *lightSpotSize; + QTreeWidgetItem *lightShape; + QTreeWidgetItem *lightFactorA; + QTreeWidgetItem *lightFactorB; + QTreeWidgetItem *lightName; }; class lcQPropertiesTreeDelegate : public QItemDelegate From 00a3ad71472bbca13fe868c36c4f3c5685cd9991 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Wed, 5 Jul 2023 03:13:47 +0200 Subject: [PATCH 08/42] Blender lights - actions --- common/lc_mainwindow.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 759e7871..4bc9aff9 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -206,6 +206,16 @@ void lcMainWindow::CreateActions() EditActionLightIcon.addFile(":/resources/action_light_16.png"); mActions[LC_EDIT_ACTION_LIGHT]->setIcon(EditActionLightIcon); + QIcon EditActionArealightIcon; + EditActionArealightIcon.addFile(":/resources/action_arealight.png"); + EditActionArealightIcon.addFile(":/resources/action_arealight_16.png"); + mActions[LC_EDIT_ACTION_AREALIGHT]->setIcon(EditActionArealightIcon); + + QIcon EditActionSunlightIcon; + EditActionSunlightIcon.addFile(":/resources/action_sunlight.png"); + EditActionSunlightIcon.addFile(":/resources/action_sunlight_16.png"); + mActions[LC_EDIT_ACTION_SUNLIGHT]->setIcon(EditActionSunlightIcon); + QIcon EditActionSpotLightIcon; EditActionSpotLightIcon.addFile(":/resources/action_spotlight.png"); EditActionSpotLightIcon.addFile(":/resources/action_spotlight_16.png"); @@ -422,6 +432,8 @@ void lcMainWindow::CreateMenus() mToolsMenu = new QMenu(tr("Tools"), this); mToolsMenu->addAction(mActions[LC_EDIT_ACTION_INSERT]); mToolsMenu->addAction(mActions[LC_EDIT_ACTION_LIGHT]); + mToolsMenu->addAction(mActions[LC_EDIT_ACTION_AREALIGHT]); + mToolsMenu->addAction(mActions[LC_EDIT_ACTION_SUNLIGHT]); mToolsMenu->addAction(mActions[LC_EDIT_ACTION_SPOTLIGHT]); mToolsMenu->addAction(mActions[LC_EDIT_ACTION_CAMERA]); mToolsMenu->addSeparator(); @@ -665,6 +677,8 @@ void lcMainWindow::CreateToolBars() insertToolBarBreak(mToolsToolBar); mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_INSERT]); mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_LIGHT]); + mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_AREALIGHT]); + mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_SUNLIGHT]); mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_SPOTLIGHT]); mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_CAMERA]); mToolsToolBar->addSeparator(); @@ -3366,6 +3380,14 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) SetTool(lcTool::Light); break; + case LC_EDIT_ACTION_AREALIGHT: + SetTool(lcTool::AreaLight); + break; + + case LC_EDIT_ACTION_SUNLIGHT: + SetTool(lcTool::SunLight); + break; + case LC_EDIT_ACTION_SPOTLIGHT: SetTool(lcTool::SpotLight); break; From 415354bfe88533b37b88a6c9e1b4b37a5360207d Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Thu, 3 Aug 2023 18:54:06 +0200 Subject: [PATCH 09/42] Blender lights - merge spot light and directional lights --- common/lc_model.cpp | 2 +- common/light.cpp | 439 ++++++++++++++++++++++++-------------------- common/light.h | 19 +- 3 files changed, 251 insertions(+), 209 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 6069cfad..56909b48 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3163,7 +3163,7 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota Center += Light->GetSectionPosition(LC_LIGHT_SECTION_POSITION); NumSelected++; - if (Light->IsSpotLight() || Light->IsDirectionalLight()) + if (Light->IsDirectionalLight()) { Center += Light->GetSectionPosition(LC_LIGHT_SECTION_TARGET); NumSelected++; diff --git a/common/light.cpp b/common/light.cpp index fbf11ec2..6865cd3d 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -11,7 +11,8 @@ #define LC_LIGHT_POSITION_EDGE 7.5f #define LC_LIGHT_TARGET_EDGE 5.0f #define LC_LIGHT_SPHERE_RADIUS 5.0f -#define LC_LIGHT_BASEFACE_EDGE 12.5f +#define LC_LIGHT_SUN_RADIUS 8.5f +#define LC_LIGHT_SPOT_BASE_EDGE 12.5f // New omni light. lcLight::lcLight(float px, float py, float pz) @@ -21,15 +22,11 @@ lcLight::lcLight(float px, float py, float pz) UpdatePosition(1); } -// New directional or spot light. +// New directional light. lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType) : lcObject(lcObjectType::Light) { Initialize(lcVector3(px, py, pz), lcVector3(tx, ty, tz), LightType); - if (LightType == LC_SPOTLIGHT) - mState |= LC_LIGHT_SPOT; - else - mState |= LC_LIGHT_DIRECTIONAL; UpdatePosition(1); } @@ -41,10 +38,8 @@ void lcLight::SetLightState(int LightType) { case LC_AREALIGHT: case LC_SUNLIGHT: - mState |= LC_LIGHT_DIRECTIONAL; - break; case LC_SPOTLIGHT: - mState |= LC_LIGHT_SPOT; + mState |= LC_LIGHT_DIRECTIONAL; break; default: break; @@ -152,10 +147,11 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; break; case LC_SPOTLIGHT: - if (mLightFactorKeys.GetSize() > 1) { + if (mLightFactorKeys.GetSize() > 1) mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); - } else { - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + else + { + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << (mPOVRayLight ? SpotRadius : mLightFactor[0]) << LineEnding; Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; } if (mLightSpotSizeKeys.GetSize() > 1) @@ -164,17 +160,19 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; break; case LC_AREALIGHT: - if (mLightFactorKeys.GetSize() > 1) { + if (mLightFactorKeys.GetSize() > 1) mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); - } else { + else + { if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE) Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding; else Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding; } - if (mLightShapeKeys.GetSize() > 1) { + if (mLightShapeKeys.GetSize() > 1) mLightShapeKeys.SaveKeysLDraw(Stream, "LIGHT SHAPE_KEY "); - } else { + else + { Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE "); QString Shape = QLatin1String("Undefined "); @@ -203,15 +201,14 @@ void lcLight::SaveLDraw(QTextStream& Stream) const } if (mLightTypeKeys.GetSize() > 1) - { mLightTypeKeys.SaveKeysLDraw(Stream, "LIGHT TYPE_KEY "); - } else { Stream << QLatin1String("0 !LEOCAD LIGHT TYPE "); QString Type = QLatin1String("Undefined "); - switch(mLightType){ + switch(mLightType) + { case LC_POINTLIGHT: Type = QLatin1String("Point "); break; @@ -376,24 +373,30 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) mName.replace("\"", ""); // Set default settings per light type - if (mLightType == LC_SPOTLIGHT) { - if (!mSpotBlendSet) { + if (mLightType == LC_SPOTLIGHT) + { + if (!mSpotBlendSet) + { mLightFactor[1] = 0.15f; mLightFactorKeys.ChangeKey(mLightFactor, 1, true); } } if (mLightType == LC_AREALIGHT && (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE)) { - if (!mHeightSet) { + if (!mHeightSet) + { mLightFactor[1] = 0.25f; mLightFactorKeys.ChangeKey(mLightFactor, 1, true); } } - if (mLightType == LC_SUNLIGHT) { - if (!mAngleSet) { + if (mLightType == LC_SUNLIGHT) + { + if (!mAngleSet) + { mLightFactor[0] = 11.4f; mLightFactorKeys.ChangeKey(mLightFactor, 1, true); } - if (!mSpotCutoffSet) { + if (!mSpotCutoffSet) + { mSpotCutoff = 0.0f; mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); } @@ -425,7 +428,8 @@ void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max) void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) { - switch(Property){ + switch(Property) + { case LC_LIGHT_SHAPE: mLightShape = Props.mLightShape; mLightShapeKeys.ChangeKey(mLightShape, Step, false); @@ -664,10 +668,8 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const if (IsPointLight()) DrawPointLight(Context); - else if (IsDirectionalLight()) - DrawDirectionalLight(Context); else - DrawSpotLight(Context); + DrawDirectionalLight(Context); } void lcLight::DrawDirectionalLight(lcContext* Context) const @@ -694,210 +696,250 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const LightMatrix = lcMatrix44AffineInverse(LightMatrix); LightMatrix.SetTranslation(lcVector3(0, 0, 0)); - lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); + const lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); Context->SetWorldMatrix(LightViewMatrix); + float Length = FrontVector.Length(); + float Verts[(20 + 8 + 2 + 16) * 3]; float* CurVert = Verts; - for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) + if (mLightType != LC_SUNLIGHT) { - float c = cosf(float(EdgeIdx) / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; - float s = sinf(float(EdgeIdx) / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; - - *CurVert++ = c; - *CurVert++ = s; - *CurVert++ = LC_LIGHT_POSITION_EDGE; - *CurVert++ = c; - *CurVert++ = s; - *CurVert++ = -LC_LIGHT_POSITION_EDGE; - } + if (mLightType == LC_SPOTLIGHT) + { + for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) + { + float c = cosf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; + float s = sinf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; + + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } - if (mLightType == LC_SUNLIGHT) { + *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } + else if (mLightType == LC_AREALIGHT) + { + const float LC_LIGHT_AREA_EDGE = 5.0f; + const float LC_LIGHT_AREA_H_EDGE = 8.5f; + const float LC_LIGHT_AREA_W_EDGE = 17.0f; + + *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + + *CurVert++ = -LC_LIGHT_AREA_H_EDGE; *CurVert++ = -LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_H_EDGE; *CurVert++ = -LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_AREA_H_EDGE; *CurVert++ = LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = -LC_LIGHT_AREA_H_EDGE; *CurVert++ = LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + } - // set base face to same size (LC_LIGHT_TARGET_EDGE) as body - was 12.5f - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - } else { + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; - *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = -LC_LIGHT_BASEFACE_EDGE; *CurVert++ = LC_LIGHT_BASEFACE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); } + int BaseIndices = 0; - float Length = FrontVector.Length(); - - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; - - const GLushort Indices[56 + 24 + 2 + 40] = + if (mLightType == LC_SPOTLIGHT) + { + BaseIndices = 56; + const GLushort Indices[56 + 24 + 2 + 40] = { - // base body 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1, - // base face 16, 17, 17, 18, 18, 19, 19, 16, - // targe box 20, 21, 21, 22, 22, 23, 23, 20, 24, 25, 25, 26, 26, 27, 27, 24, 20, 24, 21, 25, 22, 26, 23, 27, - // target line - from base to target 28, 29, + 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, + 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 30, + 28, 30, 28, 34, 28, 38, 28, 42 }; - Context->SetVertexBufferPointer(Verts); - Context->SetVertexFormatPosition(3); - Context->SetIndexBufferPointer(Indices); - - const lcPreferences& Preferences = lcGetPreferences(); - const float LineWidth = Preferences.mLineWidth; - const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); - const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); - const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); - - if (!IsSelected()) + Context->SetIndexBufferPointer(Indices); + } + else if (mLightType == LC_AREALIGHT) { - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); + BaseIndices = 32; + const GLushort Indices[32 + 24 + 2] = + { + 0, 1, 1, 2, 2, 3, 3, 0, + 4, 5, 5, 6, 6, 7, 7, 4, + 0, 4, 1, 5, 2, 6, 3, 7, + 8, 9, 9, 10, 10, 11, 11, 8, + 12, 13, 13, 14, 14, 15, 15, 12, + 16, 17, 17, 18, 18, 19, 19, 16, + 12, 16, 13, 17, 14, 18, 15, 19, + 20, 21 + }; - Context->DrawIndexedPrimitives(GL_LINES, 56 + 24 + 2, GL_UNSIGNED_SHORT, 0); + Context->SetIndexBufferPointer(Indices); } - else + else if (mLightType == LC_SUNLIGHT) { - if (IsSelected(LC_LIGHT_SECTION_POSITION)) - { - Context->SetLineWidth(2.0f * LineWidth); - if (IsFocused(LC_LIGHT_SECTION_POSITION)) - Context->SetColor(FocusedColor); - else - Context->SetColor(SelectedColor); - } - else - { - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); - } + constexpr float Radius = LC_LIGHT_SUN_RADIUS; + constexpr int Slices = 9; // longitude + constexpr int Stacks = 9; // latitude + constexpr int NumSphereVertices = 918; // Slices * 2 * 3 * 3 + (Stacks - 2) * Slices * 4 * 3 + constexpr int NumSphereIndices = 306; // Slices * 2 + (Stacks - 1) * Slices * 2 * 2 - Context->DrawIndexedPrimitives(GL_LINES, 56, GL_UNSIGNED_SHORT, 0); + BaseIndices = NumSphereIndices; - if (IsSelected(LC_LIGHT_SECTION_TARGET)) + float Vertices[NumSphereVertices + 24 + 6]; + float *Vert = Vertices; + + quint16 Indices[NumSphereIndices + 24 + 2]; + quint16 *Indx = Indices; + + auto AddVertex = [&](float x, float y, float z) { - Context->SetLineWidth(2.0f * LineWidth); - if (IsFocused(LC_LIGHT_SECTION_TARGET)) - Context->SetColor(FocusedColor); - else - Context->SetColor(SelectedColor); - } - else + *Vert++ = x; + *Vert++ = y; + *Vert++ = z; + }; + + auto AddLineIndex = [&](quint16 v1, quint16 v2) { - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); - } + *Indx++ = v1; + *Indx++ = v2; + }; - Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 56 * 2); + std::vector WrkVertices; - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); + float Slice = LC_2PI / Slices; + float Stack = LC_PI / Stacks; + float SliceAngle, StackAngle; - Context->DrawIndexedPrimitives(GL_LINES, 2 + 40, GL_UNSIGNED_SHORT, (56 + 24) * 2); - } -} + for(int i = 0; i <= Stacks; ++i) + { + StackAngle = LC_PI / 2 - i * Stack; // starting from pi/2 to -pi/2 + float xy = Radius * cosf(StackAngle); + float z = Radius * sinf(StackAngle); -void lcLight::DrawSpotLight(lcContext* Context) const -{ - lcVector3 FrontVector(mTargetPosition - mPosition); - lcVector3 UpVector(1, 1, 1); + for(int j = 0; j <= Slices; ++j) // add (Slices+1) vertices per stack + { + SliceAngle = j * Slice; - if (fabs(FrontVector[0]) < fabs(FrontVector[1])) - { - if (fabs(FrontVector[0]) < fabs(FrontVector[2])) - UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); - } - else - { - if (fabs(FrontVector[1]) < fabs(FrontVector[2])) - UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); - } + lcVector3 Vertex; + Vertex.x = xy * cosf(SliceAngle); + Vertex.y = xy * sinf(SliceAngle); + Vertex.z = z; - lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); - LightMatrix = lcMatrix44AffineInverse(LightMatrix); - LightMatrix.SetTranslation(lcVector3(0, 0, 0)); + WrkVertices.push_back(Vertex); + } + } - const lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); - Context->SetWorldMatrix(LightViewMatrix); + int Index = 0; - float Verts[(20 + 8 + 2 + 16) * 3]; - float* CurVert = Verts; + lcVector3 v1, v2, v3, v4; - for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) - { - float c = cosf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; - float s = sinf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; - - *CurVert++ = c; - *CurVert++ = s; - *CurVert++ = LC_LIGHT_POSITION_EDGE; - *CurVert++ = c; - *CurVert++ = s; - *CurVert++ = -LC_LIGHT_POSITION_EDGE; - } + for(int i = 0; i < Stacks; ++i) + { + int vi1 = i * (Slices + 1); + int vi2 = (i + 1) * (Slices + 1); - *CurVert++ = -12.5f; *CurVert++ = -12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = 12.5f; *CurVert++ = -12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = 12.5f; *CurVert++ = 12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = -12.5f; *CurVert++ = 12.5f; *CurVert++ = -LC_LIGHT_POSITION_EDGE; + for(int j = 0; j < Slices; ++j, ++vi1, ++vi2) + { + // 4 vertices per slice + // v1--v3 + // | | + // v2--v4 + v1 = WrkVertices[vi1]; + v2 = WrkVertices[vi2]; + v3 = WrkVertices[vi1 + 1]; + v4 = WrkVertices[vi2 + 1]; + + // if first stack or last stack, store 1 triangle per slice else, store 2 triangles (1 quad) per slice + if(i == 0) + { + // first stack triangle v1-v2-v4 + AddVertex(v1.x, v1.y, v1.z); + AddVertex(v2.x, v2.y, v2.z); + AddVertex(v4.x, v4.y, v4.z); - float Length = FrontVector.Length(); + // only vertical lines for first stack) + AddLineIndex(Index, Index+1); + + Index += 3; + } + else if(i == (Stacks-1)) + { + // last stack inverted triangle v1-v2-v3 + AddVertex(v1.x, v1.y, v1.z); + AddVertex(v2.x, v2.y, v2.z); + AddVertex(v3.x, v3.y, v3.z); - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; + // both vertical and horizontal lines for last stack + AddLineIndex(Index, Index+1); + AddLineIndex(Index, Index+2); - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; + Index += 3; + } + else + { + // 2 triangles (quad vertices v1-v2-v3-v4) for other stacks + AddVertex(v1.x, v1.y, v1.z); + AddVertex(v2.x, v2.y, v2.z); + AddVertex(v3.x, v3.y, v3.z); + AddVertex(v4.x, v4.y, v4.z); - const GLushort Indices[56 + 24 + 2 + 40] = - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, - 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1, - 16, 17, 17, 18, 18, 19, 19, 16, - 20, 21, 21, 22, 22, 23, 23, 20, - 24, 25, 25, 26, 26, 27, 27, 24, - 20, 24, 21, 25, 22, 26, 23, 27, - 28, 29, - 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, - 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 30, - 28, 30, 28, 34, 28, 38, 28, 42 - }; + // both vertical and horizontal lines for other stacks + AddLineIndex(Index, Index+1); + AddLineIndex(Index, Index+2); - Context->SetVertexBufferPointer(Verts); - Context->SetVertexFormatPosition(3); - Context->SetIndexBufferPointer(Indices); + Index += 4; + } + } + } + + AddVertex( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); + AddVertex(-LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); + AddVertex(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); + AddVertex( LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); + AddVertex( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); + AddVertex(-LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); + AddVertex(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); + AddVertex( LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); + AddVertex(0.0f, 0.0f, 0.0f); + AddVertex(0.0f, 0.0f, -Length); + + const int Idx[10] = { Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++ }; + AddLineIndex(Idx[0], Idx[1]); AddLineIndex(Idx[1], Idx[2]); AddLineIndex(Idx[2], Idx[3]); AddLineIndex(Idx[3], Idx[0]); + AddLineIndex(Idx[4], Idx[5]); AddLineIndex(Idx[5], Idx[6]); AddLineIndex(Idx[6], Idx[7]); AddLineIndex(Idx[7], Idx[4]); + AddLineIndex(Idx[0], Idx[4]); AddLineIndex(Idx[1], Idx[5]); AddLineIndex(Idx[2], Idx[6]); AddLineIndex(Idx[3], Idx[7]); + AddLineIndex(Idx[8], Idx[9]); + + Context->SetVertexBufferPointer(Vertices); + Context->SetVertexFormatPosition(3); + Context->SetIndexBufferPointer(Indices); + } const lcPreferences& Preferences = lcGetPreferences(); const float LineWidth = Preferences.mLineWidth; @@ -910,7 +952,7 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->SetLineWidth(LineWidth); Context->SetColor(LightColor); - Context->DrawIndexedPrimitives(GL_LINES, 56 + 24 + 2, GL_UNSIGNED_SHORT, 0); + Context->DrawIndexedPrimitives(GL_LINES, BaseIndices + 24 + 2, GL_UNSIGNED_SHORT, 0); } else { @@ -928,7 +970,7 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->SetColor(LightColor); } - Context->DrawIndexedPrimitives(GL_LINES, 56, GL_UNSIGNED_SHORT, 0); + Context->DrawIndexedPrimitives(GL_LINES, BaseIndices, GL_UNSIGNED_SHORT, 0); if (IsSelected(LC_LIGHT_SECTION_TARGET)) { @@ -944,21 +986,28 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->SetColor(LightColor); } - Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 56 * 2); + Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, BaseIndices * 2); Context->SetLineWidth(LineWidth); Context->SetColor(LightColor); - float Radius = tanf(LC_DTOR * mSpotCutoff) * Length; + int SpotCone = 0; - for (int EdgeIdx = 0; EdgeIdx < 16; EdgeIdx++) + if (mLightType == LC_SPOTLIGHT) { - *CurVert++ = cosf((float)EdgeIdx / 16 * LC_2PI) * Radius; - *CurVert++ = sinf((float)EdgeIdx / 16 * LC_2PI) * Radius; - *CurVert++ = -Length; + SpotCone = 40; + + float Radius = tanf(LC_DTOR * mSpotCutoff) * Length; + + for (int EdgeIdx = 0; EdgeIdx < 16; EdgeIdx++) + { + *CurVert++ = cosf((float)EdgeIdx / 16 * LC_2PI) * Radius; + *CurVert++ = sinf((float)EdgeIdx / 16 * LC_2PI) * Radius; + *CurVert++ = -Length; + } } - Context->DrawIndexedPrimitives(GL_LINES, 2 + 40, GL_UNSIGNED_SHORT, (56 + 24) * 2); + Context->DrawIndexedPrimitives(GL_LINES, 2 + SpotCone, GL_UNSIGNED_SHORT, (BaseIndices + 24) * 2); } } diff --git a/common/light.h b/common/light.h index 0163d8d2..f440c8dd 100644 --- a/common/light.h +++ b/common/light.h @@ -5,12 +5,11 @@ #define LC_LIGHT_HIDDEN 0x0001 #define LC_LIGHT_DISABLED 0x0002 -#define LC_LIGHT_SPOT 0x0004 -#define LC_LIGHT_DIRECTIONAL 0x0008 -#define LC_LIGHT_POSITION_SELECTED 0x0010 -#define LC_LIGHT_POSITION_FOCUSED 0x0020 -#define LC_LIGHT_TARGET_SELECTED 0x0040 -#define LC_LIGHT_TARGET_FOCUSED 0x0080 +#define LC_LIGHT_DIRECTIONAL 0x0004 +#define LC_LIGHT_POSITION_SELECTED 0x0008 +#define LC_LIGHT_POSITION_FOCUSED 0x0010 +#define LC_LIGHT_TARGET_SELECTED 0x0020 +#define LC_LIGHT_TARGET_FOCUSED 0x0040 #define LC_LIGHT_SELECTION_MASK (LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED) #define LC_LIGHT_FOCUS_MASK (LC_LIGHT_POSITION_FOCUSED | LC_LIGHT_TARGET_FOCUSED) @@ -79,12 +78,7 @@ class lcLight : public lcObject bool IsPointLight() const { - return (mState & (LC_LIGHT_SPOT | LC_LIGHT_DIRECTIONAL)) == 0; - } - - bool IsSpotLight() const - { - return (mState & LC_LIGHT_SPOT) != 0; + return (mState & LC_LIGHT_DIRECTIONAL) == 0; } bool IsDirectionalLight() const @@ -309,7 +303,6 @@ class lcLight : public lcObject void DrawDirectionalLight(lcContext* Context) const; void DrawPointLight(lcContext* Context) const; - void DrawSpotLight(lcContext* Context) const; void SetLightState(int LightType); quint32 mState; From 201d7e870ca15c0a6129e67d49820a593021cc29 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Mon, 7 Aug 2023 13:22:59 +0200 Subject: [PATCH 10/42] POVRay lights - lcLight --- common/light.cpp | 300 ++++++++++++++++++++++++++++++++++++++--------- common/light.h | 35 +++++- 2 files changed, 279 insertions(+), 56 deletions(-) diff --git a/common/light.cpp b/common/light.cpp index 6865cd3d..51e406d2 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -50,6 +50,8 @@ void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosit { SetLightState(LightType); + mPOVRayLight = false; + mShadowless = false; mEnableCutoff = false; mPosition = Position; mTargetPosition = TargetPosition; @@ -57,15 +59,21 @@ void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosit mDiffuseColor = lcVector4(0.8f, 0.8f, 0.8f, 1.0f); mSpecularColor = lcVector4(1.0f, 1.0f, 1.0f, 1.0f); mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); - mLightColor = lcVector3(1.0f, 1.0f, 1.0f); //RGB - White + mLightColor = lcVector3(1.0f, 1.0f, 1.0f); /*RGB - White*/ mLightType = LightType ? LightType : int(LC_POINTLIGHT); mLightFactor[0] = LightType ? LightType == LC_SUNLIGHT ? 11.4f : 0.25f : 0.0f; mLightFactor[1] = LightType == LC_AREALIGHT ? 0.25f : LightType == LC_SPOTLIGHT ? 0.150f : 0.0f; + mLightDiffuse = 1.0f; mLightSpecular = 1.0f; + mSpotExponent = 10.0f; + mPOVRayExponent = 1.0f; mSpotSize = 75.0f; - mLightShape = 0 /*Square*/; mSpotCutoff = LightType ? LightType != LC_SUNLIGHT ? 40.0f : 0.0f : 30.0f; - mSpotExponent = 10.0f; /*Energy/Power*/ + mSpotFalloff = 45.0f; + mSpotTightness = 0; + mAreaGrid = lcVector2(10.0f, 10.0f); + mAreaSize = lcVector2(200.0f, 200.0f); + mLightShape = LC_LIGHT_SHAPE_SQUARE; mPositionKeys.ChangeKey(mPosition, 1, true); mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); @@ -77,10 +85,14 @@ void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosit mLightColorKeys.ChangeKey(mLightColor, 1, true); mLightTypeKeys.ChangeKey(mLightType, 1, true); mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); + mSpotFalloffKeys.ChangeKey(mSpotFalloff, 1, true); mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); - mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, true); + mSpotSizeKeys.ChangeKey(mSpotSize, 1, true); + mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); + mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); } lcLight::~lcLight() @@ -91,46 +103,66 @@ void lcLight::SaveLDraw(QTextStream& Stream) const { const QLatin1String LineEnding("\r\n"); + if (mPOVRayLight) + Stream << QLatin1String("0 !LEOCAD LIGHT POV_RAY") << LineEnding; + + if (mShadowless) + Stream << QLatin1String("0 !LEOCAD LIGHT SHADOWLESS") << LineEnding; + if (mPositionKeys.GetSize() > 1) mPositionKeys.SaveKeysLDraw(Stream, "LIGHT POSITION_KEY "); else Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding; - if (mTargetPositionKeys.GetSize() > 1) - mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding; + if (mLightType != LC_POINTLIGHT && !(mLightType == LC_AREALIGHT && mPOVRayLight)) + { + if (mTargetPositionKeys.GetSize() > 1) + mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding; + } if (mLightColorKeys.GetSize() > 1) mLightColorKeys.SaveKeysLDraw(Stream, "LIGHT COLOR_RGB_KEY "); else Stream << QLatin1String("0 !LEOCAD LIGHT COLOR_RGB ") << mLightColor[0] << ' ' << mLightColor[1] << ' ' << mLightColor[2] << LineEnding; - if (mLightSpecularKeys.GetSize() > 1) - mLightSpecularKeys.SaveKeysLDraw(Stream, "LIGHT SPECULAR_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPECULAR ") << mLightSpecular << LineEnding; + if (!mPOVRayLight) + { + if (mLightDiffuseKeys.GetSize() > 1) + mLightDiffuseKeys.SaveKeysLDraw(Stream, "LIGHT DIFFUSE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT DIFFUSE ") << mLightDiffuse << LineEnding; + + if (mLightSpecularKeys.GetSize() > 1) + mLightSpecularKeys.SaveKeysLDraw(Stream, "LIGHT SPECULAR_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPECULAR ") << mLightSpecular << LineEnding; + } if (mLightType == LC_SUNLIGHT) { if (mSpotExponentKeys.GetSize() > 1) mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT STRENGTH_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << mSpotExponent << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << (mPOVRayLight ? mPOVRayExponent : mSpotExponent) << LineEnding; - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT ANGLE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT ANGLE ") << mLightFactor[0] << LineEnding; + if (!mPOVRayLight) + { + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT ANGLE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT ANGLE ") << mLightFactor[0] << LineEnding; + } } else { if (mSpotExponentKeys.GetSize() > 1) mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT POWER_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT POWER ") << mSpotExponent << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT POWER ") << (mPOVRayLight ? mPOVRayExponent : mSpotExponent) << LineEnding; - if (mEnableCutoff) + if (mEnableCutoff && !mPOVRayLight) { if (mSpotCutoffKeys.GetSize() > 1) mSpotCutoffKeys.SaveKeysLDraw(Stream, "LIGHT CUTOFF_DISTANCE_KEY "); @@ -141,33 +173,69 @@ void lcLight::SaveLDraw(QTextStream& Stream) const switch (mLightType) { case LC_POINTLIGHT: - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + if (!mPOVRayLight) + { + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + } break; case LC_SPOTLIGHT: - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); - else + if (mPOVRayLight) { - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << (mPOVRayLight ? SpotRadius : mLightFactor[0]) << LineEnding; - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << (mSpotSize - mSpotFalloff) << LineEnding; + if (mSpotFalloffKeys.GetSize() > 1) + mSpotFalloffKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_FALLOFF_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_FALLOFF ") << mSpotFalloff << LineEnding; + if (mSpotTightnessKeys.GetSize() > 1) + mSpotTightnessKeys.SaveKeysLDraw(Stream, "SPOT_TIGHTNESS_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_TIGHTNESS ") << mSpotTightness << LineEnding; } - if (mLightSpotSizeKeys.GetSize() > 1) - mLightSpotSizeKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_SIZE_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; + { + if (mSpotSizeKeys.GetSize() > 1) + mSpotSizeKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_SIZE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; + + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); + else + { + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; + } + } break; case LC_AREALIGHT: + if (mPOVRayLight) + { + if (mAreaGridKeys.GetSize() > 1) + mAreaGridKeys.SaveKeysLDraw(Stream, "LIGHT AREA_GRID_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT AREA_ROWS ") << mAreaGrid[0] << QLatin1String(" AREA_COLUMNS ") << mAreaGrid[1] << LineEnding; + } if (mLightFactorKeys.GetSize() > 1) mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); else { - if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE) - Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding; + if (mPOVRayLight) + { + Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mAreaSize[0] << QLatin1String(" HEIGHT ") << mAreaSize[1] << LineEnding; + } else - Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding; + { + if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE || mLightFactor[1] > 0) + Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding; + else + Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding; + } } if (mLightShapeKeys.GetSize() > 1) mLightShapeKeys.SaveKeysLDraw(Stream, "LIGHT SHAPE_KEY "); @@ -182,7 +250,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Shape = QLatin1String("Square "); break; case LC_LIGHT_SHAPE_DISK: - Shape = QLatin1String("Disk "); + Shape = mPOVRayLight ? QLatin1String("Circle ") : QLatin1String("Disk "); break; case LC_LIGHT_SHAPE_RECTANGLE: Shape = QLatin1String("Rectangle "); @@ -279,21 +347,64 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) { - Stream >> mSpotExponent; - mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); + if (mPOVRayLight) + { + Stream >> mPOVRayExponent; + mSpotExponentKeys.ChangeKey(mPOVRayExponent, 1, true); + } + else + { + Stream >> mSpotExponent; + mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); + } } else if (Token == QLatin1String("RADIUS") || Token == QLatin1String("SIZE") || Token == QLatin1String("WIDTH") || (mHeightSet = Token == QLatin1String("HEIGHT")) || (mSpotBlendSet = Token == QLatin1String("SPOT_BLEND")) || (mAngleSet = Token == QLatin1String("ANGLE"))) { - if(Token == QLatin1String("HEIGHT") || Token == QLatin1String("SPOT_BLEND")) - Stream >> mLightFactor[1]; + if (mPOVRayLight) + { + if (Token == QLatin1String("WIDTH")) + Stream >> mAreaSize[0]; + else if (Token == QLatin1String("HEIGHT")) + Stream >> mAreaSize[1]; + mLightFactorKeys.ChangeKey(mAreaSize, 1, true); + } else - Stream >> mLightFactor[0]; - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + { + if(Token == QLatin1String("HEIGHT") || Token == QLatin1String("SPOT_BLEND")) + Stream >> mLightFactor[1]; + else + Stream >> mLightFactor[0]; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + } + else if (Token == QLatin1String("AREA_ROWS")) + { + mPOVRayLight = true; + Stream >> mAreaGrid[0]; + mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); + } + else if (Token == QLatin1String("AREA_COLUMNS")) + { + mPOVRayLight = true; + Stream >> mAreaGrid[1]; + mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); + } + else if (Token == QLatin1String("SPOT_FALLOFF")) + { + mPOVRayLight = true; + Stream >> mSpotFalloff; + mSpotFalloffKeys.ChangeKey(mSpotFalloff, 1, true); + } + else if (Token == QLatin1String("SPOT_TIGHTNESS")) + { + mPOVRayLight = true; + Stream >> mSpotTightness; + mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); } else if (Token == QLatin1String("SPOT_SIZE")) { Stream >> mSpotSize; - mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, true); + mSpotSizeKeys.ChangeKey(mSpotSize, 1, true); } else if (Token == QLatin1String("SHAPE")) { @@ -310,6 +421,11 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) mLightShape = LC_LIGHT_SHAPE_ELLIPSE; mLightShapeKeys.ChangeKey(mLightShape, 1, true); } + else if (Token == QLatin1String("DIFFUSE")) + { + Stream >>mLightDiffuse; + mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); + } else if (Token == QLatin1String("SPECULAR")) { Stream >>mLightSpecular; @@ -347,6 +463,14 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); } + else if (Token == QLatin1String("POV_RAY")) + { + mPOVRayLight = true; + } + else if (Token == QLatin1String("SHADOWLESS")) + { + mShadowless = true; + } else if (Token == QLatin1String("COLOR_RGB_KEY")) mLightColorKeys.LoadKeysLDraw(Stream); else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) @@ -354,9 +478,17 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) else if ((Token == QLatin1String("ANGLE_KEY")) || (Token == QLatin1String("RADIUS_KEY")) || (Token == QLatin1String("SIZE_KEY")) || (Token == QLatin1String("RADIUS_AND_SPOT_BLEND_KEY"))) mLightFactorKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("SPOT_SIZE_KEY")) - mLightSpotSizeKeys.LoadKeysLDraw(Stream); + mSpotSizeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPOT_FALLOFF_KEY")) + mSpotFalloffKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPOT_TIGHTNESS_KEY")) + mSpotTightnessKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("AREA_GRID_KEY")) + mAreaGridKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("SHAPE_KEY")) mLightShapeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("DIFFUSE_KEY")) + mLightDiffuseKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("SPECULAR_KEY")) mLightSpecularKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("CUTOFF_DISTANCE_KEY")) @@ -439,20 +571,55 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) mLightColorKeys.ChangeKey(mLightColor, Step, false); break; case LC_LIGHT_FACTOR: - mLightFactor = Props.mLightFactor; - mLightFactorKeys.ChangeKey(mLightFactor, Step, false); + if (Props.mPOVRayLight && mLightType == LC_AREALIGHT) + { + mAreaSize = Props.mLightFactor; + mLightFactorKeys.ChangeKey(mAreaSize, 1, true); + } + else + { + mLightFactor = Props.mLightFactor; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + break; + case LC_LIGHT_DIFFUSE: + mLightDiffuse = Props.mLightDiffuse; + mLightDiffuseKeys.ChangeKey(mLightDiffuse, Step, false); break; case LC_LIGHT_SPECULAR: mLightSpecular = Props.mLightSpecular; mLightSpecularKeys.ChangeKey(mLightSpecular, Step, false); break; + case LC_LIGHT_SHADOWLESS: + mShadowless = Props.mShadowless; + break; case LC_LIGHT_EXPONENT: - mSpotExponent = Props.mSpotExponent; - mSpotExponentKeys.ChangeKey(mSpotExponent, Step, false); + if (Props.mPOVRayLight) + { + mPOVRayExponent = Props.mSpotExponent; + mSpotExponentKeys.ChangeKey(mPOVRayExponent, Step, false); + } + else + { + mSpotExponent = Props.mSpotExponent; + mSpotExponentKeys.ChangeKey(mSpotExponent, Step, false); + } + break; + case LC_LIGHT_AREA_GRID: + mAreaGrid = Props.mAreaGrid; + mAreaGridKeys.ChangeKey(mAreaGrid, Step, false); break; case LC_LIGHT_SPOT_SIZE: mSpotSize = Props.mSpotSize; - mLightSpotSizeKeys.ChangeKey(mSpotSize, Step, false); + mSpotSizeKeys.ChangeKey(mSpotSize, Step, false); + break; + case LC_LIGHT_SPOT_FALLOFF: + mSpotFalloff = Props.mSpotFalloff; + mSpotFalloffKeys.ChangeKey(mSpotFalloff, Step, false); + break; + case LC_LIGHT_SPOT_TIGHTNESS: + mSpotTightness = Props.mSpotTightness; + mSpotTightnessKeys.ChangeKey(mSpotTightness, Step, false); break; case LC_LIGHT_CUTOFF: mSpotCutoff = Props.mSpotCutoff; @@ -461,6 +628,9 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) case LC_LIGHT_USE_CUTOFF: mEnableCutoff = Props.mEnableCutoff; break; + case LC_LIGHT_POVRAY: + mPOVRayLight = Props.mPOVRayLight; + break; } UpdatePosition(Step); } @@ -591,10 +761,14 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mLightColorKeys.InsertTime(Start, Time); mLightTypeKeys.InsertTime(Start, Time); mLightFactorKeys.InsertTime(Start, Time); + mLightDiffuseKeys.InsertTime(Start, Time); mLightSpecularKeys.InsertTime(Start, Time); - mLightSpotSizeKeys.InsertTime(Start, Time); + mSpotSizeKeys.InsertTime(Start, Time); mSpotCutoffKeys.InsertTime(Start, Time); mSpotExponentKeys.InsertTime(Start, Time); + mSpotFalloffKeys.InsertTime(Start, Time); + mSpotTightnessKeys.InsertTime(Start, Time); + mAreaGridKeys.InsertTime(Start, Time); } void lcLight::RemoveTime(lcStep Start, lcStep Time) @@ -609,10 +783,14 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mLightColorKeys.RemoveTime(Start, Time); mLightTypeKeys.RemoveTime(Start, Time); mLightFactorKeys.RemoveTime(Start, Time); + mLightDiffuseKeys.RemoveTime(Start, Time); mLightSpecularKeys.RemoveTime(Start, Time); - mLightSpotSizeKeys.RemoveTime(Start, Time); + mSpotSizeKeys.RemoveTime(Start, Time); mSpotCutoffKeys.RemoveTime(Start, Time); mSpotExponentKeys.RemoveTime(Start, Time); + mSpotFalloffKeys.RemoveTime(Start, Time); + mSpotTightnessKeys.RemoveTime(Start, Time); + mAreaGridKeys.RemoveTime(Start, Time); } void lcLight::UpdatePosition(lcStep Step) @@ -627,10 +805,14 @@ void lcLight::UpdatePosition(lcStep Step) mLightColor = mLightColorKeys.CalculateKey(Step); mLightType = mLightTypeKeys.CalculateKey(Step); mLightFactor = mLightFactorKeys.CalculateKey(Step); + mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); mLightSpecular = mLightSpecularKeys.CalculateKey(Step); - mSpotSize = mLightSpotSizeKeys.CalculateKey(Step); + mSpotSize = mSpotSizeKeys.CalculateKey(Step); mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); mSpotExponent = mSpotExponentKeys.CalculateKey(Step); + mSpotFalloff = mSpotFalloffKeys.CalculateKey(Step); + mSpotTightness = mSpotTightnessKeys.CalculateKey(Step); + mAreaGrid = mAreaGridKeys.CalculateKey(Step); if (IsPointLight()) { @@ -1146,17 +1328,29 @@ void lcLight::RemoveKeyFrames() mLightTypeKeys.RemoveAll(); mLightTypeKeys.ChangeKey(mLightType, 1, true); + mLightDiffuseKeys.RemoveAll(); + mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); + mLightSpecularKeys.RemoveAll(); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); - mLightSpotSizeKeys.RemoveAll(); - mLightSpotSizeKeys.ChangeKey(mSpotSize, 1, false); + mSpotSizeKeys.RemoveAll(); + mSpotSizeKeys.ChangeKey(mSpotSize, 1, false); mSpotCutoffKeys.RemoveAll(); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); mSpotExponentKeys.RemoveAll(); mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); + + mSpotFalloffKeys.RemoveAll(); + mSpotFalloffKeys.ChangeKey(mSpotFalloff, 1, true); + + mSpotTightnessKeys.RemoveAll(); + mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); + + mAreaGridKeys.RemoveAll(); + mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); } bool lcLight::Setup(int LightIndex) diff --git a/common/light.h b/common/light.h index f440c8dd..410c36b9 100644 --- a/common/light.h +++ b/common/light.h @@ -45,22 +45,34 @@ enum lcLightProperty LC_LIGHT_COLOR, LC_LIGHT_TYPE, LC_LIGHT_FACTOR, + LC_LIGHT_DIFFUSE, LC_LIGHT_SPECULAR, + LC_LIGHT_SHADOWLESS, LC_LIGHT_EXPONENT, + LC_LIGHT_AREA_GRID, LC_LIGHT_SPOT_SIZE, + LC_LIGHT_SPOT_FALLOFF, + LC_LIGHT_SPOT_TIGHTNESS, LC_LIGHT_CUTOFF, - LC_LIGHT_USE_CUTOFF + LC_LIGHT_USE_CUTOFF, + LC_LIGHT_POVRAY }; struct lcLightProperties { lcVector3 mLightColor; lcVector2 mLightFactor; + lcVector2 mAreaGrid; + float mLightDiffuse; float mLightSpecular; float mSpotExponent; float mSpotCutoff; + float mSpotFalloff; + float mSpotTightness; float mSpotSize; bool mEnableCutoff; + bool mShadowless; + bool mPOVRayLight; int mLightShape; }; @@ -251,16 +263,21 @@ class lcLight : public lcObject lcLightProperties props; props.mLightColor = mLightColor; props.mLightFactor = mLightFactor; + props.mLightDiffuse = mLightDiffuse; props.mLightSpecular = mLightSpecular; props.mSpotExponent = mSpotExponent; props.mSpotCutoff = mSpotCutoff; + props.mSpotFalloff = mSpotFalloff; + props.mSpotTightness = mSpotTightness; props.mSpotSize = mSpotSize; + props.mPOVRayLight = mPOVRayLight; props.mEnableCutoff = mEnableCutoff; + props.mShadowless = mShadowless; + props.mAreaGrid = mAreaGrid; props.mLightShape = mLightShape; return props; } - // Temporary parameters lcMatrix44 mWorldLight; lcVector3 mPosition; lcVector3 mTargetPosition; @@ -270,17 +287,25 @@ class lcLight : public lcObject lcVector3 mAttenuation; lcVector3 mLightColor; lcVector2 mLightFactor; + lcVector2 mAreaGrid; + lcVector2 mAreaSize; bool mAngleSet; bool mSpotBlendSet; bool mSpotCutoffSet; bool mHeightSet; bool mEnableCutoff; + bool mPOVRayLight; + bool mShadowless; int mLightType; int mLightShape; + float mLightDiffuse; float mLightSpecular; float mSpotSize; float mSpotCutoff; + float mSpotFalloff; + float mSpotTightness; float mSpotExponent; + float mPOVRayExponent; QString mName; protected: @@ -292,12 +317,16 @@ class lcLight : public lcObject lcObjectKeyArray mAttenuationKeys; lcObjectKeyArray mLightColorKeys; lcObjectKeyArray mLightFactorKeys; + lcObjectKeyArray mAreaGridKeys; lcObjectKeyArray mLightTypeKeys; lcObjectKeyArray mLightShapeKeys; lcObjectKeyArray mLightSpecularKeys; - lcObjectKeyArray mLightSpotSizeKeys; + lcObjectKeyArray mLightDiffuseKeys; + lcObjectKeyArray mSpotSizeKeys; lcObjectKeyArray mSpotCutoffKeys; + lcObjectKeyArray mSpotFalloffKeys; lcObjectKeyArray mSpotExponentKeys; + lcObjectKeyArray mSpotTightnessKeys; void Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType); From 1f075624b825579265f59a6573638465702f281f Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Mon, 7 Aug 2023 13:08:13 +0200 Subject: [PATCH 11/42] POVRay lights - lc_qpropertiestree --- qt/lc_qpropertiestree.cpp | 333 +++++++++++++++++++++++++++++--------- qt/lc_qpropertiestree.h | 12 +- 2 files changed, 272 insertions(+), 73 deletions(-) diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 7c562a1d..0114cb5a 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -470,6 +470,19 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return editor; } + case PropertyFloatLightSpotFalloff: + { + QLineEdit *editor = new QLineEdit(parent); + float value = item->data(0, PropertyValueRole).toFloat(); + + editor->setValidator(new QDoubleValidator(1.0, 90.0,1, editor)); + editor->setText(lcFormatValueLocalized(value)); + editor->setToolTip(tr("Angle of the spotlight beam beteeen the cone edge and center line.")); + + connect(editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); + return editor; + } + case PropertyFloatReadOnly: { QLineEdit *editor = new QLineEdit(parent); @@ -532,6 +545,25 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return editor; } + case PropertyLightFormat: + { + QComboBox *editor = new QComboBox(parent); + + editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); + editor->setMinimumContentsLength(1); + + QStringList formats = { "Blender", "POVRay" }; + for (int i = 0; i < formats.size(); i++) + editor->addItem(formats.at(i), QVariant::fromValue(i)); + + int value = item->data(0, PropertyValueRole).toInt(); + editor->setCurrentIndex(value); + + connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); + + return editor; + } + case PropertyLightShape: { QComboBox *editor = new QComboBox(parent); @@ -539,7 +571,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); editor->setMinimumContentsLength(1); - QStringList shapes = { "Square", "Disk", "Rectangle", "Ellipse"}; + QStringList shapes = { "Square", "Disk", "Rectangle", "Ellipse" }; for (int i = 0; i < shapes.size(); i++) editor->addItem(shapes.at(i), QVariant::fromValue(i)); @@ -660,8 +692,6 @@ void lcQPropertiesTree::slotToggled(bool Value) if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA) { - lcObject* Focus = Model->GetFocusObject(); - if (Focus && Focus->IsCamera()) { lcCamera* Camera = (lcCamera*)Focus; @@ -684,11 +714,6 @@ void lcQPropertiesTree::slotToggled(bool Value) Props.mEnableCutoff = Value; Model->UpdateLight(Light, Props, LC_LIGHT_USE_CUTOFF); } - else if (Item == lightPOVRay) - { - Props.mPOVRayLight = Value; - Model->UpdateLight(Light, Props, LC_LIGHT_POVRAY); - } else if (Item == lightShadowless) { Props.mShadowless = Value; @@ -918,6 +943,12 @@ void lcQPropertiesTree::slotReturnPressed() Model->UpdateLight(Light, Props, LC_LIGHT_FACTOR); } + else if (Item == lightDiffuse) + { + Props.mLightDiffuse = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_DIFFUSE); + } else if (Item == lightSpecular) { Props.mLightSpecular = lcParseValueLocalized(Editor->text()); @@ -942,6 +973,30 @@ void lcQPropertiesTree::slotReturnPressed() Model->UpdateLight(Light, Props, LC_LIGHT_SPOT_SIZE); } + + else if (Item == lightSpotFalloff) + { + Props.mSpotFalloff = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_SPOT_FALLOFF); + } + else if (Item == lightSpotTightness) + { + Props.mSpotTightness = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_SPOT_TIGHTNESS); + } + else if (Item == lightAreaGridRows || Item == lightAreaGridColumns) + { + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightAreaGridRows) + Props.mAreaGrid[0] = Value; + else if (Item == lightAreaGridColumns) + Props.mAreaGrid[1] = Value; + + Model->UpdateLight(Light, Props, LC_LIGHT_AREA_GRID); + } + else if (Item == lightName) { QString Value = Editor->text(); @@ -987,11 +1042,19 @@ void lcQPropertiesTree::slotSetValue(int Value) lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; - if (Light && Item == lightShape) + if (Light) { lcLightProperties Props = Light->GetLightProperties(); - Props.mLightShape = static_cast(Value); - Model->UpdateLight(Light, Props, LC_LIGHT_SHAPE); + if (Item == lightShape) + { + Props.mLightShape = static_cast(Value); + Model->UpdateLight(Light, Props, LC_LIGHT_SHAPE); + } + else if (Item == lightFormat) + { + Props.mPOVRayLight = Value; + Model->UpdateLight(Light, Props, LC_LIGHT_POVRAY); + } } } } @@ -1119,6 +1182,7 @@ void lcQPropertiesTree::SetEmpty() cameraFar = nullptr; cameraName = nullptr; + lightConfiguration = nullptr; lightPosition = nullptr; lightPositionX = nullptr; lightPositionY = nullptr; @@ -1133,6 +1197,7 @@ void lcQPropertiesTree::SetEmpty() lightColorG = nullptr; lightColorB = nullptr; lightProperties = nullptr; + lightDiffuse = nullptr; lightSpecular = nullptr; lightCutoff = nullptr; lightEnableCutoff = nullptr; @@ -1143,6 +1208,12 @@ void lcQPropertiesTree::SetEmpty() lightName = nullptr; lightSpotSize = nullptr; lightShape = nullptr; + lightFormat = nullptr; + lightShadowless = nullptr; + lightAreaGridRows = nullptr; + lightAreaGridColumns = nullptr; + lightSpotFalloff = nullptr; + lightSpotTightness = nullptr; mWidgetMode = LC_PROPERTY_WIDGET_EMPTY; mFocus = nullptr; @@ -1375,28 +1446,42 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; QString Name = tr("Light"); - QString FactorALabel = tr("FactorA"); QString ExponentLabel = tr("Exponent"); - QString Type, Shape, FactorAToolTip, FactorBToolTip; + QString FactorALabel = QLatin1String("FactorA"); + QString Type = QLatin1String("Undefined"); + QString Format, Shape, SpotSizeToolTip, ExponentToolTip, FactorAToolTip, FactorBToolTip; lcLightType LightIndex = LC_UNDEFINED_LIGHT; lcLightShape ShapeIndex = LC_LIGHT_SHAPE_UNDEFINED; + int FormatIndex = 0; float SpotSize = 0.0f; + float SpotFalloff = 0.0f; + float SpotTightness = 0.0f; + float Diffuse = 0.0f; float Specular = 0.0f; float Cutoff = 0.0f; float Exponent = 0.0f; bool EnableCutoff = false; + bool POVRayLight = false; + bool Shadowless = false; PropertyType TargetProperty = PropertyFloat; + PropertyType SpotSizeProperty = PropertyFloatLightSpotSize; lcVector3 Position(0.0f, 0.0f, 0.0f); lcVector3 Target(0.0f, 0.0f, 0.0f); lcVector3 Color(0.0f, 0.0f, 0.0f); lcVector2 Factor(0.0f, 0.0f); + lcVector2 AreaGrid(0.0f, 0.0f); if (Light) { Name = Light->GetName(); - Position = Light->mPosition; // normalizeDegrees(Light->mPosition); - Target = Light->mTargetPosition; // normalizeDegrees(Light->mTargetPosition); + POVRayLight = Light->mPOVRayLight; + FormatIndex = static_cast(POVRayLight); + Format = POVRayLight ? QLatin1String("POVRay") : QLatin1String("Blender"); + + Shadowless = Light->mShadowless; + Position = Light->mPosition; + Target = Light->mTargetPosition; Color = Light->mLightColor; Factor = Light->mLightFactor; LightIndex = static_cast(Light->mLightType); @@ -1406,28 +1491,48 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) case LC_POINTLIGHT: Type = QLatin1String("Point"); FactorALabel = tr("Radius (m)"); - FactorAToolTip = tr("Shadow soft size - Light size for shadow sampling"); + FactorAToolTip = tr("The light size for shadow sampling in metres."); break; case LC_AREALIGHT: Type = QLatin1String("Area"); - FactorALabel = tr("Width (X)"); - FactorAToolTip = tr("Size of the area of the area light. X direction size for rectangular shapes"); - FactorBToolTip = tr("Size of the area of the area light. Y direction size for rectangular shapes"); + if (POVRayLight) + { + Factor = Light->mAreaSize; + FactorALabel = tr("Width"); + FactorAToolTip = tr("The width (X direction) of the area light in units."); + FactorBToolTip = tr("The height (Y direction) of the area light in units."); + } + else + { + FactorALabel = tr("Width (m)"); + FactorAToolTip = tr("The width (X direction) of the area light in metres."); + FactorBToolTip = tr("The height (Y direction) of the area light in units."); + } break; case LC_SUNLIGHT: Type = QLatin1String("Sun"); FactorALabel = tr("Angle (°)"); - FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth"); + FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth."); break; case LC_SPOTLIGHT: Type = QLatin1String("Spot"); - FactorALabel = tr("Radius (m)"); - FactorAToolTip = tr("Shadow soft size - Light size for shadow sampling"); - FactorBToolTip = tr("Shadow blend - The softness of the spotlight edge"); + FactorBToolTip = tr("The softness of the spotlight edge."); + if (POVRayLight) + { + FactorALabel = tr("Radius (°)"); + FactorAToolTip = tr("The angle between the \"hot-spot\" edge at the beam center and the center line."); + SpotSizeToolTip = tr("Angle of the spotlight beam - Read only."); + Factor[0] = Light->mSpotSize - Light->mSpotFalloff; + SpotSizeProperty = PropertyFloatReadOnly; + } + else + { + FactorALabel = tr("Radius (m)"); + FactorAToolTip = tr("Shadow soft size - Light size in metres for shadow sampling."); + SpotSizeToolTip = tr("Angle of the spotlight beam."); + } break; default: - Type = QLatin1String("Undefined"); - FactorALabel = tr("FactorA"); break; } @@ -1435,47 +1540,63 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) switch(ShapeIndex) { case LC_LIGHT_SHAPE_SQUARE: - Shape = QLatin1String("Square"); + Shape = tr("Square"); break; case LC_LIGHT_SHAPE_DISK: - Shape = QLatin1String("Disk"); + Shape = POVRayLight ? tr("Circle") : tr("Disk"); break; case LC_LIGHT_SHAPE_RECTANGLE: - Shape = QLatin1String("Rectangle"); + Shape = tr("Rectangle"); break; case LC_LIGHT_SHAPE_ELLIPSE: - Shape = QLatin1String("Ellipse"); + Shape = tr("Ellipse"); break; default: break; } + Diffuse = Light->mLightDiffuse; Specular = Light->mLightSpecular; - Exponent = Light->mSpotExponent; - ExponentLabel = LightIndex ? LightIndex == LC_SUNLIGHT ? tr("Strength") : tr("Power") : tr("Exponent"); + if (POVRayLight) + { + Exponent = Light->mPOVRayExponent; + ExponentToolTip = tr("Intensity of the light with typical range of 0 to 1.0."); + } + else + { + Exponent = Light->mSpotExponent; + ExponentToolTip = tr("Intensity of the light in watts."); + } + ExponentLabel = LightIndex == LC_SUNLIGHT ? tr("Strength") : tr("Power"); Cutoff = Light->mSpotCutoff; EnableCutoff = Light->mEnableCutoff; TargetProperty = Light->mLightType > LC_POINTLIGHT ? PropertyFloat : PropertyFloatReadOnly; SpotSize = Light->mSpotSize; + SpotFalloff = Light->mSpotFalloff; + SpotTightness = Light->mSpotTightness; + AreaGrid = Light->mAreaGrid; } - if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightIndex || mLightShape != ShapeIndex) + if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightIndex || mLightShape != ShapeIndex || mPOVRayLight != POVRayLight) { SetEmpty(); + // Configuration + lightConfiguration = addProperty(nullptr, tr("Configuration"), PropertyGroup); + lightFormat = addProperty(lightConfiguration, tr("Format"), PropertyLightFormat); // Position lightPosition = addProperty(nullptr, tr("Position"), PropertyGroup); lightPositionX = addProperty(lightPosition, tr("X"), PropertyFloat); lightPositionY = addProperty(lightPosition, tr("Y"), PropertyFloat); lightPositionZ = addProperty(lightPosition, tr("Z"), PropertyFloat); // Target Position - if (LightIndex != LC_POINTLIGHT) + if (LightIndex != LC_POINTLIGHT && !(LightIndex == LC_AREALIGHT && POVRayLight)) { lightTarget = addProperty(nullptr, tr("Target"), PropertyGroup); lightTargetX = addProperty(lightTarget, tr("X"), TargetProperty); lightTargetY = addProperty(lightTarget, tr("Y"), TargetProperty); lightTargetZ = addProperty(lightTarget, tr("Z"), TargetProperty); } - // Ambient Colour + // Light Colour lightColor = addProperty(nullptr, tr("Color"), PropertyGroup); lightColorIcon = addProperty(lightColor, tr("Name"), PropertyLightColor); lightColorR = addProperty(lightColor, tr("Red"), PropertyFloat); @@ -1484,30 +1605,52 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) // Properties lightProperties = addProperty(nullptr, tr("Properties"), PropertyGroup); lightType = addProperty(lightProperties, tr("Type"), PropertyStringLightReadOnly); + lightShadowless = addProperty(lightProperties, tr("Shadowless"), PropertyBool); lightExponent = addProperty(lightProperties, ExponentLabel, PropertyFloat); - lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); + if ((LightIndex == LC_POINTLIGHT || LightIndex == LC_SUNLIGHT) && !POVRayLight) + lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); if (LightIndex == LC_AREALIGHT) { - if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE) - lightFactorB = addProperty(lightProperties, tr("Height (Y)"), PropertyFloat); lightShape = addProperty(lightProperties, tr("Shape"), PropertyLightShape); + lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); + if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE || POVRayLight) + lightFactorB = addProperty(lightProperties, tr("Height (Y)"), PropertyFloat); + else + FactorAToolTip = tr("The size of the area light grid in metres."); + if (POVRayLight) + { + lightAreaGridRows = addProperty(lightProperties, tr("Grid Rows"), PropertyFloat); + lightAreaGridColumns = addProperty(lightProperties, tr("Grid Columns"), PropertyFloat); + } } else if (LightIndex == LC_SPOTLIGHT) { - lightFactorB = addProperty(lightProperties, tr("Spot Blend"), PropertyFloat); - lightSpotSize = addProperty(lightProperties, tr("Spot Size (°)"), PropertyFloatLightSpotSize); + lightSpotSize = addProperty(lightProperties, tr("Spot Size (°)"), SpotSizeProperty); + lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); + if (!POVRayLight) + lightFactorB = addProperty(lightProperties, tr("Spot Blend"), PropertyFloat); + else + { + lightSpotFalloff = addProperty(lightProperties, tr("Spot Falloff (°)"), PropertyFloatLightSpotFalloff); + lightSpotTightness = addProperty(lightProperties, tr("Spot Tightness"), PropertyFloat); + } } - if (LightIndex != LC_SUNLIGHT) + if (!POVRayLight) { - lightEnableCutoff = addProperty(lightProperties, tr("Cutoff"), PropertyBool); - lightCutoff = addProperty(lightProperties, tr("Cutoff Distance"), PropertyFloat); + if (LightIndex != LC_SUNLIGHT) + { + lightEnableCutoff = addProperty(lightProperties, tr("Cutoff"), PropertyBool); + lightCutoff = addProperty(lightProperties, tr("Cutoff Distance"), PropertyFloat); + } + lightDiffuse = addProperty(lightProperties, tr("Diffuse"), PropertyFloat); + lightSpecular = addProperty(lightProperties, tr("Specular"), PropertyFloat); } - lightSpecular = addProperty(lightProperties, tr("Specular"), PropertyFloat); lightName = addProperty(lightProperties, tr("Name"), PropertyString); mWidgetMode = LC_PROPERTY_WIDGET_LIGHT; mLightType = LightIndex; mLightShape = ShapeIndex; + mPOVRayLight = POVRayLight; } mFocus = Light; @@ -1519,7 +1662,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightPositionZ->setText(1, lcFormatValueLocalized(Position[2])); lightPositionZ->setData(0, PropertyValueRole, Position[2]); - if (LightIndex != LC_POINTLIGHT) + if (LightIndex != LC_POINTLIGHT && !(LightIndex == LC_AREALIGHT && POVRayLight)) { lightTargetX->setText(1, lcFormatValueLocalized(Target[0])); lightTargetX->setData(0, PropertyValueRole, Target[0]); @@ -1547,63 +1690,109 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightColorR->setText(1, lcFormatValueLocalized(Color[0])); lightColorR->setData(0, PropertyValueRole, Color[0]); - lightColorR->setToolTip(1, tr("Red color component - use .0 - 1 format")); + lightColorR->setToolTip(1, tr("Red color using 0 to 1 decimal.")); lightColorG->setText(1, lcFormatValueLocalized(Color[1])); lightColorG->setData(0, PropertyValueRole, Color[1]); - lightColorG->setToolTip(1, tr("Green color component - use .0 - 1 format")); + lightColorG->setToolTip(1, tr("Green color using 0 to 1 decimal.")); lightColorB->setText(1, lcFormatValueLocalized(Color[2])); lightColorB->setData(0, PropertyValueRole, Color[2]); - lightColorB->setToolTip(1, tr("Blue color component - use .0 - 1 format")); + lightColorB->setToolTip(1, tr("Blue color using 0 to 1 decimal.")); + + lightFormat->setText(1, Format); + lightFormat->setData(0, PropertyValueRole, FormatIndex); lightType->setText(1, Type); lightType->setData(0, PropertyValueRole, Type); + lightShadowless->setText(1, Shadowless ? "True" : "False"); + lightShadowless->setData(0, PropertyValueRole, Shadowless); + lightExponent->setText(1, lcFormatValueLocalized(Exponent)); lightExponent->setData(0, PropertyValueRole, Exponent); - lightExponent->setToolTip(1, tr("Intensity of the light in Watts.")); - - lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); - lightFactorA->setData(0, PropertyValueRole, Factor[0]); - lightFactorA->setToolTip(1, FactorAToolTip); + lightExponent->setToolTip(1, ExponentToolTip); - if (LightIndex == LC_AREALIGHT) + if ((LightIndex == LC_POINTLIGHT || LightIndex == LC_SUNLIGHT) && !POVRayLight) { - if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE) + lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); + lightFactorA->setData(0, PropertyValueRole, Factor[0]); + lightFactorA->setToolTip(1, FactorAToolTip); + } + else if (LightIndex == LC_AREALIGHT) + { + lightShape->setText(1, Shape); + lightShape->setData(0, PropertyValueRole, ShapeIndex); + lightShape->setToolTip(1, tr("Suggested shape of the arealight.")); + + lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); + lightFactorA->setData(0, PropertyValueRole, Factor[0]); + lightFactorA->setToolTip(1, FactorAToolTip); + + if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE || POVRayLight) { lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); lightFactorB->setData(0, PropertyValueRole, Factor[1]); lightFactorB->setToolTip(1, FactorBToolTip); } - lightShape->setText(1, Shape); - lightShape->setData(0, PropertyValueRole, ShapeIndex); - lightShape->setToolTip(1, tr("Shape of the arealight.")); + if (POVRayLight) + { + lightAreaGridRows->setText(1, lcFormatValueLocalized(AreaGrid[0])); + lightAreaGridRows->setData(0, PropertyValueRole, AreaGrid[0]); + lightAreaGridRows->setToolTip(1, tr("The number of sample rows in the area light.")); + lightAreaGridColumns->setText(1, lcFormatValueLocalized(AreaGrid[1])); + lightAreaGridColumns->setData(0, PropertyValueRole, AreaGrid[1]); + lightAreaGridColumns->setToolTip(1, tr("The number of sample columns in the area light.")); + } } else if (LightIndex == LC_SPOTLIGHT) { - lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); - lightFactorB->setData(0, PropertyValueRole, Factor[1]); - lightFactorB->setToolTip(1, FactorBToolTip); - lightSpotSize->setText(1, lcFormatValueLocalized(SpotSize)); lightSpotSize->setData(0, PropertyValueRole, SpotSize); - lightSpotSize->setToolTip(1, tr("Angle of the spotlight beam.")); + lightSpotSize->setToolTip(1, SpotSizeToolTip); + + lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); + lightFactorA->setData(0, PropertyValueRole, Factor[0]); + lightFactorA->setToolTip(1, FactorAToolTip); + + if (!POVRayLight) + { + lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); + lightFactorB->setData(0, PropertyValueRole, Factor[1]); + lightFactorB->setToolTip(1, FactorBToolTip); + } + else + { + lightSpotFalloff->setText(1, lcFormatValueLocalized(SpotFalloff)); + lightSpotFalloff->setData(0, PropertyValueRole, SpotFalloff); + lightSpotFalloff->setToolTip(1, tr("The angle between the spot beam edge and center line.")); + + lightSpotTightness->setText(1, lcFormatValueLocalized(SpotTightness)); + lightSpotTightness->setData(0, PropertyValueRole, SpotTightness); + lightSpotTightness->setToolTip(1, tr("Additional exponential spotlight edge softening.")); + } } - if (LightIndex != LC_SUNLIGHT) + if (!POVRayLight) { - lightEnableCutoff->setText(1, EnableCutoff ? "True" : "False"); - lightEnableCutoff->setData(0, PropertyValueRole, EnableCutoff); + if (LightIndex != LC_SUNLIGHT) + { + lightEnableCutoff->setText(1, EnableCutoff ? "True" : "False"); + lightEnableCutoff->setData(0, PropertyValueRole, EnableCutoff); - lightCutoff->setText(1, lcFormatValueLocalized(Cutoff)); - lightCutoff->setData(0, PropertyValueRole, Cutoff); - lightCutoff->setToolTip(1, tr("Distance at which the light influence will be set to 0.")); - } + lightCutoff->setText(1, lcFormatValueLocalized(Cutoff)); + lightCutoff->setData(0, PropertyValueRole, Cutoff); + lightCutoff->setToolTip(1, tr("Distance at which the light influence will be set to 0.")); + } + + lightDiffuse->setText(1, lcFormatValueLocalized(Diffuse)); + lightDiffuse->setData(0, PropertyValueRole, Diffuse); + lightDiffuse->setToolTip(1, tr("Diffuse reflection multiplier factor.")); - lightSpecular->setText(1, lcFormatValueLocalized(Specular)); - lightSpecular->setData(0, PropertyValueRole, Specular); - lightSpecular->setToolTip(1, tr("Specular reflection multiplier factor.")); + lightSpecular->setText(1, lcFormatValueLocalized(Specular)); + lightSpecular->setData(0, PropertyValueRole, Specular); + lightSpecular->setToolTip(1, tr("Specular reflection multiplier factor.")); + } lightName->setText(1, Name); lightName->setData(0, PropertyValueRole, QVariant::fromValue(Name)); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 5b06a330..39759441 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -46,9 +46,11 @@ class lcQPropertiesTree : public QTreeWidget PropertyFloat, PropertyFloatReadOnly, PropertyFloatLightSpotSize, + PropertyFloatLightSpotFalloff, PropertyStep, PropertyString, PropertyStringLightReadOnly, + PropertyLightFormat, PropertyLightShape, PropertyLightColor, PropertyColor, @@ -81,6 +83,7 @@ protected slots: int mLightType; int mLightShape; + bool mPOVRayLight; lcPropertyWidgetMode mWidgetMode; lcObject* mFocus; @@ -124,6 +127,7 @@ protected slots: QTreeWidgetItem *cameraFar; QTreeWidgetItem *cameraName; + QTreeWidgetItem *lightConfiguration; QTreeWidgetItem *lightPosition; QTreeWidgetItem *lightPositionX; QTreeWidgetItem *lightPositionY; @@ -138,6 +142,7 @@ protected slots: QTreeWidgetItem *lightColorG; QTreeWidgetItem *lightColorB; QTreeWidgetItem *lightProperties; + QTreeWidgetItem *lightDiffuse; QTreeWidgetItem *lightSpecular; QTreeWidgetItem *lightCutoff; QTreeWidgetItem *lightEnableCutoff; @@ -148,6 +153,12 @@ protected slots: QTreeWidgetItem *lightFactorA; QTreeWidgetItem *lightFactorB; QTreeWidgetItem *lightName; + QTreeWidgetItem *lightFormat; + QTreeWidgetItem *lightShadowless; + QTreeWidgetItem *lightAreaGridRows; + QTreeWidgetItem *lightAreaGridColumns; + QTreeWidgetItem *lightSpotFalloff; + QTreeWidgetItem *lightSpotTightness; }; class lcQPropertiesTreeDelegate : public QItemDelegate @@ -196,4 +207,3 @@ private slots: mutable QWidget *m_editedWidget; mutable bool m_disablePainting; }; - From d29c5b932314f2716e399ffae0c5aafe4047f2f0 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Wed, 9 Aug 2023 12:35:07 +0200 Subject: [PATCH 12/42] POVRay lights - POV file preferences --- common/lc_model.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++ common/lc_model.h | 26 +++++++++++++ qt/lc_renderdialog.cpp | 31 ++++++++++++---- 3 files changed, 133 insertions(+), 8 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 56909b48..ab9ac067 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -107,6 +107,86 @@ void lcModelProperties::ParseLDrawLine(QTextStream& Stream) } } +lcPOVRayOptions::lcPOVRayOptions() : + UseLGEO(false), + ExcludeFloor(false), + ExcludeBackground(false), + NoReflection(false), + NoShadow(false), + FloorAxis(1), + FloorAmbient(0.4f), + FloorDiffuse(0.4f), + FloorColor(0.8f,0.8f,0.8f) +{} + +void lcPOVRayOptions::ParseLDrawLine(QTextStream& LineStream) +{ + QString Token; + LineStream >> Token; + + if (Token == QLatin1String("HEADER_INCLUDE_FILE")) + { + LineStream >> HeaderIncludeFile; + if (!QFileInfo(HeaderIncludeFile).isReadable()) + HeaderIncludeFile.clear(); + } + else if (Token == QLatin1String("FOOTER_INCLUDE_FILE")) + { + LineStream >> FooterIncludeFile; + if (!QFileInfo(FooterIncludeFile).isReadable()) + FooterIncludeFile.clear(); + } + else if (Token == QLatin1String("FLOOR_AXIS")) + { + LineStream >> FloorAxis; + if (FloorAxis < 0 || FloorAxis > 2) + FloorAxis = 1; // y + } + else if (Token == QLatin1String("FLOOR_COLOR_RGB")) + LineStream >> FloorColor[0] >> FloorColor[1] >> FloorColor[2]; + else if (Token == QLatin1String("FLOOR_AMBIENT")) + LineStream >> FloorAmbient; + else if (Token == QLatin1String("FLOOR_DIFFUSE")) + LineStream >> FloorDiffuse; + else if (Token == QLatin1String("EXCLUDE_FLOOR")) + ExcludeFloor = true; + else if (Token == QLatin1String("EXCLUDE_BACKGROUND")) + ExcludeFloor = true; + else if (Token == QLatin1String("NO_REFLECTION")) + NoReflection = true; + else if (Token == QLatin1String("NO_SHADOWS")) + NoShadow = true; + else if (Token == QLatin1String("USE_LGEO")) + UseLGEO = true; +} + +void lcPOVRayOptions::SaveLDraw(QTextStream& Stream) const +{ + const QLatin1String LineEnding("\r\n"); + if (!HeaderIncludeFile.isEmpty()) + Stream << QLatin1String("0 !LEOCAD POV_RAY HEADER_INCLUDE_FILE ") << QDir::toNativeSeparators(HeaderIncludeFile) << LineEnding; + if (!FooterIncludeFile.isEmpty()) + Stream << QLatin1String("0 !LEOCAD POV_RAY FOOTER_INCLUDE_FILE ") << QDir::toNativeSeparators(FooterIncludeFile) << LineEnding; + if (FloorAxis != 1) + Stream << QLatin1String("0 !LEOCAD POV_RAY FLOOR_AXIS ") << FloorAxis << LineEnding; + if (FloorColor != lcVector3(0.8f,0.8f,0.8f)) + Stream << QLatin1String("0 !LEOCAD POV_RAY FLOOR_COLOR_RGB ") << FloorColor[0] << ' ' << FloorColor[1] << ' ' << FloorColor[2] << LineEnding; + if (FloorAmbient != 0.4f) + Stream << QLatin1String("0 !LEOCAD POV_RAY FLOOR_AMBIENT ") << FloorAmbient << LineEnding; + if (FloorDiffuse != 0.4f) + Stream << QLatin1String("0 !LEOCAD POV_RAY FLOOR_DIFFUSE ") << FloorDiffuse << LineEnding; + if (ExcludeFloor) + Stream << QLatin1String("0 !LEOCAD POV_RAY EXCLUDE_FLOOR") << LineEnding; + if (ExcludeBackground) + Stream << QLatin1String("0 !LEOCAD POV_RAY EXCLUDE_BACKGROUND") << LineEnding; + if (NoReflection) + Stream << QLatin1String("0 !LEOCAD POV_RAY NO_REFLECTION") << LineEnding; + if (NoShadow) + Stream << QLatin1String("0 !LEOCAD POV_RAY NO_SHADOWS") << LineEnding; + if (UseLGEO) + Stream << QLatin1String("0 !LEOCAD POV_RAY USE_LGEO") << LineEnding; +} + lcModel::lcModel(const QString& FileName, Project* Project, bool Preview) : mProject(Project), mIsPreview(Preview) { @@ -581,6 +661,10 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) Light = nullptr; } } + else if (Token == QLatin1String("POV_RAY")) + { + mPOVRayOptions.ParseLDrawLine(LineStream); + } else if (Token == QLatin1String("GROUP")) { LineStream >> Token; diff --git a/common/lc_model.h b/common/lc_model.h index e92b1c03..996fe387 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -67,6 +67,26 @@ class lcModelProperties lcVector3 mAmbientColor; }; +class lcPOVRayOptions +{ +public: + lcPOVRayOptions(); + void ParseLDrawLine(QTextStream& LineStream); + void SaveLDraw(QTextStream& Stream) const; + + bool UseLGEO; + bool ExcludeFloor; + bool ExcludeBackground; + bool NoReflection; + bool NoShadow; + int FloorAxis; + float FloorAmbient; + float FloorDiffuse; + lcVector3 FloorColor; + QString HeaderIncludeFile; + QString FooterIncludeFile; +}; + struct lcModelHistoryEntry { QByteArray File; @@ -136,6 +156,11 @@ class lcModel return mProperties; } + const lcPOVRayOptions& GetPOVRayOptions() const + { + return mPOVRayOptions; + } + void SetFileName(const QString& FileName) { if (mProperties.mModelName == mProperties.mFileName) @@ -366,6 +391,7 @@ class lcModel void AddPiece(lcPiece* Piece); void InsertPiece(lcPiece* Piece, int Index); + lcPOVRayOptions mPOVRayOptions; lcModelProperties mProperties; Project* const mProject; PieceInfo* mPieceInfo; diff --git a/qt/lc_renderdialog.cpp b/qt/lc_renderdialog.cpp index 2b1c20c9..144ba99f 100644 --- a/qt/lc_renderdialog.cpp +++ b/qt/lc_renderdialog.cpp @@ -348,14 +348,6 @@ void lcRenderDialog::on_RenderButton_clicked() break; } - /* - if (!LGEOPath.isEmpty()) - { - Arguments.append(QString::fromLatin1("+L%1lg/").arg(LGEOPath)); - Arguments.append(QString::fromLatin1("+L%1ar/").arg(LGEOPath)); - } - */ - QString POVRayPath; #ifdef Q_OS_WIN @@ -372,6 +364,29 @@ void lcRenderDialog::on_RenderButton_clicked() POVRayPath = QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/povray")); #endif + const QString POVRayDir = QFileInfo(POVRayPath).absolutePath(); + const QString IncludePath = QDir::cleanPath(POVRayDir + "/include"); + if (QFileInfo(IncludePath).exists()) + Arguments.append(QString("+L\"%1\"").arg(IncludePath)); + const QString IniPath = QDir::cleanPath(POVRayDir + "/ini"); + if (QFileInfo(IniPath).exists()) + Arguments.append(QString("+L\"%1\"").arg(IniPath)); + if (lcGetActiveProject()->GetModels()[0]->GetPOVRayOptions().UseLGEO) { + const QString LGEOPath = lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH); + if (QFileInfo(LGEOPath).exists()) + { + const QString LgPath = QDir::cleanPath(LGEOPath + "/lg"); + if (QFileInfo(LgPath).exists()) + Arguments.append(QString("+L\"%1\"").arg(LgPath)); + const QString ArPath = QDir::cleanPath(LGEOPath + "/ar"); + if (QFileInfo(ArPath).exists()) + Arguments.append(QString("+L\"%1\"").arg(ArPath)); + const QString StlPath = QDir::cleanPath(LGEOPath + "/stl"); + if (QFileInfo(StlPath).exists()) + Arguments.append(QString("+L\"%1\"").arg(StlPath)); + } + } + mProcess = new lcRenderProcess(this); #ifdef Q_OS_LINUX connect(mProcess, SIGNAL(readyReadStandardError()), this, SLOT(ReadStdErr())); From 6b5bfbf99f426fc968e27ae0cb77839e905fbe95 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Thu, 10 Aug 2023 06:22:52 +0200 Subject: [PATCH 13/42] POVRay lights - export POV file --- common/lc_colors.cpp | 25 +- common/lc_colors.h | 12 + common/lc_mesh.cpp | 4 +- common/project.cpp | 597 +++++++++++++++++++++++++++++++++++-------- 4 files changed, 531 insertions(+), 107 deletions(-) diff --git a/common/lc_colors.cpp b/common/lc_colors.cpp index c870c838..e0ec391c 100644 --- a/common/lc_colors.cpp +++ b/common/lc_colors.cpp @@ -85,6 +85,8 @@ static std::vector lcParseColorFile(lcFile& File) Color.Code = ~0U; Color.Translucent = false; + Color.Chrome = false; + Color.Rubber = false; Color.Group = LC_COLORGROUP_SOLID; Color.Value[0] = FLT_MAX; Color.Value[1] = FLT_MAX; @@ -157,8 +159,17 @@ static std::vector lcParseColorFile(lcFile& File) else if (Value != 0) Color.Group = LC_COLORGROUP_SPECIAL; } - else if (!strcmp(Token, "CHROME") || !strcmp(Token, "PEARLESCENT") || !strcmp(Token, "RUBBER") || - !strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE")) + else if (!strcmp(Token, "CHROME")) + { + Color.Chrome = true; + Color.Group = LC_COLORGROUP_SPECIAL; + } + else if (!strcmp(Token, "RUBBER")) + { + Color.Rubber = true; + Color.Group = LC_COLORGROUP_SPECIAL; + } + else if (!strcmp(Token, "PEARLESCENT") || !strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE")) { Color.Group = LC_COLORGROUP_SPECIAL; } @@ -236,6 +247,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) MainColor.Code = 16; MainColor.Translucent = false; + MainColor.Chrome = false; + MainColor.Rubber = false; MainColor.Group = LC_COLORGROUP_SOLID; MainColor.Value[0] = 1.0f; MainColor.Value[1] = 1.0f; @@ -257,6 +270,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) EdgeColor.Code = 24; EdgeColor.Translucent = false; + EdgeColor.Chrome = false; + EdgeColor.Rubber = false; EdgeColor.Group = LC_NUM_COLORGROUPS; EdgeColor.Value[0] = 0.5f; EdgeColor.Value[1] = 0.5f; @@ -279,6 +294,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) StudCylinderColor.Code = LC_STUD_CYLINDER_COLOR_CODE; StudCylinderColor.Translucent = false; + StudCylinderColor.Chrome = false; + StudCylinderColor.Rubber = false; StudCylinderColor.Group = LC_NUM_COLORGROUPS; StudCylinderColor.Value = lcVector4FromColor(Preferences.mStudCylinderColor); StudCylinderColor.Edge = lcVector4FromColor(Preferences.mPartEdgeColor); @@ -294,6 +311,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) NoColor.Code = LC_COLOR_NOCOLOR; NoColor.Translucent = false; + NoColor.Chrome = false; + NoColor.Rubber = false; NoColor.Group = LC_NUM_COLORGROUPS; NoColor.Value[0] = 0.5f; NoColor.Value[1] = 0.5f; @@ -362,6 +381,8 @@ int lcGetColorIndex(quint32 ColorCode) Color.Code = ColorCode; Color.Translucent = false; + Color.Chrome = false; + Color.Rubber = false; Color.Edge[0] = 0.2f; Color.Edge[1] = 0.2f; Color.Edge[2] = 0.2f; diff --git a/common/lc_colors.h b/common/lc_colors.h index c2559d0a..90fa9cf5 100644 --- a/common/lc_colors.h +++ b/common/lc_colors.h @@ -13,6 +13,8 @@ struct lcColor quint32 Code; int Group; bool Translucent = false; + bool Chrome = false; + bool Rubber = false; bool Adjusted = false; lcVector4 Value; lcVector4 Edge; @@ -64,3 +66,13 @@ inline bool lcIsColorTranslucent(size_t ColorIndex) { return gColorList[ColorIndex].Translucent; } + +inline bool lcIsColorChrome(size_t ColorIndex) +{ + return gColorList[ColorIndex].Chrome; +} + +inline bool lcIsColorRubber(size_t ColorIndex) +{ + return gColorList[ColorIndex].Rubber; +} diff --git a/common/lc_mesh.cpp b/common/lc_mesh.cpp index 79ae599c..388f4bc9 100644 --- a/common/lc_mesh.cpp +++ b/common/lc_mesh.cpp @@ -305,14 +305,14 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color const lcVector3 n2 = lcUnpackNormal(Verts[Indices[Idx + 1]].Normal); const lcVector3 n3 = lcUnpackNormal(Verts[Indices[Idx + 2]].Normal); - sprintf(Line, " smooth_triangle { <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f> }\n", + sprintf(Line, " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n", -v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z); File.WriteLine(Line); } if (Section->ColorIndex != gDefaultColor) { - sprintf(Line, "material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]); + sprintf(Line, " material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]); File.WriteLine(Line); } diff --git a/common/project.cpp b/common/project.cpp index 5d7cc23c..1190cd79 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -7,6 +7,7 @@ #include "project.h" #include "lc_instructions.h" #include "image.h" +#include "light.h" #include "lc_mainwindow.h" #include "lc_view.h" #include "lc_library.h" @@ -1828,15 +1829,6 @@ bool Project::ExportPOVRay(const QString& FileName) return false; } - POVFile.WriteLine("#version 3.7;\n\nglobal_settings {\n assumed_gamma 1.0\n}\n\n"); - - char Line[1024]; - - lcPiecesLibrary* Library = lcGetPiecesLibrary(); - std::map> PieceTable; - size_t NumColors = gColorList.size(); - std::vector> ColorTable(NumColors); - enum { LGEO_PIECE_LGEO = 0x01, @@ -1855,10 +1847,386 @@ bool Project::ExportPOVRay(const QString& FileName) LGEO_COLOR_GLITTER = 0x40 }; - QString LGEOPath; // todo: load lgeo from registry and make sure it still works + char Line[1024]; + + sprintf(Line, "// Generated By: LeoCAD %s\n// LDraw File: %s\n// Date: %s\n\n", + LC_VERSION_TEXT, + mModels[0]->GetProperties().mFileName.toLatin1().constData(), + QDateTime::currentDateTime().toString(Qt::ISODate).toLatin1().constData()); + POVFile.WriteLine(Line); + + POVFile.WriteLine("#version 3.7;\n\n"); + + POVFile.WriteLine("global_settings { assumed_gamma 1.0 }\n\n"); + + /* POV-Ray uses a left-handed coordinate system + * - positive x-axis pointing right + * - positive y-axis pointing up + * - positive z-axis pointing away from you + * POVRay [0]x,[1]y,[2]z = LeoCAD [1]y,[0]x,[2]z */ + + lcPiecesLibrary* Library = lcGetPiecesLibrary(); + std::map> PieceTable; + size_t NumColors = gColorList.size(); + std::vector> LgeoColorTable(NumColors); + std::vector> ColorTable(NumColors); + + const lcArray Lights = gMainWindow->GetActiveModel()->GetLights(); + const lcCamera* Camera = gMainWindow->GetActiveView()->GetCamera(); + const QString CameraName = QString(Camera->GetName()).replace(" ","_"); + const lcVector3& Position = Camera->mPosition; + const lcVector3& Target = Camera->mTargetPosition; + const lcVector3& Up = Camera->mUpVector; + const lcVector3 BackgroundColor = lcVector3FromColor(lcGetPreferences().mBackgroundSolidColor); + const lcPOVRayOptions& POVRayOptions = mModels[0]->GetPOVRayOptions(); + const QString TopModelName = QString("LC_%1").arg(QString(mModels[0]->GetFileName()).replace(" ","_").replace(".","_dot_")); + const QString LGEOPath = lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH); + const bool UseLGEO = POVRayOptions.UseLGEO && !LGEOPath.isEmpty(); + const int TopModelColorCode = 7; + QStringList ColorMacros, MaterialColors; + + lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX); + lcVector3 Max(-FLT_MAX, -FLT_MAX, -FLT_MAX); + + for (const lcModelPartsEntry& ModelPart : ModelParts) + { + lcVector3 Points[8]; + + lcGetBoxCorners(ModelPart.Info->GetBoundingBox(), Points); + + for (int PointIdx = 0; PointIdx < 8; PointIdx++) + { + lcVector3 Point = lcMul31(Points[PointIdx], ModelPart.WorldMatrix); + + Min = lcMin(Point, Min); + Max = lcMax(Point, Max); + } + } + + lcVector3 Center = (Min + Max) / 2.0f; + float Radius = (Max - Center).Length() / 25.0f; + Center = lcVector3(Center[1], Center[0], Center[2]) / 25.0f; + + lcVector3 FloorColor = POVRayOptions.FloorColor; + float FloorAmbient = POVRayOptions.FloorAmbient; + float FloorDiffuse = POVRayOptions.FloorDiffuse; + char FloorLocation[32]; + char FloorAxis[16]; + if (POVRayOptions.FloorAxis == 0) + { + sprintf(FloorAxis, "x"); + sprintf(FloorLocation, "MaxX"); + } + else if (POVRayOptions.FloorAxis == 1) + { + sprintf(FloorAxis, "y"); + sprintf(FloorLocation, "MaxY"); + } + else + { + sprintf(FloorAxis, "z"); + sprintf(FloorLocation, "MaxZ"); + } + + for (const lcLight* Light : Lights) + { + if (Light->mLightType == LC_AREALIGHT) + { + if (FloorColor == lcVector3(0.8f,0.8f,0.8f)) + FloorColor = {1.0f,1.0f,1.0f}; + if (FloorAmbient == 0.4f) + FloorAmbient = 0.0f; + if (FloorDiffuse == 0.4f) + FloorDiffuse = 0.9f; + break; + } + } + + if (!POVRayOptions.HeaderIncludeFile.isEmpty()) + { + sprintf(Line, "#include \"%s\"\n\n", POVRayOptions.HeaderIncludeFile.toLatin1().constData()); + POVFile.WriteLine(Line); + } + + sprintf(Line, + "#ifndef (MinX) #declare MinX = %g; #end\n" + "#ifndef (MinY) #declare MinY = %g; #end\n" + "#ifndef (MinZ) #declare MinZ = %g; #end\n" + "#ifndef (MaxX) #declare MaxX = %g; #end\n" + "#ifndef (MaxY) #declare MaxY = %g; #end\n" + "#ifndef (MaxZ) #declare MaxZ = %g; #end\n" + "#ifndef (CenterX) #declare CenterX = %g; #end\n" + "#ifndef (CenterY) #declare CenterY = %g; #end\n" + "#ifndef (CenterZ) #declare CenterZ = %g; #end\n" + "#ifndef (Center) #declare Center = ; #end\n" + "#ifndef (Radius) #declare Radius = %g; #end\n", + Min[0], Min[1], Min[2], Max[0], -Max[1], Max[2], Center[0], Center[1], Center[2], Radius); + POVFile.WriteLine(Line); + sprintf(Line, + "#ifndef (CameraSky) #declare CameraSky = <%g,%g,%g>; #end\n" + "#ifndef (CameraLocation) #declare CameraLocation = <%g, %g, %g>; #end\n" + "#ifndef (CameraTarget) #declare CameraTarget = <%g, %g, %g>; #end\n" + "#ifndef (CameraAngle) #declare CameraAngle = %g; #end\n", + Up[1], Up[0], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy); + POVFile.WriteLine(Line); + sprintf(Line, + "#ifndef (BackgroundColor) #declare BackgroundColor = <%1g, %1g, %1g>; #end\n" + "#ifndef (Background) #declare Background = %s; #end\n", + BackgroundColor[0], BackgroundColor[1], BackgroundColor[2], (POVRayOptions.ExcludeBackground ? "false" : "true")); + POVFile.WriteLine(Line); + sprintf(Line, + "#ifndef (FloorAxis) #declare FloorAxis = %s; #end\n" + "#ifndef (FloorLocation) #declare FloorLocation = %s; #end\n" + "#ifndef (FloorColor) #declare FloorColor = <%1g, %1g, %1g>; #end\n" + "#ifndef (FloorAmbient) #declare FloorAmbient = %1g; #end\n" + "#ifndef (FloorDiffuse) #declare FloorDiffuse = %1g; #end\n" + "#ifndef (Floor) #declare Floor = %s; #end\n", + FloorAxis, FloorLocation, FloorColor[0], FloorColor[1], FloorColor[2], FloorAmbient, FloorDiffuse, (POVRayOptions.ExcludeFloor ? "false" : "true")); + POVFile.WriteLine(Line); + sprintf(Line, + "#ifndef (Ambient) #declare Ambient = 0.4; #end\n" + "#ifndef (Diffuse) #declare Diffuse = 0.4; #end\n" + "#ifndef (Reflection) #declare Reflection = 0.08; #end\n" + "#ifndef (Phong) #declare Phong = 0.5; #end\n" + "#ifndef (PhongSize) #declare PhongSize = 40; #end\n" + "#ifndef (TransReflection) #declare TransReflection = 0.2; #end\n" + "#ifndef (TransFilter) #declare TransFilter = 0.85; #end\n" + "#ifndef (TransIoR) #declare TransIoR = 1.25; #end\n" + "#ifndef (RubberReflection) #declare RubberReflection = 0; #end\n" + "#ifndef (RubberPhong) #declare RubberPhong = 0.1; #end\n" + "#ifndef (RubberPhongS) #declare RubberPhongS = 10; #end\n" + "#ifndef (ChromeReflection) #declare ChromeReflection = 0.85; #end\n" + "#ifndef (ChromeBrilliance) #declare ChromeBrilliance = 5; #end\n" + "#ifndef (ChromeSpecular) #declare ChromeSpecular = 0.8; #end\n" + "#ifndef (ChromeRough) #declare ChromeRough = 0.01; #end\n" + "#ifndef (OpaqueNormal) #declare OpaqueNormal = normal { bumps 0.001 scale 0.5 }; #end\n" + "#ifndef (TransNormal) #declare TransNormal = normal { bumps 0.001 scale 0.5 }; #end\n"); + POVFile.WriteLine(Line); + sprintf(Line, + "#ifndef (Quality) #declare Quality = 3; #end\n" + "#ifndef (Studs) #declare Studs = 1; #end\n" + "#ifndef (LgeoLibrary) #declare LgeoLibrary = %s; #end\n" + "#ifndef (ModelReflection) #declare ModelReflection = %i; #end\n" + "#ifndef (ModelShadow) #declare ModelShadow = %i; #end\n\n", + (POVRayOptions.UseLGEO ? "true" : "false"), (POVRayOptions.NoReflection ? 0 : 1), (POVRayOptions.NoShadow ? 0 : 1)); + POVFile.WriteLine(Line); + + sprintf(Line, + "#ifndef (SkipWriteLightMacro)\n" + "#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n" + " #local PointLight = %i;\n" + " #local AreaLight = %i;\n" + " #local SunLight = %i;\n" + " #local SpotLight = %i;\n" + " light_source {\n" + " Location\n" + " color rgb Color*Power\n" + " #if (Shadowless > 0)\n" + " shadowless\n" + " #end\n" + " #if (Type = AreaLight)\n" + " area_light AreaWidth, AreaHeight, AreaRows, AreaColumns\n" + " jitter\n" + " #if (AreaCircle > 0 & AreaWidth > 2 & AreaHeight > 2 & AreaRows > 1 & AreaColumns > 1 )\n" + " circular \n" + " #if (AreaWidth = AreaHeight & AreaRows = AreaColumns)\n" + " orient\n" + " #end\n" + " #end\n" + " #elseif (Type = SunLight)\n" + " parallel\n" + " point_at Target\n" + " #elseif (Type = SpotLight)\n" + " spotlight\n" + " radius SpotRadius\n" + " falloff SpotFalloff\n" + " tightness SpotTightness\n" + " point_at Target\n" + " #end\n" + " }\n" + "#end\n" + "#end\n\n", + LC_POINTLIGHT, LC_AREALIGHT, LC_SUNLIGHT, LC_SPOTLIGHT); + POVFile.WriteLine(Line); + + for (const lcModelPartsEntry& ModelPart : ModelParts) + { + int ColorIdx = ModelPart.ColorIndex; + + if (lcIsColorTranslucent(ColorIdx)) + { + if (!ColorMacros.contains("TranslucentColor")) + { + sprintf(Line, + "#ifndef (SkipTranslucentColorMacro)\n" + "#macro TranslucentColor(r, g, b, f)\n" + " material {\n" + " texture {\n" + " pigment { srgbf }\n" + " finish { emission 0 ambient Ambient diffuse Diffuse }\n" + " finish { phong Phong phong_size PhongSize reflection TransReflection }\n" + " normal { TransNormal }\n" + " }\n" + " interior { ior TransIoR }\n" + " }\n" + "#end\n" + "#end\n\n"); + POVFile.WriteLine(Line); + ColorMacros.append("TranslucentColor"); + } + } + else if (lcIsColorChrome(ColorIdx)) + { + if (!ColorMacros.contains("ChromeColor")) + { + sprintf(Line, + "#ifndef (SkipChromeColorMacro)\n" + "#macro ChromeColor(r, g, b)\n" + "#if (LgeoLibrary) material { #end\n" + " texture {\n" + " pigment { srgbf }\n" + " finish { emission 0 ambient Ambient diffuse Diffuse }\n" + " finish { phong Phong phong_size PhongSize reflection ChromeReflection brilliance ChromeBrilliance metallic specular ChromeSpecular roughness ChromeRough }\n" + " }\n" + "#if (LgeoLibrary) } #end\n" + "#end\n" + "#end\n\n"); + POVFile.WriteLine(Line); + ColorMacros.append("ChromeColor"); + } + } + else if (lcIsColorRubber(ColorIdx)) + { + if (!ColorMacros.contains("RubberColor")) + { + sprintf(Line, + "#ifndef (SkipRubberColorMacro)\n" + "#macro RubberColor(r, g, b)\n" + "#if (LgeoLibrary) material { #end\n" + " texture {\n" + " pigment { srgbf }\n" + " finish { emission 0 ambient Ambient diffuse Diffuse }\n" + " finish { phong RubberPhong phong_size RubberPhongS reflection RubberReflection }\n" + " }\n" + "#if (LgeoLibrary) } #end\n" + "#end\n" + "#end\n\n"); + POVFile.WriteLine(Line); + ColorMacros.append("RubberColor"); + } + } + else + { + if (!ColorMacros.contains("OpaqueColor")) + { + sprintf(Line, + "#ifndef (SkipOpaqueColorMacro)\n" + "#macro OpaqueColor(r, g, b)\n" + "#if (LgeoLibrary) material { #end\n" + " texture {\n" + " pigment { srgbf }\n" + " finish { emission 0 ambient Ambient diffuse Diffuse }\n" + " finish { phong Phong phong_size PhongSize reflection Reflection }\n" + " normal { OpaqueNormal }\n" + " }\n" + "#if (LgeoLibrary) } #end\n" + "#end\n" + "#end\n\n"); + POVFile.WriteLine(Line); + ColorMacros.append("OpaqueColor"); + } + } + } + + sprintf(Line, "#if (Background)\n background {\n color rgb BackgroundColor\n }\n#end\n\n"); + POVFile.WriteLine(Line); + + sprintf(Line, "#ifndef (Skip%s)\n camera {\n perspective\n right x * image_width / image_height\n sky CameraSky\n location CameraLocation\n look_at CameraTarget\n angle CameraAngle * image_width / image_height\n }\n#end\n\n", + (CameraName.isEmpty() ? "Camera" : CameraName.toLatin1().constData())); + POVFile.WriteLine(Line); + + lcVector3 LightTarget(0.0f, 0.0f, 0.0f), LightColor(1.0f, 1.0f, 1.0f); + lcVector2 AreaSize(200.0f, 200.0f), AreaGrid(10.0f, 10.0f); + int AreaCircle = 0, Shadowless = 0, LightType = LC_AREALIGHT; + float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0; + if (Lights.IsEmpty()) + { + lcVector3 Location[4]; + Location[0] = {0.0f * Radius + Center[0], -1.5f * Radius + Center[1], -1.5f * Radius + Center[2]}; + Location[1] = {1.5f * Radius + Center[0], -1.0f * Radius + Center[1], 0.866026f * Radius + Center[2]}; + Location[2] = {0.0f * Radius + Center[0], -2.0f * Radius + Center[1], 0.0f * Radius + Center[2]}; + Location[3] = {2.0f * Radius + Center[0], 0.0f * Radius + Center[1], -2.0f * Radius + Center[2]}; + for (int Idx = 0; Idx < 4; Idx++) + { + Power = Idx < 2 ? 0.75f : 0.5f; + sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, %i, %i, %i, %i)\n#end\n\n", + Idx, + LightType, + Shadowless, + Location[Idx][0], Location[Idx][1], Location[Idx][2], + LightTarget[0], LightTarget[1], LightTarget[2], + LightColor[0], LightColor[1], LightColor[2], + Power, + SpotRadius, SpotFalloff, SpotTightness, + AreaCircle, (int)AreaSize[0], (int)AreaSize[1], (int)AreaGrid[0], (int)AreaGrid[1]); + POVFile.WriteLine(Line); + } + } + else + { + for (const lcLight* Light : Lights) + { + const lcVector3& Location = Light->mPosition; + const QString LightName = QString(Light->mName).replace(" ","_"); + LightType = Light->mLightType; + Shadowless = static_cast(Light->mShadowless); + LightColor = Light->mLightColor; + Power = Light->mPOVRayExponent; + switch(LightType) + { + case LC_AREALIGHT: + AreaCircle = Light->mLightShape == LC_LIGHT_SHAPE_DISK ? 1 : 0; + AreaSize = Light->mAreaSize; + AreaGrid = Light->mAreaGrid; + break; + case LC_SUNLIGHT: + LightTarget = Light->mTargetPosition; + break; + case LC_SPOTLIGHT: + LightTarget = Light->mTargetPosition; + SpotFalloff = Light->mSpotFalloff; + SpotRadius = Light->mSpotSize - SpotFalloff; + break; + default: + break; + } + + sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, %i, %i, %i, %i)\n#end\n\n", + LightName.toLatin1().constData(), + LightType, + Shadowless, + Location[1], Location[0], Location[2], + LightTarget[1], LightTarget[0], LightTarget[2], + LightColor[0], LightColor[1], LightColor[2], + Power, + SpotRadius, SpotFalloff, SpotTightness, + AreaCircle, (int)AreaSize[0], (int)AreaSize[1], (int)AreaGrid[0], (int)AreaGrid[1]); + POVFile.WriteLine(Line); + } + } + + POVFile.WriteLine("#ifndef (lg_quality) #declare lg_quality = Quality; #end\n\n"); - if (!LGEOPath.isEmpty()) + if (UseLGEO) { + memset(Line, 0, 1024); + + POVFile.WriteLine("#ifndef (lg_studs) #declare lg_studs = Studs; #end\n\n"); + + POVFile.WriteLine("#if (lg_quality = 3) #declare lg_quality = 4; #end\n\n"); + + POVFile.WriteLine("#include \"lg_defs.inc\"\n\n#include \"lg_color.inc\"\n\n"); + lcDiskFile TableFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_elements.lst")).absoluteFilePath()); if (!TableFile.Open(QIODevice::ReadOnly)) @@ -1869,6 +2237,7 @@ bool Project::ExportPOVRay(const QString& FileName) while (TableFile.ReadLine(Line, sizeof(Line))) { + char Src[129], Dst[129], Flags[11]; if (*Line == ';') @@ -1877,20 +2246,22 @@ bool Project::ExportPOVRay(const QString& FileName) if (sscanf(Line,"%128s%128s%10s", Src, Dst, Flags) != 3) continue; - strcat(Src, ".dat"); + strncat(Src, ".dat", 4); PieceInfo* Info = Library->FindPiece(Src, nullptr, false, false); if (!Info) continue; - if (strchr(Flags, 'L')) + bool LgeoPartFound = false; + + if ((LgeoPartFound = strchr(Flags, 'L'))) { std::pair& Entry = PieceTable[Info]; Entry.second |= LGEO_PIECE_LGEO; sprintf(Entry.first, "lg_%s", Dst); } - if (strchr(Flags, 'A')) + if (strchr(Flags, 'A') && !LgeoPartFound) { std::pair& Entry = PieceTable[Info]; Entry.second |= LGEO_PIECE_AR; @@ -1905,15 +2276,15 @@ bool Project::ExportPOVRay(const QString& FileName) } } - lcDiskFile ColorFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_colors.lst")).absoluteFilePath()); + lcDiskFile LgeoColorFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_colors.lst")).absoluteFilePath()); - if (!ColorFile.Open(QIODevice::ReadOnly)) + if (!LgeoColorFile.Open(QIODevice::ReadOnly)) { QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Could not find LGEO files in folder '%1'.").arg(LGEOPath)); return false; } - while (ColorFile.ReadLine(Line, sizeof(Line))) + while (LgeoColorFile.ReadLine(Line, sizeof(Line))) { char Name[1024], Flags[1024]; int Code; @@ -1924,20 +2295,82 @@ bool Project::ExportPOVRay(const QString& FileName) if (sscanf(Line,"%d%s%s", &Code, Name, Flags) != 3) continue; - size_t Color = lcGetColorIndex(Code); - if (Color >= NumColors) + size_t ColorIdx = lcGetColorIndex(Code); + if (ColorIdx >= NumColors) continue; - strcpy(ColorTable[Color].data(), Name); + strncpy(LgeoColorTable[ColorIdx].data(), Name, LC_MAX_COLOR_NAME); } } - std::set AddedMeshes; + for (const lcModelPartsEntry& ModelPart : ModelParts) + { + size_t ColorIdx = ModelPart.ColorIndex; + + if (!ColorTable[ColorIdx][0]) + { + lcColor* Color = &gColorList[ColorIdx]; + + if (!LgeoColorTable[ColorIdx][0]) + { + sprintf(ColorTable[ColorIdx].data(), "lc_%s", Color->SafeName); + + if (lcIsColorTranslucent(ColorIdx)) + { + if (!UseLGEO && !MaterialColors.contains(ColorTable[ColorIdx].data())) + MaterialColors.append(ColorTable[ColorIdx].data()); + + sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = TranslucentColor(%g, %g, %g, TransFilter)\n#end\n\n", + Color->SafeName, Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); + } + else + { + char MacroName[LC_MAX_COLOR_NAME]; + if (lcIsColorChrome(ColorIdx)) + sprintf(MacroName, "Chrome"); + else if (lcIsColorRubber(ColorIdx)) + sprintf(MacroName, "Rubber"); + else + sprintf(MacroName, "Opaque"); - if (!LGEOPath.isEmpty()) + sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = %sColor(%g, %g, %g)\n#end\n\n", + Color->SafeName, Color->SafeName, MacroName, Color->Value[0], Color->Value[1], Color->Value[2]); + } + } + else + { + sprintf(ColorTable[ColorIdx].data(), "LDXColor%i", Color->Code); + + sprintf(Line,"#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n", + Color->Code, Color->Name, Color->Code, LgeoColorTable[ColorIdx].data()); + } + + POVFile.WriteLine(Line); + } + } + + if (!ColorTable[lcGetColorIndex(TopModelColorCode)][0]) { - POVFile.WriteLine("#include \"lg_defs.inc\"\n#include \"lg_color.inc\"\n\n"); + size_t ColorIdx = lcGetColorIndex(TopModelColorCode); + + lcColor* Color = &gColorList[ColorIdx]; + + sprintf(ColorTable[ColorIdx].data(), "LDXColor%i", Color->Code); + + if (!LgeoColorTable[ColorIdx][0]) + sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = OpaqueColor(%g, %g, %g)\n#end\n\n", + Color->SafeName, Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); + else + sprintf(Line,"#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n", + Color->Code, Color->Name, Color->Code, LgeoColorTable[ColorIdx].data()); + + POVFile.WriteLine(Line); + } + std::set AddedMeshes; + + if (UseLGEO) + { for (const lcModelPartsEntry& ModelPart : ModelParts) { if (ModelPart.Mesh) @@ -1958,7 +2391,7 @@ bool Project::ExportPOVRay(const QString& FileName) const std::pair& Entry = Search->second; if (Entry.first[0]) { - sprintf(Line, "#include \"%s.inc\"\n", Entry.first); + sprintf(Line, "#include \"%s.inc\" // %s\n", Entry.first, ModelPart.Info->m_strDescription); POVFile.WriteLine(Line); } } @@ -1966,29 +2399,6 @@ bool Project::ExportPOVRay(const QString& FileName) POVFile.WriteLine("\n"); } - for (size_t ColorIdx = 0; ColorIdx < gColorList.size(); ColorIdx++) - { - lcColor* Color = &gColorList[ColorIdx]; - - if (lcIsColorTranslucent(ColorIdx)) - { - sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> filter 0.9 } finish { ambient 0.3 diffuse 0.2 reflection 0.25 phong 0.3 phong_size 60 } }\n", - Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); - } - else - { - sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> } finish { ambient 0.1 phong 0.2 phong_size 20 } }\n", - Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); - } - - POVFile.WriteLine(Line); - - if (!ColorTable[ColorIdx][0]) - sprintf(ColorTable[ColorIdx].data(), "lc_%s", Color->SafeName); - } - - POVFile.WriteLine("\n"); - std::vector ColorTablePointer; ColorTablePointer.resize(NumColors); for (size_t ColorIdx = 0; ColorIdx < NumColors; ColorIdx++) @@ -1996,7 +2406,7 @@ bool Project::ExportPOVRay(const QString& FileName) auto GetMeshName = [](const lcModelPartsEntry& ModelPart, char (&Name)[LC_PIECE_NAME_LEN]) { - strcpy(Name, ModelPart.Info->mFileName); + strncpy(Name, ModelPart.Info->mFileName, sizeof(Name)); for (char* c = Name; *c; c++) if (*c == '-' || *c == '.') @@ -2006,7 +2416,7 @@ bool Project::ExportPOVRay(const QString& FileName) { char Suffix[32]; sprintf(Suffix, "_%p", ModelPart.Mesh); - strncat(Name, Suffix, sizeof(Name) - 1); + strncat(Name, Suffix, sizeof(Name) - strlen(Name) - 1); Name[sizeof(Name) - 1] = 0; } }; @@ -2027,7 +2437,7 @@ bool Project::ExportPOVRay(const QString& FileName) if (!ModelPart.Mesh) { std::pair& Entry = PieceTable[ModelPart.Info]; - strcpy(Entry.first, "lc_"); + strncpy(Entry.first, "lc_", 3); strncat(Entry.first, Name, sizeof(Entry.first) - 1); Entry.first[sizeof(Entry.first) - 1] = 0; } @@ -2038,65 +2448,30 @@ bool Project::ExportPOVRay(const QString& FileName) POVFile.WriteLine(Line); } - const lcCamera* Camera = gMainWindow->GetActiveView()->GetCamera(); - const lcVector3& Position = Camera->mPosition; - const lcVector3& Target = Camera->mTargetPosition; - const lcVector3& Up = Camera->mUpVector; - - sprintf(Line, "camera {\n perspective\n right x * image_width / image_height\n sky<%1g,%1g,%1g>\n location <%1g, %1g, %1g>\n look_at <%1g, %1g, %1g>\n angle %.0f * image_width / image_height\n}\n\n", - Up[1], Up[0], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy); - POVFile.WriteLine(Line); - lcVector3 BackgroundColor = lcVector3FromColor(lcGetPreferences().mBackgroundSolidColor); - sprintf(Line, "background { color rgb <%1g, %1g, %1g> }\n\n", BackgroundColor[0], BackgroundColor[1], BackgroundColor[2]); - POVFile.WriteLine(Line); - - lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX); - lcVector3 Max(-FLT_MAX, -FLT_MAX, -FLT_MAX); - - for (const lcModelPartsEntry& ModelPart : ModelParts) - { - lcVector3 Points[8]; - - lcGetBoxCorners(ModelPart.Info->GetBoundingBox(), Points); - - for (int PointIdx = 0; PointIdx < 8; PointIdx++) - { - lcVector3 Point = lcMul31(Points[PointIdx], ModelPart.WorldMatrix); - - Min = lcMin(Point, Min); - Max = lcMax(Point, Max); - } - } - - lcVector3 Center = (Min + Max) / 2.0f; - float Radius = (Max - Center).Length() / 25.0f; - Center = lcVector3(Center[1], Center[0], Center[2]) / 25.0f; - - sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.75\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 0.0f * Radius + Center.x, -1.5f * Radius + Center.y, -1.5f * Radius + Center.z); - POVFile.WriteLine(Line); - sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.75\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 1.5f * Radius + Center.x, -1.0f * Radius + Center.y, 0.866026f * Radius + Center.z); - POVFile.WriteLine(Line); - sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.5\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 0.0f * Radius + Center.x, -2.0f * Radius + Center.y, 0.0f * Radius + Center.z); - POVFile.WriteLine(Line); - sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.5\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 2.0f * Radius + Center.x, 0.0f * Radius + Center.y, -2.0f * Radius + Center.z); + sprintf(Line, "#declare %s = union {\n", TopModelName.toLatin1().constData()); POVFile.WriteLine(Line); for (const lcModelPartsEntry& ModelPart : ModelParts) { - int Color = ModelPart.ColorIndex; - const char* Suffix = lcIsColorTranslucent(Color) ? "_clear" : ""; + int ColorIdx = ModelPart.ColorIndex; + const char* Suffix = lcIsColorTranslucent(ColorIdx) ? "_clear" : ""; const float* f = ModelPart.WorldMatrix; - + char Modifier[32]; + if (UseLGEO || MaterialColors.contains(ColorTable[ColorIdx].data())) + sprintf(Modifier, "material"); + else + sprintf(Modifier, "texture"); if (!ModelPart.Mesh) { std::pair& Entry = PieceTable[ModelPart.Info]; if (Entry.second & LGEO_PIECE_SLOPE) { - sprintf(Line, "merge {\n object {\n %s%s\n texture { %s }\n }\n" - " object {\n %s_slope\n texture { %s normal { bumps 0.3 scale 0.02 } }\n }\n" - " matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n", - Entry.first, Suffix, ColorTable[Color].data(), Entry.first, ColorTable[Color].data(), + sprintf(Line, + " merge {\n object {\n %s%s\n %s { %s }\n }\n" + " object {\n %s_slope\n texture {\n %s normal { bumps 0.3 scale 0.02 }\n }\n }\n" + " matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n", + Entry.first, Suffix, Modifier, ColorTable[ColorIdx].data(), Entry.first, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); } else @@ -2104,8 +2479,8 @@ bool Project::ExportPOVRay(const QString& FileName) if (!ModelPart.Info || !ModelPart.Info->GetMesh()) continue; - sprintf(Line, "object {\n %s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n", - Entry.first, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); + sprintf(Line, " object {\n %s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n", + Entry.first, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); } } @@ -2114,13 +2489,29 @@ bool Project::ExportPOVRay(const QString& FileName) char Name[LC_PIECE_NAME_LEN]; GetMeshName(ModelPart, Name); - sprintf(Line, "object {\n lc_%s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n", - Name, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); + sprintf(Line, " object {\n lc_%s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n", + Name, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); } POVFile.WriteLine(Line); } + sprintf(Line, "\n #if (ModelReflection = 0)\n no_reflection\n #end\n #if (ModelShadow = 0)\n no_shadow\n #end\n}\n\n"); + POVFile.WriteLine(Line); + + sprintf(Line, "object {\n %s\n %s { %s }\n}\n\n", + TopModelName.toLatin1().constData(), (UseLGEO ? "material" : "texture"), ColorTable[lcGetColorIndex(TopModelColorCode)].data()); + POVFile.WriteLine(Line); + + sprintf(Line, "#if (Floor)\n object {\n plane { FloorAxis, FloorLocation hollow }\n texture {\n pigment { color srgb FloorColor }\n finish { emission 0 ambient FloorAmbient diffuse FloorDiffuse }\n }\n }\n#end\n"); + POVFile.WriteLine(Line); + + if (!POVRayOptions.FooterIncludeFile.isEmpty()) + { + sprintf(Line, "\n#include \"%s\"\n", POVRayOptions.FooterIncludeFile.toLatin1().constData()); + POVFile.WriteLine(Line); + } + return true; } @@ -2239,7 +2630,7 @@ void Project::SaveImage() if (Dialog.exec() != QDialog::Accepted) return; - + QString Extension = QFileInfo(Dialog.mFileName).suffix(); if (!Extension.isEmpty()) From 8cfadc804d29a4075e9f659541b9b07e3ee6bde2 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sun, 13 Aug 2023 15:15:52 +0200 Subject: [PATCH 14/42] Made light type/shape immutable. --- common/lc_commands.cpp | 144 ++++++------- common/lc_commands.h | 12 +- common/lc_global.h | 1 + common/lc_mainwindow.cpp | 46 ++--- common/lc_model.cpp | 46 +++-- common/lc_model.h | 2 +- common/lc_view.cpp | 230 +++++++++++---------- common/lc_view.h | 10 +- common/lc_viewmanipulator.cpp | 4 +- common/light.cpp | 378 +++++++++++++++------------------- common/light.h | 48 ++--- common/project.cpp | 57 +++-- qt/lc_qpropertiestree.cpp | 161 ++++++++------- qt/lc_qpropertiestree.h | 2 +- resources/leocad_cs.ts | 2 +- resources/leocad_de.ts | 2 +- resources/leocad_es.ts | 2 +- resources/leocad_fr.ts | 2 +- resources/leocad_pt.ts | 2 +- resources/leocad_uk.ts | 2 +- 20 files changed, 563 insertions(+), 590 deletions(-) diff --git a/common/lc_commands.cpp b/common/lc_commands.cpp index 79ff61f5..94530fa4 100644 --- a/common/lc_commands.cpp +++ b/common/lc_commands.cpp @@ -333,46 +333,46 @@ const lcCommand gCommands[] = QT_TRANSLATE_NOOP("Status", "Select all pieces of the same type and color"), "" }, - // LC_EDIT_TRANSFORM_RELATIVE - { - QT_TRANSLATE_NOOP("Action", "Edit.TransformRelative"), - QT_TRANSLATE_NOOP("Menu", "Relative Transforms"), - QT_TRANSLATE_NOOP("Status", "Move and rotate objects relative to the one that has focus"), - "" - }, - // LC_EDIT_TRANSFORM_ABSOLUTE - { - QT_TRANSLATE_NOOP("Action", "Edit.TransformAbsolute"), - QT_TRANSLATE_NOOP("Menu", "Absolute Transforms"), - QT_TRANSLATE_NOOP("Status", "Move and rotate objects in absolute coordinates"), - "" - }, - // LC_EDIT_TRANSFORM_TOGGLE_RELATIVE - { - QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleRelative"), - QT_TRANSLATE_NOOP("Menu", "Toggle Relative Transforms"), - QT_TRANSLATE_NOOP("Status", "Toggle moving and rotating objects relative to the one that has focus"), - "" - }, - // LC_EDIT_TRANSFORM_SEPARATELY - { - QT_TRANSLATE_NOOP("Action", "Edit.TransformSeparately"), - QT_TRANSLATE_NOOP("Menu", "Rotate Separately"), - QT_TRANSLATE_NOOP("Status", "Rotate selected pieces separately"), - "" - }, - // LC_EDIT_TRANSFORM_TOGETHER - { - QT_TRANSLATE_NOOP("Action", "Edit.TransformTogether"), - QT_TRANSLATE_NOOP("Menu", "Rotate Together"), - QT_TRANSLATE_NOOP("Status", "Rotate selected pieces together"), - "" - }, - // LC_EDIT_TRANSFORM_TOGGLE_SEPARATE - { - QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleSeparate"), - QT_TRANSLATE_NOOP("Menu", "Toggle Separate Transforms"), - QT_TRANSLATE_NOOP("Status", "Toggle rotating selected pieces separately"), + // LC_EDIT_TRANSFORM_RELATIVE + { + QT_TRANSLATE_NOOP("Action", "Edit.TransformRelative"), + QT_TRANSLATE_NOOP("Menu", "Relative Transforms"), + QT_TRANSLATE_NOOP("Status", "Move and rotate objects relative to the one that has focus"), + "" + }, + // LC_EDIT_TRANSFORM_ABSOLUTE + { + QT_TRANSLATE_NOOP("Action", "Edit.TransformAbsolute"), + QT_TRANSLATE_NOOP("Menu", "Absolute Transforms"), + QT_TRANSLATE_NOOP("Status", "Move and rotate objects in absolute coordinates"), + "" + }, + // LC_EDIT_TRANSFORM_TOGGLE_RELATIVE + { + QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleRelative"), + QT_TRANSLATE_NOOP("Menu", "Toggle Relative Transforms"), + QT_TRANSLATE_NOOP("Status", "Toggle moving and rotating objects relative to the one that has focus"), + "" + }, + // LC_EDIT_TRANSFORM_SEPARATELY + { + QT_TRANSLATE_NOOP("Action", "Edit.TransformSeparately"), + QT_TRANSLATE_NOOP("Menu", "Rotate Separately"), + QT_TRANSLATE_NOOP("Status", "Rotate selected pieces separately"), + "" + }, + // LC_EDIT_TRANSFORM_TOGETHER + { + QT_TRANSLATE_NOOP("Action", "Edit.TransformTogether"), + QT_TRANSLATE_NOOP("Menu", "Rotate Together"), + QT_TRANSLATE_NOOP("Status", "Rotate selected pieces together"), + "" + }, + // LC_EDIT_TRANSFORM_TOGGLE_SEPARATE + { + QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleSeparate"), + QT_TRANSLATE_NOOP("Menu", "Toggle Separate Transforms"), + QT_TRANSLATE_NOOP("Status", "Toggle rotating selected pieces separately"), "" }, // LC_EDIT_SNAP_MOVE_TOGGLE @@ -641,32 +641,32 @@ const lcCommand gCommands[] = QT_TRANSLATE_NOOP("Status", "Add new pieces to the model"), "" }, - // LC_EDIT_ACTION_LIGHT + // LC_EDIT_ACTION_POINT_LIGHT { - QT_TRANSLATE_NOOP("Action", "Edit.Tool.Light"), - QT_TRANSLATE_NOOP("Menu", "Light"), + QT_TRANSLATE_NOOP("Action", "Edit.Tool.PointLight"), + QT_TRANSLATE_NOOP("Menu", "Point Light"), QT_TRANSLATE_NOOP("Status", "Add new omni light sources to the model"), "" }, - // LC_EDIT_ACTION_AREALIGHT + // LC_EDIT_ACTION_SPOTLIGHT { - QT_TRANSLATE_NOOP("Action", "Edit.Tool.Arealight"), - QT_TRANSLATE_NOOP("Menu", "Arealight"), - QT_TRANSLATE_NOOP("Status", "Add new arealight sources to the model - edit in Properties tab"), + QT_TRANSLATE_NOOP("Action", "Edit.Tool.Spotlight"), + QT_TRANSLATE_NOOP("Menu", "Spotlight"), + QT_TRANSLATE_NOOP("Status", "Add new spotlights to the model"), "" }, - // LC_EDIT_ACTION_SUNLIGHT + // LC_EDIT_ACTION_DIRECTIONAL_LIGHT { - QT_TRANSLATE_NOOP("Action", "Edit.Tool.Sunlight"), - QT_TRANSLATE_NOOP("Menu", "Sunlight"), + QT_TRANSLATE_NOOP("Action", "Edit.Tool.DirectionalLight"), + QT_TRANSLATE_NOOP("Menu", "Directional Light"), QT_TRANSLATE_NOOP("Status", "Add new omnidirectional sunlight sources to the model - edit in Properties tab"), "" }, - // LC_EDIT_ACTION_SPOTLIGHT + // LC_EDIT_ACTION_AREA_LIGHT { - QT_TRANSLATE_NOOP("Action", "Edit.Tool.Spotlight"), - QT_TRANSLATE_NOOP("Menu", "Spotlight"), - QT_TRANSLATE_NOOP("Status", "Add new spotlights to the model"), + QT_TRANSLATE_NOOP("Action", "Edit.Tool.AreaLight"), + QT_TRANSLATE_NOOP("Menu", "Area Light"), + QT_TRANSLATE_NOOP("Status", "Add new arealight sources to the model - edit in Properties tab"), "" }, // LC_EDIT_ACTION_CAMERA @@ -1376,7 +1376,7 @@ const lcCommand gCommands[] = QT_TRANSLATE_NOOP("Status", "Make copies of the selected pieces"), "" }, - // LC_PIECE_VIEW_SELECTED_MODEL + // LC_PIECE_VIEW_SELECTED_MODEL { QT_TRANSLATE_NOOP("Action", "Piece.ViewSelectedModel"), QT_TRANSLATE_NOOP("Menu", "Open Selected Model"), @@ -1872,23 +1872,23 @@ LC_ARRAY_SIZE_CHECK(gCommands, LC_NUM_COMMANDS); const char* gToolNames[] = { - QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert - QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::Light - QT_TRANSLATE_NOOP("Mouse", "NewAreaLight"), // lcTool::AreaLight - QT_TRANSLATE_NOOP("Mouse", "NewSunLight"), // lcTool::SunLight - QT_TRANSLATE_NOOP("Mouse", "NewSpotLight"), // lcTool::SpotLight - QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera - QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select - QT_TRANSLATE_NOOP("Mouse", "Move"), // lcTool::Move - QT_TRANSLATE_NOOP("Mouse", "Rotate"), // lcTool::Rotate - QT_TRANSLATE_NOOP("Mouse", "Delete"), // lcTool::Eraser - QT_TRANSLATE_NOOP("Mouse", "Paint"), // lcTool::Paint - QT_TRANSLATE_NOOP("Mouse", "ColorPicker"), // lcTool::ColorPicker - QT_TRANSLATE_NOOP("Mouse", "Zoom"), // lcTool::Zoom - QT_TRANSLATE_NOOP("Mouse", "Pan"), // lcTool::Pan - QT_TRANSLATE_NOOP("Mouse", "Orbit"), // lcTool::RotateView - QT_TRANSLATE_NOOP("Mouse", "Roll"), // lcTool::Roll - QT_TRANSLATE_NOOP("Mouse", "ZoomRegion") // lcTool::ZoomRegion + QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert + QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::PointLight + QT_TRANSLATE_NOOP("Mouse", "NewSpotlight"), // lcTool::Spotlight + QT_TRANSLATE_NOOP("Mouse", "NewDirectionalLight"), // lcTool::DirectionalLight + QT_TRANSLATE_NOOP("Mouse", "NewAreaLight"), // lcTool::AreaLight + QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera + QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select + QT_TRANSLATE_NOOP("Mouse", "Move"), // lcTool::Move + QT_TRANSLATE_NOOP("Mouse", "Rotate"), // lcTool::Rotate + QT_TRANSLATE_NOOP("Mouse", "Delete"), // lcTool::Eraser + QT_TRANSLATE_NOOP("Mouse", "Paint"), // lcTool::Paint + QT_TRANSLATE_NOOP("Mouse", "ColorPicker"), // lcTool::ColorPicker + QT_TRANSLATE_NOOP("Mouse", "Zoom"), // lcTool::Zoom + QT_TRANSLATE_NOOP("Mouse", "Pan"), // lcTool::Pan + QT_TRANSLATE_NOOP("Mouse", "Orbit"), // lcTool::RotateView + QT_TRANSLATE_NOOP("Mouse", "Roll"), // lcTool::Roll + QT_TRANSLATE_NOOP("Mouse", "ZoomRegion") // lcTool::ZoomRegion }; LC_ARRAY_SIZE_CHECK(gToolNames, lcTool::Count); diff --git a/common/lc_commands.h b/common/lc_commands.h index 6db95a22..ea334c92 100644 --- a/common/lc_commands.h +++ b/common/lc_commands.h @@ -98,10 +98,10 @@ enum lcCommandId LC_EDIT_TRANSFORM_RELATIVE_ROTATION, LC_EDIT_ACTION_FIRST, LC_EDIT_ACTION_INSERT = LC_EDIT_ACTION_FIRST, - LC_EDIT_ACTION_LIGHT, - LC_EDIT_ACTION_AREALIGHT, - LC_EDIT_ACTION_SUNLIGHT, + LC_EDIT_ACTION_POINT_LIGHT, LC_EDIT_ACTION_SPOTLIGHT, + LC_EDIT_ACTION_DIRECTIONAL_LIGHT, + LC_EDIT_ACTION_AREA_LIGHT, LC_EDIT_ACTION_CAMERA, LC_EDIT_ACTION_SELECT, LC_EDIT_ACTION_MOVE, @@ -300,10 +300,10 @@ extern const lcCommand gCommands[]; enum class lcTool { Insert, - Light, + PointLight, + Spotlight, + DirectionalLight, AreaLight, - SunLight, - SpotLight, Camera, Select, Move, diff --git a/common/lc_global.h b/common/lc_global.h index f079df05..48a3b33e 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -75,6 +75,7 @@ class lcObject; class lcPiece; class lcCamera; class lcLight; +enum class lcLightType; class lcGroup; class PieceInfo; typedef std::map> lcPartsList; diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 4bc9aff9..29267c05 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -204,22 +204,22 @@ void lcMainWindow::CreateActions() QIcon EditActionLightIcon; EditActionLightIcon.addFile(":/resources/action_light.png"); EditActionLightIcon.addFile(":/resources/action_light_16.png"); - mActions[LC_EDIT_ACTION_LIGHT]->setIcon(EditActionLightIcon); + mActions[LC_EDIT_ACTION_POINT_LIGHT]->setIcon(EditActionLightIcon); - QIcon EditActionArealightIcon; - EditActionArealightIcon.addFile(":/resources/action_arealight.png"); - EditActionArealightIcon.addFile(":/resources/action_arealight_16.png"); - mActions[LC_EDIT_ACTION_AREALIGHT]->setIcon(EditActionArealightIcon); + QIcon EditActionSpotLightIcon; + EditActionSpotLightIcon.addFile(":/resources/action_spotlight.png"); + EditActionSpotLightIcon.addFile(":/resources/action_spotlight_16.png"); + mActions[LC_EDIT_ACTION_SPOTLIGHT]->setIcon(EditActionSpotLightIcon); QIcon EditActionSunlightIcon; EditActionSunlightIcon.addFile(":/resources/action_sunlight.png"); EditActionSunlightIcon.addFile(":/resources/action_sunlight_16.png"); - mActions[LC_EDIT_ACTION_SUNLIGHT]->setIcon(EditActionSunlightIcon); + mActions[LC_EDIT_ACTION_DIRECTIONAL_LIGHT]->setIcon(EditActionSunlightIcon); - QIcon EditActionSpotLightIcon; - EditActionSpotLightIcon.addFile(":/resources/action_spotlight.png"); - EditActionSpotLightIcon.addFile(":/resources/action_spotlight_16.png"); - mActions[LC_EDIT_ACTION_SPOTLIGHT]->setIcon(EditActionSpotLightIcon); + QIcon EditActionArealightIcon; + EditActionArealightIcon.addFile(":/resources/action_arealight.png"); + EditActionArealightIcon.addFile(":/resources/action_arealight_16.png"); + mActions[LC_EDIT_ACTION_AREA_LIGHT]->setIcon(EditActionArealightIcon); QIcon EditActionSelectIcon; EditActionSelectIcon.addFile(":/resources/action_select.png"); @@ -431,10 +431,10 @@ void lcMainWindow::CreateMenus() mToolsMenu = new QMenu(tr("Tools"), this); mToolsMenu->addAction(mActions[LC_EDIT_ACTION_INSERT]); - mToolsMenu->addAction(mActions[LC_EDIT_ACTION_LIGHT]); - mToolsMenu->addAction(mActions[LC_EDIT_ACTION_AREALIGHT]); - mToolsMenu->addAction(mActions[LC_EDIT_ACTION_SUNLIGHT]); + mToolsMenu->addAction(mActions[LC_EDIT_ACTION_POINT_LIGHT]); mToolsMenu->addAction(mActions[LC_EDIT_ACTION_SPOTLIGHT]); + mToolsMenu->addAction(mActions[LC_EDIT_ACTION_DIRECTIONAL_LIGHT]); + mToolsMenu->addAction(mActions[LC_EDIT_ACTION_AREA_LIGHT]); mToolsMenu->addAction(mActions[LC_EDIT_ACTION_CAMERA]); mToolsMenu->addSeparator(); mToolsMenu->addAction(mActions[LC_EDIT_ACTION_SELECT]); @@ -676,10 +676,10 @@ void lcMainWindow::CreateToolBars() mToolsToolBar->setObjectName("ToolsToolbar"); insertToolBarBreak(mToolsToolBar); mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_INSERT]); - mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_LIGHT]); - mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_AREALIGHT]); - mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_SUNLIGHT]); + mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_POINT_LIGHT]); mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_SPOTLIGHT]); + mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_DIRECTIONAL_LIGHT]); + mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_AREA_LIGHT]); mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_CAMERA]); mToolsToolBar->addSeparator(); mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_SELECT]); @@ -831,7 +831,7 @@ void lcMainWindow::TogglePreviewWidget(bool Visible) else mPreviewToolBar->hide(); } - else if (Visible) + else if (Visible) { CreatePreviewWidget(); } @@ -3376,20 +3376,20 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) SetTool(lcTool::Insert); break; - case LC_EDIT_ACTION_LIGHT: - SetTool(lcTool::Light); + case LC_EDIT_ACTION_POINT_LIGHT: + SetTool(lcTool::PointLight); break; - case LC_EDIT_ACTION_AREALIGHT: + case LC_EDIT_ACTION_AREA_LIGHT: SetTool(lcTool::AreaLight); break; - case LC_EDIT_ACTION_SUNLIGHT: - SetTool(lcTool::SunLight); + case LC_EDIT_ACTION_DIRECTIONAL_LIGHT: + SetTool(lcTool::DirectionalLight); break; case LC_EDIT_ACTION_SPOTLIGHT: - SetTool(lcTool::SpotLight); + SetTool(lcTool::Spotlight); break; case LC_EDIT_ACTION_CAMERA: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index ab9ac067..65ea2c61 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -620,7 +620,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) if (Token != QLatin1String("!LEOCAD")) { - mFileLines.append(OriginalLine); + mFileLines.append(OriginalLine); continue; } @@ -652,7 +652,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) else if (Token == QLatin1String("LIGHT")) { if (!Light) - Light = new lcLight(0.0f, 0.0f, 0.0f); + Light = new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point); if (Light->ParseLDrawLine(LineStream)) { @@ -734,7 +734,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) if (Library->IsPrimitive(CleanId.constData())) { - mFileLines.append(OriginalLine); + mFileLines.append(OriginalLine); } else { @@ -1039,7 +1039,7 @@ bool lcModel::LoadLDD(const QString& FileData) { std::vector Pieces; std::vector> Groups; - + if (!lcImportLXFMLFile(FileData, Pieces, Groups)) return false; @@ -4069,13 +4069,13 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) switch (Tool) { case lcTool::Insert: - case lcTool::Light: + case lcTool::PointLight: + case lcTool::DirectionalLight: case lcTool::AreaLight: - case lcTool::SunLight: break; - case lcTool::SpotLight: - SaveCheckpoint(tr("New SpotLight")); + case lcTool::Spotlight: + SaveCheckpoint(tr("New Spotlight")); break; case lcTool::Camera: @@ -4143,25 +4143,41 @@ void lcModel::InsertPieceToolClicked(const lcMatrix44& WorldMatrix) void lcModel::PointLightToolClicked(const lcVector3& Position) { - lcLight* Light = new lcLight(Position[0], Position[1], Position[2]); + lcLight* Light = new lcLight(Position, lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point); Light->CreateName(mLights); mLights.Add(Light); ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); - SaveCheckpoint(tr("New Light")); + SaveCheckpoint(tr("New Point Light")); } -void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, int LightType) +void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, lcLightType LightType) { - lcLight* Light = new lcLight(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2], LightType); + lcLight* Light = new lcLight(Position, Target, LightType); Light->CreateName(mLights); mLights.Add(Light); mMouseToolDistance = Target; ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_TARGET, false); - QString light(LightType == LC_AREALIGHT ? "Arealight " : LightType == LC_SUNLIGHT ? "Sunlight " : "Spotlight "); - SaveCheckpoint(tr("%1").arg(light)); + + switch (LightType) + { + case lcLightType::Point: + break; + + case lcLightType::Spot: + SaveCheckpoint(tr("New Spot Light")); + break; + + case lcLightType::Directional: + SaveCheckpoint(tr("New Directional Light")); + break; + + case lcLightType::Area: + SaveCheckpoint(tr("New Area Light")); + break; + } } void lcModel::UpdateDirectionalLightTool(const lcVector3& Position) @@ -4467,7 +4483,7 @@ void lcModel::ShowArrayDialog() QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("No pieces selected.")); return; } - + lcArrayDialog Dialog(gMainWindow); if (Dialog.exec() != QDialog::Accepted) diff --git a/common/lc_model.h b/common/lc_model.h index 996fe387..4973b078 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -327,7 +327,7 @@ class lcModel void EndMouseTool(lcTool Tool, bool Accept); void InsertPieceToolClicked(const lcMatrix44& WorldMatrix); void PointLightToolClicked(const lcVector3& Position); - void BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, int LightType); + void BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, lcLightType LightType); void UpdateDirectionalLightTool(const lcVector3& Position); void BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target); void BeginCameraTool(const lcVector3& Position, const lcVector3& Target); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 370fe84a..032b7923 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -416,7 +416,7 @@ lcMatrix44 lcView::GetPieceInsertPosition(bool IgnoreSelected, PieceInfo* Info) lcModel* ActiveModel = GetActiveModel(); lcPieceInfoRayTest PieceInfoRayTest = FindPieceInfoUnderPointer(IgnoreSelected); - + if (PieceInfoRayTest.Info) { lcVector3 Position = PieceInfoRayTest.Plane; @@ -1362,7 +1362,7 @@ void lcView::DrawRotateViewOverlay() mContext->SetVertexBufferPointer(Verts); mContext->SetVertexFormatPosition(2); - GLushort Indices[64 + 32] = + GLushort Indices[64 + 32] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 0, @@ -1595,23 +1595,23 @@ lcTrackTool lcView::GetOverrideTrackTool(Qt::MouseButton Button) const constexpr lcTrackTool TrackToolFromTool[] = { - lcTrackTool::Insert, // lcTool::Insert - lcTrackTool::PointLight, // lcTool::Light - lcTrackTool::AreaLight, // lcTool::AreaLight - lcTrackTool::SunLight, // lcTool::SunLight - lcTrackTool::SpotLight, // lcTool::SpotLight - lcTrackTool::Camera, // lcTool::Camera - lcTrackTool::Select, // lcTool::Select - lcTrackTool::MoveXYZ, // lcTool::Move - lcTrackTool::RotateXYZ, // lcTool::Rotate - lcTrackTool::Eraser, // lcTool::Eraser - lcTrackTool::Paint, // lcTool::Paint - lcTrackTool::ColorPicker, // lcTool::ColorPicker - lcTrackTool::Zoom, // lcTool::Zoom - lcTrackTool::Pan, // lcTool::Pan - lcTrackTool::OrbitXY, // lcTool::RotateView - lcTrackTool::Roll, // lcTool::Roll - lcTrackTool::ZoomRegion // lcTool::ZoomRegion + lcTrackTool::Insert, // lcTool::Insert + lcTrackTool::PointLight, // lcTool::PointLight + lcTrackTool::Spotlight, // lcTool::Spotlight + lcTrackTool::DirectionalLight, // lcTool::DirectionalLight + lcTrackTool::AreaLight, // lcTool::AreaLight + lcTrackTool::Camera, // lcTool::Camera + lcTrackTool::Select, // lcTool::Select + lcTrackTool::MoveXYZ, // lcTool::Move + lcTrackTool::RotateXYZ, // lcTool::Rotate + lcTrackTool::Eraser, // lcTool::Eraser + lcTrackTool::Paint, // lcTool::Paint + lcTrackTool::ColorPicker, // lcTool::ColorPicker + lcTrackTool::Zoom, // lcTool::Zoom + lcTrackTool::Pan, // lcTool::Pan + lcTrackTool::OrbitXY, // lcTool::RotateView + lcTrackTool::Roll, // lcTool::Roll + lcTrackTool::ZoomRegion // lcTool::ZoomRegion }; LC_ARRAY_SIZE_CHECK(TrackToolFromTool, lcTool::Count); @@ -1867,38 +1867,38 @@ lcCursor lcView::GetCursor() const constexpr lcCursor CursorFromTrackTool[] = { - lcCursor::Select, // lcTrackTool::None - lcCursor::Brick, // lcTrackTool::Insert - lcCursor::Light, // lcTrackTool::PointLight - lcCursor::Arealight, // lcTrackTool::AreaLight - lcCursor::Sunlight, // lcTrackTool::SunLight - lcCursor::Spotlight, // lcTrackTool::SpotLight - lcCursor::Camera, // lcTrackTool::Camera - lcCursor::Select, // lcTrackTool::Select - lcCursor::Move, // lcTrackTool::MoveX - lcCursor::Move, // lcTrackTool::MoveY - lcCursor::Move, // lcTrackTool::MoveZ - lcCursor::Move, // lcTrackTool::MoveXY - lcCursor::Move, // lcTrackTool::MoveXZ - lcCursor::Move, // lcTrackTool::MoveYZ - lcCursor::Move, // lcTrackTool::MoveXYZ - lcCursor::Rotate, // lcTrackTool::RotateX - lcCursor::Rotate, // lcTrackTool::RotateY - lcCursor::Rotate, // lcTrackTool::RotateZ - lcCursor::Rotate, // lcTrackTool::RotateXY - lcCursor::Rotate, // lcTrackTool::RotateXYZ - lcCursor::Move, // lcTrackTool::ScalePlus - lcCursor::Move, // lcTrackTool::ScaleMinus - lcCursor::Delete, // lcTrackTool::Eraser - lcCursor::Paint, // lcTrackTool::Paint - lcCursor::ColorPicker, // lcTrackTool::ColorPicker - lcCursor::Zoom, // lcTrackTool::Zoom - lcCursor::Pan, // lcTrackTool::Pan - lcCursor::RotateX, // lcTrackTool::OrbitX - lcCursor::RotateY, // lcTrackTool::OrbitY - lcCursor::RotateView, // lcTrackTool::OrbitXY - lcCursor::Roll, // lcTrackTool::Roll - lcCursor::ZoomRegion // lcTrackTool::ZoomRegion + lcCursor::Select, // lcTrackTool::None + lcCursor::Brick, // lcTrackTool::Insert + lcCursor::PointLight, // lcTrackTool::PointLight + lcCursor::Spotlight, // lcTrackTool::Spotlight + lcCursor::DirectionalLight, // lcTrackTool::DirectionalLight + lcCursor::AreaLight, // lcTrackTool::AreaLight + lcCursor::Camera, // lcTrackTool::Camera + lcCursor::Select, // lcTrackTool::Select + lcCursor::Move, // lcTrackTool::MoveX + lcCursor::Move, // lcTrackTool::MoveY + lcCursor::Move, // lcTrackTool::MoveZ + lcCursor::Move, // lcTrackTool::MoveXY + lcCursor::Move, // lcTrackTool::MoveXZ + lcCursor::Move, // lcTrackTool::MoveYZ + lcCursor::Move, // lcTrackTool::MoveXYZ + lcCursor::Rotate, // lcTrackTool::RotateX + lcCursor::Rotate, // lcTrackTool::RotateY + lcCursor::Rotate, // lcTrackTool::RotateZ + lcCursor::Rotate, // lcTrackTool::RotateXY + lcCursor::Rotate, // lcTrackTool::RotateXYZ + lcCursor::Move, // lcTrackTool::ScalePlus + lcCursor::Move, // lcTrackTool::ScaleMinus + lcCursor::Delete, // lcTrackTool::Eraser + lcCursor::Paint, // lcTrackTool::Paint + lcCursor::ColorPicker, // lcTrackTool::ColorPicker + lcCursor::Zoom, // lcTrackTool::Zoom + lcCursor::Pan, // lcTrackTool::Pan + lcCursor::RotateX, // lcTrackTool::OrbitX + lcCursor::RotateY, // lcTrackTool::OrbitY + lcCursor::RotateView, // lcTrackTool::OrbitXY + lcCursor::Roll, // lcTrackTool::Roll + lcCursor::ZoomRegion // lcTrackTool::ZoomRegion }; LC_ARRAY_SIZE_CHECK(CursorFromTrackTool, lcTrackTool::Count); @@ -1925,10 +1925,10 @@ void lcView::SetCursor(lcCursor CursorType) { 0, 0, "" }, // lcCursor::Hidden { 0, 0, "" }, // lcCursor::Default { 8, 3, ":/resources/cursor_insert" }, // lcCursor::Brick - { 15, 15, ":/resources/cursor_light" }, // lcCursor::Light - { 15, 15, ":/resources/cursor_arealight" }, // lcCursor::Arealight - { 15, 15, ":/resources/cursor_sunlight" }, // lcCursor::Sunlight + { 15, 15, ":/resources/cursor_light" }, // lcCursor::PointLight { 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::Spotlight + { 15, 15, ":/resources/cursor_sunlight" }, // lcCursor::DirectionalLight + { 15, 15, ":/resources/cursor_arealight" }, // lcCursor::AreaLight { 15, 9, ":/resources/cursor_camera" }, // lcCursor::Camera { 0, 2, ":/resources/cursor_select" }, // lcCursor::Select { 0, 2, ":/resources/cursor_select_add" }, // lcCursor::SelectAdd @@ -1976,38 +1976,38 @@ lcTool lcView::GetCurrentTool() const { constexpr lcTool ToolFromTrackTool[] = { - lcTool::Select, // lcTrackTool::None - lcTool::Insert, // lcTrackTool::Insert - lcTool::Light, // lcTrackTool::PointLight - lcTool::AreaLight, // lcTrackTool::AreaLight - lcTool::SunLight, // lcTrackTool::SunLight - lcTool::SpotLight, // lcTrackTool::SpotLight - lcTool::Camera, // lcTrackTool::Camera - lcTool::Select, // lcTrackTool::Select - lcTool::Move, // lcTrackTool::MoveX - lcTool::Move, // lcTrackTool::MoveY - lcTool::Move, // lcTrackTool::MoveZ - lcTool::Move, // lcTrackTool::MoveXY - lcTool::Move, // lcTrackTool::MoveXZ - lcTool::Move, // lcTrackTool::MoveYZ - lcTool::Move, // lcTrackTool::MoveXYZ - lcTool::Rotate, // lcTrackTool::RotateX - lcTool::Rotate, // lcTrackTool::RotateY - lcTool::Rotate, // lcTrackTool::RotateZ - lcTool::Rotate, // lcTrackTool::RotateXY - lcTool::Rotate, // lcTrackTool::RotateXYZ - lcTool::Move, // lcTrackTool::ScalePlus - lcTool::Move, // lcTrackTool::ScaleMinus - lcTool::Eraser, // lcTrackTool::Eraser - lcTool::Paint, // lcTrackTool::Paint - lcTool::ColorPicker, // lcTrackTool::ColorPicker - lcTool::Zoom, // lcTrackTool::Zoom - lcTool::Pan, // lcTrackTool::Pan - lcTool::RotateView, // lcTrackTool::OrbitX - lcTool::RotateView, // lcTrackTool::OrbitY - lcTool::RotateView, // lcTrackTool::OrbitXY - lcTool::Roll, // lcTrackTool::Roll - lcTool::ZoomRegion // lcTrackTool::ZoomRegion + lcTool::Select, // lcTrackTool::None + lcTool::Insert, // lcTrackTool::Insert + lcTool::PointLight, // lcTrackTool::PointLight + lcTool::Spotlight, // lcTrackTool::Spotlight + lcTool::DirectionalLight, // lcTrackTool::DirectionalLight + lcTool::AreaLight, // lcTrackTool::AreaLight + lcTool::Camera, // lcTrackTool::Camera + lcTool::Select, // lcTrackTool::Select + lcTool::Move, // lcTrackTool::MoveX + lcTool::Move, // lcTrackTool::MoveY + lcTool::Move, // lcTrackTool::MoveZ + lcTool::Move, // lcTrackTool::MoveXY + lcTool::Move, // lcTrackTool::MoveXZ + lcTool::Move, // lcTrackTool::MoveYZ + lcTool::Move, // lcTrackTool::MoveXYZ + lcTool::Rotate, // lcTrackTool::RotateX + lcTool::Rotate, // lcTrackTool::RotateY + lcTool::Rotate, // lcTrackTool::RotateZ + lcTool::Rotate, // lcTrackTool::RotateXY + lcTool::Rotate, // lcTrackTool::RotateXYZ + lcTool::Move, // lcTrackTool::ScalePlus + lcTool::Move, // lcTrackTool::ScaleMinus + lcTool::Eraser, // lcTrackTool::Eraser + lcTool::Paint, // lcTrackTool::Paint + lcTool::ColorPicker, // lcTrackTool::ColorPicker + lcTool::Zoom, // lcTrackTool::Zoom + lcTool::Pan, // lcTrackTool::Pan + lcTool::RotateView, // lcTrackTool::OrbitX + lcTool::RotateView, // lcTrackTool::OrbitY + lcTool::RotateView, // lcTrackTool::OrbitXY + lcTool::Roll, // lcTrackTool::Roll + lcTool::ZoomRegion // lcTrackTool::ZoomRegion }; LC_ARRAY_SIZE_CHECK(ToolFromTrackTool, lcTrackTool::Count); @@ -2041,20 +2041,20 @@ void lcView::UpdateTrackTool() NewTrackTool = lcTrackTool::Insert; break; - case lcTool::Light: + case lcTool::PointLight: NewTrackTool = lcTrackTool::PointLight; break; - case lcTool::AreaLight: - NewTrackTool = lcTrackTool::AreaLight;; + case lcTool::Spotlight: + NewTrackTool = lcTrackTool::Spotlight; break; - case lcTool::SunLight: - NewTrackTool = lcTrackTool::SunLight; + case lcTool::DirectionalLight: + NewTrackTool = lcTrackTool::DirectionalLight; break; - case lcTool::SpotLight: - NewTrackTool = lcTrackTool::SpotLight; + case lcTool::AreaLight: + NewTrackTool = lcTrackTool::AreaLight;; break; case lcTool::Camera: @@ -2272,22 +2272,30 @@ void lcView::StartTracking(lcTrackButton TrackButton) lcTool Tool = GetCurrentTool(); lcModel* ActiveModel = GetActiveModel(); + auto AddLight = [this, ActiveModel](lcLightType LightType) + { + lcVector3 Position = GetCameraLightInsertPosition(); + lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f); + ActiveModel->BeginDirectionalLightTool(Position, Target, LightType); + }; + switch (Tool) { case lcTool::Insert: - case lcTool::Light: + case lcTool::PointLight: + break; + + case lcTool::Spotlight: + AddLight(lcLightType::Spot); + break; + + case lcTool::DirectionalLight: + AddLight(lcLightType::Directional); break; case lcTool::AreaLight: - case lcTool::SunLight: - case lcTool::SpotLight: - { - lcVector3 Position = GetCameraLightInsertPosition(); - lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f); - int LightType = Tool == lcTool::AreaLight ? LC_AREALIGHT : Tool == lcTool::SunLight ? LC_SUNLIGHT : LC_SPOTLIGHT; - ActiveModel->BeginDirectionalLightTool(Position, Target, LightType); - } - break; + AddLight(lcLightType::Area); + break; case lcTool::Camera: { @@ -2342,12 +2350,12 @@ void lcView::StopTracking(bool Accept) switch (Tool) { case lcTool::Insert: - case lcTool::Light: + case lcTool::PointLight: break; + case lcTool::Spotlight: + case lcTool::DirectionalLight: case lcTool::AreaLight: - case lcTool::SunLight: - case lcTool::SpotLight: case lcTool::Camera: ActiveModel->EndMouseTool(Tool, Accept); break; @@ -2474,13 +2482,13 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) } break; + case lcTrackTool::Spotlight: + case lcTrackTool::DirectionalLight: case lcTrackTool::AreaLight: - case lcTrackTool::SunLight: - case lcTrackTool::SpotLight: case lcTrackTool::Camera: StartTracking(TrackButton); break; - + case lcTrackTool::Select: { lcObjectSection ObjectSection = FindObjectUnderPointer(false, false); @@ -2713,9 +2721,9 @@ void lcView::OnMouseMove() case lcTrackTool::PointLight: break; + case lcTrackTool::Spotlight: + case lcTrackTool::DirectionalLight: case lcTrackTool::AreaLight: - case lcTrackTool::SunLight: - case lcTrackTool::SpotLight: ActiveModel->UpdateDirectionalLightTool(GetCameraLightInsertPosition()); break; diff --git a/common/lc_view.h b/common/lc_view.h index 0227be62..4aa934a0 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -17,10 +17,10 @@ enum class lcCursor Hidden = First, Default, Brick, - Light, - Arealight, - Sunlight, + PointLight, Spotlight, + DirectionalLight, + AreaLight, Camera, Select, SelectAdd, @@ -53,9 +53,9 @@ enum class lcTrackTool None, Insert, PointLight, + Spotlight, + DirectionalLight, AreaLight, - SunLight, - SpotLight, Camera, Select, MoveX, diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index 84ef75db..da4799c6 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -674,9 +674,9 @@ bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 Allowe case lcTrackTool::None: case lcTrackTool::Insert: case lcTrackTool::PointLight: + case lcTrackTool::Spotlight: + case lcTrackTool::DirectionalLight: case lcTrackTool::AreaLight: - case lcTrackTool::SunLight: - case lcTrackTool::SpotLight: case lcTrackTool::Camera: case lcTrackTool::Select: return true; diff --git a/common/light.cpp b/common/light.cpp index 51e406d2..549b6b02 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -14,61 +14,30 @@ #define LC_LIGHT_SUN_RADIUS 8.5f #define LC_LIGHT_SPOT_BASE_EDGE 12.5f -// New omni light. -lcLight::lcLight(float px, float py, float pz) - : lcObject(lcObjectType::Light) -{ - Initialize(lcVector3(px, py, pz), lcVector3(0.0f, 0.0f, 0.0f), LC_POINTLIGHT); - UpdatePosition(1); -} +static const std::array gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") }; -// New directional light. -lcLight::lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType) - : lcObject(lcObjectType::Light) -{ - Initialize(lcVector3(px, py, pz), lcVector3(tx, ty, tz), LightType); - UpdatePosition(1); -} - -void lcLight::SetLightState(int LightType) +lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcLightType LightType) + : lcObject(lcObjectType::Light), mPosition(Position), mTargetPosition(TargetPosition), mLightType(LightType) { mState = 0; - switch (LightType) - { - case LC_AREALIGHT: - case LC_SUNLIGHT: - case LC_SPOTLIGHT: - mState |= LC_LIGHT_DIRECTIONAL; - break; - default: - break; - } -} - -void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType) -{ - SetLightState(LightType); - mPOVRayLight = false; mShadowless = false; mEnableCutoff = false; - mPosition = Position; mTargetPosition = TargetPosition; mAmbientColor = lcVector4(0.0f, 0.0f, 0.0f, 1.0f); mDiffuseColor = lcVector4(0.8f, 0.8f, 0.8f, 1.0f); mSpecularColor = lcVector4(1.0f, 1.0f, 1.0f, 1.0f); mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); mLightColor = lcVector3(1.0f, 1.0f, 1.0f); /*RGB - White*/ - mLightType = LightType ? LightType : int(LC_POINTLIGHT); - mLightFactor[0] = LightType ? LightType == LC_SUNLIGHT ? 11.4f : 0.25f : 0.0f; - mLightFactor[1] = LightType == LC_AREALIGHT ? 0.25f : LightType == LC_SPOTLIGHT ? 0.150f : 0.0f; + mLightFactor[0] = LightType == lcLightType::Directional ? 11.4f : 0.25f; + mLightFactor[1] = LightType == lcLightType::Area ? 0.25f : LightType == lcLightType::Spot ? 0.150f : 0.0f; mLightDiffuse = 1.0f; mLightSpecular = 1.0f; mSpotExponent = 10.0f; mPOVRayExponent = 1.0f; mSpotSize = 75.0f; - mSpotCutoff = LightType ? LightType != LC_SUNLIGHT ? 40.0f : 0.0f : 30.0f; + mSpotCutoff = LightType != lcLightType::Directional ? 40.0f : 0.0f; mSpotFalloff = 45.0f; mSpotTightness = 0; mAreaGrid = lcVector2(10.0f, 10.0f); @@ -81,9 +50,7 @@ void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosit mDiffuseColorKeys.ChangeKey(mDiffuseColor, 1, true); mSpecularColorKeys.ChangeKey(mSpecularColor, 1, true); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); - mLightShapeKeys.ChangeKey(mLightShape, 1, true); mLightColorKeys.ChangeKey(mLightColor, 1, true); - mLightTypeKeys.ChangeKey(mLightType, 1, true); mLightFactorKeys.ChangeKey(mLightFactor, 1, true); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); @@ -93,10 +60,8 @@ void lcLight::Initialize(const lcVector3& Position, const lcVector3& TargetPosit mSpotSizeKeys.ChangeKey(mSpotSize, 1, true); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); -} -lcLight::~lcLight() -{ + UpdatePosition(1); } void lcLight::SaveLDraw(QTextStream& Stream) const @@ -114,7 +79,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const else Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding; - if (mLightType != LC_POINTLIGHT && !(mLightType == LC_AREALIGHT && mPOVRayLight)) + if (mLightType != lcLightType::Point && !(mLightType == lcLightType::Area && mPOVRayLight)) { if (mTargetPositionKeys.GetSize() > 1) mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY "); @@ -140,158 +105,126 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT SPECULAR ") << mLightSpecular << LineEnding; } - if (mLightType == LC_SUNLIGHT) + if (mSpotExponentKeys.GetSize() > 1) + mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT POWER_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT POWER ") << (mPOVRayLight ? mPOVRayExponent : mSpotExponent) << LineEnding; + + if (mEnableCutoff && !mPOVRayLight) { - if (mSpotExponentKeys.GetSize() > 1) - mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT STRENGTH_KEY "); + if (mSpotCutoffKeys.GetSize() > 1) + mSpotCutoffKeys.SaveKeysLDraw(Stream, "LIGHT CUTOFF_DISTANCE_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << (mPOVRayLight ? mPOVRayExponent : mSpotExponent) << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT CUTOFF_DISTANCE ") << mSpotCutoff << LineEnding; + } + switch (mLightType) + { + case lcLightType::Point: if (!mPOVRayLight) { if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT ANGLE_KEY "); + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT ANGLE ") << mLightFactor[0] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; } - } - else - { - if (mSpotExponentKeys.GetSize() > 1) - mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT POWER_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT POWER ") << (mPOVRayLight ? mPOVRayExponent : mSpotExponent) << LineEnding; + break; - if (mEnableCutoff && !mPOVRayLight) + case lcLightType::Spot: + if (mPOVRayLight) { - if (mSpotCutoffKeys.GetSize() > 1) - mSpotCutoffKeys.SaveKeysLDraw(Stream, "LIGHT CUTOFF_DISTANCE_KEY "); + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << (mSpotSize - mSpotFalloff) << LineEnding; + if (mSpotFalloffKeys.GetSize() > 1) + mSpotFalloffKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_FALLOFF_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_FALLOFF ") << mSpotFalloff << LineEnding; + if (mSpotTightnessKeys.GetSize() > 1) + mSpotTightnessKeys.SaveKeysLDraw(Stream, "SPOT_TIGHTNESS_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT CUTOFF_DISTANCE ") << mSpotCutoff << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_TIGHTNESS ") << mSpotTightness << LineEnding; } - - switch (mLightType) + else { - case LC_POINTLIGHT: - if (!mPOVRayLight) - { - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; - } - break; - case LC_SPOTLIGHT: - if (mPOVRayLight) - { - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << (mSpotSize - mSpotFalloff) << LineEnding; - if (mSpotFalloffKeys.GetSize() > 1) - mSpotFalloffKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_FALLOFF_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_FALLOFF ") << mSpotFalloff << LineEnding; - if (mSpotTightnessKeys.GetSize() > 1) - mSpotTightnessKeys.SaveKeysLDraw(Stream, "SPOT_TIGHTNESS_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_TIGHTNESS ") << mSpotTightness << LineEnding; - } + if (mSpotSizeKeys.GetSize() > 1) + mSpotSizeKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_SIZE_KEY "); else - { - if (mSpotSizeKeys.GetSize() > 1) - mSpotSizeKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_SIZE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); - else - { - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; - } - } - break; - case LC_AREALIGHT: - if (mPOVRayLight) + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); + else { - if (mAreaGridKeys.GetSize() > 1) - mAreaGridKeys.SaveKeysLDraw(Stream, "LIGHT AREA_GRID_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT AREA_ROWS ") << mAreaGrid[0] << QLatin1String(" AREA_COLUMNS ") << mAreaGrid[1] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; } - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); + } + break; + + case lcLightType::Directional: + if (mSpotExponentKeys.GetSize() > 1) + mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT STRENGTH_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << mSpotExponent << LineEnding; + + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT ANGLE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT ANGLE ") << mLightFactor[0] << LineEnding; + break; + + case lcLightType::Area: + if (mPOVRayLight) + { + if (mAreaGridKeys.GetSize() > 1) + mAreaGridKeys.SaveKeysLDraw(Stream, "LIGHT AREA_GRID_KEY "); else + Stream << QLatin1String("0 !LEOCAD LIGHT AREA_ROWS ") << mAreaGrid[0] << QLatin1String(" AREA_COLUMNS ") << mAreaGrid[1] << LineEnding; + } + if (mLightFactorKeys.GetSize() > 1) + mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); + else + { + if (mPOVRayLight) { - if (mPOVRayLight) - { - Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mAreaSize[0] << QLatin1String(" HEIGHT ") << mAreaSize[1] << LineEnding; - } - else - { - if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE || mLightFactor[1] > 0) - Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding; - else - Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding; - } + Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mAreaSize[0] << QLatin1String(" HEIGHT ") << mAreaSize[1] << LineEnding; } - if (mLightShapeKeys.GetSize() > 1) - mLightShapeKeys.SaveKeysLDraw(Stream, "LIGHT SHAPE_KEY "); else { - Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE "); - - QString Shape = QLatin1String("Undefined "); - switch(mLightShape) - { - case LC_LIGHT_SHAPE_SQUARE: - Shape = QLatin1String("Square "); - break; - case LC_LIGHT_SHAPE_DISK: - Shape = mPOVRayLight ? QLatin1String("Circle ") : QLatin1String("Disk "); - break; - case LC_LIGHT_SHAPE_RECTANGLE: - Shape = QLatin1String("Rectangle "); - break; - case LC_LIGHT_SHAPE_ELLIPSE: - Shape = QLatin1String("Ellipse "); - break; - default: - break; - } - Stream << QLatin1String(Shape.toLatin1()) << LineEnding; + if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE || mLightFactor[1] > 0) + Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding; + else + Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding; } - - break; } - } - if (mLightTypeKeys.GetSize() > 1) - mLightTypeKeys.SaveKeysLDraw(Stream, "LIGHT TYPE_KEY "); - else - { - Stream << QLatin1String("0 !LEOCAD LIGHT TYPE "); + Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE "); - QString Type = QLatin1String("Undefined "); - switch(mLightType) + QString Shape = QLatin1String("UNDEFINED "); + switch (mLightShape) { - case LC_POINTLIGHT: - Type = QLatin1String("Point "); + case LC_LIGHT_SHAPE_SQUARE: + Shape = QLatin1String("SQUARE "); break; - case LC_SUNLIGHT: - Type = QLatin1String("Sun "); + case LC_LIGHT_SHAPE_DISK: + Shape = QLatin1String("DISK "); break; - case LC_AREALIGHT: - Type = QLatin1String("Area "); + case LC_LIGHT_SHAPE_RECTANGLE: + Shape = QLatin1String("RECTANGLE "); break; - case LC_SPOTLIGHT: - Type = QLatin1String("Spot "); + case LC_LIGHT_SHAPE_ELLIPSE: + Shape = QLatin1String("ELLIPSE "); break; } - Stream << QLatin1String(Type.toLatin1()) << QLatin1String("NAME ") << mName << LineEnding; + + Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE ") << Shape << LineEnding; + + break; } + + Stream << QLatin1String("0 !LEOCAD LIGHT TYPE ") << gLightTypes[static_cast(mLightType)] << QLatin1String(" NAME ") << mName << LineEnding; } void lcLight::CreateName(const lcArray& Lights) @@ -315,7 +248,26 @@ void lcLight::CreateName(const lcArray& Lights) int MaxLightNumber = 0; - const QLatin1String Prefix(mLightType == LC_POINTLIGHT ? "Pointlight " : mLightType == LC_AREALIGHT ? "Arealight " : mLightType == LC_SUNLIGHT ? "Sunlight " : "Spotlight "); + QString Prefix; + + switch (mLightType) + { + case lcLightType::Point: + Prefix = QLatin1String("Pointlight "); + break; + + case lcLightType::Spot: + Prefix = QLatin1String("Spotlight "); + break; + + case lcLightType::Directional: + Prefix = QLatin1String("Directionallight "); + break; + + case lcLightType::Area: + Prefix = QLatin1String("Arealight "); + break; + } for (const lcLight* Light : Lights) { @@ -410,16 +362,16 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) { QString Shape; Stream >> Shape; - Shape = Shape.replace("\"", "").toLower(); - if (Shape == QLatin1String("square")) + Shape.replace("\"", ""); + + if (Shape == QLatin1String("SQUARE")) mLightShape = LC_LIGHT_SHAPE_SQUARE; - else if (Shape == QLatin1String("disk") || Shape == QLatin1String("circle")) + else if (Shape == QLatin1String("DISK") || Shape == QLatin1String("CIRCLE")) mLightShape = LC_LIGHT_SHAPE_DISK; - else if (Shape == QLatin1String("rectangle")) + else if (Shape == QLatin1String("RECTANGLE")) mLightShape = LC_LIGHT_SHAPE_RECTANGLE; - else if (Shape == QLatin1String("ellipse")) + else if (Shape == QLatin1String("ELLIPSE")) mLightShape = LC_LIGHT_SHAPE_ELLIPSE; - mLightShapeKeys.ChangeKey(mLightShape, 1, true); } else if (Token == QLatin1String("DIFFUSE")) { @@ -441,17 +393,15 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) { QString Type; Stream >> Type; - Type = Type.replace("\"", "").toLower(); - if (Type == QLatin1String("point")) - mLightType = LC_POINTLIGHT; - else if (Type == QLatin1String("sun")) - mLightType = LC_SUNLIGHT; - else if (Type == QLatin1String("spot")) - mLightType = LC_SPOTLIGHT; - else if (Type == QLatin1String("area")) - mLightType = LC_AREALIGHT; - SetLightState(mLightType); - mLightTypeKeys.ChangeKey(mLightType, 1, true); + + for (size_t TypeIndex = 0; TypeIndex < gLightTypes.size(); TypeIndex++) + { + if (Type == gLightTypes[TypeIndex]) + { + mLightType = static_cast(TypeIndex); + break; + } + } } else if (Token == QLatin1String("POSITION")) { @@ -485,16 +435,12 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) mSpotTightnessKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("AREA_GRID_KEY")) mAreaGridKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SHAPE_KEY")) - mLightShapeKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("DIFFUSE_KEY")) mLightDiffuseKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("SPECULAR_KEY")) mLightSpecularKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("CUTOFF_DISTANCE_KEY")) mSpotCutoffKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("TYPE_KEY")) - mLightTypeKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("POSITION_KEY")) mPositionKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("TARGET_POSITION_KEY")) @@ -505,34 +451,45 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) mName.replace("\"", ""); // Set default settings per light type - if (mLightType == LC_SPOTLIGHT) + switch (mLightType) { + case lcLightType::Point: + break; + + case lcLightType::Spot: if (!mSpotBlendSet) { mLightFactor[1] = 0.15f; mLightFactorKeys.ChangeKey(mLightFactor, 1, true); } - } - if (mLightType == LC_AREALIGHT && (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE)) { - if (!mHeightSet) - { - mLightFactor[1] = 0.25f; - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); - } - } - if (mLightType == LC_SUNLIGHT) - { + break; + + case lcLightType::Directional: if (!mAngleSet) { mLightFactor[0] = 11.4f; mLightFactorKeys.ChangeKey(mLightFactor, 1, true); } + if (!mSpotCutoffSet) { - mSpotCutoff = 0.0f; + mSpotCutoff = 0.0f; mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); } + break; + + case lcLightType::Area: + if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE) + { + if (!mHeightSet) + { + mLightFactor[1] = 0.25f; + mLightFactorKeys.ChangeKey(mLightFactor, 1, true); + } + } + break; } + return true; } } @@ -564,14 +521,13 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) { case LC_LIGHT_SHAPE: mLightShape = Props.mLightShape; - mLightShapeKeys.ChangeKey(mLightShape, Step, false); break; case LC_LIGHT_COLOR: mLightColor = Props.mLightColor; mLightColorKeys.ChangeKey(mLightColor, Step, false); break; case LC_LIGHT_FACTOR: - if (Props.mPOVRayLight && mLightType == LC_AREALIGHT) + if (Props.mPOVRayLight && mLightType == lcLightType::Area) { mAreaSize = Props.mLightFactor; mLightFactorKeys.ChangeKey(mAreaSize, 1, true); @@ -757,9 +713,7 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mDiffuseColorKeys.InsertTime(Start, Time); mSpecularColorKeys.InsertTime(Start, Time); mAttenuationKeys.InsertTime(Start, Time); - mLightShapeKeys.InsertTime(Start, Time); mLightColorKeys.InsertTime(Start, Time); - mLightTypeKeys.InsertTime(Start, Time); mLightFactorKeys.InsertTime(Start, Time); mLightDiffuseKeys.InsertTime(Start, Time); mLightSpecularKeys.InsertTime(Start, Time); @@ -779,9 +733,7 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mDiffuseColorKeys.RemoveTime(Start, Time); mSpecularColorKeys.RemoveTime(Start, Time); mAttenuationKeys.RemoveTime(Start, Time); - mLightShapeKeys.RemoveTime(Start, Time); mLightColorKeys.RemoveTime(Start, Time); - mLightTypeKeys.RemoveTime(Start, Time); mLightFactorKeys.RemoveTime(Start, Time); mLightDiffuseKeys.RemoveTime(Start, Time); mLightSpecularKeys.RemoveTime(Start, Time); @@ -801,9 +753,7 @@ void lcLight::UpdatePosition(lcStep Step) mDiffuseColor = mDiffuseColorKeys.CalculateKey(Step); mSpecularColor = mSpecularColorKeys.CalculateKey(Step); mAttenuation = mAttenuationKeys.CalculateKey(Step); - mLightShape = mLightShapeKeys.CalculateKey(Step); mLightColor = mLightColorKeys.CalculateKey(Step); - mLightType = mLightTypeKeys.CalculateKey(Step); mLightFactor = mLightFactorKeys.CalculateKey(Step); mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); mLightSpecular = mLightSpecularKeys.CalculateKey(Step); @@ -886,9 +836,9 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const float Verts[(20 + 8 + 2 + 16) * 3]; float* CurVert = Verts; - if (mLightType != LC_SUNLIGHT) + if (mLightType != lcLightType::Directional) { - if (mLightType == LC_SPOTLIGHT) + if (mLightType == lcLightType::Spot) { for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) { @@ -908,7 +858,7 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; } - else if (mLightType == LC_AREALIGHT) + else if (mLightType == lcLightType::Area) { const float LC_LIGHT_AREA_EDGE = 5.0f; const float LC_LIGHT_AREA_H_EDGE = 8.5f; @@ -947,7 +897,7 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const int BaseIndices = 0; - if (mLightType == LC_SPOTLIGHT) + if (mLightType == lcLightType::Spot) { BaseIndices = 56; const GLushort Indices[56 + 24 + 2 + 40] = @@ -967,7 +917,7 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const Context->SetIndexBufferPointer(Indices); } - else if (mLightType == LC_AREALIGHT) + else if (mLightType == lcLightType::Area) { BaseIndices = 32; const GLushort Indices[32 + 24 + 2] = @@ -984,7 +934,7 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const Context->SetIndexBufferPointer(Indices); } - else if (mLightType == LC_SUNLIGHT) + else if (mLightType == lcLightType::Directional) { constexpr float Radius = LC_LIGHT_SUN_RADIUS; constexpr int Slices = 9; // longitude @@ -1175,7 +1125,7 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const int SpotCone = 0; - if (mLightType == LC_SPOTLIGHT) + if (mLightType == lcLightType::Spot) { SpotCone = 40; @@ -1316,18 +1266,12 @@ void lcLight::RemoveKeyFrames() mAttenuationKeys.RemoveAll(); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); - mLightShapeKeys.RemoveAll(); - mLightShapeKeys.ChangeKey(mLightShape, 1, false); - mLightColorKeys.RemoveAll(); mLightColorKeys.ChangeKey(mLightColor, 1, true); mLightFactorKeys.RemoveAll(); mLightFactorKeys.ChangeKey(mLightFactor, 1, true); - mLightTypeKeys.RemoveAll(); - mLightTypeKeys.ChangeKey(mLightType, 1, true); - mLightDiffuseKeys.RemoveAll(); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); diff --git a/common/light.h b/common/light.h index 410c36b9..5a4a121c 100644 --- a/common/light.h +++ b/common/light.h @@ -5,11 +5,10 @@ #define LC_LIGHT_HIDDEN 0x0001 #define LC_LIGHT_DISABLED 0x0002 -#define LC_LIGHT_DIRECTIONAL 0x0004 -#define LC_LIGHT_POSITION_SELECTED 0x0008 -#define LC_LIGHT_POSITION_FOCUSED 0x0010 -#define LC_LIGHT_TARGET_SELECTED 0x0020 -#define LC_LIGHT_TARGET_FOCUSED 0x0040 +#define LC_LIGHT_POSITION_SELECTED 0x0010 +#define LC_LIGHT_POSITION_FOCUSED 0x0020 +#define LC_LIGHT_TARGET_SELECTED 0x0040 +#define LC_LIGHT_TARGET_FOCUSED 0x0080 #define LC_LIGHT_SELECTION_MASK (LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED) #define LC_LIGHT_FOCUS_MASK (LC_LIGHT_POSITION_FOCUSED | LC_LIGHT_TARGET_FOCUSED) @@ -20,13 +19,12 @@ enum lcLightSection LC_LIGHT_SECTION_TARGET }; -enum lcLightType +enum class lcLightType { - LC_UNDEFINED_LIGHT, - LC_POINTLIGHT, - LC_AREALIGHT, - LC_SUNLIGHT, - LC_SPOTLIGHT + Point, + Spot, + Directional, + Area }; enum lcLightShape @@ -79,9 +77,8 @@ struct lcLightProperties class lcLight : public lcObject { public: - lcLight(float px, float py, float pz); - lcLight(float px, float py, float pz, float tx, float ty, float tz, int LightType); - ~lcLight(); + lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcLightType LightType); + virtual ~lcLight() = default; lcLight(const lcLight&) = delete; lcLight(lcLight&&) = delete; @@ -90,12 +87,22 @@ class lcLight : public lcObject bool IsPointLight() const { - return (mState & LC_LIGHT_DIRECTIONAL) == 0; + return mLightType == lcLightType::Point; } bool IsDirectionalLight() const { - return (mState & LC_LIGHT_DIRECTIONAL) != 0; + return mLightType == lcLightType::Directional; + } + + lcLightType GetLightType() const + { + return mLightType; + } + + int GetLightShape() const + { + return mLightShape; } bool IsSelected() const override @@ -296,8 +303,6 @@ class lcLight : public lcObject bool mEnableCutoff; bool mPOVRayLight; bool mShadowless; - int mLightType; - int mLightShape; float mLightDiffuse; float mLightSpecular; float mSpotSize; @@ -318,8 +323,6 @@ class lcLight : public lcObject lcObjectKeyArray mLightColorKeys; lcObjectKeyArray mLightFactorKeys; lcObjectKeyArray mAreaGridKeys; - lcObjectKeyArray mLightTypeKeys; - lcObjectKeyArray mLightShapeKeys; lcObjectKeyArray mLightSpecularKeys; lcObjectKeyArray mLightDiffuseKeys; lcObjectKeyArray mSpotSizeKeys; @@ -328,11 +331,10 @@ class lcLight : public lcObject lcObjectKeyArray mSpotExponentKeys; lcObjectKeyArray mSpotTightnessKeys; - void Initialize(const lcVector3& Position, const lcVector3& TargetPosition, int LightType); - void DrawDirectionalLight(lcContext* Context) const; void DrawPointLight(lcContext* Context) const; - void SetLightState(int LightType); quint32 mState; + lcLightType mLightType; + int mLightShape; }; diff --git a/common/project.cpp b/common/project.cpp index 1190cd79..fd46faa0 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -1859,12 +1859,6 @@ bool Project::ExportPOVRay(const QString& FileName) POVFile.WriteLine("global_settings { assumed_gamma 1.0 }\n\n"); - /* POV-Ray uses a left-handed coordinate system - * - positive x-axis pointing right - * - positive y-axis pointing up - * - positive z-axis pointing away from you - * POVRay [0]x,[1]y,[2]z = LeoCAD [1]y,[0]x,[2]z */ - lcPiecesLibrary* Library = lcGetPiecesLibrary(); std::map> PieceTable; size_t NumColors = gColorList.size(); @@ -1930,7 +1924,7 @@ bool Project::ExportPOVRay(const QString& FileName) for (const lcLight* Light : Lights) { - if (Light->mLightType == LC_AREALIGHT) + if (Light->GetLightType() == lcLightType::Area) { if (FloorColor == lcVector3(0.8f,0.8f,0.8f)) FloorColor = {1.0f,1.0f,1.0f}; @@ -2015,16 +2009,25 @@ bool Project::ExportPOVRay(const QString& FileName) "#ifndef (SkipWriteLightMacro)\n" "#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n" " #local PointLight = %i;\n" + " #local Spotlight = %i;\n" + " #local DirectionalLight = %i;\n" " #local AreaLight = %i;\n" - " #local SunLight = %i;\n" - " #local SpotLight = %i;\n" " light_source {\n" " Location\n" " color rgb Color*Power\n" " #if (Shadowless > 0)\n" " shadowless\n" " #end\n" - " #if (Type = AreaLight)\n" + " #if (Type = Spotlight)\n" + " spotlight\n" + " radius SpotRadius\n" + " falloff SpotFalloff\n" + " tightness SpotTightness\n" + " point_at Target\n" + " #elseif (Type = DirectionalLight)\n" + " parallel\n" + " point_at Target\n" + " #elseif (Type = AreaLight)\n" " area_light AreaWidth, AreaHeight, AreaRows, AreaColumns\n" " jitter\n" " #if (AreaCircle > 0 & AreaWidth > 2 & AreaHeight > 2 & AreaRows > 1 & AreaColumns > 1 )\n" @@ -2033,20 +2036,11 @@ bool Project::ExportPOVRay(const QString& FileName) " orient\n" " #end\n" " #end\n" - " #elseif (Type = SunLight)\n" - " parallel\n" - " point_at Target\n" - " #elseif (Type = SpotLight)\n" - " spotlight\n" - " radius SpotRadius\n" - " falloff SpotFalloff\n" - " tightness SpotTightness\n" - " point_at Target\n" " #end\n" " }\n" "#end\n" "#end\n\n", - LC_POINTLIGHT, LC_AREALIGHT, LC_SUNLIGHT, LC_SPOTLIGHT); + lcLightType::Point, lcLightType::Spot, lcLightType::Directional, lcLightType::Area); POVFile.WriteLine(Line); for (const lcModelPartsEntry& ModelPart : ModelParts) @@ -2147,7 +2141,8 @@ bool Project::ExportPOVRay(const QString& FileName) lcVector3 LightTarget(0.0f, 0.0f, 0.0f), LightColor(1.0f, 1.0f, 1.0f); lcVector2 AreaSize(200.0f, 200.0f), AreaGrid(10.0f, 10.0f); - int AreaCircle = 0, Shadowless = 0, LightType = LC_AREALIGHT; + int AreaCircle = 0, Shadowless = 0; + lcLightType LightType = lcLightType::Area; float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0; if (Lights.IsEmpty()) { @@ -2178,25 +2173,25 @@ bool Project::ExportPOVRay(const QString& FileName) { const lcVector3& Location = Light->mPosition; const QString LightName = QString(Light->mName).replace(" ","_"); - LightType = Light->mLightType; + LightType = Light->GetLightType(); Shadowless = static_cast(Light->mShadowless); LightColor = Light->mLightColor; Power = Light->mPOVRayExponent; switch(LightType) { - case LC_AREALIGHT: - AreaCircle = Light->mLightShape == LC_LIGHT_SHAPE_DISK ? 1 : 0; - AreaSize = Light->mAreaSize; - AreaGrid = Light->mAreaGrid; - break; - case LC_SUNLIGHT: - LightTarget = Light->mTargetPosition; - break; - case LC_SPOTLIGHT: + case lcLightType::Spot: LightTarget = Light->mTargetPosition; SpotFalloff = Light->mSpotFalloff; SpotRadius = Light->mSpotSize - SpotFalloff; break; + case lcLightType::Directional: + LightTarget = Light->mTargetPosition; + break; + case lcLightType::Area: + AreaCircle = Light->GetLightShape() == LC_LIGHT_SHAPE_DISK ? 1 : 0; + AreaSize = Light->mAreaSize; + AreaGrid = Light->mAreaGrid; + break; default: break; } diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 0114cb5a..4eba20f9 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -300,7 +300,7 @@ void lcQPropertiesTree::mousePressEvent(QMouseEvent *event) if (item) { if ((item != m_delegate->editedItem()) && (event->button() == Qt::LeftButton) && (header()->logicalIndexAt(event->pos().x()) == 1) && - ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) + ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) editItem(item, 1); } } @@ -484,16 +484,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) } case PropertyFloatReadOnly: - { - QLineEdit *editor = new QLineEdit(parent); - float value = item->data(0, PropertyValueRole).toFloat(); - - editor->setText(lcFormatValueLocalized(value)); - editor->setReadOnly(true); - editor->setToolTip(tr("Property is read only")); - - return editor; - } + return nullptr; case PropertyStep: { @@ -534,16 +525,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) } case PropertyStringLightReadOnly: - { - QLineEdit *editor = new QLineEdit(parent); - const char *value = (const char*)item->data(0, PropertyValueRole).value(); - - editor->setText(value); - editor->setReadOnly(true); - editor->setToolTip(tr("Property is read only")); - - return editor; - } + return nullptr; case PropertyLightFormat: { @@ -552,7 +534,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); editor->setMinimumContentsLength(1); - QStringList formats = { "Blender", "POVRay" }; + QStringList formats = { QLatin1String("Blender"), QLatin1String("POVRay") }; for (int i = 0; i < formats.size(); i++) editor->addItem(formats.at(i), QVariant::fromValue(i)); @@ -571,7 +553,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); editor->setMinimumContentsLength(1); - QStringList shapes = { "Square", "Disk", "Rectangle", "Ellipse" }; + QStringList shapes = { tr("Square"), tr("Disk"), tr("Rectangle"), tr("Ellipse") }; for (int i = 0; i < shapes.size(); i++) editor->addItem(shapes.at(i), QVariant::fromValue(i)); @@ -1141,6 +1123,9 @@ QTreeWidgetItem *lcQPropertiesTree::addProperty(QTreeWidgetItem *parent, const Q newItem->setIcon(0, m_expandIcon); } + if (propertyType == PropertyStringLightReadOnly || propertyType == PropertyFloatReadOnly) + newItem->setFlags(newItem->flags() & ~Qt::ItemIsEditable); + return newItem; } @@ -1450,7 +1435,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) QString FactorALabel = QLatin1String("FactorA"); QString Type = QLatin1String("Undefined"); QString Format, Shape, SpotSizeToolTip, ExponentToolTip, FactorAToolTip, FactorBToolTip; - lcLightType LightIndex = LC_UNDEFINED_LIGHT; + lcLightType LightType = lcLightType::Point; lcLightShape ShapeIndex = LC_LIGHT_SHAPE_UNDEFINED; int FormatIndex = 0; float SpotSize = 0.0f; @@ -1484,59 +1469,66 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Target = Light->mTargetPosition; Color = Light->mLightColor; Factor = Light->mLightFactor; - LightIndex = static_cast(Light->mLightType); + LightType = Light->GetLightType(); - switch(LightIndex) + switch(LightType) { - case LC_POINTLIGHT: - Type = QLatin1String("Point"); + case lcLightType::Point: + Type = tr("Point"); FactorALabel = tr("Radius (m)"); FactorAToolTip = tr("The light size for shadow sampling in metres."); + ExponentLabel = tr("Exponent"); break; - case LC_AREALIGHT: - Type = QLatin1String("Area"); + case lcLightType::Spot: + Type = tr("Spot"); + FactorBToolTip = tr("The softness of the spotlight edge."); + ExponentLabel = tr("Power"); + if (POVRayLight) { - Factor = Light->mAreaSize; - FactorALabel = tr("Width"); - FactorAToolTip = tr("The width (X direction) of the area light in units."); - FactorBToolTip = tr("The height (Y direction) of the area light in units."); + FactorALabel = tr("Radius (°)"); + FactorAToolTip = tr("The angle between the \"hot-spot\" edge at the beam center and the center line."); + SpotSizeToolTip = tr("Angle of the spotlight beam - Read only."); + Factor[0] = Light->mSpotSize - Light->mSpotFalloff; + SpotSizeProperty = PropertyFloatReadOnly; } else { - FactorALabel = tr("Width (m)"); - FactorAToolTip = tr("The width (X direction) of the area light in metres."); - FactorBToolTip = tr("The height (Y direction) of the area light in units."); + FactorALabel = tr("Radius (m)"); + FactorAToolTip = tr("Shadow soft size - Light size in metres for shadow sampling."); + SpotSizeToolTip = tr("Angle of the spotlight beam."); } break; - case LC_SUNLIGHT: - Type = QLatin1String("Sun"); + case lcLightType::Directional: + Type = tr("Sun"); FactorALabel = tr("Angle (°)"); FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth."); + ExponentLabel = tr("Strength"); break; - case LC_SPOTLIGHT: - Type = QLatin1String("Spot"); - FactorBToolTip = tr("The softness of the spotlight edge."); + case lcLightType::Area: + Type = tr("Area"); + ExponentLabel = tr("Power"); + if (POVRayLight) { - FactorALabel = tr("Radius (°)"); - FactorAToolTip = tr("The angle between the \"hot-spot\" edge at the beam center and the center line."); - SpotSizeToolTip = tr("Angle of the spotlight beam - Read only."); - Factor[0] = Light->mSpotSize - Light->mSpotFalloff; - SpotSizeProperty = PropertyFloatReadOnly; + Factor = Light->mAreaSize; + FactorALabel = tr("Width"); + FactorAToolTip = tr("The width (X direction) of the area light in units."); + FactorBToolTip = tr("The height (Y direction) of the area light in units."); } else { - FactorALabel = tr("Radius (m)"); - FactorAToolTip = tr("Shadow soft size - Light size in metres for shadow sampling."); - SpotSizeToolTip = tr("Angle of the spotlight beam."); + FactorALabel = tr("Width (m)"); + FactorAToolTip = tr("The width (X direction) of the area light in metres."); + FactorBToolTip = tr("The height (Y direction) of the area light in units."); } break; default: break; } - ShapeIndex = static_cast(Light->mLightShape); + ShapeIndex = static_cast(Light->GetLightType()); + switch(ShapeIndex) { case LC_LIGHT_SHAPE_SQUARE: @@ -1557,6 +1549,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Diffuse = Light->mLightDiffuse; Specular = Light->mLightSpecular; + if (POVRayLight) { Exponent = Light->mPOVRayExponent; @@ -1567,88 +1560,102 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Exponent = Light->mSpotExponent; ExponentToolTip = tr("Intensity of the light in watts."); } - ExponentLabel = LightIndex == LC_SUNLIGHT ? tr("Strength") : tr("Power"); + + ExponentLabel = LightType == lcLightType::Directional ? tr("Strength") : tr("Power"); Cutoff = Light->mSpotCutoff; EnableCutoff = Light->mEnableCutoff; - TargetProperty = Light->mLightType > LC_POINTLIGHT ? PropertyFloat : PropertyFloatReadOnly; + TargetProperty = LightType != lcLightType::Point ? PropertyFloat : PropertyFloatReadOnly; SpotSize = Light->mSpotSize; SpotFalloff = Light->mSpotFalloff; SpotTightness = Light->mSpotTightness; AreaGrid = Light->mAreaGrid; } - if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightIndex || mLightShape != ShapeIndex || mPOVRayLight != POVRayLight) + if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType || mLightShape != ShapeIndex || mPOVRayLight != POVRayLight) { SetEmpty(); + // Configuration lightConfiguration = addProperty(nullptr, tr("Configuration"), PropertyGroup); lightFormat = addProperty(lightConfiguration, tr("Format"), PropertyLightFormat); + // Position lightPosition = addProperty(nullptr, tr("Position"), PropertyGroup); lightPositionX = addProperty(lightPosition, tr("X"), PropertyFloat); lightPositionY = addProperty(lightPosition, tr("Y"), PropertyFloat); lightPositionZ = addProperty(lightPosition, tr("Z"), PropertyFloat); + // Target Position - if (LightIndex != LC_POINTLIGHT && !(LightIndex == LC_AREALIGHT && POVRayLight)) + if (LightType != lcLightType::Point && !(LightType == lcLightType::Area && POVRayLight)) { lightTarget = addProperty(nullptr, tr("Target"), PropertyGroup); lightTargetX = addProperty(lightTarget, tr("X"), TargetProperty); lightTargetY = addProperty(lightTarget, tr("Y"), TargetProperty); lightTargetZ = addProperty(lightTarget, tr("Z"), TargetProperty); } + // Light Colour lightColor = addProperty(nullptr, tr("Color"), PropertyGroup); lightColorIcon = addProperty(lightColor, tr("Name"), PropertyLightColor); lightColorR = addProperty(lightColor, tr("Red"), PropertyFloat); lightColorG = addProperty(lightColor, tr("Green"), PropertyFloat); lightColorB = addProperty(lightColor, tr("Blue"), PropertyFloat); + // Properties lightProperties = addProperty(nullptr, tr("Properties"), PropertyGroup); lightType = addProperty(lightProperties, tr("Type"), PropertyStringLightReadOnly); lightShadowless = addProperty(lightProperties, tr("Shadowless"), PropertyBool); lightExponent = addProperty(lightProperties, ExponentLabel, PropertyFloat); - if ((LightIndex == LC_POINTLIGHT || LightIndex == LC_SUNLIGHT) && !POVRayLight) + + if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); - if (LightIndex == LC_AREALIGHT) + + if (LightType == lcLightType::Spot) + { + lightSpotSize = addProperty(lightProperties, tr("Spot Size (°)"), SpotSizeProperty); + lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloatLightSpotSize); + + if (!POVRayLight) + lightFactorB = addProperty(lightProperties, tr("Spot Blend"), PropertyFloat); + else + { + lightSpotFalloff = addProperty(lightProperties, tr("Spot Falloff (°)"), PropertyFloatLightSpotFalloff); + lightSpotTightness = addProperty(lightProperties, tr("Spot Tightness"), PropertyFloat); + } + } + else if (LightType == lcLightType::Area) { lightShape = addProperty(lightProperties, tr("Shape"), PropertyLightShape); lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); + if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE || POVRayLight) - lightFactorB = addProperty(lightProperties, tr("Height (Y)"), PropertyFloat); + lightFactorB = addProperty(lightProperties, tr("Height"), PropertyFloat); else FactorAToolTip = tr("The size of the area light grid in metres."); + if (POVRayLight) { lightAreaGridRows = addProperty(lightProperties, tr("Grid Rows"), PropertyFloat); lightAreaGridColumns = addProperty(lightProperties, tr("Grid Columns"), PropertyFloat); } } - else if (LightIndex == LC_SPOTLIGHT) - { - lightSpotSize = addProperty(lightProperties, tr("Spot Size (°)"), SpotSizeProperty); - lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); - if (!POVRayLight) - lightFactorB = addProperty(lightProperties, tr("Spot Blend"), PropertyFloat); - else - { - lightSpotFalloff = addProperty(lightProperties, tr("Spot Falloff (°)"), PropertyFloatLightSpotFalloff); - lightSpotTightness = addProperty(lightProperties, tr("Spot Tightness"), PropertyFloat); - } - } + if (!POVRayLight) { - if (LightIndex != LC_SUNLIGHT) + if (LightType != lcLightType::Directional) { lightEnableCutoff = addProperty(lightProperties, tr("Cutoff"), PropertyBool); lightCutoff = addProperty(lightProperties, tr("Cutoff Distance"), PropertyFloat); } + lightDiffuse = addProperty(lightProperties, tr("Diffuse"), PropertyFloat); lightSpecular = addProperty(lightProperties, tr("Specular"), PropertyFloat); } + lightName = addProperty(lightProperties, tr("Name"), PropertyString); mWidgetMode = LC_PROPERTY_WIDGET_LIGHT; - mLightType = LightIndex; + mLightType = LightType; mLightShape = ShapeIndex; mPOVRayLight = POVRayLight; } @@ -1662,7 +1669,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightPositionZ->setText(1, lcFormatValueLocalized(Position[2])); lightPositionZ->setData(0, PropertyValueRole, Position[2]); - if (LightIndex != LC_POINTLIGHT && !(LightIndex == LC_AREALIGHT && POVRayLight)) + if (LightType != lcLightType::Point && !(LightType == lcLightType::Area && POVRayLight)) { lightTargetX->setText(1, lcFormatValueLocalized(Target[0])); lightTargetX->setData(0, PropertyValueRole, Target[0]); @@ -1711,13 +1718,13 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightExponent->setData(0, PropertyValueRole, Exponent); lightExponent->setToolTip(1, ExponentToolTip); - if ((LightIndex == LC_POINTLIGHT || LightIndex == LC_SUNLIGHT) && !POVRayLight) + if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) { lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); lightFactorA->setData(0, PropertyValueRole, Factor[0]); lightFactorA->setToolTip(1, FactorAToolTip); } - else if (LightIndex == LC_AREALIGHT) + else if (LightType == lcLightType::Area) { lightShape->setText(1, Shape); lightShape->setData(0, PropertyValueRole, ShapeIndex); @@ -1745,7 +1752,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightAreaGridColumns->setToolTip(1, tr("The number of sample columns in the area light.")); } } - else if (LightIndex == LC_SPOTLIGHT) + else if (LightType == lcLightType::Spot) { lightSpotSize->setText(1, lcFormatValueLocalized(SpotSize)); lightSpotSize->setData(0, PropertyValueRole, SpotSize); @@ -1775,7 +1782,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) if (!POVRayLight) { - if (LightIndex != LC_SUNLIGHT) + if (LightType != lcLightType::Directional) { lightEnableCutoff->setText(1, EnableCutoff ? "True" : "False"); lightEnableCutoff->setData(0, PropertyValueRole, EnableCutoff); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 39759441..9c68e3e6 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -81,7 +81,7 @@ protected slots: void getPartProperties(lcPartProperties *properties); - int mLightType; + lcLightType mLightType; int mLightShape; bool mPOVRayLight; diff --git a/resources/leocad_cs.ts b/resources/leocad_cs.ts index b3a735fa..420f3ef0 100644 --- a/resources/leocad_cs.ts +++ b/resources/leocad_cs.ts @@ -5602,7 +5602,7 @@ Informace o tom, jak stáhnout a nainstalovat knihovnu, naleznete na adrese http - New SpotLight + New Spotlight Nový zdroj osvětlení diff --git a/resources/leocad_de.ts b/resources/leocad_de.ts index f714bd70..50375b10 100644 --- a/resources/leocad_de.ts +++ b/resources/leocad_de.ts @@ -5501,7 +5501,7 @@ Bitte lesen sie unter https://www.leocad.org nach wie man eine Bibliothek herunt - New SpotLight + New Spotlight Neues Scheinwerferlicht diff --git a/resources/leocad_es.ts b/resources/leocad_es.ts index be484c24..b3bc96d8 100644 --- a/resources/leocad_es.ts +++ b/resources/leocad_es.ts @@ -5577,7 +5577,7 @@ Por favor, visita https://www.leocad.org para saber cómo descargar e instalar u - New SpotLight + New Spotlight nuevo foco diff --git a/resources/leocad_fr.ts b/resources/leocad_fr.ts index 98584deb..13bfc749 100644 --- a/resources/leocad_fr.ts +++ b/resources/leocad_fr.ts @@ -5485,7 +5485,7 @@ SVP visitez https://www.leocad.org pour apprendre comment télécharger et insta - New SpotLight + New Spotlight Nouvelle lumière projecteur diff --git a/resources/leocad_pt.ts b/resources/leocad_pt.ts index bfee18a7..6e30a294 100644 --- a/resources/leocad_pt.ts +++ b/resources/leocad_pt.ts @@ -5412,7 +5412,7 @@ Veja https://www.leocad.org para saber como descarragar e instalar uma bibliotec - New SpotLight + New Spotlight Novo Projector diff --git a/resources/leocad_uk.ts b/resources/leocad_uk.ts index 48c29f6c..6299d91c 100644 --- a/resources/leocad_uk.ts +++ b/resources/leocad_uk.ts @@ -5477,7 +5477,7 @@ Please visit https://www.leocad.org for information on how to download and insta - New SpotLight + New Spotlight From 73d28c67b1e6016bb98147c6b5fb41902e84fad5 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sun, 13 Aug 2023 21:30:24 +0200 Subject: [PATCH 15/42] Directional light update --- qt/lc_qpropertiestree.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 4eba20f9..f964abf5 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -1487,7 +1487,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) if (POVRayLight) { FactorALabel = tr("Radius (°)"); - FactorAToolTip = tr("The angle between the \"hot-spot\" edge at the beam center and the center line."); + FactorAToolTip = tr("The angle between the \"hot-spot\" edge at the beam center and the center line."); SpotSizeToolTip = tr("Angle of the spotlight beam - Read only."); Factor[0] = Light->mSpotSize - Light->mSpotFalloff; SpotSizeProperty = PropertyFloatReadOnly; @@ -1500,7 +1500,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) } break; case lcLightType::Directional: - Type = tr("Sun"); + Type = tr("Directional"); FactorALabel = tr("Angle (°)"); FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth."); ExponentLabel = tr("Strength"); From 8bfbe7dcd8c7c4677bba4debe4a68c4818e5d7b7 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sat, 19 Aug 2023 11:51:22 +0200 Subject: [PATCH 16/42] Save POVRay area light target for subsequent import --- common/light.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/light.cpp b/common/light.cpp index 549b6b02..290d0728 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -79,7 +79,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const else Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding; - if (mLightType != lcLightType::Point && !(mLightType == lcLightType::Area && mPOVRayLight)) + if (mLightType != lcLightType::Point) { if (mTargetPositionKeys.GetSize() > 1) mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY "); From 136a3f9c9f163e34a350420a3b98a59780337306 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sat, 19 Aug 2023 16:30:01 +0200 Subject: [PATCH 17/42] Blender addon - set import lights default to true --- common/lc_blenderpreferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index a9426a7e..a8e7fc58 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -192,7 +192,7 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM /* 05 LBL_DISPLAY_LOGO */ {"displaylogo", "1", QObject::tr("Display Logo"), QObject::tr("Display the logo on the stud")}, /* 06 LBL_IMPORT_CAMERAS_MM */ {"importcameras", "1", QObject::tr("Import Cameras"), QObject::tr("%1 can specify camera definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, /* 07 LBL_IMPORT_EDGES */ {"importedges", "0", QObject::tr("Import Edges"), QObject::tr("Import LDraw edges as edges")}, - /* 08 LBL_IMPORT_LIGHTS_MM */ {"importlights", "0", QObject::tr("Import Lights"), QObject::tr("%1 can specify point and sunlight definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, + /* 08 LBL_IMPORT_LIGHTS_MM */ {"importlights", "1", QObject::tr("Import Lights"), QObject::tr("%1 can specify point and sunlight definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)}, /* 09 LBL_KEEP_ASPECT_RATIO_MM */ {"keepaspectratio", "1", QObject::tr("Keep Aspect Ratio"), QObject::tr("Maintain the aspect ratio when resizing the output image - this attribute is not passed to Blender")}, /* 10 LBL_MAKE_GAPS */ {"makegaps", "1", QObject::tr("Make Gaps"), QObject::tr("Make small gaps between bricks. A small gap is more realistic")}, /* 11 LBL_META_BFC */ {"metabfc", "1", QObject::tr("BFC"), QObject::tr("Process LDraw Back Face Culling meta commands")}, From 410bdb2bb607c87ff7e5333ba8ddf8d081d7e347 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sat, 19 Aug 2023 17:33:57 +0200 Subject: [PATCH 18/42] Blender addon - fix chosen logo options --- common/lc_blenderpreferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index a8e7fc58..01212eeb 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -250,7 +250,7 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO_ITEMS_MM] = { /* FIRST item set as default Data Item: */ - /* 00 LBL_CHOSEN_LOGO */ {"logo|logo2|logo3", QObject::tr("Logo (Not Used)|Logo2 (Not Used)|Flattened(3)")}, + /* 00 LBL_CHOSEN_LOGO */ {"logo3|logo4|logo5", QObject::tr("Raised flattened logo geometry(3)|Raised rounded logo geometry(4)|Subtle rounded logo geometry(5)")}, /* 01 LBL_COLOUR_SCHEME_MM */ {"lgeo|ldraw|alt|custom", QObject::tr("Realistic Colours|Original LDraw Colours|Alternate LDraw Colours|Custom Colours")}, /* 02 LBL_COLOUR_STRATEGY */ {"material|vertex_colors", QObject::tr("Material|Vertex Colors")}, /* 03 LBL_GAP_SCALE_STRATEGY */ {"object|constraint", QObject::tr("Gap applied directly to object|Gap scaled to adjust to gaps between parts")}, From 2f5594b5f6eb6b7adadf14d2e8fe219c96a5f96c Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sun, 20 Aug 2023 01:06:23 +0200 Subject: [PATCH 19/42] Blender addon - change smooth_type default to bmesh_split --- common/lc_blenderpreferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index 01212eeb..37bc8c2c 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -244,7 +244,7 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM /* 55/03 LBL_GAP_SCALE_STRATEGY */ {"gapscalestrategy", "constraint", QObject::tr("Gap Strategy"), QObject::tr("Apply gap to object directly or scale and empty to adjust to gaps between parts")}, /* 56/04 LBL_GAP_TARGET */ {"gaptarget", "object", QObject::tr("Gap Target"), QObject::tr("Whether to scale the object data or mesh data")}, /* 57/05 LBL_RESOLUTION_MM */ {"resolution", "Standard", QObject::tr("Resolution"), QObject::tr("Resolution of part primitives, ie. how much geometry they have")}, - /* 58/06 LBL_SMOOTH_TYPE */ {"smoothtype", "edge_split", QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")} + /* 58/06 LBL_SMOOTH_TYPE */ {"smoothtype", "bmesh_split",QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")} }; lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO_ITEMS_MM] = From 3942156acfe66df108d9f4e8076e118ee9431e4c Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 26 Aug 2023 12:41:16 -0700 Subject: [PATCH 20/42] New light gizmos. --- common/lc_math.h | 119 +++++++ common/light.cpp | 670 ++++++++++++++++++++------------------ common/light.h | 10 +- qt/lc_qpropertiestree.cpp | 16 +- 4 files changed, 495 insertions(+), 320 deletions(-) diff --git a/common/lc_math.h b/common/lc_math.h index bc7eb1b1..4fcb0d4b 100644 --- a/common/lc_math.h +++ b/common/lc_math.h @@ -1991,6 +1991,125 @@ inline bool lcSphereRayMinIntersectDistance(const lcVector3& Center, float Radiu } } +inline bool lcConeRayMinIntersectDistance(const lcVector3& Tip, const lcVector3& Direction, float Radius, float Height, const lcVector3& Start, const lcVector3& End, float* Dist) +{ + const lcVector3 v = End - Start; + const lcVector3 h = Direction; + const lcVector3 w = Start - Tip; + const float vh = lcDot(v, h); + const float wh = lcDot(w, h); + const float m = (Radius * Radius) / (Height * Height); + + const float a = lcDot(v, v) - m * vh * vh - vh * vh; + const float b = 2 * (lcDot(v, w) - m * vh * wh - vh * wh); + const float c = lcDot(w, w) - m * wh * wh - wh * wh; + + const float delta = b * b - 4 * a * c; + + if (delta < 0.0f) + return false; + + float ts[2] = { (-b - sqrtf(delta)) / (2 * a), (-b + sqrtf(delta)) / (2 * a) }; + + for (int ti = 0; ti < 2; ti++) + { + float t = ts[ti]; + lcVector3 Intersection = Start + v * t; + + float ConeD = lcDot(Intersection - Tip, Direction); + + if (ConeD < 0.0f) + continue; + + if (ConeD < Height) + { + *Dist = lcLength(Intersection - Start); + + return true; + } + + lcVector3 Center(Tip + Direction * Height); + lcVector4 Plane(Direction, -lcDot(Direction, Center)); + + if (lcLineSegmentPlaneIntersection(&Intersection, Start, End, Plane)) + { + if (lcLengthSquared(Center - Intersection) < Radius * Radius) + { + *Dist = lcLength(Intersection - Start); + + return true; + } + } + } + + return false; +} + +inline bool lcCylinderRayMinIntersectDistance(float Radius, float Height, const lcVector3& Start, const lcVector3& End, float* Dist) +{ + lcVector4 BottomPlane(0.0f, 0.0f, 1.0f, 0.0f); + lcVector3 Intersection; + float MinDistance = FLT_MAX; + + if (lcLineSegmentPlaneIntersection(&Intersection, Start, End, BottomPlane)) + { + if (Intersection.x * Intersection.x + Intersection.y * Intersection.y < Radius * Radius) + { + float Distance = lcLength(Intersection - Start); + + if (Distance < MinDistance) + MinDistance = Distance; + } + } + + lcVector4 TopPlane(0.0f, 0.0f, 1.0f, -Height); + + if (lcLineSegmentPlaneIntersection(&Intersection, Start, End, TopPlane)) + { + if (Intersection.x * Intersection.x + Intersection.y * Intersection.y < Radius * Radius) + { + float Distance = lcLength(Intersection - Start); + + if (Distance < MinDistance) + MinDistance = Distance; + } + } + + lcVector3 Direction = End - Start; + + float a = (Direction.x * Direction.x) + (Direction.y * Direction.y); + float b = 2 * (Direction.x * Start.x + Direction.y * Start.y); + float c = (Start.x * Start.x) + (Start.y * Start.y) - (Radius * Radius); + + float delta = b * b - 4 * (a * c); + + if (delta > 0.0f) + { + float ts[2] = { (-b - sqrtf(delta)) / (2 * a), (-b + sqrtf(delta)) / (2 * a) }; + + for (int ti = 0; ti < 2; ti++) + { + float t = ts[ti]; + Intersection = Start + Direction * t; + + if (Intersection.z < 0.0f || Intersection.z > Height) + continue; + + float Distance = lcLength(Intersection - Start); + + if (Distance < MinDistance) + MinDistance = Distance; + } + } + + if (MinDistance == FLT_MAX) + return false; + + *Dist = MinDistance; + + return true; +} + inline lcVector3 lcRayPointClosestPoint(const lcVector3& Point, const lcVector3& Start, const lcVector3& End) { const lcVector3 Dir = Point - Start; diff --git a/common/light.cpp b/common/light.cpp index 290d0728..b3584a8c 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -8,11 +8,14 @@ #include "lc_application.h" #include "lc_context.h" -#define LC_LIGHT_POSITION_EDGE 7.5f -#define LC_LIGHT_TARGET_EDGE 5.0f #define LC_LIGHT_SPHERE_RADIUS 5.0f -#define LC_LIGHT_SUN_RADIUS 8.5f -#define LC_LIGHT_SPOT_BASE_EDGE 12.5f +#define LC_LIGHT_TARGET_EDGE 5.0f +#define LC_LIGHT_SPOT_CONE_HEIGHT 10.0f +#define LC_LIGHT_SPOT_CONE_RADIUS 7.5f +#define LC_LIGHT_DIRECTIONAL_RADIUS 5.0f +#define LC_LIGHT_DIRECTIONAL_HEIGHT 7.5f + +#define LC_LIGHT_POSITION_EDGE 7.5f static const std::array gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") }; @@ -597,7 +600,7 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const { float Distance; - if (lcSphereRayMinIntersectDistance(mPosition, LC_LIGHT_SPHERE_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance)) + if (lcSphereRayMinIntersectDistance(mPosition, LC_LIGHT_SPHERE_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance)) { ObjectRayTest.ObjectSection.Object = const_cast(this); ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION; @@ -607,8 +610,63 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const return; } - lcVector3 Min = lcVector3(-LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE); - lcVector3 Max = lcVector3(LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE); + if (mLightType == lcLightType::Spot) + { + float Distance; + lcVector3 Direction = lcNormalize(mTargetPosition - mPosition); + + if (lcConeRayMinIntersectDistance(mPosition - Direction * LC_LIGHT_SPOT_CONE_HEIGHT, Direction, LC_LIGHT_SPOT_CONE_RADIUS, LC_LIGHT_SPOT_CONE_HEIGHT, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance)) + { + ObjectRayTest.ObjectSection.Object = const_cast(this); + ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION; + ObjectRayTest.Distance = Distance; + } + } + else if (mLightType == lcLightType::Area) + { + lcVector3 FrontVector = mTargetPosition - mPosition; + lcVector4 Plane(FrontVector, -lcDot(FrontVector, mPosition)); + lcVector3 Intersection; + + if (lcLineSegmentPlaneIntersection(&Intersection, ObjectRayTest.Start, ObjectRayTest.End, Plane)) + { + lcVector3 UpVector(1, 1, 1); + + if (fabs(FrontVector[0]) < fabs(FrontVector[1])) + { + if (fabs(FrontVector[0]) < fabs(FrontVector[2])) + UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); + else + UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + } + else + { + if (fabs(FrontVector[1]) < fabs(FrontVector[2])) + UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); + else + UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + } + + lcVector3 XAxis = lcNormalize(lcCross(FrontVector, UpVector)); + lcVector3 YAxis = lcNormalize(lcCross(FrontVector, XAxis)); + lcVector3 IntersectionDirection = Intersection - mPosition; + + float x = lcDot(IntersectionDirection, XAxis); + float y = lcDot(IntersectionDirection, YAxis); + + if (fabsf(x) < mAreaSize.x / 2.0f && fabsf(y) < mAreaSize.y / 2.0f) + { + float Distance = lcLength(Intersection - ObjectRayTest.Start); + + if (Distance < ObjectRayTest.Distance) + { + ObjectRayTest.ObjectSection.Object = const_cast(this); + ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION; + ObjectRayTest.Distance = Distance; + } + } + } + } lcVector3 Start = lcMul31(ObjectRayTest.Start, mWorldLight); lcVector3 End = lcMul31(ObjectRayTest.End, mWorldLight); @@ -616,16 +674,19 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const float Distance; lcVector3 Plane; - if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance)) + if (mLightType == lcLightType::Directional) { - ObjectRayTest.ObjectSection.Object = const_cast(this); - ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION; - ObjectRayTest.Distance = Distance; - ObjectRayTest.PieceInfoRayTest.Plane = Plane; + if (lcCylinderRayMinIntersectDistance(LC_LIGHT_DIRECTIONAL_RADIUS, LC_LIGHT_DIRECTIONAL_HEIGHT, Start, End, &Distance) && (Distance < ObjectRayTest.Distance)) + { + ObjectRayTest.ObjectSection.Object = const_cast(this); + ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION; + ObjectRayTest.Distance = Distance; + ObjectRayTest.PieceInfoRayTest.Plane = Plane; + } } - Min = lcVector3(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE); - Max = lcVector3(LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE); + lcVector3 Min = lcVector3(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE); + lcVector3 Max = lcVector3( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE); lcMatrix44 WorldTarget = mWorldLight; WorldTarget.SetTranslation(lcMul30(-mTargetPosition, WorldTarget)); @@ -654,7 +715,7 @@ void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const return; } - lcVector3 Min(-LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE); + lcVector3 Min(-LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE); // todo: fix light box test lcVector3 Max(LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE); lcVector4 LocalPlanes[6]; @@ -798,357 +859,232 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const Q_UNUSED(Scene); Context->SetMaterial(lcMaterialType::UnlitColor); - if (IsPointLight()) + switch (mLightType) + { + case lcLightType::Point: DrawPointLight(Context); - else + break; + + case lcLightType::Spot: + DrawSpotLight(Context); + break; + + case lcLightType::Directional: DrawDirectionalLight(Context); + break; + + case lcLightType::Area: + DrawAreaLight(Context); + break; + } } -void lcLight::DrawDirectionalLight(lcContext* Context) const +void lcLight::DrawPointLight(lcContext* Context) const { - lcVector3 FrontVector(mTargetPosition - mPosition); - lcVector3 UpVector(1, 1, 1); + Context->SetWorldMatrix(lcMatrix44Translation(mPosition)); - if (fabs(FrontVector[0]) < fabs(FrontVector[1])) + const lcPreferences& Preferences = lcGetPreferences(); + + if (IsFocused(LC_LIGHT_SECTION_POSITION)) { - if (fabs(FrontVector[0]) < fabs(FrontVector[2])) - UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); + Context->SetColor(FocusedColor); + } + else if (IsSelected(LC_LIGHT_SECTION_POSITION)) + { + const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); + Context->SetColor(SelectedColor); } else { - if (fabs(FrontVector[1]) < fabs(FrontVector[2])) - UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); + Context->SetColor(LightColor); } - lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); - LightMatrix = lcMatrix44AffineInverse(LightMatrix); - LightMatrix.SetTranslation(lcVector3(0, 0, 0)); - - const lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); - Context->SetWorldMatrix(LightViewMatrix); + DrawSphere(Context, LC_LIGHT_SPHERE_RADIUS); +} - float Length = FrontVector.Length(); +void lcLight::DrawSpotLight(lcContext* Context) const +{ + constexpr int ConeEdges = 8; + float TargetDistance = SetupLightMatrix(Context); - float Verts[(20 + 8 + 2 + 16) * 3]; + float Verts[(ConeEdges + 1) * 3]; float* CurVert = Verts; - if (mLightType != lcLightType::Directional) + for (int EdgeIndex = 0; EdgeIndex < ConeEdges; EdgeIndex++) { - if (mLightType == lcLightType::Spot) - { - for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++) - { - float c = cosf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; - float s = sinf((float)EdgeIdx / 4 * LC_PI) * LC_LIGHT_POSITION_EDGE; - - *CurVert++ = c; - *CurVert++ = s; - *CurVert++ = LC_LIGHT_POSITION_EDGE; - *CurVert++ = c; - *CurVert++ = s; - *CurVert++ = -LC_LIGHT_POSITION_EDGE; - } + float c = cosf((float)EdgeIndex / ConeEdges * LC_2PI) * LC_LIGHT_SPOT_CONE_RADIUS; + float s = sinf((float)EdgeIndex / ConeEdges * LC_2PI) * LC_LIGHT_SPOT_CONE_RADIUS; - *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = -LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = LC_LIGHT_SPOT_BASE_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - } - else if (mLightType == lcLightType::Area) - { - const float LC_LIGHT_AREA_EDGE = 5.0f; - const float LC_LIGHT_AREA_H_EDGE = 8.5f; - const float LC_LIGHT_AREA_W_EDGE = 17.0f; - - *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; - *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; - *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_AREA_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - - *CurVert++ = -LC_LIGHT_AREA_H_EDGE; *CurVert++ = -LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_AREA_H_EDGE; *CurVert++ = -LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = LC_LIGHT_AREA_H_EDGE; *CurVert++ = LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - *CurVert++ = -LC_LIGHT_AREA_H_EDGE; *CurVert++ = LC_LIGHT_AREA_W_EDGE; *CurVert++ = -LC_LIGHT_POSITION_EDGE; - } - - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - Length; - - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; - - Context->SetVertexBufferPointer(Verts); - Context->SetVertexFormatPosition(3); + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = 0.0f; } - int BaseIndices = 0; + *CurVert++ = 0.0f; + *CurVert++ = 0.0f; + *CurVert++ = LC_LIGHT_SPOT_CONE_HEIGHT; - if (mLightType == lcLightType::Spot) - { - BaseIndices = 56; - const GLushort Indices[56 + 24 + 2 + 40] = - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, - 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1, - 16, 17, 17, 18, 18, 19, 19, 16, - 20, 21, 21, 22, 22, 23, 23, 20, - 24, 25, 25, 26, 26, 27, 27, 24, - 20, 24, 21, 25, 22, 26, 23, 27, - 28, 29, - 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, - 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 30, - 28, 30, 28, 34, 28, 38, 28, 42 - }; + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); - Context->SetIndexBufferPointer(Indices); - } - else if (mLightType == lcLightType::Area) + const GLushort Indices[(ConeEdges + 4) * 2] = { - BaseIndices = 32; - const GLushort Indices[32 + 24 + 2] = - { - 0, 1, 1, 2, 2, 3, 3, 0, - 4, 5, 5, 6, 6, 7, 7, 4, - 0, 4, 1, 5, 2, 6, 3, 7, - 8, 9, 9, 10, 10, 11, 11, 8, - 12, 13, 13, 14, 14, 15, 15, 12, - 16, 17, 17, 18, 18, 19, 19, 16, - 12, 16, 13, 17, 14, 18, 15, 19, - 20, 21 - }; + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 0, + 0, 8, 2, 8, 4, 8, 6, 8, + }; - Context->SetIndexBufferPointer(Indices); - } - else if (mLightType == lcLightType::Directional) - { - constexpr float Radius = LC_LIGHT_SUN_RADIUS; - constexpr int Slices = 9; // longitude - constexpr int Stacks = 9; // latitude - constexpr int NumSphereVertices = 918; // Slices * 2 * 3 * 3 + (Stacks - 2) * Slices * 4 * 3 - constexpr int NumSphereIndices = 306; // Slices * 2 + (Stacks - 1) * Slices * 2 * 2 + Context->SetIndexBufferPointer(Indices); - BaseIndices = NumSphereIndices; + Context->DrawIndexedPrimitives(GL_LINES, (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0); - float Vertices[NumSphereVertices + 24 + 6]; - float *Vert = Vertices; + DrawTarget(Context, TargetDistance); - quint16 Indices[NumSphereIndices + 24 + 2]; - quint16 *Indx = Indices; + if (IsSelected()) + DrawCone(Context, TargetDistance); +} - auto AddVertex = [&](float x, float y, float z) - { - *Vert++ = x; - *Vert++ = y; - *Vert++ = z; - }; +void lcLight::DrawDirectionalLight(lcContext* Context) const +{ + float TargetDistance = SetupLightMatrix(Context); - auto AddLineIndex = [&](quint16 v1, quint16 v2) - { - *Indx++ = v1; - *Indx++ = v2; - }; + DrawCylinder(Context, LC_LIGHT_DIRECTIONAL_RADIUS, LC_LIGHT_DIRECTIONAL_HEIGHT); - std::vector WrkVertices; + DrawTarget(Context, TargetDistance); +} - float Slice = LC_2PI / Slices; - float Stack = LC_PI / Stacks; - float SliceAngle, StackAngle; +void lcLight::DrawAreaLight(lcContext* Context) const +{ + float TargetDistance = SetupLightMatrix(Context); - for(int i = 0; i <= Stacks; ++i) - { - StackAngle = LC_PI / 2 - i * Stack; // starting from pi/2 to -pi/2 - float xy = Radius * cosf(StackAngle); - float z = Radius * sinf(StackAngle); + if (mLightShape == LC_LIGHT_SHAPE_SQUARE || mLightShape == LC_LIGHT_SHAPE_RECTANGLE) + { + float Verts[4 * 3]; + float* CurVert = Verts; - for(int j = 0; j <= Slices; ++j) // add (Slices+1) vertices per stack - { - SliceAngle = j * Slice; + *CurVert++ = -mAreaSize.x / 2.0f; + *CurVert++ = -mAreaSize.y / 2.0f; + *CurVert++ = 0.0f; - lcVector3 Vertex; - Vertex.x = xy * cosf(SliceAngle); - Vertex.y = xy * sinf(SliceAngle); - Vertex.z = z; + *CurVert++ = mAreaSize.x / 2.0f; + *CurVert++ = -mAreaSize.y / 2.0f; + *CurVert++ = 0.0f; - WrkVertices.push_back(Vertex); - } - } + *CurVert++ = mAreaSize.x / 2.0f; + *CurVert++ = mAreaSize.y / 2.0f; + *CurVert++ = 0.0f; - int Index = 0; + *CurVert++ = -mAreaSize.x / 2.0f; + *CurVert++ = mAreaSize.y / 2.0f; + *CurVert++ = 0.0f; - lcVector3 v1, v2, v3, v4; + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); - for(int i = 0; i < Stacks; ++i) + const GLushort Indices[(4 + 2) * 2] = { - int vi1 = i * (Slices + 1); - int vi2 = (i + 1) * (Slices + 1); - - for(int j = 0; j < Slices; ++j, ++vi1, ++vi2) - { - // 4 vertices per slice - // v1--v3 - // | | - // v2--v4 - v1 = WrkVertices[vi1]; - v2 = WrkVertices[vi2]; - v3 = WrkVertices[vi1 + 1]; - v4 = WrkVertices[vi2 + 1]; - - // if first stack or last stack, store 1 triangle per slice else, store 2 triangles (1 quad) per slice - if(i == 0) - { - // first stack triangle v1-v2-v4 - AddVertex(v1.x, v1.y, v1.z); - AddVertex(v2.x, v2.y, v2.z); - AddVertex(v4.x, v4.y, v4.z); - - // only vertical lines for first stack) - AddLineIndex(Index, Index+1); + 0, 1, 1, 2, 2, 3, 3, 0, + 0, 2, 1, 3, + }; - Index += 3; - } - else if(i == (Stacks-1)) - { - // last stack inverted triangle v1-v2-v3 - AddVertex(v1.x, v1.y, v1.z); - AddVertex(v2.x, v2.y, v2.z); - AddVertex(v3.x, v3.y, v3.z); + Context->SetIndexBufferPointer(Indices); - // both vertical and horizontal lines for last stack - AddLineIndex(Index, Index+1); - AddLineIndex(Index, Index+2); + Context->DrawIndexedPrimitives(GL_LINES, (4 + 2) * 2, GL_UNSIGNED_SHORT, 0); + } + else + { + constexpr int CircleEdges = 16; - Index += 3; - } - else - { - // 2 triangles (quad vertices v1-v2-v3-v4) for other stacks - AddVertex(v1.x, v1.y, v1.z); - AddVertex(v2.x, v2.y, v2.z); - AddVertex(v3.x, v3.y, v3.z); - AddVertex(v4.x, v4.y, v4.z); + float Verts[CircleEdges * 3]; + float* CurVert = Verts; - // both vertical and horizontal lines for other stacks - AddLineIndex(Index, Index+1); - AddLineIndex(Index, Index+2); + for (int EdgeIndex = 0; EdgeIndex < CircleEdges; EdgeIndex++) + { + float c = cosf((float)EdgeIndex / CircleEdges * LC_2PI) * mAreaSize.x / 2.0f; + float s = sinf((float)EdgeIndex / CircleEdges * LC_2PI) * mAreaSize.y / 2.0f; - Index += 4; - } - } + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = 0.0f; } - AddVertex( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); - AddVertex(-LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); - AddVertex(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); - AddVertex( LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE - Length); - AddVertex( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); - AddVertex(-LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); - AddVertex(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); - AddVertex( LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE - Length); - AddVertex(0.0f, 0.0f, 0.0f); - AddVertex(0.0f, 0.0f, -Length); - - const int Idx[10] = { Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++, Index++ }; - AddLineIndex(Idx[0], Idx[1]); AddLineIndex(Idx[1], Idx[2]); AddLineIndex(Idx[2], Idx[3]); AddLineIndex(Idx[3], Idx[0]); - AddLineIndex(Idx[4], Idx[5]); AddLineIndex(Idx[5], Idx[6]); AddLineIndex(Idx[6], Idx[7]); AddLineIndex(Idx[7], Idx[4]); - AddLineIndex(Idx[0], Idx[4]); AddLineIndex(Idx[1], Idx[5]); AddLineIndex(Idx[2], Idx[6]); AddLineIndex(Idx[3], Idx[7]); - AddLineIndex(Idx[8], Idx[9]); - - Context->SetVertexBufferPointer(Vertices); + Context->SetVertexBufferPointer(Verts); Context->SetVertexFormatPosition(3); + + const GLushort Indices[(CircleEdges + 2) * 2] = + { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 0, + 0, 8, 4, 12 + }; + Context->SetIndexBufferPointer(Indices); + + Context->DrawIndexedPrimitives(GL_LINES, (CircleEdges + 2) * 2, GL_UNSIGNED_SHORT, 0); } - const lcPreferences& Preferences = lcGetPreferences(); - const float LineWidth = Preferences.mLineWidth; - const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); - const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); - const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); + DrawTarget(Context, TargetDistance); +} - if (!IsSelected()) - { - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); +float lcLight::SetupLightMatrix(lcContext* Context) const +{ + lcVector3 FrontVector(mTargetPosition - mPosition); + lcVector3 UpVector(1, 1, 1); - Context->DrawIndexedPrimitives(GL_LINES, BaseIndices + 24 + 2, GL_UNSIGNED_SHORT, 0); + if (fabs(FrontVector[0]) < fabs(FrontVector[1])) + { + if (fabs(FrontVector[0]) < fabs(FrontVector[2])) + UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); + else + UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); } else { - if (IsSelected(LC_LIGHT_SECTION_POSITION)) - { - Context->SetLineWidth(2.0f * LineWidth); - if (IsFocused(LC_LIGHT_SECTION_POSITION)) - Context->SetColor(FocusedColor); - else - Context->SetColor(SelectedColor); - } - else - { - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); - } - - Context->DrawIndexedPrimitives(GL_LINES, BaseIndices, GL_UNSIGNED_SHORT, 0); - - if (IsSelected(LC_LIGHT_SECTION_TARGET)) - { - Context->SetLineWidth(2.0f * LineWidth); - if (IsFocused(LC_LIGHT_SECTION_TARGET)) - Context->SetColor(FocusedColor); - else - Context->SetColor(SelectedColor); - } + if (fabs(FrontVector[1]) < fabs(FrontVector[2])) + UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); else - { - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); - } + UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + } - Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, BaseIndices * 2); + lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); + LightMatrix = lcMatrix44AffineInverse(LightMatrix); + LightMatrix.SetTranslation(lcVector3(0, 0, 0)); - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); + const lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); + Context->SetWorldMatrix(LightViewMatrix); - int SpotCone = 0; + const lcPreferences& Preferences = lcGetPreferences(); + const float LineWidth = Preferences.mLineWidth; - if (mLightType == lcLightType::Spot) - { - SpotCone = 40; + if (IsSelected(LC_LIGHT_SECTION_POSITION)) + { + const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); + const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); - float Radius = tanf(LC_DTOR * mSpotCutoff) * Length; + Context->SetLineWidth(2.0f * LineWidth); - for (int EdgeIdx = 0; EdgeIdx < 16; EdgeIdx++) - { - *CurVert++ = cosf((float)EdgeIdx / 16 * LC_2PI) * Radius; - *CurVert++ = sinf((float)EdgeIdx / 16 * LC_2PI) * Radius; - *CurVert++ = -Length; - } - } + if (IsFocused(LC_LIGHT_SECTION_POSITION)) + Context->SetColor(FocusedColor); + else + Context->SetColor(SelectedColor); + } + else + { + const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); - Context->DrawIndexedPrimitives(GL_LINES, 2 + SpotCone, GL_UNSIGNED_SHORT, (BaseIndices + 24) * 2); + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); } + + return FrontVector.Length(); } -void lcLight::DrawPointLight(lcContext* Context) const +void lcLight::DrawSphere(lcContext* Context, float Radius) const { constexpr int Slices = 6; constexpr int NumIndices = 3 * Slices + 6 * Slices * (Slices - 2) + 3 * Slices; constexpr int NumVertices = (Slices - 1) * Slices + 2; - constexpr float Radius = LC_LIGHT_SPHERE_RADIUS; lcVector3 Vertices[NumVertices]; quint16 Indices[NumIndices]; @@ -1157,7 +1093,7 @@ void lcLight::DrawPointLight(lcContext* Context) const *Vertex++ = lcVector3(0, 0, Radius); - for (int i = 1; i < Slices; i++ ) + for (int i = 1; i < Slices; i++) { const float r0 = Radius * sinf(i * (LC_PI / Slices)); const float z0 = Radius * cosf(i * (LC_PI / Slices)); @@ -1173,7 +1109,7 @@ void lcLight::DrawPointLight(lcContext* Context) const *Vertex++ = lcVector3(0, 0, -Radius); - for (quint16 i = 0; i < Slices - 1; i++ ) + for (quint16 i = 0; i < Slices - 1; i++) { *Index++ = 0; *Index++ = 1 + i; @@ -1184,12 +1120,12 @@ void lcLight::DrawPointLight(lcContext* Context) const *Index++ = 1; *Index++ = 1 + Slices - 1; - for (quint16 i = 0; i < Slices - 2; i++ ) + for (quint16 i = 0; i < Slices - 2; i++) { quint16 Row1 = 1 + i * Slices; quint16 Row2 = 1 + (i + 1) * Slices; - for (quint16 j = 0; j < Slices - 1; j++ ) + for (quint16 j = 0; j < Slices - 1; j++) { *Index++ = Row1 + j; *Index++ = Row2 + j + 1; @@ -1209,7 +1145,7 @@ void lcLight::DrawPointLight(lcContext* Context) const *Index++ = Row1 + 0; } - for (quint16 i = 0; i < Slices - 1; i++ ) + for (quint16 i = 0; i < Slices - 1; i++) { *Index++ = (Slices - 1) * Slices + 1; *Index++ = (Slices - 1) * (Slices - 1) + i; @@ -1220,30 +1156,142 @@ void lcLight::DrawPointLight(lcContext* Context) const *Index++ = (Slices - 1) * (Slices - 1) + (Slices - 2) + 1; *Index++ = (Slices - 1) * (Slices - 1); - Context->SetWorldMatrix(lcMatrix44Translation(mPosition)); + Context->SetVertexBufferPointer(Vertices); + Context->SetVertexFormatPosition(3); + Context->SetIndexBufferPointer(Indices); - const lcPreferences& Preferences = lcGetPreferences(); + Context->DrawIndexedPrimitives(GL_TRIANGLES, NumIndices, GL_UNSIGNED_SHORT, 0); +} - if (IsFocused(LC_LIGHT_SECTION_POSITION)) +void lcLight::DrawCylinder(lcContext* Context, float Radius, float Height) const +{ + constexpr int Slices = 8; + + float Verts[(Slices * 2) * 3]; + float* CurVert = Verts; + + for (int EdgeIndex = 0; EdgeIndex < Slices; EdgeIndex++) { - const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); - Context->SetColor(FocusedColor); + float c = cosf((float)EdgeIndex / Slices * LC_2PI) * Radius; + float s = sinf((float)EdgeIndex / Slices * LC_2PI) * Radius; + + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = Height; + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = 0.0f; } - else if (IsSelected(LC_LIGHT_SECTION_POSITION)) + + const GLushort Indices[48] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 0, + 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15, 15, 1, + }; + + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); + Context->SetIndexBufferPointer(Indices); + + Context->DrawIndexedPrimitives(GL_LINES, 48, GL_UNSIGNED_SHORT, 0); +} + +void lcLight::DrawTarget(lcContext* Context, float TargetDistance) const +{ + float Verts[10 * 3]; + float* CurVert = Verts; + + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - TargetDistance; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - TargetDistance; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - TargetDistance; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - TargetDistance; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - TargetDistance; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - TargetDistance; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - TargetDistance; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - TargetDistance; + + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -TargetDistance; + + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); + + const GLushort Indices[(12 + 1) * 2] = + { + 0, 1, 1, 2, 2, 3, 3, 0, + 4, 5, 5, 6, 6, 7, 7, 4, + 0, 4, 1, 5, 2, 6, 3, 7, + 8, 9 + }; + + Context->SetIndexBufferPointer(Indices); + + const lcPreferences& Preferences = lcGetPreferences(); + const float LineWidth = Preferences.mLineWidth; + const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); + + if (IsSelected(LC_LIGHT_SECTION_TARGET)) { const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); - Context->SetColor(SelectedColor); + const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); + + Context->SetLineWidth(2.0f * LineWidth); + + if (IsFocused(LC_LIGHT_SECTION_TARGET)) + Context->SetColor(FocusedColor); + else + Context->SetColor(SelectedColor); } else { - const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); + Context->SetLineWidth(LineWidth); Context->SetColor(LightColor); } - Context->SetVertexBufferPointer(Vertices); + Context->DrawIndexedPrimitives(GL_LINES, 12 * 2, GL_UNSIGNED_SHORT, 0); + + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + + Context->DrawIndexedPrimitives(GL_LINES, 2, GL_UNSIGNED_SHORT, 12 * 2 * 2); +} + +void lcLight::DrawCone(lcContext* Context, float TargetDistance) const +{ + constexpr int ConeEdges = 16; + const float Radius = tanf(LC_DTOR * mSpotCutoff) * TargetDistance; + + float Verts[(ConeEdges + 1) * 3]; + float* CurVert = Verts; + + for (int EdgeIndex = 0; EdgeIndex < ConeEdges; EdgeIndex++) + { + float c = cosf((float)EdgeIndex / ConeEdges * LC_2PI) * Radius; + float s = sinf((float)EdgeIndex / ConeEdges * LC_2PI) * Radius; + + *CurVert++ = c; + *CurVert++ = s; + *CurVert++ = -TargetDistance; + } + + *CurVert++ = 0.0f; + *CurVert++ = 0.0f; + *CurVert++ = 0.0f; + + Context->SetVertexBufferPointer(Verts); Context->SetVertexFormatPosition(3); + + const GLushort Indices[(ConeEdges + 4) * 2] = + { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 0, + 16, 0, 16, 4, 16, 8, 16, 12 + }; + Context->SetIndexBufferPointer(Indices); - Context->DrawIndexedPrimitives(GL_TRIANGLES, NumIndices, GL_UNSIGNED_SHORT, 0); + + Context->DrawIndexedPrimitives(GL_LINES, (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0); } void lcLight::RemoveKeyFrames() diff --git a/common/light.h b/common/light.h index 5a4a121c..23c56300 100644 --- a/common/light.h +++ b/common/light.h @@ -331,8 +331,16 @@ class lcLight : public lcObject lcObjectKeyArray mSpotExponentKeys; lcObjectKeyArray mSpotTightnessKeys; - void DrawDirectionalLight(lcContext* Context) const; void DrawPointLight(lcContext* Context) const; + void DrawSpotLight(lcContext* Context) const; + void DrawDirectionalLight(lcContext* Context) const; + void DrawAreaLight(lcContext* Context) const; + + float SetupLightMatrix(lcContext* Context) const; + void DrawSphere(lcContext* Context, float Radius) const; + void DrawCylinder(lcContext* Context, float Radius, float Height) const; + void DrawTarget(lcContext* Context, float TargetDistance) const; + void DrawCone(lcContext* Context, float TargetDistance) const; quint32 mState; lcLightType mLightType; diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index f964abf5..dfb025ac 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -983,7 +983,7 @@ void lcQPropertiesTree::slotReturnPressed() { QString Value = Editor->text(); - Model->SetLightName(Light, Value.toLocal8Bit().data()); + Model->SetLightName(Light, Value); } } } @@ -1513,14 +1513,14 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) { Factor = Light->mAreaSize; FactorALabel = tr("Width"); - FactorAToolTip = tr("The width (X direction) of the area light in units."); - FactorBToolTip = tr("The height (Y direction) of the area light in units."); + FactorAToolTip = tr("The width (X direction) of the area light."); + FactorBToolTip = tr("The height (Y direction) of the area light."); } else { - FactorALabel = tr("Width (m)"); - FactorAToolTip = tr("The width (X direction) of the area light in metres."); - FactorBToolTip = tr("The height (Y direction) of the area light in units."); + FactorALabel = tr("Width"); + FactorAToolTip = tr("The width (X direction) of the area light."); + FactorBToolTip = tr("The height (Y direction) of the area light."); } break; default: @@ -1623,7 +1623,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightSpotTightness = addProperty(lightProperties, tr("Spot Tightness"), PropertyFloat); } } - else if (LightType == lcLightType::Area) + else if (LightType == lcLightType::Area) { lightShape = addProperty(lightProperties, tr("Shape"), PropertyLightShape); lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); @@ -1631,7 +1631,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE || POVRayLight) lightFactorB = addProperty(lightProperties, tr("Height"), PropertyFloat); else - FactorAToolTip = tr("The size of the area light grid in metres."); + FactorAToolTip = tr("The size of the area light grid."); if (POVRayLight) { From 5f3eb69ae7cf0e98e7a083e12af094ad1112cbd6 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 26 Aug 2023 19:43:08 -0700 Subject: [PATCH 21/42] Added up vector to area lights. --- common/light.cpp | 197 +++++++++++++++++++++++++++++++++++++++++------ common/light.h | 58 +++++++++++++- 2 files changed, 230 insertions(+), 25 deletions(-) diff --git a/common/light.cpp b/common/light.cpp index b3584a8c..5a9aa9c3 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -20,19 +20,35 @@ static const std::array gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") }; lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcLightType LightType) - : lcObject(lcObjectType::Light), mPosition(Position), mTargetPosition(TargetPosition), mLightType(LightType) + : lcObject(lcObjectType::Light), mLightType(LightType) { mState = 0; + mPosition = Position; + mTargetPosition = TargetPosition; + mUpVector = lcVector3(0, 0, 1); + + if (IsAreaLight()) + { + lcVector3 FrontVector = lcNormalize(TargetPosition - Position), SideVector; + + if (FrontVector == mUpVector) + SideVector = lcVector3(1, 0, 0); + else + SideVector = lcCross(FrontVector, mUpVector); + + mUpVector = lcCross(SideVector, FrontVector); + mUpVector.Normalize(); + } + mPOVRayLight = false; mShadowless = false; mEnableCutoff = false; - mTargetPosition = TargetPosition; mAmbientColor = lcVector4(0.0f, 0.0f, 0.0f, 1.0f); mDiffuseColor = lcVector4(0.8f, 0.8f, 0.8f, 1.0f); mSpecularColor = lcVector4(1.0f, 1.0f, 1.0f, 1.0f); mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); - mLightColor = lcVector3(1.0f, 1.0f, 1.0f); /*RGB - White*/ + mLightColor = lcVector3(1.0f, 1.0f, 1.0f); mLightFactor[0] = LightType == lcLightType::Directional ? 11.4f : 0.25f; mLightFactor[1] = LightType == lcLightType::Area ? 0.25f : LightType == lcLightType::Spot ? 0.150f : 0.0f; mLightDiffuse = 1.0f; @@ -49,6 +65,7 @@ lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcL mPositionKeys.ChangeKey(mPosition, 1, true); mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); + mUpVectorKeys.ChangeKey(mUpVector, 1, true); mAmbientColorKeys.ChangeKey(mAmbientColor, 1, true); mDiffuseColorKeys.ChangeKey(mDiffuseColor, 1, true); mSpecularColorKeys.ChangeKey(mSpecularColor, 1, true); @@ -90,6 +107,14 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding; } + if (mLightType == lcLightType::Area) + { + if (mUpVectorKeys.GetSize() > 1) + mUpVectorKeys.SaveKeysLDraw(Stream, "LIGHT UP_VECTOR_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT UP_VECTOR ") << mUpVector[0] << ' ' << mUpVector[1] << ' ' << mUpVector[2] << LineEnding; + } + if (mLightColorKeys.GetSize() > 1) mLightColorKeys.SaveKeysLDraw(Stream, "LIGHT COLOR_RGB_KEY "); else @@ -295,7 +320,29 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) { QString Token; Stream >> Token; - if (Token == QLatin1String("COLOR_RGB")) + + if (Token == QLatin1String("POSITION")) + { + Stream >> mPosition[0] >> mPosition[1] >> mPosition[2]; + mPositionKeys.ChangeKey(mPosition, 1, true); + } + else if (Token == QLatin1String("TARGET_POSITION")) + { + Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; + mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); + } + else if (Token == QLatin1String("UP_VECTOR")) + { + Stream >> mUpVector[0] >> mUpVector[1] >> mUpVector[2]; + mUpVectorKeys.ChangeKey(mUpVector, 1, true); + } + else if (Token == QLatin1String("POSITION_KEY")) + mPositionKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("TARGET_POSITION_KEY")) + mTargetPositionKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("UP_VECTOR_KEY")) + mUpVectorKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("COLOR_RGB")) { Stream >> mLightColor[0] >> mLightColor[1] >> mLightColor[2]; mLightColorKeys.ChangeKey(mLightColor, 1, true); @@ -406,16 +453,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } } } - else if (Token == QLatin1String("POSITION")) - { - Stream >> mPosition[0] >> mPosition[1] >> mPosition[2]; - mPositionKeys.ChangeKey(mPosition, 1, true); - } - else if (Token == QLatin1String("TARGET_POSITION")) - { - Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; - mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); - } else if (Token == QLatin1String("POV_RAY")) { mPOVRayLight = true; @@ -701,6 +738,26 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const ObjectRayTest.Distance = Distance; ObjectRayTest.PieceInfoRayTest.Plane = Plane; } + + if (IsAreaLight()) + { + const lcMatrix44 LightWorld = lcMatrix44AffineInverse(mWorldLight); + const lcVector3 UpVectorPosition = lcMul31(lcVector3(0, 25, 0), LightWorld); + + lcMatrix44 WorldLight = mWorldLight; + WorldLight.SetTranslation(lcMul30(-UpVectorPosition, WorldLight)); + + Start = lcMul31(ObjectRayTest.Start, WorldLight); + End = lcMul31(ObjectRayTest.End, WorldLight); + + if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance)) + { + ObjectRayTest.ObjectSection.Object = const_cast(this); + ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_UPVECTOR; + ObjectRayTest.Distance = Distance; + ObjectRayTest.PieceInfoRayTest.Plane = Plane; + } + } } void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const @@ -764,12 +821,31 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance) mTargetPosition += Distance; mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey); } + else if (IsSelected(LC_LIGHT_SECTION_UPVECTOR)) + { + mUpVector += Distance; + mUpVector.Normalize(); + mUpVectorKeys.ChangeKey(mUpVector, Step, AddKey); + } + + if (IsAreaLight()) + { + const lcVector3 FrontVector(mTargetPosition - mPosition); + lcVector3 SideVector = lcCross(FrontVector, mUpVector); + + if (fabsf(lcDot(mUpVector, SideVector)) > 0.99f) + SideVector = lcVector3(1, 0, 0); + + mUpVector = lcCross(SideVector, FrontVector); + mUpVector.Normalize(); + } } void lcLight::InsertTime(lcStep Start, lcStep Time) { mPositionKeys.InsertTime(Start, Time); mTargetPositionKeys.InsertTime(Start, Time); + mUpVectorKeys.InsertTime(Start, Time); mAmbientColorKeys.InsertTime(Start, Time); mDiffuseColorKeys.InsertTime(Start, Time); mSpecularColorKeys.InsertTime(Start, Time); @@ -790,6 +866,7 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) { mPositionKeys.RemoveTime(Start, Time); mTargetPositionKeys.RemoveTime(Start, Time); + mUpVectorKeys.RemoveTime(Start, Time); mAmbientColorKeys.RemoveTime(Start, Time); mDiffuseColorKeys.RemoveTime(Start, Time); mSpecularColorKeys.RemoveTime(Start, Time); @@ -810,6 +887,7 @@ void lcLight::UpdatePosition(lcStep Step) { mPosition = mPositionKeys.CalculateKey(Step); mTargetPosition = mTargetPositionKeys.CalculateKey(Step); + mUpVector = mUpVectorKeys.CalculateKey(Step); mAmbientColor = mAmbientColorKeys.CalculateKey(Step); mDiffuseColor = mDiffuseColorKeys.CalculateKey(Step); mSpecularColor = mSpecularColorKeys.CalculateKey(Step); @@ -830,6 +908,14 @@ void lcLight::UpdatePosition(lcStep Step) mWorldLight = lcMatrix44Identity(); mWorldLight.SetTranslation(-mPosition); } + else if (IsAreaLight()) + { + lcVector3 FrontVector(mTargetPosition - mPosition); + const lcVector3 SideVector = lcCross(FrontVector, mUpVector); + mUpVector = lcNormalize(lcCross(SideVector, FrontVector)); + + mWorldLight = lcMatrix44LookAt(mPosition, mTargetPosition, mUpVector); + } else { lcVector3 FrontVector(mTargetPosition - mPosition); @@ -1025,6 +1111,63 @@ void lcLight::DrawAreaLight(lcContext* Context) const } DrawTarget(Context, TargetDistance); + + float Verts[10 * 3]; + float* CurVert = Verts; + + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE; + *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE; + *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE; + + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; + *CurVert++ = 0.0f; *CurVert++ = 25.0f; *CurVert++ = 0.0f; + + Context->SetVertexBufferPointer(Verts); + Context->SetVertexFormatPosition(3); + + const GLushort Indices[(12 + 1) * 2] = + { + 0, 1, 1, 2, 2, 3, 3, 0, + 4, 5, 5, 6, 6, 7, 7, 4, + 0, 4, 1, 5, 2, 6, 3, 7, + 8, 9 + }; + + Context->SetIndexBufferPointer(Indices); + + const lcPreferences& Preferences = lcGetPreferences(); + const float LineWidth = Preferences.mLineWidth; + const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); + + if (IsSelected(LC_LIGHT_SECTION_UPVECTOR)) + { + const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); + const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); + + Context->SetLineWidth(2.0f * LineWidth); + + if (IsFocused(LC_LIGHT_SECTION_UPVECTOR)) + Context->SetColor(FocusedColor); + else + Context->SetColor(SelectedColor); + } + else + { + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + } + + Context->DrawIndexedPrimitives(GL_LINES, 12 * 2, GL_UNSIGNED_SHORT, 0); + + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + + Context->DrawIndexedPrimitives(GL_LINES, 2, GL_UNSIGNED_SHORT, 12 * 2 * 2); } float lcLight::SetupLightMatrix(lcContext* Context) const @@ -1032,19 +1175,26 @@ float lcLight::SetupLightMatrix(lcContext* Context) const lcVector3 FrontVector(mTargetPosition - mPosition); lcVector3 UpVector(1, 1, 1); - if (fabs(FrontVector[0]) < fabs(FrontVector[1])) + if (IsAreaLight()) { - if (fabs(FrontVector[0]) < fabs(FrontVector[2])) - UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + UpVector = mUpVector; } else { - if (fabs(FrontVector[1]) < fabs(FrontVector[2])) - UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); + if (fabs(FrontVector[0]) < fabs(FrontVector[1])) + { + if (fabs(FrontVector[0]) < fabs(FrontVector[2])) + UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); + else + UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + } else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + { + if (fabs(FrontVector[1]) < fabs(FrontVector[2])) + UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); + else + UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); + } } lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); @@ -1302,6 +1452,9 @@ void lcLight::RemoveKeyFrames() mTargetPositionKeys.RemoveAll(); mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); + mUpVectorKeys.RemoveAll(); + mUpVectorKeys.ChangeKey(mUpVector, 1, true); + mAmbientColorKeys.RemoveAll(); mAmbientColorKeys.ChangeKey(mAmbientColor, 1, true); diff --git a/common/light.h b/common/light.h index 23c56300..7acf79d0 100644 --- a/common/light.h +++ b/common/light.h @@ -9,14 +9,17 @@ #define LC_LIGHT_POSITION_FOCUSED 0x0020 #define LC_LIGHT_TARGET_SELECTED 0x0040 #define LC_LIGHT_TARGET_FOCUSED 0x0080 +#define LC_LIGHT_UPVECTOR_SELECTED 0x0100 +#define LC_LIGHT_UPVECTOR_FOCUSED 0x0200 -#define LC_LIGHT_SELECTION_MASK (LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED) -#define LC_LIGHT_FOCUS_MASK (LC_LIGHT_POSITION_FOCUSED | LC_LIGHT_TARGET_FOCUSED) +#define LC_LIGHT_SELECTION_MASK (LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED | LC_LIGHT_UPVECTOR_SELECTED) +#define LC_LIGHT_FOCUS_MASK (LC_LIGHT_POSITION_FOCUSED | LC_LIGHT_TARGET_FOCUSED | LC_LIGHT_UPVECTOR_FOCUSED) enum lcLightSection { LC_LIGHT_SECTION_POSITION, - LC_LIGHT_SECTION_TARGET + LC_LIGHT_SECTION_TARGET, + LC_LIGHT_SECTION_UPVECTOR }; enum class lcLightType @@ -90,11 +93,21 @@ class lcLight : public lcObject return mLightType == lcLightType::Point; } + bool IsSpotlight() const + { + return mLightType == lcLightType::Spot; + } + bool IsDirectionalLight() const { return mLightType == lcLightType::Directional; } + bool IsAreaLight() const + { + return mLightType == lcLightType::Area; + } + lcLightType GetLightType() const { return mLightType; @@ -121,6 +134,10 @@ class lcLight : public lcObject case LC_LIGHT_SECTION_TARGET: return (mState & LC_LIGHT_TARGET_SELECTED) != 0; break; + + case LC_LIGHT_SECTION_UPVECTOR: + return (mState & LC_LIGHT_UPVECTOR_SELECTED) != 0; + break; } return false; } @@ -158,6 +175,16 @@ class lcLight : public lcObject else mState &= ~(LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED); break; + + case LC_LIGHT_SECTION_UPVECTOR: + if (Selected) + { + if (!IsPointLight()) + mState |= LC_LIGHT_UPVECTOR_SELECTED; + } + else + mState &= ~(LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED); + break; } } @@ -177,7 +204,12 @@ class lcLight : public lcObject case LC_LIGHT_SECTION_TARGET: return (mState & LC_LIGHT_TARGET_FOCUSED) != 0; break; + + case LC_LIGHT_SECTION_UPVECTOR: + return (mState & LC_LIGHT_UPVECTOR_FOCUSED) != 0; + break; } + return false; } @@ -201,6 +233,16 @@ class lcLight : public lcObject else mState &= ~(LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED); break; + + case LC_LIGHT_SECTION_UPVECTOR: + if (Focused) + { + if (!IsPointLight()) + mState |= LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED; + } + else + mState &= ~(LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED); + break; } } @@ -212,6 +254,9 @@ class lcLight : public lcObject if (!IsPointLight() && (mState & LC_LIGHT_TARGET_FOCUSED)) return LC_LIGHT_SECTION_TARGET; + if (IsAreaLight() && (mState & LC_LIGHT_UPVECTOR_FOCUSED)) + return LC_LIGHT_SECTION_UPVECTOR; + return ~0U; } @@ -229,6 +274,9 @@ class lcLight : public lcObject case LC_LIGHT_SECTION_TARGET: return mTargetPosition; + + case LC_LIGHT_SECTION_UPVECTOR: + return lcMul31(lcVector3(0, 25, 0), lcMatrix44AffineInverse(mWorldLight)); } return lcVector3(0.0f, 0.0f, 0.0f); @@ -288,6 +336,8 @@ class lcLight : public lcObject lcMatrix44 mWorldLight; lcVector3 mPosition; lcVector3 mTargetPosition; + lcVector3 mUpVector; + lcVector4 mAmbientColor; lcVector4 mDiffuseColor; lcVector4 mSpecularColor; @@ -316,6 +366,8 @@ class lcLight : public lcObject protected: lcObjectKeyArray mPositionKeys; lcObjectKeyArray mTargetPositionKeys; + lcObjectKeyArray mUpVectorKeys; + lcObjectKeyArray mAmbientColorKeys; lcObjectKeyArray mDiffuseColorKeys; lcObjectKeyArray mSpecularColorKeys; From 4e09ceaf7d79cca3591a5c993967f1560ae54952 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 27 Aug 2023 10:19:07 -0700 Subject: [PATCH 22/42] Fixed light selection checks. --- common/light.h | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/common/light.h b/common/light.h index 7acf79d0..8f484840 100644 --- a/common/light.h +++ b/common/light.h @@ -146,10 +146,21 @@ class lcLight : public lcObject { if (Selected) { - if (IsPointLight()) + switch (mLightType) + { + case lcLightType::Point: mState |= LC_LIGHT_POSITION_SELECTED; - else - mState |= LC_LIGHT_SELECTION_MASK; + break; + + case lcLightType::Spot: + case lcLightType::Directional: + mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED; + break; + + case lcLightType::Area: + mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED | LC_LIGHT_UPVECTOR_SELECTED; + break; + } } else mState &= ~(LC_LIGHT_SELECTION_MASK | LC_LIGHT_FOCUS_MASK); @@ -179,7 +190,7 @@ class lcLight : public lcObject case LC_LIGHT_SECTION_UPVECTOR: if (Selected) { - if (!IsPointLight()) + if (IsAreaLight()) mState |= LC_LIGHT_UPVECTOR_SELECTED; } else @@ -237,7 +248,7 @@ class lcLight : public lcObject case LC_LIGHT_SECTION_UPVECTOR: if (Focused) { - if (!IsPointLight()) + if (IsAreaLight()) mState |= LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED; } else From 9d60160f6a84d5b1c23f3e18715d82fba31b18cd Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 27 Aug 2023 11:17:07 -0700 Subject: [PATCH 23/42] Consolidated light color properties. --- common/lc_math.h | 10 +++ common/lc_model.cpp | 13 ++++ common/lc_model.h | 2 + common/light.cpp | 71 +++++++------------ common/light.h | 25 +++---- common/project.cpp | 2 +- qt/lc_qpropertiestree.cpp | 144 ++++++++++++++++++++------------------ qt/lc_qpropertiestree.h | 8 +-- 8 files changed, 140 insertions(+), 135 deletions(-) diff --git a/common/lc_math.h b/common/lc_math.h index 4fcb0d4b..4e2e7090 100644 --- a/common/lc_math.h +++ b/common/lc_math.h @@ -649,6 +649,11 @@ inline lcVector3 lcVector3FromColor(quint32 Color) return v; } +inline lcVector3 lcVector3FromQColor(QColor Color) +{ + return lcVector3(Color.redF(), Color.greenF(), Color.blueF()); +} + inline lcVector4 lcVector4FromColor(quint32 Color) { lcVector4 v(LC_RGBA_RED(Color), LC_RGBA_GREEN(Color), LC_RGBA_BLUE(Color), LC_RGBA_ALPHA(Color)); @@ -661,6 +666,11 @@ inline quint32 lcColorFromVector3(const lcVector3& Color) return LC_RGB(roundf(Color[0] * 255), roundf(Color[1] * 255), roundf(Color[2] * 255)); } +inline QColor lcQColorFromVector3(const lcVector3& Color) +{ + return QColor::fromRgb(roundf(Color[0] * 255), roundf(Color[1] * 255), roundf(Color[2] * 255)); +} + inline float lcLuminescence(const lcVector3& Color) { return 0.2126f * Color[0] + 0.7152f * Color[1] + 0.0722f * Color[2]; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 65ea2c61..b66e03df 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3113,6 +3113,19 @@ void lcModel::SetCameraName(lcCamera* Camera, const QString& Name) gMainWindow->UpdateCameraMenu(); } +void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color) +{ + if (Light->GetColor() == Color) + return; + + Light->SetColor(Color, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Light Color")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetLightName(lcLight* Light, const QString &Name) { if (Light->GetName() == Name) diff --git a/common/lc_model.h b/common/lc_model.h index 4973b078..08da54b2 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -367,6 +367,8 @@ class lcModel void SetCameraZNear(lcCamera* Camera, float ZNear); void SetCameraZFar(lcCamera* Camera, float ZFar); void SetCameraName(lcCamera* Camera, const QString& Name); + + void SetLightColor(lcLight* Light, const lcVector3& Color); void SetLightName(lcLight* Light, const QString& Name); void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); diff --git a/common/light.cpp b/common/light.cpp index 5a9aa9c3..ece6c5b5 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -44,11 +44,8 @@ lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcL mPOVRayLight = false; mShadowless = false; mEnableCutoff = false; - mAmbientColor = lcVector4(0.0f, 0.0f, 0.0f, 1.0f); - mDiffuseColor = lcVector4(0.8f, 0.8f, 0.8f, 1.0f); - mSpecularColor = lcVector4(1.0f, 1.0f, 1.0f, 1.0f); + mColor = lcVector3(1.0f, 1.0f, 1.0f); mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); - mLightColor = lcVector3(1.0f, 1.0f, 1.0f); mLightFactor[0] = LightType == lcLightType::Directional ? 11.4f : 0.25f; mLightFactor[1] = LightType == lcLightType::Area ? 0.25f : LightType == lcLightType::Spot ? 0.150f : 0.0f; mLightDiffuse = 1.0f; @@ -66,11 +63,8 @@ lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcL mPositionKeys.ChangeKey(mPosition, 1, true); mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); mUpVectorKeys.ChangeKey(mUpVector, 1, true); - mAmbientColorKeys.ChangeKey(mAmbientColor, 1, true); - mDiffuseColorKeys.ChangeKey(mDiffuseColor, 1, true); - mSpecularColorKeys.ChangeKey(mSpecularColor, 1, true); + mColorKeys.ChangeKey(mColor, 1, true); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); - mLightColorKeys.ChangeKey(mLightColor, 1, true); mLightFactorKeys.ChangeKey(mLightFactor, 1, true); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); @@ -115,10 +109,10 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT UP_VECTOR ") << mUpVector[0] << ' ' << mUpVector[1] << ' ' << mUpVector[2] << LineEnding; } - if (mLightColorKeys.GetSize() > 1) - mLightColorKeys.SaveKeysLDraw(Stream, "LIGHT COLOR_RGB_KEY "); + if (mColorKeys.GetSize() > 1) + mColorKeys.SaveKeysLDraw(Stream, "LIGHT COLOR_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT COLOR_RGB ") << mLightColor[0] << ' ' << mLightColor[1] << ' ' << mLightColor[2] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT COLOR ") << mColor[0] << ' ' << mColor[1] << ' ' << mColor[2] << LineEnding; if (!mPOVRayLight) { @@ -326,27 +320,29 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) Stream >> mPosition[0] >> mPosition[1] >> mPosition[2]; mPositionKeys.ChangeKey(mPosition, 1, true); } + else if (Token == QLatin1String("POSITION_KEY")) + mPositionKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("TARGET_POSITION")) { Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); } + else if (Token == QLatin1String("TARGET_POSITION_KEY")) + mTargetPositionKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("UP_VECTOR")) { Stream >> mUpVector[0] >> mUpVector[1] >> mUpVector[2]; mUpVectorKeys.ChangeKey(mUpVector, 1, true); } - else if (Token == QLatin1String("POSITION_KEY")) - mPositionKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("TARGET_POSITION_KEY")) - mTargetPositionKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("UP_VECTOR_KEY")) mUpVectorKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("COLOR_RGB")) + else if (Token == QLatin1String("COLOR")) { - Stream >> mLightColor[0] >> mLightColor[1] >> mLightColor[2]; - mLightColorKeys.ChangeKey(mLightColor, 1, true); + Stream >> mColor[0] >> mColor[1] >> mColor[2]; + mColorKeys.ChangeKey(mColor, 1, true); } + else if (Token == QLatin1String("COLOR_KEY")) + mColorKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) { if (mPOVRayLight) @@ -461,8 +457,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) { mShadowless = true; } - else if (Token == QLatin1String("COLOR_RGB_KEY")) - mLightColorKeys.LoadKeysLDraw(Stream); else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) mSpotExponentKeys.LoadKeysLDraw(Stream); else if ((Token == QLatin1String("ANGLE_KEY")) || (Token == QLatin1String("RADIUS_KEY")) || (Token == QLatin1String("SIZE_KEY")) || (Token == QLatin1String("RADIUS_AND_SPOT_BLEND_KEY"))) @@ -562,10 +556,6 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) case LC_LIGHT_SHAPE: mLightShape = Props.mLightShape; break; - case LC_LIGHT_COLOR: - mLightColor = Props.mLightColor; - mLightColorKeys.ChangeKey(mLightColor, Step, false); - break; case LC_LIGHT_FACTOR: if (Props.mPOVRayLight && mLightType == lcLightType::Area) { @@ -841,16 +831,18 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance) } } +void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey) +{ + mColorKeys.ChangeKey(Color, Step, AddKey); +} + void lcLight::InsertTime(lcStep Start, lcStep Time) { mPositionKeys.InsertTime(Start, Time); mTargetPositionKeys.InsertTime(Start, Time); mUpVectorKeys.InsertTime(Start, Time); - mAmbientColorKeys.InsertTime(Start, Time); - mDiffuseColorKeys.InsertTime(Start, Time); - mSpecularColorKeys.InsertTime(Start, Time); + mColorKeys.InsertTime(Start, Time); mAttenuationKeys.InsertTime(Start, Time); - mLightColorKeys.InsertTime(Start, Time); mLightFactorKeys.InsertTime(Start, Time); mLightDiffuseKeys.InsertTime(Start, Time); mLightSpecularKeys.InsertTime(Start, Time); @@ -867,11 +859,8 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mPositionKeys.RemoveTime(Start, Time); mTargetPositionKeys.RemoveTime(Start, Time); mUpVectorKeys.RemoveTime(Start, Time); - mAmbientColorKeys.RemoveTime(Start, Time); - mDiffuseColorKeys.RemoveTime(Start, Time); - mSpecularColorKeys.RemoveTime(Start, Time); + mColorKeys.RemoveTime(Start, Time); mAttenuationKeys.RemoveTime(Start, Time); - mLightColorKeys.RemoveTime(Start, Time); mLightFactorKeys.RemoveTime(Start, Time); mLightDiffuseKeys.RemoveTime(Start, Time); mLightSpecularKeys.RemoveTime(Start, Time); @@ -888,11 +877,8 @@ void lcLight::UpdatePosition(lcStep Step) mPosition = mPositionKeys.CalculateKey(Step); mTargetPosition = mTargetPositionKeys.CalculateKey(Step); mUpVector = mUpVectorKeys.CalculateKey(Step); - mAmbientColor = mAmbientColorKeys.CalculateKey(Step); - mDiffuseColor = mDiffuseColorKeys.CalculateKey(Step); - mSpecularColor = mSpecularColorKeys.CalculateKey(Step); + mColor = mColorKeys.CalculateKey(Step); mAttenuation = mAttenuationKeys.CalculateKey(Step); - mLightColor = mLightColorKeys.CalculateKey(Step); mLightFactor = mLightFactorKeys.CalculateKey(Step); mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); mLightSpecular = mLightSpecularKeys.CalculateKey(Step); @@ -1455,21 +1441,12 @@ void lcLight::RemoveKeyFrames() mUpVectorKeys.RemoveAll(); mUpVectorKeys.ChangeKey(mUpVector, 1, true); - mAmbientColorKeys.RemoveAll(); - mAmbientColorKeys.ChangeKey(mAmbientColor, 1, true); - - mDiffuseColorKeys.RemoveAll(); - mDiffuseColorKeys.ChangeKey(mDiffuseColor, 1, true); - - mSpecularColorKeys.RemoveAll(); - mSpecularColorKeys.ChangeKey(mSpecularColor, 1, true); + mColorKeys.RemoveAll(); + mColorKeys.ChangeKey(mColor, 1, true); mAttenuationKeys.RemoveAll(); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); - mLightColorKeys.RemoveAll(); - mLightColorKeys.ChangeKey(mLightColor, 1, true); - mLightFactorKeys.RemoveAll(); mLightFactorKeys.ChangeKey(mLightFactor, 1, true); diff --git a/common/light.h b/common/light.h index 8f484840..e1d021ec 100644 --- a/common/light.h +++ b/common/light.h @@ -43,7 +43,6 @@ enum lcLightProperty { LC_LIGHT_NONE, LC_LIGHT_SHAPE, - LC_LIGHT_COLOR, LC_LIGHT_TYPE, LC_LIGHT_FACTOR, LC_LIGHT_DIFFUSE, @@ -61,7 +60,6 @@ enum lcLightProperty struct lcLightProperties { - lcVector3 mLightColor; lcVector2 mLightFactor; lcVector2 mAreaGrid; float mLightDiffuse; @@ -306,7 +304,16 @@ class lcLight : public lcObject void RemoveTime(lcStep Start, lcStep Time); bool IsVisible() const - { return (mState & LC_LIGHT_HIDDEN) == 0; } + { + return (mState & LC_LIGHT_HIDDEN) == 0; + } + + void SetColor(const lcVector3& Color, lcStep Step, bool AddKey); + + lcVector3 GetColor() const + { + return mColor; + } void SetName(const QString& Name) { @@ -327,7 +334,6 @@ class lcLight : public lcObject lcLightProperties GetLightProperties() const { lcLightProperties props; - props.mLightColor = mLightColor; props.mLightFactor = mLightFactor; props.mLightDiffuse = mLightDiffuse; props.mLightSpecular = mLightSpecular; @@ -349,11 +355,7 @@ class lcLight : public lcObject lcVector3 mTargetPosition; lcVector3 mUpVector; - lcVector4 mAmbientColor; - lcVector4 mDiffuseColor; - lcVector4 mSpecularColor; lcVector3 mAttenuation; - lcVector3 mLightColor; lcVector2 mLightFactor; lcVector2 mAreaGrid; lcVector2 mAreaSize; @@ -375,15 +377,14 @@ class lcLight : public lcObject QString mName; protected: + lcVector3 mColor; + lcObjectKeyArray mPositionKeys; lcObjectKeyArray mTargetPositionKeys; lcObjectKeyArray mUpVectorKeys; + lcObjectKeyArray mColorKeys; - lcObjectKeyArray mAmbientColorKeys; - lcObjectKeyArray mDiffuseColorKeys; - lcObjectKeyArray mSpecularColorKeys; lcObjectKeyArray mAttenuationKeys; - lcObjectKeyArray mLightColorKeys; lcObjectKeyArray mLightFactorKeys; lcObjectKeyArray mAreaGridKeys; lcObjectKeyArray mLightSpecularKeys; diff --git a/common/project.cpp b/common/project.cpp index fd46faa0..ef93266e 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2175,7 +2175,7 @@ bool Project::ExportPOVRay(const QString& FileName) const QString LightName = QString(Light->mName).replace(" ","_"); LightType = Light->GetLightType(); Shadowless = static_cast(Light->mShadowless); - LightColor = Light->mLightColor; + LightColor = Light->GetColor(); Power = Light->mPOVRayExponent; switch(LightType) { diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index dfb025ac..4e3ff1dd 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -222,9 +222,9 @@ lcQPropertiesTree::lcQPropertiesTree(QWidget *parent) : m_checkedIcon = drawCheckBox(true); m_uncheckedIcon = drawCheckBox(false); - m_delegate = new lcQPropertiesTreeDelegate(parent); - m_delegate->setTreeWidget(this); - setItemDelegate(m_delegate); + mDelegate = new lcQPropertiesTreeDelegate(parent); + mDelegate->setTreeWidget(this); + setItemDelegate(mDelegate); SetEmpty(); @@ -264,7 +264,7 @@ void lcQPropertiesTree::keyPressEvent(QKeyEvent *event) case Qt::Key_Return: case Qt::Key_Enter: case Qt::Key_Space: // Trigger Edit - if (!m_delegate->editedItem()) + if (!mDelegate->editedItem()) { if (const QTreeWidgetItem *item = currentItem()) { @@ -299,7 +299,7 @@ void lcQPropertiesTree::mousePressEvent(QMouseEvent *event) if (item) { - if ((item != m_delegate->editedItem()) && (event->button() == Qt::LeftButton) && (header()->logicalIndexAt(event->pos().x()) == 1) && + if ((item != mDelegate->editedItem()) && (event->button() == Qt::LeftButton) && (header()->logicalIndexAt(event->pos().x()) == 1) && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) editItem(item, 1); } @@ -567,14 +567,14 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyLightColor: { - QPushButton *editor = new QPushButton(parent); - QColor value = item->data(0, PropertyValueRole).value(); + QPushButton *Editor = new QPushButton(parent); + QColor Value = item->data(0, PropertyValueRole).value(); - updateLightColorEditor(editor, value); + UpdateLightColorEditor(Editor, Value); - connect(editor, SIGNAL(clicked()), this, SLOT(slotColorButtonClicked())); + connect(Editor, &QPushButton::clicked, this, &lcQPropertiesTree::LightColorButtonClicked); - return editor; + return Editor; } case PropertyColor: @@ -649,26 +649,26 @@ void lcQPropertiesTree::updateColorEditor(QPushButton *editor, int value) const editor->setText(color->Name); } -void lcQPropertiesTree::updateLightColorEditor(QPushButton *editor, QColor color) const +void lcQPropertiesTree::UpdateLightColorEditor(QPushButton* Editor, QColor Color) const { - QImage img(12, 12, QImage::Format_ARGB32); - img.fill(0); - - QPainter painter(&img); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.setPen(Qt::darkGray); - painter.setBrush(color); - painter.drawRect(0, 0, img.width() - 1, img.height() - 1); - painter.end(); - - editor->setStyleSheet("Text-align:left"); - editor->setIcon(QPixmap::fromImage(img)); - editor->setText(color.name().toUpper()); + QImage Image(12, 12, QImage::Format_ARGB32); + Image.fill(0); + + QPainter Painter(&Image); + Painter.setCompositionMode(QPainter::CompositionMode_Source); + Painter.setPen(Qt::darkGray); + Painter.setBrush(Color); + Painter.drawRect(0, 0, Image.width() - 1, Image.height() - 1); + Painter.end(); + + Editor->setStyleSheet("Text-align:left"); + Editor->setIcon(QPixmap::fromImage(Image)); + Editor->setText(Color.name().toUpper()); } void lcQPropertiesTree::slotToggled(bool Value) { - QTreeWidgetItem* Item = m_delegate->editedItem(); + QTreeWidgetItem* Item = mDelegate->editedItem(); lcModel* Model = gMainWindow->GetActiveModel(); lcObject* Focus = Model->GetFocusObject(); @@ -708,7 +708,7 @@ void lcQPropertiesTree::slotToggled(bool Value) void lcQPropertiesTree::slotReturnPressed() { QLineEdit* Editor = (QLineEdit*)sender(); - QTreeWidgetItem* Item = m_delegate->editedItem(); + QTreeWidgetItem* Item = mDelegate->editedItem(); lcModel* Model = gMainWindow->GetActiveModel(); if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE) @@ -905,15 +905,17 @@ void lcQPropertiesTree::slotReturnPressed() } else if (Item == lightColorR || Item == lightColorG || Item == lightColorB) { + lcVector3 Color = Light->GetColor(); float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightColorR) - Props.mLightColor[0] = Value; + Color[0] = Value; else if (Item == lightColorG) - Props.mLightColor[2] = Value; + Color[2] = Value; else if (Item == lightColorB) - Props.mLightColor[1] = Value; + Color[1] = Value; - Model->UpdateLight(Light, Props, LC_LIGHT_COLOR); + Model->SetLightColor(Light, Color); } else if (Item == lightFactorA || Item == lightFactorB) { @@ -991,7 +993,7 @@ void lcQPropertiesTree::slotReturnPressed() void lcQPropertiesTree::slotSetValue(int Value) { - QTreeWidgetItem* Item = m_delegate->editedItem(); + QTreeWidgetItem* Item = mDelegate->editedItem(); lcModel* Model = gMainWindow->GetActiveModel(); if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE) @@ -1000,7 +1002,7 @@ void lcQPropertiesTree::slotSetValue(int Value) { Model->SetSelectedPiecesColorIndex(Value); - QPushButton *editor = (QPushButton*)m_delegate->editor(); + QPushButton *editor = (QPushButton*)mDelegate->editor(); updateColorEditor(editor, Value); } else if (Item == partID) @@ -1041,24 +1043,6 @@ void lcQPropertiesTree::slotSetValue(int Value) } } -void lcQPropertiesTree::slotSetColorValue(QColor Value) -{ - lcModel* Model = gMainWindow->GetActiveModel(); - lcObject* Focus = Model->GetFocusObject(); - lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; - if (Light) - { - float r = Value.red(); - float g = Value.green(); - float b = Value.blue(); - lcVector3 Color(r/255, g/255, b/255); - - lcLightProperties Props = Light->GetLightProperties(); - Props.mLightColor = Color; - Model->UpdateLight(Light, Props, LC_LIGHT_COLOR); - } -} - void lcQPropertiesTree::slotColorButtonClicked() { int ColorIndex = gDefaultColor; @@ -1104,6 +1088,28 @@ void lcQPropertiesTree::slotColorButtonClicked() Popup->show(); } +void lcQPropertiesTree::LightColorButtonClicked() +{ + lcModel* Model = gMainWindow->GetActiveModel(); + lcObject* Focus = Model->GetFocusObject(); + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; + + if (!Light) + return; + + QColor Color = QColorDialog::getColor(lcQColorFromVector3(Light->GetColor()), this, tr("Select Light Color")); + + if (!Color.isValid()) + return; + + Model->SetLightColor(Light, lcVector3FromQColor(Color)); + + QPushButton* Editor = qobject_cast(mDelegate->editor()); + + if (Editor) + UpdateLightColorEditor(Editor, Color); +} + QTreeWidgetItem *lcQPropertiesTree::addProperty(QTreeWidgetItem *parent, const QString& label, PropertyType propertyType) { QTreeWidgetItem *newItem; @@ -1452,7 +1458,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) PropertyType SpotSizeProperty = PropertyFloatLightSpotSize; lcVector3 Position(0.0f, 0.0f, 0.0f); lcVector3 Target(0.0f, 0.0f, 0.0f); - lcVector3 Color(0.0f, 0.0f, 0.0f); + QColor Color(Qt::white); lcVector2 Factor(0.0f, 0.0f); lcVector2 AreaGrid(0.0f, 0.0f); @@ -1467,7 +1473,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Shadowless = Light->mShadowless; Position = Light->mPosition; Target = Light->mTargetPosition; - Color = Light->mLightColor; + Color = lcQColorFromVector3(Light->GetColor()); Factor = Light->mLightFactor; LightType = Light->GetLightType(); @@ -1594,9 +1600,9 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightTargetZ = addProperty(lightTarget, tr("Z"), TargetProperty); } - // Light Colour + // Light Color lightColor = addProperty(nullptr, tr("Color"), PropertyGroup); - lightColorIcon = addProperty(lightColor, tr("Name"), PropertyLightColor); + lightColorIcon = addProperty(lightColor, tr("Value"), PropertyLightColor); lightColorR = addProperty(lightColor, tr("Red"), PropertyFloat); lightColorG = addProperty(lightColor, tr("Green"), PropertyFloat); lightColorB = addProperty(lightColor, tr("Blue"), PropertyFloat); @@ -1679,30 +1685,28 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightTargetZ->setData(0, PropertyValueRole, Target[2]); } - QImage img(16, 16, QImage::Format_ARGB32); - img.fill(0); - - QColor RgbColor = QColor::fromRgb(int(Color[1]*255), int(Color[1]*255), int(Color[2]*255)); + QImage ColorImage(16, 16, QImage::Format_ARGB32); + ColorImage.fill(0); - QPainter painter(&img); + QPainter painter(&ColorImage); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.setPen(Qt::darkGray); - painter.setBrush(RgbColor); - painter.drawRect(0, 0, img.width() - 1, img.height() - 1); + painter.setBrush(Color); + painter.drawRect(0, 0, ColorImage.width() - 1, ColorImage.height() - 1); painter.end(); - lightColorIcon->setIcon(1, QIcon(QPixmap::fromImage(img))); - lightColorIcon->setText(1, RgbColor.name().toUpper()); - lightColorIcon->setData(0, PropertyValueRole, RgbColor); + lightColorIcon->setIcon(1, QIcon(QPixmap::fromImage(ColorImage))); + lightColorIcon->setText(1, Color.name().toUpper()); + lightColorIcon->setData(0, PropertyValueRole, Color); - lightColorR->setText(1, lcFormatValueLocalized(Color[0])); - lightColorR->setData(0, PropertyValueRole, Color[0]); + lightColorR->setText(1, lcFormatValueLocalized(Color.redF())); + lightColorR->setData(0, PropertyValueRole, Color.redF()); lightColorR->setToolTip(1, tr("Red color using 0 to 1 decimal.")); - lightColorG->setText(1, lcFormatValueLocalized(Color[1])); - lightColorG->setData(0, PropertyValueRole, Color[1]); + lightColorG->setText(1, lcFormatValueLocalized(Color.greenF())); + lightColorG->setData(0, PropertyValueRole, Color.greenF()); lightColorG->setToolTip(1, tr("Green color using 0 to 1 decimal.")); - lightColorB->setText(1, lcFormatValueLocalized(Color[2])); - lightColorB->setData(0, PropertyValueRole, Color[2]); + lightColorB->setText(1, lcFormatValueLocalized(Color.blueF())); + lightColorB->setData(0, PropertyValueRole, Color.blueF()); lightColorB->setToolTip(1, tr("Blue color using 0 to 1 decimal.")); lightFormat->setText(1, Format); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 9c68e3e6..76727b47 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -62,14 +62,14 @@ protected slots: void slotReturnPressed(); void slotSetValue(int value); void slotColorButtonClicked(); - void slotSetColorValue(QColor Value); + void LightColorButtonClicked(); protected: void keyPressEvent(QKeyEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void updateColorEditor(QPushButton *editor, int value) const; - void updateLightColorEditor(QPushButton *editor, QColor color) const; + void UpdateLightColorEditor(QPushButton* Editor, QColor Color) const; QTreeWidgetItem *addProperty(QTreeWidgetItem *parent, const QString& label, PropertyType propertyType); @@ -79,8 +79,6 @@ protected slots: void SetLight(lcObject* Focus); void SetMultiple(); - void getPartProperties(lcPartProperties *properties); - lcLightType mLightType; int mLightShape; bool mPOVRayLight; @@ -88,7 +86,7 @@ protected slots: lcPropertyWidgetMode mWidgetMode; lcObject* mFocus; - lcQPropertiesTreeDelegate *m_delegate; + lcQPropertiesTreeDelegate* mDelegate; QIcon m_expandIcon; QIcon m_checkedIcon; QIcon m_uncheckedIcon; From 7d289f2cfe3d59c0c7801fe78d065f9e8120bd32 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 1 Sep 2023 20:46:29 -0700 Subject: [PATCH 24/42] Made light type editable. --- common/lc_model.cpp | 13 ++++++++++ common/lc_model.h | 1 + common/light.cpp | 52 ++++++++++++++++++++++++++++++++++++--- common/light.h | 10 +++++++- qt/lc_qpropertiestree.cpp | 40 +++++++++++++++++++----------- qt/lc_qpropertiestree.h | 4 +-- 6 files changed, 99 insertions(+), 21 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index b66e03df..8dee6032 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3113,6 +3113,16 @@ void lcModel::SetCameraName(lcCamera* Camera, const QString& Name) gMainWindow->UpdateCameraMenu(); } +void lcModel::SetLightType(lcLight* Light, lcLightType LightType) +{ + Light->SetLightType(LightType); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Light Type")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color) { if (Light->GetColor() == Color) @@ -4190,6 +4200,9 @@ void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVecto case lcLightType::Area: SaveCheckpoint(tr("New Area Light")); break; + + case lcLightType::Count: + break; } } diff --git a/common/lc_model.h b/common/lc_model.h index 08da54b2..e853d91d 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -368,6 +368,7 @@ class lcModel void SetCameraZFar(lcCamera* Camera, float ZFar); void SetCameraName(lcCamera* Camera, const QString& Name); + void SetLightType(lcLight* Light, lcLightType LightType); void SetLightColor(lcLight* Light, const lcVector3& Color); void SetLightName(lcLight* Light, const QString& Name); void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); diff --git a/common/light.cpp b/common/light.cpp index ece6c5b5..bfb1367b 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -17,7 +17,7 @@ #define LC_LIGHT_POSITION_EDGE 7.5f -static const std::array gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") }; +static const std::array(lcLightType::Count)> gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") }; lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcLightType LightType) : lcObject(lcObjectType::Light), mLightType(LightType) @@ -78,6 +78,29 @@ lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcL UpdatePosition(1); } +QString lcLight::GetLightTypeString(lcLightType LightType) +{ + switch (LightType) + { + case lcLightType::Point: + return QT_TRANSLATE_NOOP("Light Names", "Point Light"); + + case lcLightType::Spot: + return QT_TRANSLATE_NOOP("Light Names", "Spotlight"); + + case lcLightType::Directional: + return QT_TRANSLATE_NOOP("Light Names", "Directional Light"); + + case lcLightType::Area: + return QT_TRANSLATE_NOOP("Light Names", "Area Light"); + + case lcLightType::Count: + break; + } + + return QString(); +} + void lcLight::SaveLDraw(QTextStream& Stream) const { const QLatin1String LineEnding("\r\n"); @@ -142,6 +165,9 @@ void lcLight::SaveLDraw(QTextStream& Stream) const switch (mLightType) { + case lcLightType::Count: + break; + case lcLightType::Point: if (!mPOVRayLight) { @@ -225,6 +251,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE "); QString Shape = QLatin1String("UNDEFINED "); + switch (mLightShape) { case LC_LIGHT_SHAPE_SQUARE: @@ -275,7 +302,7 @@ void lcLight::CreateName(const lcArray& Lights) switch (mLightType) { case lcLightType::Point: - Prefix = QLatin1String("Pointlight "); + Prefix = QLatin1String("Point Light "); break; case lcLightType::Spot: @@ -283,11 +310,14 @@ void lcLight::CreateName(const lcArray& Lights) break; case lcLightType::Directional: - Prefix = QLatin1String("Directionallight "); + Prefix = QLatin1String("Directional Light "); break; case lcLightType::Area: - Prefix = QLatin1String("Arealight "); + Prefix = QLatin1String("Area Light "); + break; + + case lcLightType::Count: break; } @@ -522,6 +552,9 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } } break; + + case lcLightType::Count: + break; } return true; @@ -831,6 +864,14 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance) } } +void lcLight::SetLightType(lcLightType LightType) +{ + if (static_cast(LightType) < 0 || LightType >= lcLightType::Count) + return; + + mLightType = LightType; +} + void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey) { mColorKeys.ChangeKey(Color, Step, AddKey); @@ -948,6 +989,9 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const case lcLightType::Area: DrawAreaLight(Context); break; + + case lcLightType::Count: + break; } } diff --git a/common/light.h b/common/light.h index e1d021ec..3f209f75 100644 --- a/common/light.h +++ b/common/light.h @@ -27,7 +27,8 @@ enum class lcLightType Point, Spot, Directional, - Area + Area, + Count }; enum lcLightShape @@ -86,6 +87,8 @@ class lcLight : public lcObject lcLight& operator=(const lcLight&) = delete; lcLight& operator=(lcLight&&) = delete; + static QString GetLightTypeString(lcLightType LightType); + bool IsPointLight() const { return mLightType == lcLightType::Point; @@ -111,6 +114,8 @@ class lcLight : public lcObject return mLightType; } + void SetLightType(lcLightType LightType); + int GetLightShape() const { return mLightShape; @@ -158,6 +163,9 @@ class lcLight : public lcObject case lcLightType::Area: mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED | LC_LIGHT_UPVECTOR_SELECTED; break; + + case lcLightType::Count: + break; } } else diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 4e3ff1dd..a06f3276 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -524,8 +524,21 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return editor; } - case PropertyStringLightReadOnly: - return nullptr; + case PropertyStringList: + { + QComboBox* editor = new QComboBox(parent); + + if (item == mLightTypeItem) + for (int LightTypeIndex = 0; LightTypeIndex < static_cast(lcLightType::Count); LightTypeIndex++) + editor->addItem(lcLight::GetLightTypeString(static_cast(LightTypeIndex))); + + int value = item->data(0, PropertyValueRole).toInt(); + editor->setCurrentIndex(value); + + connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); + + return editor; + } case PropertyLightFormat: { @@ -1023,13 +1036,17 @@ void lcQPropertiesTree::slotSetValue(int Value) else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) { lcObject* Focus = Model->GetFocusObject(); - lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; if (Light) { lcLightProperties Props = Light->GetLightProperties(); - if (Item == lightShape) + + if (Item == mLightTypeItem) + { + Model->SetLightType(Light, static_cast(Value)); + } + else if (Item == lightShape) { Props.mLightShape = static_cast(Value); Model->UpdateLight(Light, Props, LC_LIGHT_SHAPE); @@ -1129,7 +1146,7 @@ QTreeWidgetItem *lcQPropertiesTree::addProperty(QTreeWidgetItem *parent, const Q newItem->setIcon(0, m_expandIcon); } - if (propertyType == PropertyStringLightReadOnly || propertyType == PropertyFloatReadOnly) + if (propertyType == PropertyFloatReadOnly) newItem->setFlags(newItem->flags() & ~Qt::ItemIsEditable); return newItem; @@ -1193,7 +1210,7 @@ void lcQPropertiesTree::SetEmpty() lightCutoff = nullptr; lightEnableCutoff = nullptr; lightExponent = nullptr; - lightType = nullptr; + mLightTypeItem = nullptr; lightFactorA = nullptr; lightFactorB = nullptr; lightName = nullptr; @@ -1439,7 +1456,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) QString Name = tr("Light"); QString ExponentLabel = tr("Exponent"); QString FactorALabel = QLatin1String("FactorA"); - QString Type = QLatin1String("Undefined"); QString Format, Shape, SpotSizeToolTip, ExponentToolTip, FactorAToolTip, FactorBToolTip; lcLightType LightType = lcLightType::Point; lcLightShape ShapeIndex = LC_LIGHT_SHAPE_UNDEFINED; @@ -1480,13 +1496,11 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) switch(LightType) { case lcLightType::Point: - Type = tr("Point"); FactorALabel = tr("Radius (m)"); FactorAToolTip = tr("The light size for shadow sampling in metres."); ExponentLabel = tr("Exponent"); break; case lcLightType::Spot: - Type = tr("Spot"); FactorBToolTip = tr("The softness of the spotlight edge."); ExponentLabel = tr("Power"); @@ -1506,13 +1520,11 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) } break; case lcLightType::Directional: - Type = tr("Directional"); FactorALabel = tr("Angle (°)"); FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth."); ExponentLabel = tr("Strength"); break; case lcLightType::Area: - Type = tr("Area"); ExponentLabel = tr("Power"); if (POVRayLight) @@ -1609,7 +1621,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) // Properties lightProperties = addProperty(nullptr, tr("Properties"), PropertyGroup); - lightType = addProperty(lightProperties, tr("Type"), PropertyStringLightReadOnly); + mLightTypeItem = addProperty(lightProperties, tr("Type"), PropertyStringList); lightShadowless = addProperty(lightProperties, tr("Shadowless"), PropertyBool); lightExponent = addProperty(lightProperties, ExponentLabel, PropertyFloat); @@ -1712,8 +1724,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightFormat->setText(1, Format); lightFormat->setData(0, PropertyValueRole, FormatIndex); - lightType->setText(1, Type); - lightType->setData(0, PropertyValueRole, Type); + mLightTypeItem->setText(1, lcLight::GetLightTypeString(LightType)); + mLightTypeItem->setData(0, PropertyValueRole, static_cast(LightType)); lightShadowless->setText(1, Shadowless ? "True" : "False"); lightShadowless->setData(0, PropertyValueRole, Shadowless); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 76727b47..23d80dc6 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -49,7 +49,7 @@ class lcQPropertiesTree : public QTreeWidget PropertyFloatLightSpotFalloff, PropertyStep, PropertyString, - PropertyStringLightReadOnly, + PropertyStringList, PropertyLightFormat, PropertyLightShape, PropertyLightColor, @@ -145,7 +145,7 @@ protected slots: QTreeWidgetItem *lightCutoff; QTreeWidgetItem *lightEnableCutoff; QTreeWidgetItem *lightExponent; - QTreeWidgetItem *lightType; + QTreeWidgetItem *mLightTypeItem; QTreeWidgetItem *lightSpotSize; QTreeWidgetItem *lightShape; QTreeWidgetItem *lightFactorA; From 9648dbb97796c27abe3fb68db94d27f223baa645 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 2 Sep 2023 10:21:25 -0700 Subject: [PATCH 25/42] Reorganized properties tree. --- qt/lc_qpropertiestree.cpp | 264 ++++++++++++++++---------------------- qt/lc_qpropertiestree.h | 131 +++++++++---------- 2 files changed, 178 insertions(+), 217 deletions(-) diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index a06f3276..b25f6bff 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -430,19 +430,8 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) switch (propertyType) { case PropertyGroup: - return nullptr; - case PropertyBool: - { - QCheckBox *editor = new QCheckBox(parent); - bool value = item->data(0, PropertyValueRole).toBool(); - - editor->setChecked(value); - - connect(editor, SIGNAL(toggled(bool)), this, SLOT(slotToggled(bool))); - - return editor; - } + return nullptr; case PropertyFloat: { @@ -528,9 +517,15 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) { QComboBox* editor = new QComboBox(parent); - if (item == mLightTypeItem) + if (item == mCameraProjectionItem) + { + editor->addItems( { tr("Perspective"), tr("Orthographic") } ); + } + else if (item == mLightTypeItem) + { for (int LightTypeIndex = 0; LightTypeIndex < static_cast(lcLightType::Count); LightTypeIndex++) editor->addItem(lcLight::GetLightTypeString(static_cast(LightTypeIndex))); + } int value = item->data(0, PropertyValueRole).toInt(); editor->setCurrentIndex(value); @@ -578,7 +573,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return editor; } - case PropertyLightColor: + case PropertyColor: { QPushButton *Editor = new QPushButton(parent); QColor Value = item->data(0, PropertyValueRole).value(); @@ -590,7 +585,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return Editor; } - case PropertyColor: + case PropertyPieceColor: { QPushButton *editor = new QPushButton(parent); int value = item->data(0, PropertyValueRole).toInt(); @@ -685,19 +680,7 @@ void lcQPropertiesTree::slotToggled(bool Value) lcModel* Model = gMainWindow->GetActiveModel(); lcObject* Focus = Model->GetFocusObject(); - if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA) - { - if (Focus && Focus->IsCamera()) - { - lcCamera* Camera = (lcCamera*)Focus; - - if (Item == cameraOrtho) - { - Model->SetCameraOrthographic(Camera, Value); - } - } - } - else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) + if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) { lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; @@ -866,7 +849,7 @@ void lcQPropertiesTree::slotReturnPressed() Model->SetCameraZFar(Camera, Value); } - else if (Item == cameraName) + else if (Item == mCameraNameItem) { QString Value = Editor->text(); @@ -916,20 +899,6 @@ void lcQPropertiesTree::slotReturnPressed() Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); } - else if (Item == lightColorR || Item == lightColorG || Item == lightColorB) - { - lcVector3 Color = Light->GetColor(); - float Value = lcParseValueLocalized(Editor->text()); - - if (Item == lightColorR) - Color[0] = Value; - else if (Item == lightColorG) - Color[2] = Value; - else if (Item == lightColorB) - Color[1] = Value; - - Model->SetLightColor(Light, Color); - } else if (Item == lightFactorA || Item == lightFactorB) { float Value = lcParseValueLocalized(Editor->text()); @@ -994,7 +963,7 @@ void lcQPropertiesTree::slotReturnPressed() Model->UpdateLight(Light, Props, LC_LIGHT_AREA_GRID); } - else if (Item == lightName) + else if (Item == mLightNameItem) { QString Value = Editor->text(); @@ -1011,14 +980,14 @@ void lcQPropertiesTree::slotSetValue(int Value) if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE) { - if (Item == partColor) + if (Item == mPieceColorItem) { Model->SetSelectedPiecesColorIndex(Value); QPushButton *editor = (QPushButton*)mDelegate->editor(); updateColorEditor(editor, Value); } - else if (Item == partID) + else if (Item == mPieceIdItem) { QComboBox *editor = (QComboBox*)sender(); @@ -1033,6 +1002,20 @@ void lcQPropertiesTree::slotSetValue(int Value) gMainWindow->PreviewPiece(Info->mFileName, ColorCode, false); } } + else if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA) + { + lcObject* Focus = Model->GetFocusObject(); + + if (Focus && Focus->IsCamera()) + { + lcCamera* Camera = (lcCamera*)Focus; + + if (Item == mCameraProjectionItem) + { + Model->SetCameraOrthographic(Camera, Value == 1); + } + } + } else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) { lcObject* Focus = Model->GetFocusObject(); @@ -1137,7 +1120,10 @@ QTreeWidgetItem *lcQPropertiesTree::addProperty(QTreeWidgetItem *parent, const Q newItem = new QTreeWidgetItem(this, QStringList(label)); newItem->setData(0, PropertyTypeRole, QVariant(propertyType)); - newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); + + if (propertyType != PropertyFloatReadOnly) + newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); + newItem->setExpanded(true); if (propertyType == PropertyGroup) @@ -1146,9 +1132,6 @@ QTreeWidgetItem *lcQPropertiesTree::addProperty(QTreeWidgetItem *parent, const Q newItem->setIcon(0, m_expandIcon); } - if (propertyType == PropertyFloatReadOnly) - newItem->setFlags(newItem->flags() & ~Qt::ItemIsEditable); - return newItem; } @@ -1156,6 +1139,7 @@ void lcQPropertiesTree::SetEmpty() { clear(); + mPieceAttributesItem = nullptr; partPosition = nullptr; partPositionX = nullptr; partPositionY = nullptr; @@ -1168,8 +1152,8 @@ void lcQPropertiesTree::SetEmpty() partShow = nullptr; partHide = nullptr; partAppearance = nullptr; - partColor = nullptr; - partID = nullptr; + mPieceColorItem = nullptr; + mPieceIdItem = nullptr; cameraPosition = nullptr; cameraPositionX = nullptr; @@ -1183,12 +1167,12 @@ void lcQPropertiesTree::SetEmpty() cameraUpX = nullptr; cameraUpY = nullptr; cameraUpZ = nullptr; - cameraSettings = nullptr; - cameraOrtho = nullptr; + mCameraAttributesItem = nullptr; + mCameraProjectionItem = nullptr; cameraFOV = nullptr; cameraNear = nullptr; cameraFar = nullptr; - cameraName = nullptr; + mCameraNameItem = nullptr; lightConfiguration = nullptr; lightPosition = nullptr; @@ -1199,12 +1183,8 @@ void lcQPropertiesTree::SetEmpty() lightTargetX = nullptr; lightTargetY = nullptr; lightTargetZ = nullptr; - lightColor = nullptr; - lightColorIcon = nullptr; - lightColorR = nullptr; - lightColorG = nullptr; - lightColorB = nullptr; - lightProperties = nullptr; + mLightColorItem = nullptr; + mLightAttributesItem = nullptr; lightDiffuse = nullptr; lightSpecular = nullptr; lightCutoff = nullptr; @@ -1213,7 +1193,7 @@ void lcQPropertiesTree::SetEmpty() mLightTypeItem = nullptr; lightFactorA = nullptr; lightFactorB = nullptr; - lightName = nullptr; + mLightNameItem = nullptr; lightSpotSize = nullptr; lightShape = nullptr; lightFormat = nullptr; @@ -1233,6 +1213,14 @@ void lcQPropertiesTree::SetPiece(const lcArray& Selection, lcObject* { SetEmpty(); + mPieceAttributesItem = addProperty(nullptr, tr("Piece Attributes"), PropertyGroup); + mPieceIdItem = addProperty(mPieceAttributesItem, tr("Part"), PropertyPart); + mPieceColorItem = addProperty(mPieceAttributesItem, tr("Color"), PropertyPieceColor); + + partVisibility = addProperty(nullptr, tr("Visible Steps"), PropertyGroup); + partShow = addProperty(partVisibility, tr("Show"), PropertyStep); + partHide = addProperty(partVisibility, tr("Hide"), PropertyStep); + partPosition = addProperty(nullptr, tr("Position"), PropertyGroup); partPositionX = addProperty(partPosition, tr("X"), PropertyFloat); partPositionY = addProperty(partPosition, tr("Y"), PropertyFloat); @@ -1243,14 +1231,6 @@ void lcQPropertiesTree::SetPiece(const lcArray& Selection, lcObject* partRotationY = addProperty(partRotation, tr("Y"), PropertyFloat); partRotationZ = addProperty(partRotation, tr("Z"), PropertyFloat); - partVisibility = addProperty(nullptr, tr("Visible Steps"), PropertyGroup); - partShow = addProperty(partVisibility, tr("Show"), PropertyStep); - partHide = addProperty(partVisibility, tr("Hide"), PropertyStep); - - partAppearance = addProperty(nullptr, tr("Appearance"), PropertyGroup); - partColor = addProperty(partAppearance, tr("Color"), PropertyColor); - partID = addProperty(partAppearance, tr("Part"), PropertyPart); - mWidgetMode = LC_PROPERTY_WIDGET_PIECE; } @@ -1349,14 +1329,14 @@ void lcQPropertiesTree::SetPiece(const lcArray& Selection, lcObject* painter.drawRect(0, 0, img.width() - 1, img.height() - 1); painter.end(); - partColor->setIcon(1, QIcon(QPixmap::fromImage(img))); - partColor->setText(1, color->Name); - partColor->setData(0, PropertyValueRole, ColorIndex); + mPieceColorItem->setIcon(1, QIcon(QPixmap::fromImage(img))); + mPieceColorItem->setText(1, color->Name); + mPieceColorItem->setData(0, PropertyValueRole, ColorIndex); QString text = Info ? Info->m_strDescription : QString(); - partID->setText(1, text); - partID->setToolTip(1, text); - partID->setData(0, PropertyValueRole, QVariant::fromValue((void*)Info)); + mPieceIdItem->setText(1, text); + mPieceIdItem->setToolTip(1, text); + mPieceIdItem->setData(0, PropertyValueRole, QVariant::fromValue((void*)Info)); } void lcQPropertiesTree::SetCamera(lcObject* Focus) @@ -1365,6 +1345,13 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus) { SetEmpty(); + mCameraAttributesItem = addProperty(nullptr, tr("Camera Attributes"), PropertyGroup); + mCameraNameItem = addProperty(mCameraAttributesItem, tr("Name"), PropertyString); + mCameraProjectionItem = addProperty(mCameraAttributesItem, tr("Projection"), PropertyStringList); + cameraFOV = addProperty(mCameraAttributesItem, tr("FOV"), PropertyFloat); + cameraNear = addProperty(mCameraAttributesItem, tr("Near"), PropertyFloat); + cameraFar = addProperty(mCameraAttributesItem, tr("Far"), PropertyFloat); + cameraPosition = addProperty(nullptr, tr("Position"), PropertyGroup); cameraPositionX = addProperty(cameraPosition, tr("X"), PropertyFloat); cameraPositionY = addProperty(cameraPosition, tr("Y"), PropertyFloat); @@ -1380,13 +1367,6 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus) cameraUpY = addProperty(cameraUp, tr("Y"), PropertyFloat); cameraUpZ = addProperty(cameraUp, tr("Z"), PropertyFloat); - cameraSettings = addProperty(nullptr, tr("Up"), PropertyGroup); - cameraOrtho = addProperty(cameraSettings, tr("Orthographic"), PropertyBool); - cameraFOV = addProperty(cameraSettings, tr("FOV"), PropertyFloat); - cameraNear = addProperty(cameraSettings, tr("Near"), PropertyFloat); - cameraFar = addProperty(cameraSettings, tr("Far"), PropertyFloat); - cameraName = addProperty(cameraSettings, tr("Name"), PropertyString); - mWidgetMode = LC_PROPERTY_WIDGET_CAMERA; } @@ -1436,8 +1416,8 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus) cameraUpZ->setText(1, lcFormatValueLocalized(UpVector[2])); cameraUpZ->setData(0, PropertyValueRole, UpVector[2]); - cameraOrtho->setText(1, Ortho ? "True" : "False"); - cameraOrtho->setData(0, PropertyValueRole, Ortho); + mCameraProjectionItem->setText(1, Ortho ? tr("Orthographic") : tr("Perspective")); + mCameraProjectionItem->setData(0, PropertyValueRole, Ortho); cameraFOV->setText(1, lcFormatValueLocalized(FoV)); cameraFOV->setData(0, PropertyValueRole, FoV); cameraNear->setText(1, lcFormatValueLocalized(ZNear)); @@ -1445,8 +1425,8 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus) cameraFar->setText(1, lcFormatValueLocalized(ZFar)); cameraFar->setData(0, PropertyValueRole, ZFar); - cameraName->setText(1, Name); - cameraName->setData(0, PropertyValueRole, Name); + mCameraNameItem->setText(1, Name); + mCameraNameItem->setData(0, PropertyValueRole, Name); } void lcQPropertiesTree::SetLight(lcObject* Focus) @@ -1593,68 +1573,45 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) { SetEmpty(); - // Configuration - lightConfiguration = addProperty(nullptr, tr("Configuration"), PropertyGroup); - lightFormat = addProperty(lightConfiguration, tr("Format"), PropertyLightFormat); + // Attributes + mLightAttributesItem = addProperty(nullptr, tr("Light Attributes"), PropertyGroup); + mLightNameItem = addProperty(mLightAttributesItem, tr("Name"), PropertyString); + mLightTypeItem = addProperty(mLightAttributesItem, tr("Type"), PropertyStringList); + mLightColorItem = addProperty(mLightAttributesItem, tr("Color"), PropertyColor); - // Position - lightPosition = addProperty(nullptr, tr("Position"), PropertyGroup); - lightPositionX = addProperty(lightPosition, tr("X"), PropertyFloat); - lightPositionY = addProperty(lightPosition, tr("Y"), PropertyFloat); - lightPositionZ = addProperty(lightPosition, tr("Z"), PropertyFloat); - - // Target Position - if (LightType != lcLightType::Point && !(LightType == lcLightType::Area && POVRayLight)) - { - lightTarget = addProperty(nullptr, tr("Target"), PropertyGroup); - lightTargetX = addProperty(lightTarget, tr("X"), TargetProperty); - lightTargetY = addProperty(lightTarget, tr("Y"), TargetProperty); - lightTargetZ = addProperty(lightTarget, tr("Z"), TargetProperty); - } - - // Light Color - lightColor = addProperty(nullptr, tr("Color"), PropertyGroup); - lightColorIcon = addProperty(lightColor, tr("Value"), PropertyLightColor); - lightColorR = addProperty(lightColor, tr("Red"), PropertyFloat); - lightColorG = addProperty(lightColor, tr("Green"), PropertyFloat); - lightColorB = addProperty(lightColor, tr("Blue"), PropertyFloat); - - // Properties - lightProperties = addProperty(nullptr, tr("Properties"), PropertyGroup); - mLightTypeItem = addProperty(lightProperties, tr("Type"), PropertyStringList); - lightShadowless = addProperty(lightProperties, tr("Shadowless"), PropertyBool); - lightExponent = addProperty(lightProperties, ExponentLabel, PropertyFloat); + lightShadowless = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); + lightExponent = addProperty(mLightAttributesItem, ExponentLabel, PropertyFloat); if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) - lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); + lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloat); if (LightType == lcLightType::Spot) { - lightSpotSize = addProperty(lightProperties, tr("Spot Size (°)"), SpotSizeProperty); - lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloatLightSpotSize); + lightSpotSize = addProperty(mLightAttributesItem, tr("Spot Size (°)"), SpotSizeProperty); + lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloatLightSpotSize); if (!POVRayLight) - lightFactorB = addProperty(lightProperties, tr("Spot Blend"), PropertyFloat); + lightFactorB = addProperty(mLightAttributesItem, tr("Spot Blend"), PropertyFloat); else { - lightSpotFalloff = addProperty(lightProperties, tr("Spot Falloff (°)"), PropertyFloatLightSpotFalloff); - lightSpotTightness = addProperty(lightProperties, tr("Spot Tightness"), PropertyFloat); + lightSpotFalloff = addProperty(mLightAttributesItem, tr("Spot Falloff (°)"), PropertyFloatLightSpotFalloff); + lightSpotTightness = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat); } } else if (LightType == lcLightType::Area) { - lightShape = addProperty(lightProperties, tr("Shape"), PropertyLightShape); - lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); + lightShape = addProperty(mLightAttributesItem, tr("Shape"), PropertyLightShape); + lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloat); if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE || POVRayLight) - lightFactorB = addProperty(lightProperties, tr("Height"), PropertyFloat); + lightFactorB = addProperty(mLightAttributesItem, tr("Height"), PropertyFloat); else FactorAToolTip = tr("The size of the area light grid."); if (POVRayLight) { - lightAreaGridRows = addProperty(lightProperties, tr("Grid Rows"), PropertyFloat); - lightAreaGridColumns = addProperty(lightProperties, tr("Grid Columns"), PropertyFloat); + lightAreaGridRows = addProperty(mLightAttributesItem, tr("Grid Rows"), PropertyFloat); + lightAreaGridColumns = addProperty(mLightAttributesItem, tr("Grid Columns"), PropertyFloat); } } @@ -1662,15 +1619,32 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) { if (LightType != lcLightType::Directional) { - lightEnableCutoff = addProperty(lightProperties, tr("Cutoff"), PropertyBool); - lightCutoff = addProperty(lightProperties, tr("Cutoff Distance"), PropertyFloat); + lightEnableCutoff = addProperty(mLightAttributesItem, tr("Cutoff"), PropertyBool); + lightCutoff = addProperty(mLightAttributesItem, tr("Cutoff Distance"), PropertyFloat); } - lightDiffuse = addProperty(lightProperties, tr("Diffuse"), PropertyFloat); - lightSpecular = addProperty(lightProperties, tr("Specular"), PropertyFloat); + lightDiffuse = addProperty(mLightAttributesItem, tr("Diffuse"), PropertyFloat); + lightSpecular = addProperty(mLightAttributesItem, tr("Specular"), PropertyFloat); } - lightName = addProperty(lightProperties, tr("Name"), PropertyString); + // Configuration + lightConfiguration = addProperty(nullptr, tr("Configuration"), PropertyGroup); + lightFormat = addProperty(lightConfiguration, tr("Format"), PropertyLightFormat); + + // Position + lightPosition = addProperty(nullptr, tr("Position"), PropertyGroup); + lightPositionX = addProperty(lightPosition, tr("X"), PropertyFloat); + lightPositionY = addProperty(lightPosition, tr("Y"), PropertyFloat); + lightPositionZ = addProperty(lightPosition, tr("Z"), PropertyFloat); + + // Target Position + if (LightType != lcLightType::Point && !(LightType == lcLightType::Area && POVRayLight)) + { + lightTarget = addProperty(nullptr, tr("Target"), PropertyGroup); + lightTargetX = addProperty(lightTarget, tr("X"), TargetProperty); + lightTargetY = addProperty(lightTarget, tr("Y"), TargetProperty); + lightTargetZ = addProperty(lightTarget, tr("Z"), TargetProperty); + } mWidgetMode = LC_PROPERTY_WIDGET_LIGHT; mLightType = LightType; @@ -1707,19 +1681,9 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) painter.drawRect(0, 0, ColorImage.width() - 1, ColorImage.height() - 1); painter.end(); - lightColorIcon->setIcon(1, QIcon(QPixmap::fromImage(ColorImage))); - lightColorIcon->setText(1, Color.name().toUpper()); - lightColorIcon->setData(0, PropertyValueRole, Color); - - lightColorR->setText(1, lcFormatValueLocalized(Color.redF())); - lightColorR->setData(0, PropertyValueRole, Color.redF()); - lightColorR->setToolTip(1, tr("Red color using 0 to 1 decimal.")); - lightColorG->setText(1, lcFormatValueLocalized(Color.greenF())); - lightColorG->setData(0, PropertyValueRole, Color.greenF()); - lightColorG->setToolTip(1, tr("Green color using 0 to 1 decimal.")); - lightColorB->setText(1, lcFormatValueLocalized(Color.blueF())); - lightColorB->setData(0, PropertyValueRole, Color.blueF()); - lightColorB->setToolTip(1, tr("Blue color using 0 to 1 decimal.")); + mLightColorItem->setIcon(1, QIcon(QPixmap::fromImage(ColorImage))); + mLightColorItem->setText(1, Color.name().toUpper()); + mLightColorItem->setData(0, PropertyValueRole, Color); lightFormat->setText(1, Format); lightFormat->setData(0, PropertyValueRole, FormatIndex); @@ -1727,7 +1691,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightTypeItem->setText(1, lcLight::GetLightTypeString(LightType)); mLightTypeItem->setData(0, PropertyValueRole, static_cast(LightType)); - lightShadowless->setText(1, Shadowless ? "True" : "False"); + lightShadowless->setCheckState(1, Shadowless ? Qt::Checked : Qt::Unchecked); lightShadowless->setData(0, PropertyValueRole, Shadowless); lightExponent->setText(1, lcFormatValueLocalized(Exponent)); @@ -1800,7 +1764,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) { if (LightType != lcLightType::Directional) { - lightEnableCutoff->setText(1, EnableCutoff ? "True" : "False"); + lightEnableCutoff->setCheckState(1, EnableCutoff ? Qt::Checked : Qt::Unchecked); lightEnableCutoff->setData(0, PropertyValueRole, EnableCutoff); lightCutoff->setText(1, lcFormatValueLocalized(Cutoff)); @@ -1817,8 +1781,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightSpecular->setToolTip(1, tr("Specular reflection multiplier factor.")); } - lightName->setText(1, Name); - lightName->setData(0, PropertyValueRole, QVariant::fromValue(Name)); + mLightNameItem->setText(1, Name); + mLightNameItem->setData(0, PropertyValueRole, QVariant::fromValue(Name)); } void lcQPropertiesTree::SetMultiple() diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 23d80dc6..6c6dbfc1 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -52,8 +52,8 @@ class lcQPropertiesTree : public QTreeWidget PropertyStringList, PropertyLightFormat, PropertyLightShape, - PropertyLightColor, PropertyColor, + PropertyPieceColor, PropertyPart }; @@ -91,72 +91,69 @@ protected slots: QIcon m_checkedIcon; QIcon m_uncheckedIcon; - QTreeWidgetItem *partPosition; - QTreeWidgetItem *partPositionX; - QTreeWidgetItem *partPositionY; - QTreeWidgetItem *partPositionZ; - QTreeWidgetItem *partRotation; - QTreeWidgetItem *partRotationX; - QTreeWidgetItem *partRotationY; - QTreeWidgetItem *partRotationZ; - QTreeWidgetItem *partVisibility; - QTreeWidgetItem *partShow; - QTreeWidgetItem *partHide; - QTreeWidgetItem *partAppearance; - QTreeWidgetItem *partColor; - QTreeWidgetItem *partID; - - QTreeWidgetItem *cameraPosition; - QTreeWidgetItem *cameraPositionX; - QTreeWidgetItem *cameraPositionY; - QTreeWidgetItem *cameraPositionZ; - QTreeWidgetItem *cameraTarget; - QTreeWidgetItem *cameraTargetX; - QTreeWidgetItem *cameraTargetY; - QTreeWidgetItem *cameraTargetZ; - QTreeWidgetItem *cameraUp; - QTreeWidgetItem *cameraUpX; - QTreeWidgetItem *cameraUpY; - QTreeWidgetItem *cameraUpZ; - QTreeWidgetItem *cameraSettings; - QTreeWidgetItem *cameraOrtho; - QTreeWidgetItem *cameraFOV; - QTreeWidgetItem *cameraNear; - QTreeWidgetItem *cameraFar; - QTreeWidgetItem *cameraName; - - QTreeWidgetItem *lightConfiguration; - QTreeWidgetItem *lightPosition; - QTreeWidgetItem *lightPositionX; - QTreeWidgetItem *lightPositionY; - QTreeWidgetItem *lightPositionZ; - QTreeWidgetItem *lightTarget; - QTreeWidgetItem *lightTargetX; - QTreeWidgetItem *lightTargetY; - QTreeWidgetItem *lightTargetZ; - QTreeWidgetItem *lightColor; - QTreeWidgetItem *lightColorIcon; - QTreeWidgetItem *lightColorR; - QTreeWidgetItem *lightColorG; - QTreeWidgetItem *lightColorB; - QTreeWidgetItem *lightProperties; - QTreeWidgetItem *lightDiffuse; - QTreeWidgetItem *lightSpecular; - QTreeWidgetItem *lightCutoff; - QTreeWidgetItem *lightEnableCutoff; - QTreeWidgetItem *lightExponent; - QTreeWidgetItem *mLightTypeItem; - QTreeWidgetItem *lightSpotSize; - QTreeWidgetItem *lightShape; - QTreeWidgetItem *lightFactorA; - QTreeWidgetItem *lightFactorB; - QTreeWidgetItem *lightName; - QTreeWidgetItem *lightFormat; - QTreeWidgetItem *lightShadowless; - QTreeWidgetItem *lightAreaGridRows; - QTreeWidgetItem *lightAreaGridColumns; - QTreeWidgetItem *lightSpotFalloff; - QTreeWidgetItem *lightSpotTightness; + QTreeWidgetItem* mPieceAttributesItem; + QTreeWidgetItem* partPosition; + QTreeWidgetItem* partPositionX; + QTreeWidgetItem* partPositionY; + QTreeWidgetItem* partPositionZ; + QTreeWidgetItem* partRotation; + QTreeWidgetItem* partRotationX; + QTreeWidgetItem* partRotationY; + QTreeWidgetItem* partRotationZ; + QTreeWidgetItem* partVisibility; + QTreeWidgetItem* partShow; + QTreeWidgetItem* partHide; + QTreeWidgetItem* partAppearance; + QTreeWidgetItem* mPieceColorItem; + QTreeWidgetItem* mPieceIdItem; + + QTreeWidgetItem* cameraPosition; + QTreeWidgetItem* cameraPositionX; + QTreeWidgetItem* cameraPositionY; + QTreeWidgetItem* cameraPositionZ; + QTreeWidgetItem* cameraTarget; + QTreeWidgetItem* cameraTargetX; + QTreeWidgetItem* cameraTargetY; + QTreeWidgetItem* cameraTargetZ; + QTreeWidgetItem* cameraUp; + QTreeWidgetItem* cameraUpX; + QTreeWidgetItem* cameraUpY; + QTreeWidgetItem* cameraUpZ; + QTreeWidgetItem* mCameraAttributesItem; + QTreeWidgetItem* mCameraProjectionItem; + QTreeWidgetItem* cameraFOV; + QTreeWidgetItem* cameraNear; + QTreeWidgetItem* cameraFar; + QTreeWidgetItem* mCameraNameItem; + + QTreeWidgetItem* lightConfiguration; + QTreeWidgetItem* lightPosition; + QTreeWidgetItem* lightPositionX; + QTreeWidgetItem* lightPositionY; + QTreeWidgetItem* lightPositionZ; + QTreeWidgetItem* lightTarget; + QTreeWidgetItem* lightTargetX; + QTreeWidgetItem* lightTargetY; + QTreeWidgetItem* lightTargetZ; + QTreeWidgetItem* mLightColorItem; + QTreeWidgetItem* mLightAttributesItem; + QTreeWidgetItem* lightDiffuse; + QTreeWidgetItem* lightSpecular; + QTreeWidgetItem* lightCutoff; + QTreeWidgetItem* lightEnableCutoff; + QTreeWidgetItem* lightExponent; + QTreeWidgetItem* mLightTypeItem; + QTreeWidgetItem* lightSpotSize; + QTreeWidgetItem* lightShape; + QTreeWidgetItem* lightFactorA; + QTreeWidgetItem* lightFactorB; + QTreeWidgetItem* mLightNameItem; + QTreeWidgetItem* lightFormat; + QTreeWidgetItem* lightShadowless; + QTreeWidgetItem* lightAreaGridRows; + QTreeWidgetItem* lightAreaGridColumns; + QTreeWidgetItem* lightSpotFalloff; + QTreeWidgetItem* lightSpotTightness; }; class lcQPropertiesTreeDelegate : public QItemDelegate From 080a418e1b45d98e04e2c433dff0780d84db42cd Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 2 Sep 2023 10:40:52 -0700 Subject: [PATCH 26/42] Renamed shadowless to cast shadow. --- common/lc_model.cpp | 13 +++++++++ common/lc_model.h | 1 + common/light.cpp | 14 +++++----- common/light.h | 55 +++++++++++++++++++++------------------ common/project.cpp | 2 +- qt/lc_qpropertiestree.cpp | 19 +++++++------- qt/lc_qpropertiestree.h | 2 +- 7 files changed, 61 insertions(+), 45 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 8dee6032..5bc95876 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3136,6 +3136,19 @@ void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color) UpdateAllViews(); } +void lcModel::SetLightCastShadow(lcLight* Light, bool CastShadow) +{ + if (Light->GetCastShadow() == CastShadow) + return; + + Light->SetCastShadow(CastShadow); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Light Shadow")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetLightName(lcLight* Light, const QString &Name) { if (Light->GetName() == Name) diff --git a/common/lc_model.h b/common/lc_model.h index e853d91d..9c53a772 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -370,6 +370,7 @@ class lcModel void SetLightType(lcLight* Light, lcLightType LightType); void SetLightColor(lcLight* Light, const lcVector3& Color); + void SetLightCastShadow(lcLight* Light, bool CastShadow); void SetLightName(lcLight* Light, const QString& Name); void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); diff --git a/common/light.cpp b/common/light.cpp index bfb1367b..0863531c 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -42,9 +42,7 @@ lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcL } mPOVRayLight = false; - mShadowless = false; mEnableCutoff = false; - mColor = lcVector3(1.0f, 1.0f, 1.0f); mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); mLightFactor[0] = LightType == lcLightType::Directional ? 11.4f : 0.25f; mLightFactor[1] = LightType == lcLightType::Area ? 0.25f : LightType == lcLightType::Spot ? 0.150f : 0.0f; @@ -108,7 +106,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const if (mPOVRayLight) Stream << QLatin1String("0 !LEOCAD LIGHT POV_RAY") << LineEnding; - if (mShadowless) + if (!mCastShadow) Stream << QLatin1String("0 !LEOCAD LIGHT SHADOWLESS") << LineEnding; if (mPositionKeys.GetSize() > 1) @@ -485,7 +483,7 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if (Token == QLatin1String("SHADOWLESS")) { - mShadowless = true; + mCastShadow = false; } else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) mSpotExponentKeys.LoadKeysLDraw(Stream); @@ -609,9 +607,6 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) mLightSpecular = Props.mLightSpecular; mLightSpecularKeys.ChangeKey(mLightSpecular, Step, false); break; - case LC_LIGHT_SHADOWLESS: - mShadowless = Props.mShadowless; - break; case LC_LIGHT_EXPONENT: if (Props.mPOVRayLight) { @@ -877,6 +872,11 @@ void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey) mColorKeys.ChangeKey(Color, Step, AddKey); } +void lcLight::SetCastShadow(bool CastShadow) +{ + mCastShadow = CastShadow; +} + void lcLight::InsertTime(lcStep Start, lcStep Time) { mPositionKeys.InsertTime(Start, Time); diff --git a/common/light.h b/common/light.h index 3f209f75..87e16502 100644 --- a/common/light.h +++ b/common/light.h @@ -48,7 +48,6 @@ enum lcLightProperty LC_LIGHT_FACTOR, LC_LIGHT_DIFFUSE, LC_LIGHT_SPECULAR, - LC_LIGHT_SHADOWLESS, LC_LIGHT_EXPONENT, LC_LIGHT_AREA_GRID, LC_LIGHT_SPOT_SIZE, @@ -71,7 +70,6 @@ struct lcLightProperties float mSpotTightness; float mSpotSize; bool mEnableCutoff; - bool mShadowless; bool mPOVRayLight; int mLightShape; }; @@ -323,6 +321,13 @@ class lcLight : public lcObject return mColor; } + void SetCastShadow(bool CastShadow); + + bool GetCastShadow() const + { + return mCastShadow; + } + void SetName(const QString& Name) { mName = Name; @@ -352,7 +357,6 @@ class lcLight : public lcObject props.mSpotSize = mSpotSize; props.mPOVRayLight = mPOVRayLight; props.mEnableCutoff = mEnableCutoff; - props.mShadowless = mShadowless; props.mAreaGrid = mAreaGrid; props.mLightShape = mLightShape; return props; @@ -367,13 +371,12 @@ class lcLight : public lcObject lcVector2 mLightFactor; lcVector2 mAreaGrid; lcVector2 mAreaSize; - bool mAngleSet; - bool mSpotBlendSet; - bool mSpotCutoffSet; - bool mHeightSet; - bool mEnableCutoff; - bool mPOVRayLight; - bool mShadowless; + bool mAngleSet; + bool mSpotBlendSet; + bool mSpotCutoffSet; + bool mHeightSet; + bool mEnableCutoff; + bool mPOVRayLight; float mLightDiffuse; float mLightSpecular; float mSpotSize; @@ -385,8 +388,23 @@ class lcLight : public lcObject QString mName; protected: - lcVector3 mColor; + void DrawPointLight(lcContext* Context) const; + void DrawSpotLight(lcContext* Context) const; + void DrawDirectionalLight(lcContext* Context) const; + void DrawAreaLight(lcContext* Context) const; + + float SetupLightMatrix(lcContext* Context) const; + void DrawSphere(lcContext* Context, float Radius) const; + void DrawCylinder(lcContext* Context, float Radius, float Height) const; + void DrawTarget(lcContext* Context, float TargetDistance) const; + void DrawCone(lcContext* Context, float TargetDistance) const; + + quint32 mState; + lcLightType mLightType; + lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); + bool mCastShadow = true; + int mLightShape; lcObjectKeyArray mPositionKeys; lcObjectKeyArray mTargetPositionKeys; lcObjectKeyArray mUpVectorKeys; @@ -402,19 +420,4 @@ class lcLight : public lcObject lcObjectKeyArray mSpotFalloffKeys; lcObjectKeyArray mSpotExponentKeys; lcObjectKeyArray mSpotTightnessKeys; - - void DrawPointLight(lcContext* Context) const; - void DrawSpotLight(lcContext* Context) const; - void DrawDirectionalLight(lcContext* Context) const; - void DrawAreaLight(lcContext* Context) const; - - float SetupLightMatrix(lcContext* Context) const; - void DrawSphere(lcContext* Context, float Radius) const; - void DrawCylinder(lcContext* Context, float Radius, float Height) const; - void DrawTarget(lcContext* Context, float TargetDistance) const; - void DrawCone(lcContext* Context, float TargetDistance) const; - - quint32 mState; - lcLightType mLightType; - int mLightShape; }; diff --git a/common/project.cpp b/common/project.cpp index ef93266e..8a7288c8 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2174,7 +2174,7 @@ bool Project::ExportPOVRay(const QString& FileName) const lcVector3& Location = Light->mPosition; const QString LightName = QString(Light->mName).replace(" ","_"); LightType = Light->GetLightType(); - Shadowless = static_cast(Light->mShadowless); + Shadowless = Light->GetCastShadow() ? 0 : 1; LightColor = Light->GetColor(); Power = Light->mPOVRayExponent; switch(LightType) diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index b25f6bff..4b64ef5d 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -686,16 +686,15 @@ void lcQPropertiesTree::slotToggled(bool Value) if (Light) { - lcLightProperties Props = Light->GetLightProperties(); if (Item == lightEnableCutoff) { + lcLightProperties Props = Light->GetLightProperties(); Props.mEnableCutoff = Value; Model->UpdateLight(Light, Props, LC_LIGHT_USE_CUTOFF); } - else if (Item == lightShadowless) + else if (Item == mLightCastShadowItem) { - Props.mShadowless = Value; - Model->UpdateLight(Light, Props, LC_LIGHT_SHADOWLESS); + Model->SetLightCastShadow(Light, Value); } } } @@ -1197,7 +1196,7 @@ void lcQPropertiesTree::SetEmpty() lightSpotSize = nullptr; lightShape = nullptr; lightFormat = nullptr; - lightShadowless = nullptr; + mLightCastShadowItem = nullptr; lightAreaGridRows = nullptr; lightAreaGridColumns = nullptr; lightSpotFalloff = nullptr; @@ -1449,7 +1448,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) float Exponent = 0.0f; bool EnableCutoff = false; bool POVRayLight = false; - bool Shadowless = false; + bool CastShadow = true; PropertyType TargetProperty = PropertyFloat; PropertyType SpotSizeProperty = PropertyFloatLightSpotSize; lcVector3 Position(0.0f, 0.0f, 0.0f); @@ -1466,7 +1465,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) FormatIndex = static_cast(POVRayLight); Format = POVRayLight ? QLatin1String("POVRay") : QLatin1String("Blender"); - Shadowless = Light->mShadowless; + CastShadow = Light->GetCastShadow(); Position = Light->mPosition; Target = Light->mTargetPosition; Color = lcQColorFromVector3(Light->GetColor()); @@ -1578,8 +1577,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightNameItem = addProperty(mLightAttributesItem, tr("Name"), PropertyString); mLightTypeItem = addProperty(mLightAttributesItem, tr("Type"), PropertyStringList); mLightColorItem = addProperty(mLightAttributesItem, tr("Color"), PropertyColor); + mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); - lightShadowless = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); lightExponent = addProperty(mLightAttributesItem, ExponentLabel, PropertyFloat); if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) @@ -1691,8 +1690,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightTypeItem->setText(1, lcLight::GetLightTypeString(LightType)); mLightTypeItem->setData(0, PropertyValueRole, static_cast(LightType)); - lightShadowless->setCheckState(1, Shadowless ? Qt::Checked : Qt::Unchecked); - lightShadowless->setData(0, PropertyValueRole, Shadowless); + mLightCastShadowItem->setCheckState(1, CastShadow ? Qt::Checked : Qt::Unchecked); + mLightCastShadowItem->setData(0, PropertyValueRole, CastShadow); lightExponent->setText(1, lcFormatValueLocalized(Exponent)); lightExponent->setData(0, PropertyValueRole, Exponent); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 6c6dbfc1..4e8a352b 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -149,7 +149,7 @@ protected slots: QTreeWidgetItem* lightFactorB; QTreeWidgetItem* mLightNameItem; QTreeWidgetItem* lightFormat; - QTreeWidgetItem* lightShadowless; + QTreeWidgetItem* mLightCastShadowItem; QTreeWidgetItem* lightAreaGridRows; QTreeWidgetItem* lightAreaGridColumns; QTreeWidgetItem* lightSpotFalloff; From 86327196c23d23ca54598ac4c2c402eb2b5102f5 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 4 Sep 2023 10:59:16 -0700 Subject: [PATCH 27/42] Support rotating lights. --- common/camera.h | 2 +- common/lc_mainwindow.cpp | 12 +-- common/lc_model.cpp | 141 ++++++++++++++++++++++++++-------- common/lc_model.h | 29 +++---- common/lc_view.cpp | 4 +- common/lc_viewmanipulator.cpp | 2 +- common/light.cpp | 54 ++++++++++++- common/light.h | 45 ++++++++++- common/object.h | 21 ++--- common/piece.cpp | 8 +- qt/lc_qpropertiestree.cpp | 2 +- 11 files changed, 244 insertions(+), 76 deletions(-) diff --git a/common/camera.h b/common/camera.h index 14bff4e3..adeb76d4 100644 --- a/common/camera.h +++ b/common/camera.h @@ -202,7 +202,7 @@ class lcCamera : public lcObject quint32 GetAllowedTransforms() const override { - return LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z; + return LC_OBJECT_TRANSFORM_MOVE_XYZ; } lcVector3 GetSectionPosition(quint32 Section) const override diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 29267c05..41291e97 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -2931,32 +2931,32 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) case LC_PIECE_ROTATE_PLUSX: if (ActiveModel) - ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true); break; case LC_PIECE_ROTATE_MINUSX: if (ActiveModel) - ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(-lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(-lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true); break; case LC_PIECE_ROTATE_PLUSY: if (ActiveModel) - ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true); break; case LC_PIECE_ROTATE_MINUSY: if (ActiveModel) - ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true); break; case LC_PIECE_ROTATE_PLUSZ: if (ActiveModel) - ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true, true); break; case LC_PIECE_ROTATE_MINUSZ: if (ActiveModel) - ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true, true); break; case LC_PIECE_MINIFIG_WIZARD: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 5bc95876..1f228dfe 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2776,7 +2776,7 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector } } -void lcModel::RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint) +void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint) { if (Angles.LengthSquared() < 0.001f) return; @@ -2805,6 +2805,12 @@ void lcModel::RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool } else { + int Flags; + lcArray Selection; + lcObject* Focus; + + GetSelectionInformation(&Flags, Selection, &Focus); + if (!gMainWindow->GetSeparateTransform()) { lcVector3 Center; @@ -2822,42 +2828,78 @@ void lcModel::RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool else WorldToFocusMatrix = lcMatrix33Identity(); - for (lcPiece* Piece : mPieces) + for (lcObject* Object : Selection) { - if (!Piece->IsSelected()) - continue; + if (Object->IsPiece()) + { + lcPiece* Piece = (lcPiece*)Object; + + Piece->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix); + Piece->UpdatePosition(mCurrentStep); + Rotated = true; + } + else if (Object->IsLight()) + { + lcLight* Light = (lcLight*)Object; - Piece->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix); - Piece->UpdatePosition(mCurrentStep); - Rotated = true; + Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, WorldToFocusMatrix); + Light->UpdatePosition(mCurrentStep); + Rotated = true; + } } } else { - for (lcPiece* Piece : mPieces) + for (lcObject* Object : Selection) { - if (!Piece->IsSelected()) - continue; + if (Object->IsPiece()) + { + lcPiece* Piece = (lcPiece*)Object; - const lcVector3 Center = Piece->GetRotationCenter(); - lcMatrix33 WorldToFocusMatrix; - lcMatrix33 RelativeRotationMatrix; + const lcVector3 Center = Piece->GetRotationCenter(); + lcMatrix33 WorldToFocusMatrix; + lcMatrix33 RelativeRotationMatrix; - if (Relative) - { - const lcMatrix33 RelativeRotation = Piece->GetRelativeRotation(); - WorldToFocusMatrix = lcMatrix33AffineInverse(RelativeRotation); - RelativeRotationMatrix = lcMul(RotationMatrix, RelativeRotation); + if (Relative) + { + const lcMatrix33 RelativeRotation = Piece->GetRelativeRotation(); + WorldToFocusMatrix = lcMatrix33AffineInverse(RelativeRotation); + RelativeRotationMatrix = lcMul(RotationMatrix, RelativeRotation); + } + else + { + WorldToFocusMatrix = lcMatrix33Identity(); + RelativeRotationMatrix = RotationMatrix; + } + + Piece->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RelativeRotationMatrix, Center, WorldToFocusMatrix); + Piece->UpdatePosition(mCurrentStep); + Rotated = true; } - else + else if (Object->IsLight()) { - WorldToFocusMatrix = lcMatrix33Identity(); - RelativeRotationMatrix = RotationMatrix; - } + lcLight* Light = (lcLight*)Object; + + const lcVector3 Center = Light->GetRotationCenter(); + lcMatrix33 WorldToFocusMatrix; + lcMatrix33 RelativeRotationMatrix; + + if (Relative) + { + const lcMatrix33 RelativeRotation = Light->GetRelativeRotation(); + WorldToFocusMatrix = lcMatrix33AffineInverse(RelativeRotation); + RelativeRotationMatrix = lcMul(RotationMatrix, RelativeRotation); + } + else + { + WorldToFocusMatrix = lcMatrix33Identity(); + RelativeRotationMatrix = RotationMatrix; + } - Piece->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RelativeRotationMatrix, Center, WorldToFocusMatrix); - Piece->UpdatePosition(mCurrentStep); - Rotated = true; + Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, WorldToFocusMatrix); + Light->UpdatePosition(mCurrentStep); + Rotated = true; + } } } } @@ -2911,11 +2953,11 @@ void lcModel::TransformSelectedObjects(lcTransformType TransformType, const lcVe break; case lcTransformType::AbsoluteRotation: - RotateSelectedPieces(Transform, false, false, true, true); + RotateSelectedObjects(Transform, false, false, true, true); break; case lcTransformType::RelativeRotation: - RotateSelectedPieces(Transform, true, false, true, true); + RotateSelectedObjects(Transform, true, false, true, true); break; case lcTransformType::Count: @@ -3274,16 +3316,20 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota if (!Light->IsSelected()) continue; - if (Light->IsFocused() && Relative) + if (Light->IsFocused()) { - Center = Light->GetSectionPosition(Light->GetFocusSection()); -// RelativeRotation = Piece->GetRelativeRotation(); + Center = Light->GetRotationCenter(); + + if (Relative) + RelativeRotation = Light->GetRelativeRotation(); + return true; } Center += Light->GetSectionPosition(LC_LIGHT_SECTION_POSITION); NumSelected++; - if (Light->IsDirectionalLight()) + + if (!Light->IsPointLight()) { Center += Light->GetSectionPosition(LC_LIGHT_SECTION_TARGET); NumSelected++; @@ -3299,6 +3345,33 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota return false; } +bool lcModel::CanRotateSelection() const +{ + int Flags; + lcArray Selection; + lcObject* Focus; + + GetSelectionInformation(&Flags, Selection, &Focus); + + if (Flags & LC_SEL_PIECE) + { + if ((Flags & (LC_SEL_CAMERA | LC_SEL_LIGHT)) == 0) + return true; + } + + if ((Flags & (LC_SEL_PIECE | LC_SEL_CAMERA)) == 0) + { + if (Focus && Focus->IsLight()) + { + lcLight* Light = (lcLight*)Focus; + + return (Light->GetAllowedTransforms() & LC_OBJECT_TRANSFORM_ROTATE_XYZ) != 0; + } + } + + return false; +} + bool lcModel::GetPieceFocusOrSelectionCenter(lcVector3& Center) const { lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX), Max(-FLT_MAX, -FLT_MAX, -FLT_MAX); @@ -3573,7 +3646,7 @@ void lcModel::GetSelectionInformation(int* Flags, lcArray& Selection, if (Camera->IsSelected()) { Selection.Add(Camera); - *Flags |= LC_SEL_SELECTED; + *Flags |= LC_SEL_SELECTED | LC_SEL_CAMERA; if (Camera->IsFocused()) *Focus = Camera; @@ -3585,7 +3658,7 @@ void lcModel::GetSelectionInformation(int* Flags, lcArray& Selection, if (Light->IsSelected()) { Selection.Add(Light); - *Flags |= LC_SEL_SELECTED; + *Flags |= LC_SEL_SELECTED | LC_SEL_LIGHT; if (Light->IsFocused()) *Focus = Light; @@ -4271,7 +4344,7 @@ void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool void lcModel::UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag) { const lcVector3 Delta = SnapRotation(Angles) - SnapRotation(mMouseToolDistance); - RotateSelectedPieces(Delta, true, AlternateButtonDrag, false, false); + RotateSelectedObjects(Delta, true, AlternateButtonDrag, false, false); mMouseToolDistance = Angles; gMainWindow->UpdateSelectedObjects(false); diff --git a/common/lc_model.h b/common/lc_model.h index 9c53a772..890aee5d 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -5,18 +5,20 @@ #include "lc_array.h" #define LC_SEL_NO_PIECES 0x0001 // No pieces in model -#define LC_SEL_PIECE 0x0002 // At last 1 piece selected -#define LC_SEL_SELECTED 0x0004 // At last 1 object selected -#define LC_SEL_UNSELECTED 0x0008 // At least 1 piece unselected -#define LC_SEL_HIDDEN 0x0010 // At least one piece hidden -#define LC_SEL_HIDDEN_SELECTED 0x0020 // At least one piece selected is hidden -#define LC_SEL_VISIBLE_SELECTED 0x0040 // At least one piece selected is not hidden -#define LC_SEL_GROUPED 0x0080 // At least one piece selected is grouped -#define LC_SEL_FOCUS_GROUPED 0x0100 // Focused piece is grouped -#define LC_SEL_CAN_GROUP 0x0200 // Can make a new group -#define LC_SEL_MODEL_SELECTED 0x0400 // At least one model reference is selected -#define LC_SEL_CAN_ADD_CONTROL_POINT 0x0800 // Can add control points to focused piece -#define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x1000 // Can remove control points from focused piece +#define LC_SEL_PIECE 0x0002 // At least 1 piece selected +#define LC_SEL_CAMERA 0x0004 // At least 1 camera selected +#define LC_SEL_LIGHT 0x0008 // At least 1 light selected +#define LC_SEL_SELECTED 0x0010 // At least 1 object selected +#define LC_SEL_UNSELECTED 0x0020 // At least 1 piece unselected +#define LC_SEL_HIDDEN 0x0040 // At least one piece hidden +#define LC_SEL_HIDDEN_SELECTED 0x0080 // At least one piece selected is hidden +#define LC_SEL_VISIBLE_SELECTED 0x0100 // At least one piece selected is not hidden +#define LC_SEL_GROUPED 0x0200 // At least one piece selected is grouped +#define LC_SEL_FOCUS_GROUPED 0x0400 // Focused piece is grouped +#define LC_SEL_CAN_GROUP 0x0800 // Can make a new group +#define LC_SEL_MODEL_SELECTED 0x1000 // At least one model reference is selected +#define LC_SEL_CAN_ADD_CONTROL_POINT 0x2000 // Can add control points to focused piece +#define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x4000 // Can remove control points from focused piece enum class lcSelectionMode { @@ -279,6 +281,7 @@ class lcModel lcModel* GetFirstSelectedSubmodel() const; void GetSubModels(lcArray& SubModels) const; bool GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRotation) const; + bool CanRotateSelection() const; bool GetPieceFocusOrSelectionCenter(lcVector3& Center) const; lcVector3 GetSelectionOrModelCenter() const; bool GetFocusPosition(lcVector3& Position) const; @@ -354,7 +357,7 @@ class lcModel } void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint); - void RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint); + void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint); void ScaleSelectedPieces(const float Scale, bool Update, bool Checkpoint); void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform); void SetSelectedPiecesColorIndex(int ColorIndex); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 032b7923..dad41f1d 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -928,7 +928,7 @@ void lcView::OnDraw() mViewManipulator->DrawSelectMove(mTrackButton, mTrackTool); else if (GetCurrentTool() == lcTool::Move && mTrackButton != lcTrackButton::None) mViewManipulator->DrawSelectMove(mTrackButton, mTrackTool); - else if ((Tool == lcTool::Rotate || (Tool == lcTool::Select && mTrackButton != lcTrackButton::None && mTrackTool >= lcTrackTool::RotateX && mTrackTool <= lcTrackTool::RotateXYZ)) && ActiveModel->AnyPiecesSelected()) + else if ((Tool == lcTool::Rotate || (Tool == lcTool::Select && mTrackButton != lcTrackButton::None && mTrackTool >= lcTrackTool::RotateX && mTrackTool <= lcTrackTool::RotateXYZ)) && ActiveModel->CanRotateSelection()) mViewManipulator->DrawRotate(mTrackButton, mTrackTool); else if ((mTrackTool == lcTrackTool::Select || mTrackTool == lcTrackTool::ZoomRegion) && mTrackButton != lcTrackButton::None) DrawSelectZoomRegionOverlay(); @@ -2520,7 +2520,7 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) case lcTrackTool::RotateZ: case lcTrackTool::RotateXY: case lcTrackTool::RotateXYZ: - if (ActiveModel->AnyPiecesSelected()) + if (ActiveModel->CanRotateSelection()) StartTracking(TrackButton); break; diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index da4799c6..753a42fd 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -795,7 +795,7 @@ lcTrackTool lcViewManipulator::UpdateSelectMove() ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_FIRST; } - quint32 AllowedTransforms = Focus ? Focus->GetAllowedTransforms() : LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z | LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z; + quint32 AllowedTransforms = Focus ? Focus->GetAllowedTransforms() : LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ; for (int AxisIndex = 0; AxisIndex < 3; AxisIndex++) { diff --git a/common/light.cpp b/common/light.cpp index 0863531c..134d7da3 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -859,6 +859,48 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance) } } +void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcMatrix33& RotationFrame) +{ + if (IsPointLight()) + return; + + if (GetFocusSection() != LC_LIGHT_SECTION_POSITION) + return; + +// lcVector3 Direction = mTargetPosition - mPosition; +// +// Direction = lcMul(Direction, RotationMatrix); +// +// mTargetPosition = mPosition + Direction; +// mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey); + + + const lcMatrix33 LocalToWorldMatrix = lcMatrix33AffineInverse(lcMatrix33(mWorldLight)); + + const lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, RotationFrame); + lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix); + + const lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix); + + NewLocalToWorldMatrix.Orthonormalize(); + + lcVector3 Target = lcMul(lcVector3(0.0f, 0.0f, lcLength(mTargetPosition - mPosition)), NewLocalToWorldMatrix); + mTargetPosition = mPosition - Target; + mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey); + + if (IsAreaLight()) + { + const lcVector3 FrontVector(mTargetPosition - mPosition); + lcVector3 SideVector = lcCross(FrontVector, mUpVector); + + if (fabsf(lcDot(mUpVector, SideVector)) > 0.99f) + SideVector = lcVector3(1, 0, 0); + + mUpVector = lcCross(SideVector, FrontVector); + mUpVector.Normalize(); + } +} + void lcLight::SetLightType(lcLightType LightType) { if (static_cast(LightType) < 0 || LightType >= lcLightType::Count) @@ -937,9 +979,15 @@ void lcLight::UpdatePosition(lcStep Step) } else if (IsAreaLight()) { - lcVector3 FrontVector(mTargetPosition - mPosition); - const lcVector3 SideVector = lcCross(FrontVector, mUpVector); - mUpVector = lcNormalize(lcCross(SideVector, FrontVector)); + lcVector3 UpVector(0, 0, 1), FrontVector(mPosition), SideVector; + FrontVector.Normalize(); + if (fabsf(lcDot(UpVector, FrontVector)) > 0.99f) + SideVector = lcVector3(-1, 0, 0); + else + SideVector = lcCross(FrontVector, UpVector); + UpVector = lcCross(SideVector, FrontVector); + UpVector.Normalize(); + mUpVector = UpVector; mWorldLight = lcMatrix44LookAt(mPosition, mTargetPosition, mUpVector); } diff --git a/common/light.h b/common/light.h index 87e16502..d70e7cb2 100644 --- a/common/light.h +++ b/common/light.h @@ -277,7 +277,32 @@ class lcLight : public lcObject quint32 GetAllowedTransforms() const override { - return LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z; + if (IsPointLight()) + return LC_OBJECT_TRANSFORM_MOVE_XYZ; + + const quint32 Section = GetFocusSection(); + + if (Section == LC_LIGHT_SECTION_POSITION) + return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ; + + if (Section == LC_LIGHT_SECTION_TARGET || Section == LC_LIGHT_SECTION_UPVECTOR) + return LC_OBJECT_TRANSFORM_MOVE_XYZ; + + return 0; + } + + lcMatrix33 GetRelativeRotation() const + { + const quint32 Section = GetFocusSection(); + + if (Section == LC_LIGHT_SECTION_POSITION) + { + return lcMatrix33AffineInverse(lcMatrix33(mWorldLight)); + } + else + { + return lcMatrix33Identity(); + } } lcVector3 GetSectionPosition(quint32 Section) const override @@ -297,6 +322,23 @@ class lcLight : public lcObject return lcVector3(0.0f, 0.0f, 0.0f); } + lcVector3 GetRotationCenter() const + { + const quint32 Section = GetFocusSection(); + + switch (Section) + { + case LC_LIGHT_SECTION_POSITION: + return mPosition; + + case LC_LIGHT_SECTION_TARGET: + case LC_LIGHT_SECTION_UPVECTOR: + return mTargetPosition; + } + + return mPosition; + } + void SaveLDraw(QTextStream& Stream) const; bool ParseLDrawLine(QTextStream& Stream); @@ -341,6 +383,7 @@ class lcLight : public lcObject void CompareBoundingBox(lcVector3& Min, lcVector3& Max); void UpdatePosition(lcStep Step); void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance); + void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcMatrix33& RotationFrame); bool Setup(int LightIndex); void CreateName(const lcArray& Lights); void UpdateLight(lcStep Step, lcLightProperties Props, int Property); diff --git a/common/object.h b/common/object.h index aaf1a77b..d4694f10 100644 --- a/common/object.h +++ b/common/object.h @@ -79,15 +79,18 @@ struct lcObjectBoxTest lcArray Objects; }; -#define LC_OBJECT_TRANSFORM_MOVE_X 0x001 -#define LC_OBJECT_TRANSFORM_MOVE_Y 0x002 -#define LC_OBJECT_TRANSFORM_MOVE_Z 0x004 -#define LC_OBJECT_TRANSFORM_ROTATE_X 0x010 -#define LC_OBJECT_TRANSFORM_ROTATE_Y 0x020 -#define LC_OBJECT_TRANSFORM_ROTATE_Z 0x040 -#define LC_OBJECT_TRANSFORM_SCALE_X 0x100 -#define LC_OBJECT_TRANSFORM_SCALE_Y 0x200 -#define LC_OBJECT_TRANSFORM_SCALE_Z 0x400 +#define LC_OBJECT_TRANSFORM_MOVE_X 0x001 +#define LC_OBJECT_TRANSFORM_MOVE_Y 0x002 +#define LC_OBJECT_TRANSFORM_MOVE_Z 0x004 +#define LC_OBJECT_TRANSFORM_MOVE_XYZ (LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z) +#define LC_OBJECT_TRANSFORM_ROTATE_X 0x010 +#define LC_OBJECT_TRANSFORM_ROTATE_Y 0x020 +#define LC_OBJECT_TRANSFORM_ROTATE_Z 0x040 +#define LC_OBJECT_TRANSFORM_ROTATE_XYZ (LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z) +#define LC_OBJECT_TRANSFORM_SCALE_X 0x100 +#define LC_OBJECT_TRANSFORM_SCALE_Y 0x200 +#define LC_OBJECT_TRANSFORM_SCALE_Z 0x400 +#define LC_OBJECT_TRANSFORM_SCALE_XYZ (LC_OBJECT_TRANSFORM_SCALE_X | LC_OBJECT_TRANSFORM_SCALE_Y | LC_OBJECT_TRANSFORM_SCALE_Z) class lcObject { diff --git a/common/piece.cpp b/common/piece.cpp index bba88f24..6c392d72 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -835,12 +835,10 @@ void lcPiece::RotatePivotPoint(const lcMatrix33& RotationMatrix) quint32 lcPiece::GetAllowedTransforms() const { - constexpr quint32 Move = LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z; - constexpr quint32 Rotate = LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z; const quint32 Section = GetFocusSection(); if (Section == LC_PIECE_SECTION_POSITION || Section == LC_PIECE_SECTION_INVALID) - return Move | Rotate; + return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ; const lcSynthInfo* SynthInfo = mPieceInfo->GetSynthInfo(); @@ -850,10 +848,10 @@ quint32 lcPiece::GetAllowedTransforms() const return LC_OBJECT_TRANSFORM_MOVE_Z; if (SynthInfo->IsCurve()) - return Move | Rotate | LC_OBJECT_TRANSFORM_SCALE_X; + return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ | LC_OBJECT_TRANSFORM_SCALE_X; if (SynthInfo->IsNondirectional()) - return Move; + return LC_OBJECT_TRANSFORM_MOVE_XYZ; } return 0; diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 4b64ef5d..2a46d2aa 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -747,7 +747,7 @@ void lcQPropertiesTree::slotReturnPressed() else if (Item == partRotationZ) Rotation[2] = Value; - Model->RotateSelectedPieces(Rotation - InitialRotation, true, false, true, true); + Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, true); } else if (Item == partShow) { From 6a1df617e8fb169a09b1e917b6fcce24ac4aecfc Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 4 Sep 2023 20:53:34 -0700 Subject: [PATCH 28/42] Use a matrix to store the light transform. --- common/lc_model.cpp | 72 ++---- common/lc_model.h | 5 +- common/lc_view.cpp | 49 ++-- common/light.cpp | 507 ++++++++------------------------------ common/light.h | 162 +++--------- common/project.cpp | 17 +- qt/lc_qpropertiestree.cpp | 34 +-- 7 files changed, 211 insertions(+), 635 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 1f228dfe..80b7e3dd 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -652,7 +652,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) else if (Token == QLatin1String("LIGHT")) { if (!Light) - Light = new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point); + Light = new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point); if (Light->ParseLDrawLine(LineStream)) { @@ -2224,8 +2224,14 @@ lcMatrix33 lcModel::GetRelativeRotation() const { const lcObject* Focus = GetFocusObject(); - if (Focus && Focus->IsPiece()) - return ((lcPiece*)Focus)->GetRelativeRotation(); + if (Focus) + { + if (Focus->IsPiece()) + return ((lcPiece*)Focus)->GetRelativeRotation(); + + if (Focus->IsLight()) + return ((lcLight*)Focus)->GetRelativeRotation(); + } } return lcMatrix33Identity(); @@ -2739,6 +2745,16 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector Moved = true; } } + + for (lcLight* Light : mLights) + { + if (Light->IsSelected()) + { + Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedPieceDistance); + Light->UpdatePosition(mCurrentStep); + Moved = true; + } + } } } @@ -2755,16 +2771,6 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector Moved = true; } } - - for (lcLight* Light : mLights) - { - if (Light->IsSelected()) - { - Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedObjectDistance); - Light->UpdatePosition(mCurrentStep); - Moved = true; - } - } } if (Moved && Update) @@ -2842,7 +2848,7 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool { lcLight* Light = (lcLight*)Object; - Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, WorldToFocusMatrix); + Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix); Light->UpdatePosition(mCurrentStep); Rotated = true; } @@ -2896,7 +2902,7 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RelativeRotationMatrix = RotationMatrix; } - Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, WorldToFocusMatrix); + Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix); Light->UpdatePosition(mCurrentStep); Rotated = true; } @@ -3328,12 +3334,6 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota Center += Light->GetSectionPosition(LC_LIGHT_SECTION_POSITION); NumSelected++; - - if (!Light->IsPointLight()) - { - Center += Light->GetSectionPosition(LC_LIGHT_SECTION_TARGET); - NumSelected++; - } } if (NumSelected) @@ -4250,29 +4250,18 @@ void lcModel::InsertPieceToolClicked(const lcMatrix44& WorldMatrix) SaveCheckpoint(tr("Insert")); } -void lcModel::PointLightToolClicked(const lcVector3& Position) +void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType LightType) { - lcLight* Light = new lcLight(Position, lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point); + lcLight* Light = new lcLight(Position, LightType); Light->CreateName(mLights); mLights.Add(Light); ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); - SaveCheckpoint(tr("New Point Light")); -} - -void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, lcLightType LightType) -{ - lcLight* Light = new lcLight(Position, Target, LightType); - Light->CreateName(mLights); - mLights.Add(Light); - - mMouseToolDistance = Target; - - ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_TARGET, false); switch (LightType) { case lcLightType::Point: + SaveCheckpoint(tr("New Point Light")); break; case lcLightType::Spot: @@ -4292,19 +4281,6 @@ void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVecto } } -void lcModel::UpdateDirectionalLightTool(const lcVector3& Position) -{ - lcLight* Light = mLights[mLights.GetSize() - 1]; - - Light->MoveSelected(1, false, Position - mMouseToolDistance); - Light->UpdatePosition(1); - - mMouseToolDistance = Position; - - gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); -} - void lcModel::BeginCameraTool(const lcVector3& Position, const lcVector3& Target) { lcCamera* Camera = new lcCamera(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2]); diff --git a/common/lc_model.h b/common/lc_model.h index 890aee5d..24143383 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -329,10 +329,7 @@ class lcModel void BeginMouseTool(); void EndMouseTool(lcTool Tool, bool Accept); void InsertPieceToolClicked(const lcMatrix44& WorldMatrix); - void PointLightToolClicked(const lcVector3& Position); - void BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, lcLightType LightType); - void UpdateDirectionalLightTool(const lcVector3& Position); - void BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target); + void InsertLightToolClicked(const lcVector3& Position, lcLightType LightType); void BeginCameraTool(const lcVector3& Position, const lcVector3& Target); void UpdateCameraTool(const lcVector3& Position); void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index dad41f1d..7151b0bc 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2272,29 +2272,13 @@ void lcView::StartTracking(lcTrackButton TrackButton) lcTool Tool = GetCurrentTool(); lcModel* ActiveModel = GetActiveModel(); - auto AddLight = [this, ActiveModel](lcLightType LightType) - { - lcVector3 Position = GetCameraLightInsertPosition(); - lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f); - ActiveModel->BeginDirectionalLightTool(Position, Target, LightType); - }; - switch (Tool) { case lcTool::Insert: case lcTool::PointLight: - break; - case lcTool::Spotlight: - AddLight(lcLightType::Spot); - break; - case lcTool::DirectionalLight: - AddLight(lcLightType::Directional); - break; - case lcTool::AreaLight: - AddLight(lcLightType::Area); break; case lcTool::Camera: @@ -2448,6 +2432,17 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) lcModel* ActiveModel = GetActiveModel(); mToolClicked = false; + auto AddLight = [this, ActiveModel](lcLightType LightType) + { + ActiveModel->InsertLightToolClicked(GetCameraLightInsertPosition(), LightType); + + if ((mMouseModifiers & Qt::ControlModifier) == 0) + gMainWindow->SetTool(lcTool::Select); + + mToolClicked = true; + UpdateTrackTool(); + }; + switch (mTrackTool) { case lcTrackTool::None: @@ -2471,20 +2466,21 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) break; case lcTrackTool::PointLight: - { - ActiveModel->PointLightToolClicked(GetCameraLightInsertPosition()); - - if ((mMouseModifiers & Qt::ControlModifier) == 0) - gMainWindow->SetTool(lcTool::Select); - - mToolClicked = true; - UpdateTrackTool(); - } + AddLight(lcLightType::Point); break; case lcTrackTool::Spotlight: + AddLight(lcLightType::Spot); + break; + case lcTrackTool::DirectionalLight: + AddLight(lcLightType::Directional); + break; + case lcTrackTool::AreaLight: + AddLight(lcLightType::Area); + break; + case lcTrackTool::Camera: StartTracking(TrackButton); break; @@ -2719,12 +2715,9 @@ void lcView::OnMouseMove() case lcTrackTool::None: case lcTrackTool::Insert: case lcTrackTool::PointLight: - break; - case lcTrackTool::Spotlight: case lcTrackTool::DirectionalLight: case lcTrackTool::AreaLight: - ActiveModel->UpdateDirectionalLightTool(GetCameraLightInsertPosition()); break; case lcTrackTool::Camera: diff --git a/common/light.cpp b/common/light.cpp index 134d7da3..de6e8f57 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -9,7 +9,7 @@ #include "lc_context.h" #define LC_LIGHT_SPHERE_RADIUS 5.0f -#define LC_LIGHT_TARGET_EDGE 5.0f +#define LC_LIGHT_TARGET_EDGE 2.0f #define LC_LIGHT_SPOT_CONE_HEIGHT 10.0f #define LC_LIGHT_SPOT_CONE_RADIUS 7.5f #define LC_LIGHT_DIRECTIONAL_RADIUS 5.0f @@ -19,27 +19,10 @@ static const std::array(lcLightType::Count)> gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") }; -lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcLightType LightType) +lcLight::lcLight(const lcVector3& Position, lcLightType LightType) : lcObject(lcObjectType::Light), mLightType(LightType) { - mState = 0; - - mPosition = Position; - mTargetPosition = TargetPosition; - mUpVector = lcVector3(0, 0, 1); - - if (IsAreaLight()) - { - lcVector3 FrontVector = lcNormalize(TargetPosition - Position), SideVector; - - if (FrontVector == mUpVector) - SideVector = lcVector3(1, 0, 0); - else - SideVector = lcCross(FrontVector, mUpVector); - - mUpVector = lcCross(SideVector, FrontVector); - mUpVector.Normalize(); - } + mWorldMatrix = lcMatrix44Translation(Position); mPOVRayLight = false; mEnableCutoff = false; @@ -58,10 +41,10 @@ lcLight::lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcL mAreaSize = lcVector2(200.0f, 200.0f); mLightShape = LC_LIGHT_SHAPE_SQUARE; - mPositionKeys.ChangeKey(mPosition, 1, true); - mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); - mUpVectorKeys.ChangeKey(mUpVector, 1, true); + mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true); + mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); mColorKeys.ChangeKey(mColor, 1, true); + mAttenuationKeys.ChangeKey(mAttenuation, 1, true); mLightFactorKeys.ChangeKey(mLightFactor, 1, true); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); @@ -109,25 +92,20 @@ void lcLight::SaveLDraw(QTextStream& Stream) const if (!mCastShadow) Stream << QLatin1String("0 !LEOCAD LIGHT SHADOWLESS") << LineEnding; + const float* Matrix = mWorldMatrix; + const float Numbers[12] = { Matrix[12], -Matrix[14], Matrix[13], Matrix[0], -Matrix[8], Matrix[4], -Matrix[2], Matrix[10], -Matrix[6], Matrix[1], -Matrix[9], Matrix[5] }; + if (mPositionKeys.GetSize() > 1) mPositionKeys.SaveKeysLDraw(Stream, "LIGHT POSITION_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding; - - if (mLightType != lcLightType::Point) - { - if (mTargetPositionKeys.GetSize() > 1) - mTargetPositionKeys.SaveKeysLDraw(Stream, "LIGHT TARGET_POSITION_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding; - } + Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << Numbers[0] << ' ' << Numbers[1] << ' ' << Numbers[2] << LineEnding; - if (mLightType == lcLightType::Area) + if (!IsPointLight()) { - if (mUpVectorKeys.GetSize() > 1) - mUpVectorKeys.SaveKeysLDraw(Stream, "LIGHT UP_VECTOR_KEY "); + if (mRotationKeys.GetSize() > 1) + mRotationKeys.SaveKeysLDraw(Stream, "LIGHT ROTATION_KEY "); else - Stream << QLatin1String("0 !LEOCAD LIGHT UP_VECTOR ") << mUpVector[0] << ' ' << mUpVector[1] << ' ' << mUpVector[2] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT ROTATION ") << Numbers[3] << ' ' << Numbers[4] << ' ' << Numbers[5] << ' ' << Numbers[6] << ' ' << Numbers[7] << ' ' << Numbers[8] << ' ' << Numbers[9] << ' ' << Numbers[10] << ' ' << Numbers[11] << LineEnding; } if (mColorKeys.GetSize() > 1) @@ -345,25 +323,38 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) if (Token == QLatin1String("POSITION")) { - Stream >> mPosition[0] >> mPosition[1] >> mPosition[2]; - mPositionKeys.ChangeKey(mPosition, 1, true); + lcVector3 Position; + Stream >> Position[0] >> Position[1] >> Position[2]; + + Position = lcVector3LDrawToLeoCAD(Position); + mWorldMatrix.SetTranslation(Position); + mPositionKeys.ChangeKey(Position, 1, true); } else if (Token == QLatin1String("POSITION_KEY")) - mPositionKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("TARGET_POSITION")) - { - Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; - mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); - } - else if (Token == QLatin1String("TARGET_POSITION_KEY")) - mTargetPositionKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("UP_VECTOR")) + mPositionKeys.LoadKeysLDraw(Stream); // todo: convert from ldraw + else if (Token == QLatin1String("ROTATION")) { - Stream >> mUpVector[0] >> mUpVector[1] >> mUpVector[2]; - mUpVectorKeys.ChangeKey(mUpVector, 1, true); + float Numbers[9]; + + for (int TokenIdx = 0; TokenIdx < 9; TokenIdx++) + Stream >> Numbers[TokenIdx]; + + float* Matrix = mWorldMatrix; + + Matrix[0] = Numbers[0]; + Matrix[8] = -Numbers[1]; + Matrix[4] = Numbers[2]; + Matrix[2] = -Numbers[3]; + Matrix[10] = Numbers[4]; + Matrix[6] = -Numbers[5]; + Matrix[1] = Numbers[6]; + Matrix[9] = -Numbers[7]; + Matrix[5] = Numbers[8]; + + mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); } - else if (Token == QLatin1String("UP_VECTOR_KEY")) - mUpVectorKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("ROTATION_KEY")) + mRotationKeys.LoadKeysLDraw(Stream); // todo: convert from ldraw else if (Token == QLatin1String("COLOR")) { Stream >> mColor[0] >> mColor[1] >> mColor[2]; @@ -503,10 +494,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) mLightSpecularKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("CUTOFF_DISTANCE_KEY")) mSpotCutoffKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("POSITION_KEY")) - mPositionKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("TARGET_POSITION_KEY")) - mTargetPositionKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("NAME")) { mName = Stream.readAll().trimmed(); @@ -564,20 +551,12 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max) { - const lcVector3 Points[2] = - { - mPosition, mTargetPosition - }; + const lcVector3 Point = mWorldMatrix.GetTranslation(); - for (int i = 0; i < (IsPointLight() ? 1 : 2); i++) - { - const lcVector3& Point = Points[i]; + // TODO: this should check the entire mesh - // TODO: this should check the entire mesh - - Min = lcMin(Point, Min); - Max = lcMax(Point, Max); - } + Min = lcMin(Point, Min); + Max = lcMax(Point, Max); } void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) @@ -655,7 +634,7 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const { float Distance; - if (lcSphereRayMinIntersectDistance(mPosition, LC_LIGHT_SPHERE_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance)) + if (lcSphereRayMinIntersectDistance(mWorldMatrix.GetTranslation(), LC_LIGHT_SPHERE_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance)) { ObjectRayTest.ObjectSection.Object = const_cast(this); ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION; @@ -667,10 +646,11 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const if (mLightType == lcLightType::Spot) { + const lcVector3 Direction = -lcVector3(mWorldMatrix[2]); + const lcVector3 Position = mWorldMatrix.GetTranslation() - Direction * LC_LIGHT_SPOT_CONE_HEIGHT; float Distance; - lcVector3 Direction = lcNormalize(mTargetPosition - mPosition); - if (lcConeRayMinIntersectDistance(mPosition - Direction * LC_LIGHT_SPOT_CONE_HEIGHT, Direction, LC_LIGHT_SPOT_CONE_RADIUS, LC_LIGHT_SPOT_CONE_HEIGHT, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance)) + if (lcConeRayMinIntersectDistance(Position, Direction, LC_LIGHT_SPOT_CONE_RADIUS, LC_LIGHT_SPOT_CONE_HEIGHT, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance)) { ObjectRayTest.ObjectSection.Object = const_cast(this); ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_POSITION; @@ -679,32 +659,16 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const } else if (mLightType == lcLightType::Area) { - lcVector3 FrontVector = mTargetPosition - mPosition; - lcVector4 Plane(FrontVector, -lcDot(FrontVector, mPosition)); + const lcVector3 Direction = -lcVector3(mWorldMatrix[2]); + const lcVector3 Position = mWorldMatrix.GetTranslation(); + const lcVector4 Plane(Direction, -lcDot(Direction, Position)); lcVector3 Intersection; if (lcLineSegmentPlaneIntersection(&Intersection, ObjectRayTest.Start, ObjectRayTest.End, Plane)) { - lcVector3 UpVector(1, 1, 1); - - if (fabs(FrontVector[0]) < fabs(FrontVector[1])) - { - if (fabs(FrontVector[0]) < fabs(FrontVector[2])) - UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); - } - else - { - if (fabs(FrontVector[1]) < fabs(FrontVector[2])) - UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); - } - - lcVector3 XAxis = lcNormalize(lcCross(FrontVector, UpVector)); - lcVector3 YAxis = lcNormalize(lcCross(FrontVector, XAxis)); - lcVector3 IntersectionDirection = Intersection - mPosition; + const lcVector3 XAxis = lcVector3(mWorldMatrix[0]); + const lcVector3 YAxis = lcVector3(mWorldMatrix[1]); + lcVector3 IntersectionDirection = Intersection - Position; float x = lcDot(IntersectionDirection, XAxis); float y = lcDot(IntersectionDirection, YAxis); @@ -723,8 +687,9 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const } } - lcVector3 Start = lcMul31(ObjectRayTest.Start, mWorldLight); - lcVector3 End = lcMul31(ObjectRayTest.End, mWorldLight); + const lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(mWorldMatrix); + lcVector3 Start = lcMul31(ObjectRayTest.Start, InverseWorldMatrix); + lcVector3 End = lcMul31(ObjectRayTest.End, InverseWorldMatrix); float Distance; lcVector3 Plane; @@ -739,43 +704,6 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const ObjectRayTest.PieceInfoRayTest.Plane = Plane; } } - - lcVector3 Min = lcVector3(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE); - lcVector3 Max = lcVector3( LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE); - - lcMatrix44 WorldTarget = mWorldLight; - WorldTarget.SetTranslation(lcMul30(-mTargetPosition, WorldTarget)); - - Start = lcMul31(ObjectRayTest.Start, WorldTarget); - End = lcMul31(ObjectRayTest.End, WorldTarget); - - if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance)) - { - ObjectRayTest.ObjectSection.Object = const_cast(this); - ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_TARGET; - ObjectRayTest.Distance = Distance; - ObjectRayTest.PieceInfoRayTest.Plane = Plane; - } - - if (IsAreaLight()) - { - const lcMatrix44 LightWorld = lcMatrix44AffineInverse(mWorldLight); - const lcVector3 UpVectorPosition = lcMul31(lcVector3(0, 25, 0), LightWorld); - - lcMatrix44 WorldLight = mWorldLight; - WorldLight.SetTranslation(lcMul30(-UpVectorPosition, WorldLight)); - - Start = lcMul31(ObjectRayTest.Start, WorldLight); - End = lcMul31(ObjectRayTest.End, WorldLight); - - if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance)) - { - ObjectRayTest.ObjectSection.Object = const_cast(this); - ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_UPVECTOR; - ObjectRayTest.Distance = Distance; - ObjectRayTest.PieceInfoRayTest.Plane = Plane; - } - } } void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const @@ -783,40 +711,22 @@ void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const if (IsPointLight()) { for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++) - if (lcDot3(mPosition, ObjectBoxTest.Planes[PlaneIdx]) + ObjectBoxTest.Planes[PlaneIdx][3] > LC_LIGHT_SPHERE_RADIUS) + if (lcDot3(mWorldMatrix.GetTranslation(), ObjectBoxTest.Planes[PlaneIdx]) + ObjectBoxTest.Planes[PlaneIdx][3] > LC_LIGHT_SPHERE_RADIUS) return; ObjectBoxTest.Objects.Add(const_cast(this)); return; } - + lcVector3 Min(-LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE, -LC_LIGHT_POSITION_EDGE); // todo: fix light box test - lcVector3 Max(LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE); + lcVector3 Max( LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE, LC_LIGHT_POSITION_EDGE); lcVector4 LocalPlanes[6]; for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++) { - const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], mWorldLight); - LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(mWorldLight[3], Normal)); - } - - if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes)) - { - ObjectBoxTest.Objects.Add(const_cast(this)); - return; - } - - Min = lcVector3(-LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE, -LC_LIGHT_TARGET_EDGE); - Max = lcVector3(LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE, LC_LIGHT_TARGET_EDGE); - - lcMatrix44 WorldTarget = mWorldLight; - WorldTarget.SetTranslation(lcMul30(-mTargetPosition, WorldTarget)); - - for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++) - { - const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], WorldTarget); - LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(WorldTarget[3], Normal)); + const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], mWorldMatrix); + LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(mWorldMatrix[3], Normal)); } if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes)) @@ -830,36 +740,15 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance) { if (IsSelected(LC_LIGHT_SECTION_POSITION)) { - mPosition += Distance; - mPositionKeys.ChangeKey(mPosition, Step, AddKey); - } - - if (IsSelected(LC_LIGHT_SECTION_TARGET)) - { - mTargetPosition += Distance; - mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey); - } - else if (IsSelected(LC_LIGHT_SECTION_UPVECTOR)) - { - mUpVector += Distance; - mUpVector.Normalize(); - mUpVectorKeys.ChangeKey(mUpVector, Step, AddKey); - } + const lcVector3 Position = mWorldMatrix.GetTranslation() + Distance; - if (IsAreaLight()) - { - const lcVector3 FrontVector(mTargetPosition - mPosition); - lcVector3 SideVector = lcCross(FrontVector, mUpVector); + SetPosition(Position, Step, AddKey); - if (fabsf(lcDot(mUpVector, SideVector)) > 0.99f) - SideVector = lcVector3(1, 0, 0); - - mUpVector = lcCross(SideVector, FrontVector); - mUpVector.Normalize(); + mWorldMatrix.SetTranslation(Position); } } -void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcMatrix33& RotationFrame) +void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame) { if (IsPointLight()) return; @@ -867,38 +756,21 @@ void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, if (GetFocusSection() != LC_LIGHT_SECTION_POSITION) return; -// lcVector3 Direction = mTargetPosition - mPosition; -// -// Direction = lcMul(Direction, RotationMatrix); -// -// mTargetPosition = mPosition + Direction; -// mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey); - - - const lcMatrix33 LocalToWorldMatrix = lcMatrix33AffineInverse(lcMatrix33(mWorldLight)); + lcVector3 Distance = mWorldMatrix.GetTranslation() - Center; + const lcMatrix33 LocalToWorldMatrix = lcMatrix33(mWorldMatrix); const lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, RotationFrame); lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix); const lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix); - NewLocalToWorldMatrix.Orthonormalize(); - - lcVector3 Target = lcMul(lcVector3(0.0f, 0.0f, lcLength(mTargetPosition - mPosition)), NewLocalToWorldMatrix); - mTargetPosition = mPosition - Target; - mTargetPositionKeys.ChangeKey(mTargetPosition, Step, AddKey); - - if (IsAreaLight()) - { - const lcVector3 FrontVector(mTargetPosition - mPosition); - lcVector3 SideVector = lcCross(FrontVector, mUpVector); + Distance = lcMul(Distance, WorldToLocalMatrix); + Distance = lcMul(Distance, NewLocalToWorldMatrix); - if (fabsf(lcDot(mUpVector, SideVector)) > 0.99f) - SideVector = lcVector3(1, 0, 0); + NewLocalToWorldMatrix.Orthonormalize(); - mUpVector = lcCross(SideVector, FrontVector); - mUpVector.Normalize(); - } + SetPosition(Center + Distance, Step, AddKey); + SetRotation(NewLocalToWorldMatrix, Step, AddKey); } void lcLight::SetLightType(lcLightType LightType) @@ -922,8 +794,7 @@ void lcLight::SetCastShadow(bool CastShadow) void lcLight::InsertTime(lcStep Start, lcStep Time) { mPositionKeys.InsertTime(Start, Time); - mTargetPositionKeys.InsertTime(Start, Time); - mUpVectorKeys.InsertTime(Start, Time); + mRotationKeys.InsertTime(Start, Time); mColorKeys.InsertTime(Start, Time); mAttenuationKeys.InsertTime(Start, Time); mLightFactorKeys.InsertTime(Start, Time); @@ -940,8 +811,7 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) void lcLight::RemoveTime(lcStep Start, lcStep Time) { mPositionKeys.RemoveTime(Start, Time); - mTargetPositionKeys.RemoveTime(Start, Time); - mUpVectorKeys.RemoveTime(Start, Time); + mRotationKeys.RemoveTime(Start, Time); mColorKeys.RemoveTime(Start, Time); mAttenuationKeys.RemoveTime(Start, Time); mLightFactorKeys.RemoveTime(Start, Time); @@ -957,9 +827,19 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) void lcLight::UpdatePosition(lcStep Step) { - mPosition = mPositionKeys.CalculateKey(Step); - mTargetPosition = mTargetPositionKeys.CalculateKey(Step); - mUpVector = mUpVectorKeys.CalculateKey(Step); + const lcVector3 Position = mPositionKeys.CalculateKey(Step); + + if (IsPointLight()) + { + mWorldMatrix = lcMatrix44Translation(Position); + } + else + { + const lcMatrix33 Rotation = mRotationKeys.CalculateKey(Step); + + mWorldMatrix = lcMatrix44(Rotation, Position); + } + mColor = mColorKeys.CalculateKey(Step); mAttenuation = mAttenuationKeys.CalculateKey(Step); mLightFactor = mLightFactorKeys.CalculateKey(Step); @@ -971,48 +851,6 @@ void lcLight::UpdatePosition(lcStep Step) mSpotFalloff = mSpotFalloffKeys.CalculateKey(Step); mSpotTightness = mSpotTightnessKeys.CalculateKey(Step); mAreaGrid = mAreaGridKeys.CalculateKey(Step); - - if (IsPointLight()) - { - mWorldLight = lcMatrix44Identity(); - mWorldLight.SetTranslation(-mPosition); - } - else if (IsAreaLight()) - { - lcVector3 UpVector(0, 0, 1), FrontVector(mPosition), SideVector; - FrontVector.Normalize(); - if (fabsf(lcDot(UpVector, FrontVector)) > 0.99f) - SideVector = lcVector3(-1, 0, 0); - else - SideVector = lcCross(FrontVector, UpVector); - UpVector = lcCross(SideVector, FrontVector); - UpVector.Normalize(); - mUpVector = UpVector; - - mWorldLight = lcMatrix44LookAt(mPosition, mTargetPosition, mUpVector); - } - else - { - lcVector3 FrontVector(mTargetPosition - mPosition); - lcVector3 UpVector(1, 1, 1); - - if (fabs(FrontVector[0]) < fabs(FrontVector[1])) - { - if (fabs(FrontVector[0]) < fabs(FrontVector[2])) - UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); - } - else - { - if (fabs(FrontVector[1]) < fabs(FrontVector[2])) - UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); - } - - mWorldLight = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); - } } void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const @@ -1045,34 +883,16 @@ void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const void lcLight::DrawPointLight(lcContext* Context) const { - Context->SetWorldMatrix(lcMatrix44Translation(mPosition)); - - const lcPreferences& Preferences = lcGetPreferences(); - - if (IsFocused(LC_LIGHT_SECTION_POSITION)) - { - const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); - Context->SetColor(FocusedColor); - } - else if (IsSelected(LC_LIGHT_SECTION_POSITION)) - { - const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); - Context->SetColor(SelectedColor); - } - else - { - const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); - Context->SetColor(LightColor); - } + SetupLightMatrix(Context); DrawSphere(Context, LC_LIGHT_SPHERE_RADIUS); } void lcLight::DrawSpotLight(lcContext* Context) const { - constexpr int ConeEdges = 8; - float TargetDistance = SetupLightMatrix(Context); + SetupLightMatrix(Context); + constexpr int ConeEdges = 8; float Verts[(ConeEdges + 1) * 3]; float* CurVert = Verts; @@ -1103,6 +923,8 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->DrawIndexedPrimitives(GL_LINES, (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0); + const float TargetDistance = 25.0f; + DrawTarget(Context, TargetDistance); if (IsSelected()) @@ -1111,16 +933,18 @@ void lcLight::DrawSpotLight(lcContext* Context) const void lcLight::DrawDirectionalLight(lcContext* Context) const { - float TargetDistance = SetupLightMatrix(Context); + SetupLightMatrix(Context); DrawCylinder(Context, LC_LIGHT_DIRECTIONAL_RADIUS, LC_LIGHT_DIRECTIONAL_HEIGHT); + const float TargetDistance = 25.0f; + DrawTarget(Context, TargetDistance); } void lcLight::DrawAreaLight(lcContext* Context) const { - float TargetDistance = SetupLightMatrix(Context); + SetupLightMatrix(Context); if (mLightShape == LC_LIGHT_SHAPE_SQUARE || mLightShape == LC_LIGHT_SHAPE_RECTANGLE) { @@ -1188,99 +1012,14 @@ void lcLight::DrawAreaLight(lcContext* Context) const Context->DrawIndexedPrimitives(GL_LINES, (CircleEdges + 2) * 2, GL_UNSIGNED_SHORT, 0); } - DrawTarget(Context, TargetDistance); - - float Verts[10 * 3]; - float* CurVert = Verts; + const float TargetDistance = 25.0f; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = LC_LIGHT_TARGET_EDGE; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE + 25.0f; *CurVert++ = -LC_LIGHT_TARGET_EDGE; - - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; - *CurVert++ = 0.0f; *CurVert++ = 25.0f; *CurVert++ = 0.0f; - - Context->SetVertexBufferPointer(Verts); - Context->SetVertexFormatPosition(3); - - const GLushort Indices[(12 + 1) * 2] = - { - 0, 1, 1, 2, 2, 3, 3, 0, - 4, 5, 5, 6, 6, 7, 7, 4, - 0, 4, 1, 5, 2, 6, 3, 7, - 8, 9 - }; - - Context->SetIndexBufferPointer(Indices); - - const lcPreferences& Preferences = lcGetPreferences(); - const float LineWidth = Preferences.mLineWidth; - const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); - - if (IsSelected(LC_LIGHT_SECTION_UPVECTOR)) - { - const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); - const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); - - Context->SetLineWidth(2.0f * LineWidth); - - if (IsFocused(LC_LIGHT_SECTION_UPVECTOR)) - Context->SetColor(FocusedColor); - else - Context->SetColor(SelectedColor); - } - else - { - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); - } - - Context->DrawIndexedPrimitives(GL_LINES, 12 * 2, GL_UNSIGNED_SHORT, 0); - - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); - - Context->DrawIndexedPrimitives(GL_LINES, 2, GL_UNSIGNED_SHORT, 12 * 2 * 2); + DrawTarget(Context, TargetDistance); } -float lcLight::SetupLightMatrix(lcContext* Context) const +void lcLight::SetupLightMatrix(lcContext* Context) const { - lcVector3 FrontVector(mTargetPosition - mPosition); - lcVector3 UpVector(1, 1, 1); - - if (IsAreaLight()) - { - UpVector = mUpVector; - } - else - { - if (fabs(FrontVector[0]) < fabs(FrontVector[1])) - { - if (fabs(FrontVector[0]) < fabs(FrontVector[2])) - UpVector[0] = -(UpVector[1] * FrontVector[1] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); - } - else - { - if (fabs(FrontVector[1]) < fabs(FrontVector[2])) - UpVector[1] = -(UpVector[0] * FrontVector[0] + UpVector[2] * FrontVector[2]); - else - UpVector[2] = -(UpVector[0] * FrontVector[0] + UpVector[1] * FrontVector[1]); - } - } - - lcMatrix44 LightMatrix = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector); - LightMatrix = lcMatrix44AffineInverse(LightMatrix); - LightMatrix.SetTranslation(lcVector3(0, 0, 0)); - - const lcMatrix44 LightViewMatrix = lcMul(LightMatrix, lcMatrix44Translation(mPosition)); - Context->SetWorldMatrix(LightViewMatrix); + Context->SetWorldMatrix(mWorldMatrix); const lcPreferences& Preferences = lcGetPreferences(); const float LineWidth = Preferences.mLineWidth; @@ -1304,8 +1043,6 @@ float lcLight::SetupLightMatrix(lcContext* Context) const Context->SetLineWidth(LineWidth); Context->SetColor(LightColor); } - - return FrontVector.Length(); } void lcLight::DrawSphere(lcContext* Context, float Radius) const @@ -1455,34 +1192,7 @@ void lcLight::DrawTarget(lcContext* Context, float TargetDistance) const Context->SetIndexBufferPointer(Indices); - const lcPreferences& Preferences = lcGetPreferences(); - const float LineWidth = Preferences.mLineWidth; - const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); - - if (IsSelected(LC_LIGHT_SECTION_TARGET)) - { - const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); - const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); - - Context->SetLineWidth(2.0f * LineWidth); - - if (IsFocused(LC_LIGHT_SECTION_TARGET)) - Context->SetColor(FocusedColor); - else - Context->SetColor(SelectedColor); - } - else - { - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); - } - - Context->DrawIndexedPrimitives(GL_LINES, 12 * 2, GL_UNSIGNED_SHORT, 0); - - Context->SetLineWidth(LineWidth); - Context->SetColor(LightColor); - - Context->DrawIndexedPrimitives(GL_LINES, 2, GL_UNSIGNED_SHORT, 12 * 2 * 2); + Context->DrawIndexedPrimitives(GL_LINES, (12 + 1) * 2, GL_UNSIGNED_SHORT, 0); } void lcLight::DrawCone(lcContext* Context, float TargetDistance) const @@ -1525,13 +1235,10 @@ void lcLight::DrawCone(lcContext* Context, float TargetDistance) const void lcLight::RemoveKeyFrames() { mPositionKeys.RemoveAll(); - mPositionKeys.ChangeKey(mPosition, 1, true); - - mTargetPositionKeys.RemoveAll(); - mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); + mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true); - mUpVectorKeys.RemoveAll(); - mUpVectorKeys.ChangeKey(mUpVector, 1, true); + mRotationKeys.RemoveAll(); + mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); mColorKeys.RemoveAll(); mColorKeys.ChangeKey(mColor, 1, true); diff --git a/common/light.h b/common/light.h index d70e7cb2..f9425bb0 100644 --- a/common/light.h +++ b/common/light.h @@ -7,19 +7,13 @@ #define LC_LIGHT_DISABLED 0x0002 #define LC_LIGHT_POSITION_SELECTED 0x0010 #define LC_LIGHT_POSITION_FOCUSED 0x0020 -#define LC_LIGHT_TARGET_SELECTED 0x0040 -#define LC_LIGHT_TARGET_FOCUSED 0x0080 -#define LC_LIGHT_UPVECTOR_SELECTED 0x0100 -#define LC_LIGHT_UPVECTOR_FOCUSED 0x0200 -#define LC_LIGHT_SELECTION_MASK (LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED | LC_LIGHT_UPVECTOR_SELECTED) -#define LC_LIGHT_FOCUS_MASK (LC_LIGHT_POSITION_FOCUSED | LC_LIGHT_TARGET_FOCUSED | LC_LIGHT_UPVECTOR_FOCUSED) +#define LC_LIGHT_SELECTION_MASK LC_LIGHT_POSITION_SELECTED +#define LC_LIGHT_FOCUS_MASK LC_LIGHT_POSITION_FOCUSED enum lcLightSection { - LC_LIGHT_SECTION_POSITION, - LC_LIGHT_SECTION_TARGET, - LC_LIGHT_SECTION_UPVECTOR + LC_LIGHT_SECTION_POSITION }; enum class lcLightType @@ -77,7 +71,7 @@ struct lcLightProperties class lcLight : public lcObject { public: - lcLight(const lcVector3& Position, const lcVector3& TargetPosition, lcLightType LightType); + lcLight(const lcVector3& Position, lcLightType LightType); virtual ~lcLight() = default; lcLight(const lcLight&) = delete; @@ -131,41 +125,15 @@ class lcLight : public lcObject case LC_LIGHT_SECTION_POSITION: return (mState & LC_LIGHT_POSITION_SELECTED) != 0; break; - - case LC_LIGHT_SECTION_TARGET: - return (mState & LC_LIGHT_TARGET_SELECTED) != 0; - break; - - case LC_LIGHT_SECTION_UPVECTOR: - return (mState & LC_LIGHT_UPVECTOR_SELECTED) != 0; - break; } + return false; } void SetSelected(bool Selected) override { if (Selected) - { - switch (mLightType) - { - case lcLightType::Point: - mState |= LC_LIGHT_POSITION_SELECTED; - break; - - case lcLightType::Spot: - case lcLightType::Directional: - mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED; - break; - - case lcLightType::Area: - mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED | LC_LIGHT_UPVECTOR_SELECTED; - break; - - case lcLightType::Count: - break; - } - } + mState |= LC_LIGHT_POSITION_SELECTED; else mState &= ~(LC_LIGHT_SELECTION_MASK | LC_LIGHT_FOCUS_MASK); } @@ -180,26 +148,6 @@ class lcLight : public lcObject else mState &= ~(LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED); break; - - case LC_LIGHT_SECTION_TARGET: - if (Selected) - { - if (!IsPointLight()) - mState |= LC_LIGHT_TARGET_SELECTED; - } - else - mState &= ~(LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED); - break; - - case LC_LIGHT_SECTION_UPVECTOR: - if (Selected) - { - if (IsAreaLight()) - mState |= LC_LIGHT_UPVECTOR_SELECTED; - } - else - mState &= ~(LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED); - break; } } @@ -214,15 +162,6 @@ class lcLight : public lcObject { case LC_LIGHT_SECTION_POSITION: return (mState & LC_LIGHT_POSITION_FOCUSED) != 0; - break; - - case LC_LIGHT_SECTION_TARGET: - return (mState & LC_LIGHT_TARGET_FOCUSED) != 0; - break; - - case LC_LIGHT_SECTION_UPVECTOR: - return (mState & LC_LIGHT_UPVECTOR_FOCUSED) != 0; - break; } return false; @@ -238,26 +177,6 @@ class lcLight : public lcObject else mState &= ~(LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED); break; - - case LC_LIGHT_SECTION_TARGET: - if (Focused) - { - if (!IsPointLight()) - mState |= LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED; - } - else - mState &= ~(LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED); - break; - - case LC_LIGHT_SECTION_UPVECTOR: - if (Focused) - { - if (IsAreaLight()) - mState |= LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED; - } - else - mState &= ~(LC_LIGHT_UPVECTOR_SELECTED | LC_LIGHT_UPVECTOR_FOCUSED); - break; } } @@ -266,12 +185,6 @@ class lcLight : public lcObject if (mState & LC_LIGHT_POSITION_FOCUSED) return LC_LIGHT_SECTION_POSITION; - if (!IsPointLight() && (mState & LC_LIGHT_TARGET_FOCUSED)) - return LC_LIGHT_SECTION_TARGET; - - if (IsAreaLight() && (mState & LC_LIGHT_UPVECTOR_FOCUSED)) - return LC_LIGHT_SECTION_UPVECTOR; - return ~0U; } @@ -285,9 +198,6 @@ class lcLight : public lcObject if (Section == LC_LIGHT_SECTION_POSITION) return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ; - if (Section == LC_LIGHT_SECTION_TARGET || Section == LC_LIGHT_SECTION_UPVECTOR) - return LC_OBJECT_TRANSFORM_MOVE_XYZ; - return 0; } @@ -296,47 +206,41 @@ class lcLight : public lcObject const quint32 Section = GetFocusSection(); if (Section == LC_LIGHT_SECTION_POSITION) - { - return lcMatrix33AffineInverse(lcMatrix33(mWorldLight)); - } + return lcMatrix33(mWorldMatrix); else - { return lcMatrix33Identity(); - } } lcVector3 GetSectionPosition(quint32 Section) const override { - switch (Section) - { - case LC_LIGHT_SECTION_POSITION: - return mPosition; + Q_UNUSED(Section); - case LC_LIGHT_SECTION_TARGET: - return mTargetPosition; + return mWorldMatrix.GetTranslation(); + } - case LC_LIGHT_SECTION_UPVECTOR: - return lcMul31(lcVector3(0, 25, 0), lcMatrix44AffineInverse(mWorldLight)); - } + void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey) + { + mPositionKeys.ChangeKey(Position, Step, AddKey); + } - return lcVector3(0.0f, 0.0f, 0.0f); + void SetRotation(const lcMatrix33& Rotation, lcStep Step, bool AddKey) + { + mRotationKeys.ChangeKey(Rotation, Step, AddKey); } lcVector3 GetRotationCenter() const { - const quint32 Section = GetFocusSection(); - - switch (Section) - { - case LC_LIGHT_SECTION_POSITION: - return mPosition; + return mWorldMatrix.GetTranslation(); + } - case LC_LIGHT_SECTION_TARGET: - case LC_LIGHT_SECTION_UPVECTOR: - return mTargetPosition; - } + lcVector3 GetPosition() const + { + return mWorldMatrix.GetTranslation(); + } - return mPosition; + lcVector3 GetDirection() const + { + return -lcVector3(mWorldMatrix[2]); } void SaveLDraw(QTextStream& Stream) const; @@ -383,7 +287,7 @@ class lcLight : public lcObject void CompareBoundingBox(lcVector3& Min, lcVector3& Max); void UpdatePosition(lcStep Step); void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance); - void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcMatrix33& RotationFrame); + void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame); bool Setup(int LightIndex); void CreateName(const lcArray& Lights); void UpdateLight(lcStep Step, lcLightProperties Props, int Property); @@ -405,10 +309,7 @@ class lcLight : public lcObject return props; } - lcMatrix44 mWorldLight; - lcVector3 mPosition; - lcVector3 mTargetPosition; - lcVector3 mUpVector; + lcMatrix44 mWorldMatrix; lcVector3 mAttenuation; lcVector2 mLightFactor; @@ -436,21 +337,20 @@ class lcLight : public lcObject void DrawDirectionalLight(lcContext* Context) const; void DrawAreaLight(lcContext* Context) const; - float SetupLightMatrix(lcContext* Context) const; + void SetupLightMatrix(lcContext* Context) const; void DrawSphere(lcContext* Context, float Radius) const; void DrawCylinder(lcContext* Context, float Radius, float Height) const; void DrawTarget(lcContext* Context, float TargetDistance) const; void DrawCone(lcContext* Context, float TargetDistance) const; - quint32 mState; + quint32 mState = 0; lcLightType mLightType; lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); bool mCastShadow = true; int mLightShape; lcObjectKeyArray mPositionKeys; - lcObjectKeyArray mTargetPositionKeys; - lcObjectKeyArray mUpVectorKeys; + lcObjectKeyArray mRotationKeys; lcObjectKeyArray mColorKeys; lcObjectKeyArray mAttenuationKeys; diff --git a/common/project.cpp b/common/project.cpp index 8a7288c8..694d27ca 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2139,18 +2139,21 @@ bool Project::ExportPOVRay(const QString& FileName) (CameraName.isEmpty() ? "Camera" : CameraName.toLatin1().constData())); POVFile.WriteLine(Line); - lcVector3 LightTarget(0.0f, 0.0f, 0.0f), LightColor(1.0f, 1.0f, 1.0f); lcVector2 AreaSize(200.0f, 200.0f), AreaGrid(10.0f, 10.0f); int AreaCircle = 0, Shadowless = 0; lcLightType LightType = lcLightType::Area; float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0; + if (Lights.IsEmpty()) { + const lcVector3 LightTarget(0.0f, 0.0f, 0.0f), LightColor(1.0f, 1.0f, 1.0f); lcVector3 Location[4]; + Location[0] = {0.0f * Radius + Center[0], -1.5f * Radius + Center[1], -1.5f * Radius + Center[2]}; Location[1] = {1.5f * Radius + Center[0], -1.0f * Radius + Center[1], 0.866026f * Radius + Center[2]}; Location[2] = {0.0f * Radius + Center[0], -2.0f * Radius + Center[1], 0.0f * Radius + Center[2]}; Location[3] = {2.0f * Radius + Center[0], 0.0f * Radius + Center[1], -2.0f * Radius + Center[2]}; + for (int Idx = 0; Idx < 4; Idx++) { Power = Idx < 2 ? 0.75f : 0.5f; @@ -2171,22 +2174,20 @@ bool Project::ExportPOVRay(const QString& FileName) { for (const lcLight* Light : Lights) { - const lcVector3& Location = Light->mPosition; + const lcVector3 LightPosition = Light->GetPosition(); + const lcVector3 LightTarget = LightPosition + Light->GetDirection(); + const lcVector3 LightColor = Light->GetColor(); const QString LightName = QString(Light->mName).replace(" ","_"); LightType = Light->GetLightType(); Shadowless = Light->GetCastShadow() ? 0 : 1; - LightColor = Light->GetColor(); Power = Light->mPOVRayExponent; + switch(LightType) { case lcLightType::Spot: - LightTarget = Light->mTargetPosition; SpotFalloff = Light->mSpotFalloff; SpotRadius = Light->mSpotSize - SpotFalloff; break; - case lcLightType::Directional: - LightTarget = Light->mTargetPosition; - break; case lcLightType::Area: AreaCircle = Light->GetLightShape() == LC_LIGHT_SHAPE_DISK ? 1 : 0; AreaSize = Light->mAreaSize; @@ -2200,7 +2201,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightName.toLatin1().constData(), LightType, Shadowless, - Location[1], Location[0], Location[2], + LightPosition[1], LightPosition[0], LightPosition[2], LightTarget[1], LightTarget[0], LightTarget[2], LightColor[0], LightColor[1], LightColor[2], Power, diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 2a46d2aa..185696b7 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -868,9 +868,11 @@ void lcQPropertiesTree::slotReturnPressed() if (Item == lightPositionX || Item == lightPositionY || Item == lightPositionZ) { - lcVector3 Center = Light->mPosition; + lcVector3 Center = Light->GetPosition(); lcVector3 Position = Center; + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightPositionX) Position[0] = Value; else if (Item == lightPositionY) @@ -884,19 +886,19 @@ void lcQPropertiesTree::slotReturnPressed() } else if (Item == lightTargetX || Item == lightTargetY || Item == lightTargetZ) { - lcVector3 Center = Light->mTargetPosition; - lcVector3 Position = Center; - float Value = lcParseValueLocalized(Editor->text()); - if (Item == lightTargetX) - Position[0] = Value; - else if (Item == lightTargetY) - Position[1] = Value; - else if (Item == lightTargetZ) - Position[2] = Value; - - lcVector3 Distance = Position - Center; - - Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); +// lcVector3 Center = Light->mTargetPosition; +// lcVector3 Position = Center; +// float Value = lcParseValueLocalized(Editor->text()); +// if (Item == lightTargetX) +// Position[0] = Value; +// else if (Item == lightTargetY) +// Position[1] = Value; +// else if (Item == lightTargetZ) +// Position[2] = Value; +// +// lcVector3 Distance = Position - Center; +// +// Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); } else if (Item == lightFactorA || Item == lightFactorB) { @@ -1466,8 +1468,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Format = POVRayLight ? QLatin1String("POVRay") : QLatin1String("Blender"); CastShadow = Light->GetCastShadow(); - Position = Light->mPosition; - Target = Light->mTargetPosition; + Position = Light->GetPosition(); +// Target = Light->mTargetPosition; Color = lcQColorFromVector3(Light->GetColor()); Factor = Light->mLightFactor; LightType = Light->GetLightType(); From 846ddaab0d0a0e8c1404165848f4dfb6f116c701 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Tue, 29 Aug 2023 22:59:06 +0200 Subject: [PATCH 29/42] Blender addon - remove gap scale strategy and gap target options --- common/lc_blenderpreferences.cpp | 12 ++++-------- common/lc_blenderpreferences.h | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index 37bc8c2c..ea83d777 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -241,10 +241,8 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM /* 52/00 LBL_CHOSEN_LOGO */ {"chosenlogo", "logo3", QObject::tr("Chosen Logo"), QObject::tr("Which logo to display. logo and logo2 aren't used and are only included for completeness")}, /* 53/01 LBL_COLOUR_SCHEME_MM */ {"usecolourscheme", "lgeo", QObject::tr("Colour Scheme"), QObject::tr("Colour scheme options - Realistic (lgeo), Original (LDConfig), Alternate (LDCfgalt), Custom (User Defined)")}, /* 54/02 LBL_COLOUR_STRATEGY */ {"colorstrategy", "material", QObject::tr("How To Color Parts"), QObject::tr("Colour strategy options - Material (Default - use if exporting), Vertex colors (slightly quicker to import)")}, - /* 55/03 LBL_GAP_SCALE_STRATEGY */ {"gapscalestrategy", "constraint", QObject::tr("Gap Strategy"), QObject::tr("Apply gap to object directly or scale and empty to adjust to gaps between parts")}, - /* 56/04 LBL_GAP_TARGET */ {"gaptarget", "object", QObject::tr("Gap Target"), QObject::tr("Whether to scale the object data or mesh data")}, - /* 57/05 LBL_RESOLUTION_MM */ {"resolution", "Standard", QObject::tr("Resolution"), QObject::tr("Resolution of part primitives, ie. how much geometry they have")}, - /* 58/06 LBL_SMOOTH_TYPE */ {"smoothtype", "bmesh_split",QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")} + /* 55/03 LBL_RESOLUTION_MM */ {"resolution", "Standard", QObject::tr("Resolution"), QObject::tr("Resolution of part primitives, ie. how much geometry they have")}, + /* 56/04 LBL_SMOOTH_TYPE */ {"smoothtype", "bmesh_split",QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")} }; lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO_ITEMS_MM] = @@ -253,10 +251,8 @@ lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO /* 00 LBL_CHOSEN_LOGO */ {"logo3|logo4|logo5", QObject::tr("Raised flattened logo geometry(3)|Raised rounded logo geometry(4)|Subtle rounded logo geometry(5)")}, /* 01 LBL_COLOUR_SCHEME_MM */ {"lgeo|ldraw|alt|custom", QObject::tr("Realistic Colours|Original LDraw Colours|Alternate LDraw Colours|Custom Colours")}, /* 02 LBL_COLOUR_STRATEGY */ {"material|vertex_colors", QObject::tr("Material|Vertex Colors")}, - /* 03 LBL_GAP_SCALE_STRATEGY */ {"object|constraint", QObject::tr("Gap applied directly to object|Gap scaled to adjust to gaps between parts")}, - /* 04 LBL_GAP_TARGET */ {"object|mesh", QObject::tr("Scale object data|Scale mesh data")}, - /* 05 LBL_RESOLUTION_MM */ {"Low|Standard|High", QObject::tr("Low Resolution Primitives|Standard Primitives|High Resolution Primitives")}, - /* 06 LBL_SMOOTH_TYPE */ {"edge_split|auto_smooth|bmesh_split", QObject::tr("Smooth part faces with edge split modifier|Auto-smooth part faces|Split during initial mesh processing")} + /* 03 LBL_RESOLUTION_MM */ {"Low|Standard|High", QObject::tr("Low Resolution Primitives|Standard Primitives|High Resolution Primitives")}, + /* 04 LBL_SMOOTH_TYPE */ {"bmesh_split|edge_split|auto_smooth", QObject::tr("Split during initial mesh processing|Smooth part faces with edge split modifier|Auto-smooth part faces")} }; lcBlenderPreferences* gAddonPreferences; diff --git a/common/lc_blenderpreferences.h b/common/lc_blenderpreferences.h index c034b7bb..522b61c7 100644 --- a/common/lc_blenderpreferences.h +++ b/common/lc_blenderpreferences.h @@ -292,10 +292,8 @@ private slots: LBL_CHOSEN_LOGO, // 52/ 0 QComboBox LBL_COLOUR_SCHEME_MM, // 53/ 1 QComboBox LBL_COLOUR_STRATEGY, // 54/ 2 QComboBox - LBL_GAP_SCALE_STRATEGY, // 55/ 3 QComboBox - LBL_GAP_TARGET, // 56/ 4 QComboBox - LBL_RESOLUTION_MM, // 57/ 5 QComboBox - LBL_SMOOTH_TYPE, // 58/ 6 QComboBox + LBL_RESOLUTION_MM, // 55/ 3 QComboBox + LBL_SMOOTH_TYPE, // 56/ 4 QComboBox NUM_SETTINGS_MM }; @@ -314,16 +312,14 @@ private slots: CTL_COLOUR_STRATEGY_COMBO = CTL_BLEND_FILE_TRUSTED_BOX_MM,// 2 CTL_CASE_SENSITIVE_FILESYSTEM_BOX, // 3 CTL_CAMERA_BORDER_PERCENT_EDIT_MM = CTL_CASE_SENSITIVE_FILESYSTEM_BOX,// 3 - CTL_GAP_SCALE_STRATEGY_COMBO = CTL_CASE_SENSITIVE_FILESYSTEM_BOX,// 3 + CTL_RESOLUTION_COMBO_MM = CTL_CASE_SENSITIVE_FILESYSTEM_BOX,// 3 CTL_CROP_IMAGE_BOX_MM, // 4 CTL_FRAMES_PER_STEP_EDIT = CTL_CROP_IMAGE_BOX_MM, // 4 - CTL_GAP_TARGET_COMBO = CTL_CROP_IMAGE_BOX_MM, // 4 + CTL_SMOOTH_TYPE_COMBO = CTL_CROP_IMAGE_BOX_MM, // 4 CTL_DISPLAY_LOGO_BOX, // 5 CTL_GAP_SCALE_EDIT = CTL_DISPLAY_LOGO_BOX, // 5 - CTL_RESOLUTION_COMBO_MM = CTL_DISPLAY_LOGO_BOX, // 5 CTL_IMPORT_CAMERAS_BOX_MM, // 6 CTL_IMPORT_SCALE_EDIT = CTL_IMPORT_CAMERAS_BOX_MM, // 6 - CTL_SMOOTH_TYPE_COMBO = CTL_IMPORT_CAMERAS_BOX_MM, // 6 CTL_IMPORT_EDGES_BOX, // 7 CTL_MERGE_DISTANCE_EDIT = CTL_IMPORT_EDGES_BOX, // 7 CTL_IMPORT_LIGHTS_BOX_MM, // 8 From e061eca2e8809637c2ee10f49c165c16baa0ec6d Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 9 Sep 2023 18:25:34 -0700 Subject: [PATCH 30/42] Reorganized spot light parameters. --- common/lc_commands.cpp | 44 +++---- common/lc_commands.h | 2 +- common/lc_mainwindow.cpp | 2 +- common/lc_model.cpp | 44 ++++++- common/lc_model.h | 3 + common/lc_view.cpp | 20 ++-- common/lc_view.h | 4 +- common/lc_viewmanipulator.cpp | 2 +- common/light.cpp | 195 +++++++++++++++++-------------- common/light.h | 46 +++++--- common/project.cpp | 4 +- qt/lc_qpropertiestree.cpp | 208 +++++++++++++--------------------- qt/lc_qpropertiestree.h | 11 +- 13 files changed, 304 insertions(+), 281 deletions(-) diff --git a/common/lc_commands.cpp b/common/lc_commands.cpp index 94530fa4..00d5620b 100644 --- a/common/lc_commands.cpp +++ b/common/lc_commands.cpp @@ -645,28 +645,28 @@ const lcCommand gCommands[] = { QT_TRANSLATE_NOOP("Action", "Edit.Tool.PointLight"), QT_TRANSLATE_NOOP("Menu", "Point Light"), - QT_TRANSLATE_NOOP("Status", "Add new omni light sources to the model"), + QT_TRANSLATE_NOOP("Status", "Add new point light sources to the model"), "" }, // LC_EDIT_ACTION_SPOTLIGHT { - QT_TRANSLATE_NOOP("Action", "Edit.Tool.Spotlight"), - QT_TRANSLATE_NOOP("Menu", "Spotlight"), - QT_TRANSLATE_NOOP("Status", "Add new spotlights to the model"), + QT_TRANSLATE_NOOP("Action", "Edit.Tool.SpotLight"), + QT_TRANSLATE_NOOP("Menu", "Spot Light"), + QT_TRANSLATE_NOOP("Status", "Add new spot lights to the model"), "" }, // LC_EDIT_ACTION_DIRECTIONAL_LIGHT { QT_TRANSLATE_NOOP("Action", "Edit.Tool.DirectionalLight"), QT_TRANSLATE_NOOP("Menu", "Directional Light"), - QT_TRANSLATE_NOOP("Status", "Add new omnidirectional sunlight sources to the model - edit in Properties tab"), + QT_TRANSLATE_NOOP("Status", "Add new omnidirectional light sources to the model"), "" }, // LC_EDIT_ACTION_AREA_LIGHT { QT_TRANSLATE_NOOP("Action", "Edit.Tool.AreaLight"), QT_TRANSLATE_NOOP("Menu", "Area Light"), - QT_TRANSLATE_NOOP("Status", "Add new arealight sources to the model - edit in Properties tab"), + QT_TRANSLATE_NOOP("Status", "Add new area light sources to the model"), "" }, // LC_EDIT_ACTION_CAMERA @@ -1872,23 +1872,23 @@ LC_ARRAY_SIZE_CHECK(gCommands, LC_NUM_COMMANDS); const char* gToolNames[] = { - QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert - QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::PointLight - QT_TRANSLATE_NOOP("Mouse", "NewSpotlight"), // lcTool::Spotlight + QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert + QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::PointLight + QT_TRANSLATE_NOOP("Mouse", "NewSpotLight"), // lcTool::SpotLight QT_TRANSLATE_NOOP("Mouse", "NewDirectionalLight"), // lcTool::DirectionalLight - QT_TRANSLATE_NOOP("Mouse", "NewAreaLight"), // lcTool::AreaLight - QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera - QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select - QT_TRANSLATE_NOOP("Mouse", "Move"), // lcTool::Move - QT_TRANSLATE_NOOP("Mouse", "Rotate"), // lcTool::Rotate - QT_TRANSLATE_NOOP("Mouse", "Delete"), // lcTool::Eraser - QT_TRANSLATE_NOOP("Mouse", "Paint"), // lcTool::Paint - QT_TRANSLATE_NOOP("Mouse", "ColorPicker"), // lcTool::ColorPicker - QT_TRANSLATE_NOOP("Mouse", "Zoom"), // lcTool::Zoom - QT_TRANSLATE_NOOP("Mouse", "Pan"), // lcTool::Pan - QT_TRANSLATE_NOOP("Mouse", "Orbit"), // lcTool::RotateView - QT_TRANSLATE_NOOP("Mouse", "Roll"), // lcTool::Roll - QT_TRANSLATE_NOOP("Mouse", "ZoomRegion") // lcTool::ZoomRegion + QT_TRANSLATE_NOOP("Mouse", "NewAreaLight"), // lcTool::AreaLight + QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera + QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select + QT_TRANSLATE_NOOP("Mouse", "Move"), // lcTool::Move + QT_TRANSLATE_NOOP("Mouse", "Rotate"), // lcTool::Rotate + QT_TRANSLATE_NOOP("Mouse", "Delete"), // lcTool::Eraser + QT_TRANSLATE_NOOP("Mouse", "Paint"), // lcTool::Paint + QT_TRANSLATE_NOOP("Mouse", "ColorPicker"), // lcTool::ColorPicker + QT_TRANSLATE_NOOP("Mouse", "Zoom"), // lcTool::Zoom + QT_TRANSLATE_NOOP("Mouse", "Pan"), // lcTool::Pan + QT_TRANSLATE_NOOP("Mouse", "Orbit"), // lcTool::RotateView + QT_TRANSLATE_NOOP("Mouse", "Roll"), // lcTool::Roll + QT_TRANSLATE_NOOP("Mouse", "ZoomRegion") // lcTool::ZoomRegion }; LC_ARRAY_SIZE_CHECK(gToolNames, lcTool::Count); diff --git a/common/lc_commands.h b/common/lc_commands.h index ea334c92..f88091ca 100644 --- a/common/lc_commands.h +++ b/common/lc_commands.h @@ -301,7 +301,7 @@ enum class lcTool { Insert, PointLight, - Spotlight, + SpotLight, DirectionalLight, AreaLight, Camera, diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 41291e97..80a596f0 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -3389,7 +3389,7 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) break; case LC_EDIT_ACTION_SPOTLIGHT: - SetTool(lcTool::Spotlight); + SetTool(lcTool::SpotLight); break; case LC_EDIT_ACTION_CAMERA: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 80b7e3dd..1085028d 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3184,6 +3184,45 @@ void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color) UpdateAllViews(); } +void lcModel::SetSpotLightConeAngle(lcLight* Light, float Angle) +{ + if (Light->GetSpotConeAngle() == Angle) + return; + + Light->SetSpotConeAngle(Angle, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Spot Light Cone Angle")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + +void lcModel::SetSpotLightPenumbraAngle(lcLight* Light, float Angle) +{ + if (Light->GetSpotPenumbraAngle() == Angle) + return; + + Light->SetSpotPenumbraAngle(Angle, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Spot Light Penumbra Angle")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + +void lcModel::SetSpotLightTightness(lcLight* Light, float Tightness) +{ + if (Light->GetSpotTightness() == Tightness) + return; + + Light->SetSpotTightness(Tightness, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Spot Light Tightness")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetLightCastShadow(lcLight* Light, bool CastShadow) { if (Light->GetCastShadow() == CastShadow) @@ -4179,14 +4218,11 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) { case lcTool::Insert: case lcTool::PointLight: + case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: break; - case lcTool::Spotlight: - SaveCheckpoint(tr("New Spotlight")); - break; - case lcTool::Camera: gMainWindow->UpdateCameraMenu(); SaveCheckpoint(tr("New Camera")); diff --git a/common/lc_model.h b/common/lc_model.h index 24143383..0adcc909 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -370,6 +370,9 @@ class lcModel void SetLightType(lcLight* Light, lcLightType LightType); void SetLightColor(lcLight* Light, const lcVector3& Color); + void SetSpotLightConeAngle(lcLight* Light, float Angle); + void SetSpotLightPenumbraAngle(lcLight* Light, float Angle); + void SetSpotLightTightness(lcLight* Light, float Tightness); void SetLightCastShadow(lcLight* Light, bool CastShadow); void SetLightName(lcLight* Light, const QString& Name); void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 7151b0bc..13aeabb6 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -1597,7 +1597,7 @@ lcTrackTool lcView::GetOverrideTrackTool(Qt::MouseButton Button) const { lcTrackTool::Insert, // lcTool::Insert lcTrackTool::PointLight, // lcTool::PointLight - lcTrackTool::Spotlight, // lcTool::Spotlight + lcTrackTool::SpotLight, // lcTool::SpotLight lcTrackTool::DirectionalLight, // lcTool::DirectionalLight lcTrackTool::AreaLight, // lcTool::AreaLight lcTrackTool::Camera, // lcTool::Camera @@ -1870,7 +1870,7 @@ lcCursor lcView::GetCursor() const lcCursor::Select, // lcTrackTool::None lcCursor::Brick, // lcTrackTool::Insert lcCursor::PointLight, // lcTrackTool::PointLight - lcCursor::Spotlight, // lcTrackTool::Spotlight + lcCursor::SpotLight, // lcTrackTool::SpotLight lcCursor::DirectionalLight, // lcTrackTool::DirectionalLight lcCursor::AreaLight, // lcTrackTool::AreaLight lcCursor::Camera, // lcTrackTool::Camera @@ -1926,7 +1926,7 @@ void lcView::SetCursor(lcCursor CursorType) { 0, 0, "" }, // lcCursor::Default { 8, 3, ":/resources/cursor_insert" }, // lcCursor::Brick { 15, 15, ":/resources/cursor_light" }, // lcCursor::PointLight - { 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::Spotlight + { 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::SpotLight { 15, 15, ":/resources/cursor_sunlight" }, // lcCursor::DirectionalLight { 15, 15, ":/resources/cursor_arealight" }, // lcCursor::AreaLight { 15, 9, ":/resources/cursor_camera" }, // lcCursor::Camera @@ -1979,7 +1979,7 @@ lcTool lcView::GetCurrentTool() const lcTool::Select, // lcTrackTool::None lcTool::Insert, // lcTrackTool::Insert lcTool::PointLight, // lcTrackTool::PointLight - lcTool::Spotlight, // lcTrackTool::Spotlight + lcTool::SpotLight, // lcTrackTool::SpotLight lcTool::DirectionalLight, // lcTrackTool::DirectionalLight lcTool::AreaLight, // lcTrackTool::AreaLight lcTool::Camera, // lcTrackTool::Camera @@ -2045,8 +2045,8 @@ void lcView::UpdateTrackTool() NewTrackTool = lcTrackTool::PointLight; break; - case lcTool::Spotlight: - NewTrackTool = lcTrackTool::Spotlight; + case lcTool::SpotLight: + NewTrackTool = lcTrackTool::SpotLight; break; case lcTool::DirectionalLight: @@ -2276,7 +2276,7 @@ void lcView::StartTracking(lcTrackButton TrackButton) { case lcTool::Insert: case lcTool::PointLight: - case lcTool::Spotlight: + case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: break; @@ -2337,7 +2337,7 @@ void lcView::StopTracking(bool Accept) case lcTool::PointLight: break; - case lcTool::Spotlight: + case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: case lcTool::Camera: @@ -2469,7 +2469,7 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) AddLight(lcLightType::Point); break; - case lcTrackTool::Spotlight: + case lcTrackTool::SpotLight: AddLight(lcLightType::Spot); break; @@ -2715,7 +2715,7 @@ void lcView::OnMouseMove() case lcTrackTool::None: case lcTrackTool::Insert: case lcTrackTool::PointLight: - case lcTrackTool::Spotlight: + case lcTrackTool::SpotLight: case lcTrackTool::DirectionalLight: case lcTrackTool::AreaLight: break; diff --git a/common/lc_view.h b/common/lc_view.h index 4aa934a0..1dfae560 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -18,7 +18,7 @@ enum class lcCursor Default, Brick, PointLight, - Spotlight, + SpotLight, DirectionalLight, AreaLight, Camera, @@ -53,7 +53,7 @@ enum class lcTrackTool None, Insert, PointLight, - Spotlight, + SpotLight, DirectionalLight, AreaLight, Camera, diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index 753a42fd..1d7bcaa0 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -674,7 +674,7 @@ bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 Allowe case lcTrackTool::None: case lcTrackTool::Insert: case lcTrackTool::PointLight: - case lcTrackTool::Spotlight: + case lcTrackTool::SpotLight: case lcTrackTool::DirectionalLight: case lcTrackTool::AreaLight: case lcTrackTool::Camera: diff --git a/common/light.cpp b/common/light.cpp index de6e8f57..334e0bbb 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -33,10 +33,7 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mLightSpecular = 1.0f; mSpotExponent = 10.0f; mPOVRayExponent = 1.0f; - mSpotSize = 75.0f; mSpotCutoff = LightType != lcLightType::Directional ? 40.0f : 0.0f; - mSpotFalloff = 45.0f; - mSpotTightness = 0; mAreaGrid = lcVector2(10.0f, 10.0f); mAreaSize = lcVector2(200.0f, 200.0f); mLightShape = LC_LIGHT_SHAPE_SQUARE; @@ -44,16 +41,16 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true); mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); mColorKeys.ChangeKey(mColor, 1, true); + mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); + mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); + mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); mLightFactorKeys.ChangeKey(mLightFactor, 1, true); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); - mSpotFalloffKeys.ChangeKey(mSpotFalloff, 1, true); mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); - mSpotSizeKeys.ChangeKey(mSpotSize, 1, true); - mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); UpdatePosition(1); @@ -67,7 +64,7 @@ QString lcLight::GetLightTypeString(lcLightType LightType) return QT_TRANSLATE_NOOP("Light Names", "Point Light"); case lcLightType::Spot: - return QT_TRANSLATE_NOOP("Light Names", "Spotlight"); + return QT_TRANSLATE_NOOP("Light Names", "Spot Light"); case lcLightType::Directional: return QT_TRANSLATE_NOOP("Light Names", "Directional Light"); @@ -155,28 +152,26 @@ void lcLight::SaveLDraw(QTextStream& Stream) const break; case lcLightType::Spot: + if (mSpotConeAngleKeys.GetSize() > 1) + mSpotConeAngleKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_CONE_ANGLE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_CONE_ANGLE ") << mSpotConeAngle << LineEnding; + + if (mSpotPenumbraAngleKeys.GetSize() > 1) + mSpotPenumbraAngleKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_PENUMBRA_ANGLE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_PENUMBRA_ANGLE ") << mSpotPenumbraAngle << LineEnding; + + if (mSpotTightnessKeys.GetSize() > 1) + mSpotTightnessKeys.SaveKeysLDraw(Stream, "SPOT_TIGHTNESS_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_TIGHTNESS ") << mSpotTightness << LineEnding; + if (mPOVRayLight) { - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << (mSpotSize - mSpotFalloff) << LineEnding; - if (mSpotFalloffKeys.GetSize() > 1) - mSpotFalloffKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_FALLOFF_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_FALLOFF ") << mSpotFalloff << LineEnding; - if (mSpotTightnessKeys.GetSize() > 1) - mSpotTightnessKeys.SaveKeysLDraw(Stream, "SPOT_TIGHTNESS_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_TIGHTNESS ") << mSpotTightness << LineEnding; } else { - if (mSpotSizeKeys.GetSize() > 1) - mSpotSizeKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_SIZE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_SIZE ") << mSpotSize << LineEnding; - if (mLightFactorKeys.GetSize() > 1) mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); else @@ -282,7 +277,7 @@ void lcLight::CreateName(const lcArray& Lights) break; case lcLightType::Spot: - Prefix = QLatin1String("Spotlight "); + Prefix = QLatin1String("Spot Light "); break; case lcLightType::Directional: @@ -362,6 +357,28 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if (Token == QLatin1String("COLOR_KEY")) mColorKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPOT_CONE_ANGLE")) + { + Stream >> mSpotConeAngle; + mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); + } + else if (Token == QLatin1String("SPOT_CONE_ANGLE_KEY")) + mSpotConeAngleKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPOT_PENUMBRA_ANGLE")) + { + Stream >> mSpotPenumbraAngle; + mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); + } + else if (Token == QLatin1String("SPOT_PENUMBRA_ANGLE_KEY")) + mSpotPenumbraAngleKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SPOT_TIGHTNESS")) + { + mPOVRayLight = true; + Stream >> mSpotTightness; + mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); + } + else if (Token == QLatin1String("SPOT_TIGHTNESS_KEY")) + mSpotTightnessKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) { if (mPOVRayLight) @@ -406,23 +423,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) Stream >> mAreaGrid[1]; mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); } - else if (Token == QLatin1String("SPOT_FALLOFF")) - { - mPOVRayLight = true; - Stream >> mSpotFalloff; - mSpotFalloffKeys.ChangeKey(mSpotFalloff, 1, true); - } - else if (Token == QLatin1String("SPOT_TIGHTNESS")) - { - mPOVRayLight = true; - Stream >> mSpotTightness; - mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); - } - else if (Token == QLatin1String("SPOT_SIZE")) - { - Stream >> mSpotSize; - mSpotSizeKeys.ChangeKey(mSpotSize, 1, true); - } else if (Token == QLatin1String("SHAPE")) { QString Shape; @@ -480,12 +480,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) mSpotExponentKeys.LoadKeysLDraw(Stream); else if ((Token == QLatin1String("ANGLE_KEY")) || (Token == QLatin1String("RADIUS_KEY")) || (Token == QLatin1String("SIZE_KEY")) || (Token == QLatin1String("RADIUS_AND_SPOT_BLEND_KEY"))) mLightFactorKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SPOT_SIZE_KEY")) - mSpotSizeKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SPOT_FALLOFF_KEY")) - mSpotFalloffKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SPOT_TIGHTNESS_KEY")) - mSpotTightnessKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("AREA_GRID_KEY")) mAreaGridKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("DIFFUSE_KEY")) @@ -602,18 +596,6 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) mAreaGrid = Props.mAreaGrid; mAreaGridKeys.ChangeKey(mAreaGrid, Step, false); break; - case LC_LIGHT_SPOT_SIZE: - mSpotSize = Props.mSpotSize; - mSpotSizeKeys.ChangeKey(mSpotSize, Step, false); - break; - case LC_LIGHT_SPOT_FALLOFF: - mSpotFalloff = Props.mSpotFalloff; - mSpotFalloffKeys.ChangeKey(mSpotFalloff, Step, false); - break; - case LC_LIGHT_SPOT_TIGHTNESS: - mSpotTightness = Props.mSpotTightness; - mSpotTightnessKeys.ChangeKey(mSpotTightness, Step, false); - break; case LC_LIGHT_CUTOFF: mSpotCutoff = Props.mSpotCutoff; mSpotCutoffKeys.ChangeKey(mSpotCutoff, Step, false); @@ -786,6 +768,21 @@ void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey) mColorKeys.ChangeKey(Color, Step, AddKey); } +void lcLight::SetSpotConeAngle(float Angle, lcStep Step, bool AddKey) +{ + mSpotConeAngleKeys.ChangeKey(Angle, Step, AddKey); +} + +void lcLight::SetSpotPenumbraAngle(float Angle, lcStep Step, bool AddKey) +{ + mSpotPenumbraAngleKeys.ChangeKey(Angle, Step, AddKey); +} + +void lcLight::SetSpotTightness(float Tightness, lcStep Step, bool AddKey) +{ + mSpotTightnessKeys.ChangeKey(Tightness, Step, AddKey); +} + void lcLight::SetCastShadow(bool CastShadow) { mCastShadow = CastShadow; @@ -796,15 +793,16 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mPositionKeys.InsertTime(Start, Time); mRotationKeys.InsertTime(Start, Time); mColorKeys.InsertTime(Start, Time); + mSpotConeAngleKeys.InsertTime(Start, Time); + mSpotPenumbraAngleKeys.InsertTime(Start, Time); + mSpotTightnessKeys.InsertTime(Start, Time); + mAttenuationKeys.InsertTime(Start, Time); mLightFactorKeys.InsertTime(Start, Time); mLightDiffuseKeys.InsertTime(Start, Time); mLightSpecularKeys.InsertTime(Start, Time); - mSpotSizeKeys.InsertTime(Start, Time); mSpotCutoffKeys.InsertTime(Start, Time); mSpotExponentKeys.InsertTime(Start, Time); - mSpotFalloffKeys.InsertTime(Start, Time); - mSpotTightnessKeys.InsertTime(Start, Time); mAreaGridKeys.InsertTime(Start, Time); } @@ -813,15 +811,16 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mPositionKeys.RemoveTime(Start, Time); mRotationKeys.RemoveTime(Start, Time); mColorKeys.RemoveTime(Start, Time); + mSpotConeAngleKeys.RemoveTime(Start, Time); + mSpotPenumbraAngleKeys.RemoveTime(Start, Time); + mSpotTightnessKeys.RemoveTime(Start, Time); + mAttenuationKeys.RemoveTime(Start, Time); mLightFactorKeys.RemoveTime(Start, Time); mLightDiffuseKeys.RemoveTime(Start, Time); mLightSpecularKeys.RemoveTime(Start, Time); - mSpotSizeKeys.RemoveTime(Start, Time); mSpotCutoffKeys.RemoveTime(Start, Time); mSpotExponentKeys.RemoveTime(Start, Time); - mSpotFalloffKeys.RemoveTime(Start, Time); - mSpotTightnessKeys.RemoveTime(Start, Time); mAreaGridKeys.RemoveTime(Start, Time); } @@ -841,15 +840,16 @@ void lcLight::UpdatePosition(lcStep Step) } mColor = mColorKeys.CalculateKey(Step); + mSpotConeAngle = mSpotConeAngleKeys.CalculateKey(Step); + mSpotPenumbraAngle = mSpotPenumbraAngleKeys.CalculateKey(Step); + mSpotTightness = mSpotTightnessKeys.CalculateKey(Step); + mAttenuation = mAttenuationKeys.CalculateKey(Step); mLightFactor = mLightFactorKeys.CalculateKey(Step); mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); mLightSpecular = mLightSpecularKeys.CalculateKey(Step); - mSpotSize = mSpotSizeKeys.CalculateKey(Step); mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); mSpotExponent = mSpotExponentKeys.CalculateKey(Step); - mSpotFalloff = mSpotFalloffKeys.CalculateKey(Step); - mSpotTightness = mSpotTightnessKeys.CalculateKey(Step); mAreaGrid = mAreaGridKeys.CalculateKey(Step); } @@ -923,7 +923,7 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->DrawIndexedPrimitives(GL_LINES, (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0); - const float TargetDistance = 25.0f; + const float TargetDistance = 250.0f; DrawTarget(Context, TargetDistance); @@ -1198,18 +1198,18 @@ void lcLight::DrawTarget(lcContext* Context, float TargetDistance) const void lcLight::DrawCone(lcContext* Context, float TargetDistance) const { constexpr int ConeEdges = 16; - const float Radius = tanf(LC_DTOR * mSpotCutoff) * TargetDistance; + const float OuterRadius = tanf(LC_DTOR * mSpotConeAngle / 2.0f) * TargetDistance; - float Verts[(ConeEdges + 1) * 3]; + float Verts[(ConeEdges * 2 + 1) * 3]; float* CurVert = Verts; for (int EdgeIndex = 0; EdgeIndex < ConeEdges; EdgeIndex++) { - float c = cosf((float)EdgeIndex / ConeEdges * LC_2PI) * Radius; - float s = sinf((float)EdgeIndex / ConeEdges * LC_2PI) * Radius; + const float c = cosf((float)EdgeIndex / ConeEdges * LC_2PI); + const float s = sinf((float)EdgeIndex / ConeEdges * LC_2PI); - *CurVert++ = c; - *CurVert++ = s; + *CurVert++ = c * OuterRadius; + *CurVert++ = s * OuterRadius; *CurVert++ = -TargetDistance; } @@ -1217,19 +1217,38 @@ void lcLight::DrawCone(lcContext* Context, float TargetDistance) const *CurVert++ = 0.0f; *CurVert++ = 0.0f; + const bool DrawPenumbra = mSpotPenumbraAngle > 1.0f; + + if (DrawPenumbra) + { + const float InnerRadius = tanf(LC_DTOR * (mSpotConeAngle / 2.0f - mSpotPenumbraAngle)) * TargetDistance; + + for (int EdgeIndex = 0; EdgeIndex < ConeEdges; EdgeIndex++) + { + const float c = cosf((float)EdgeIndex / ConeEdges * LC_2PI); + const float s = sinf((float)EdgeIndex / ConeEdges * LC_2PI); + + *CurVert++ = c * InnerRadius; + *CurVert++ = s * InnerRadius; + *CurVert++ = -TargetDistance; + } + } + Context->SetVertexBufferPointer(Verts); Context->SetVertexFormatPosition(3); - const GLushort Indices[(ConeEdges + 4) * 2] = + constexpr GLushort Indices[(ConeEdges * 2 + 4) * 2] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 0, - 16, 0, 16, 4, 16, 8, 16, 12 + 16, 0, 16, 4, 16, 8, 16, 12, + 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, + 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 17 }; Context->SetIndexBufferPointer(Indices); - Context->DrawIndexedPrimitives(GL_LINES, (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0); + Context->DrawIndexedPrimitives(GL_LINES, DrawPenumbra ? (ConeEdges * 2 + 4) * 2 : (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0); } void lcLight::RemoveKeyFrames() @@ -1243,6 +1262,15 @@ void lcLight::RemoveKeyFrames() mColorKeys.RemoveAll(); mColorKeys.ChangeKey(mColor, 1, true); + mSpotConeAngleKeys.RemoveAll(); + mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, false); + + mSpotPenumbraAngleKeys.RemoveAll(); + mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); + + mSpotTightnessKeys.RemoveAll(); + mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); + mAttenuationKeys.RemoveAll(); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); @@ -1255,21 +1283,12 @@ void lcLight::RemoveKeyFrames() mLightSpecularKeys.RemoveAll(); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); - mSpotSizeKeys.RemoveAll(); - mSpotSizeKeys.ChangeKey(mSpotSize, 1, false); - mSpotCutoffKeys.RemoveAll(); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); mSpotExponentKeys.RemoveAll(); mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); - mSpotFalloffKeys.RemoveAll(); - mSpotFalloffKeys.ChangeKey(mSpotFalloff, 1, true); - - mSpotTightnessKeys.RemoveAll(); - mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); - mAreaGridKeys.RemoveAll(); mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); } diff --git a/common/light.h b/common/light.h index f9425bb0..eeb67feb 100644 --- a/common/light.h +++ b/common/light.h @@ -44,9 +44,6 @@ enum lcLightProperty LC_LIGHT_SPECULAR, LC_LIGHT_EXPONENT, LC_LIGHT_AREA_GRID, - LC_LIGHT_SPOT_SIZE, - LC_LIGHT_SPOT_FALLOFF, - LC_LIGHT_SPOT_TIGHTNESS, LC_LIGHT_CUTOFF, LC_LIGHT_USE_CUTOFF, LC_LIGHT_POVRAY @@ -60,9 +57,6 @@ struct lcLightProperties float mLightSpecular; float mSpotExponent; float mSpotCutoff; - float mSpotFalloff; - float mSpotTightness; - float mSpotSize; bool mEnableCutoff; bool mPOVRayLight; int mLightShape; @@ -86,7 +80,7 @@ class lcLight : public lcObject return mLightType == lcLightType::Point; } - bool IsSpotlight() const + bool IsSpotLight() const { return mLightType == lcLightType::Spot; } @@ -267,6 +261,27 @@ class lcLight : public lcObject return mColor; } + void SetSpotConeAngle(float Angle, lcStep Step, bool AddKey); + + float GetSpotConeAngle() const + { + return mSpotConeAngle; + } + + void SetSpotPenumbraAngle(float Angle, lcStep Step, bool AddKey); + + float GetSpotPenumbraAngle() const + { + return mSpotPenumbraAngle; + } + + void SetSpotTightness(float Angle, lcStep Step, bool AddKey); + + float GetSpotTightness() const + { + return mSpotTightness; + } + void SetCastShadow(bool CastShadow); bool GetCastShadow() const @@ -299,9 +314,6 @@ class lcLight : public lcObject props.mLightSpecular = mLightSpecular; props.mSpotExponent = mSpotExponent; props.mSpotCutoff = mSpotCutoff; - props.mSpotFalloff = mSpotFalloff; - props.mSpotTightness = mSpotTightness; - props.mSpotSize = mSpotSize; props.mPOVRayLight = mPOVRayLight; props.mEnableCutoff = mEnableCutoff; props.mAreaGrid = mAreaGrid; @@ -323,10 +335,7 @@ class lcLight : public lcObject bool mPOVRayLight; float mLightDiffuse; float mLightSpecular; - float mSpotSize; float mSpotCutoff; - float mSpotFalloff; - float mSpotTightness; float mSpotExponent; float mPOVRayExponent; QString mName; @@ -345,22 +354,25 @@ class lcLight : public lcObject quint32 mState = 0; lcLightType mLightType; - lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); bool mCastShadow = true; + lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); + float mSpotConeAngle = 80.0f; + float mSpotPenumbraAngle = 0.0f; + float mSpotTightness = 0.0f; int mLightShape; lcObjectKeyArray mPositionKeys; lcObjectKeyArray mRotationKeys; lcObjectKeyArray mColorKeys; + lcObjectKeyArray mSpotConeAngleKeys; + lcObjectKeyArray mSpotPenumbraAngleKeys; + lcObjectKeyArray mSpotTightnessKeys; lcObjectKeyArray mAttenuationKeys; lcObjectKeyArray mLightFactorKeys; lcObjectKeyArray mAreaGridKeys; lcObjectKeyArray mLightSpecularKeys; lcObjectKeyArray mLightDiffuseKeys; - lcObjectKeyArray mSpotSizeKeys; lcObjectKeyArray mSpotCutoffKeys; - lcObjectKeyArray mSpotFalloffKeys; lcObjectKeyArray mSpotExponentKeys; - lcObjectKeyArray mSpotTightnessKeys; }; diff --git a/common/project.cpp b/common/project.cpp index 694d27ca..67ed8583 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2185,8 +2185,8 @@ bool Project::ExportPOVRay(const QString& FileName) switch(LightType) { case lcLightType::Spot: - SpotFalloff = Light->mSpotFalloff; - SpotRadius = Light->mSpotSize - SpotFalloff; + SpotFalloff = Light->GetSpotConeAngle() / 2.0f; + SpotRadius = SpotFalloff - Light->GetSpotPenumbraAngle(); break; case lcLightType::Area: AreaCircle = Light->GetLightShape() == LC_LIGHT_SHAPE_DISK ? 1 : 0; diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 185696b7..4d248702 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -423,11 +423,11 @@ class lcStepValidator : public QIntValidator bool mAllowEmpty; }; -QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) const +QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) const { - PropertyType propertyType = (PropertyType)item->data(0, lcQPropertiesTree::PropertyTypeRole).toInt(); + lcQPropertiesTree::PropertyType PropertyType = (lcQPropertiesTree::PropertyType)Item->data(0, lcQPropertiesTree::PropertyTypeRole).toInt(); - switch (propertyType) + switch (PropertyType) { case PropertyGroup: case PropertyBool: @@ -435,65 +435,40 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyFloat: { - QLineEdit *editor = new QLineEdit(parent); - float value = item->data(0, PropertyValueRole).toFloat(); + QLineEdit* Editor = new QLineEdit(Parent); + float Value = Item->data(0, PropertyValueRole).toFloat(); + QPointF Range = Item->data(0, PropertyRangeRole).toPointF(); - editor->setValidator(new QDoubleValidator(editor)); - editor->setText(lcFormatValueLocalized(value)); + Editor->setValidator(Range.isNull() ? new QDoubleValidator(Editor) : new QDoubleValidator(Range.x(), Range.y(), 1, Editor)); + Editor->setText(lcFormatValueLocalized(Value)); - connect(editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); + connect(Editor, &QLineEdit::returnPressed, this, &lcQPropertiesTree::slotReturnPressed); - return editor; - } - - case PropertyFloatLightSpotSize: - { - QLineEdit *editor = new QLineEdit(parent); - float value = item->data(0, PropertyValueRole).toFloat(); - - editor->setValidator(new QDoubleValidator(1.0, 180.0,1, editor)); - editor->setText(lcFormatValueLocalized(value)); - editor->setToolTip(tr("Angle of the spotlight beam.")); - - connect(editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); - return editor; + return Editor; } - case PropertyFloatLightSpotFalloff: - { - QLineEdit *editor = new QLineEdit(parent); - float value = item->data(0, PropertyValueRole).toFloat(); - - editor->setValidator(new QDoubleValidator(1.0, 90.0,1, editor)); - editor->setText(lcFormatValueLocalized(value)); - editor->setToolTip(tr("Angle of the spotlight beam beteeen the cone edge and center line.")); - - connect(editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); - return editor; - } - case PropertyFloatReadOnly: return nullptr; case PropertyStep: { - QLineEdit* Editor = new QLineEdit(parent); + QLineEdit* Editor = new QLineEdit(Parent); - lcStep Value = item->data(0, PropertyValueRole).toUInt(); + lcStep Value = Item->data(0, PropertyValueRole).toUInt(); lcStep Show = partShow->data(0, PropertyValueRole).toUInt(); lcStep Hide = partHide->data(0, PropertyValueRole).toUInt(); if (Show && Hide) { - if (item == partShow) + if (Item == partShow) Editor->setValidator(new lcStepValidator(1, Hide - 1, false)); else Editor->setValidator(new lcStepValidator(Show + 1, LC_STEP_MAX, true)); } else - Editor->setValidator(new lcStepValidator(1, LC_STEP_MAX, item == partHide)); + Editor->setValidator(new lcStepValidator(1, LC_STEP_MAX, Item == partHide)); - if (item != partHide || Value != LC_STEP_MAX) + if (Item != partHide || Value != LC_STEP_MAX) Editor->setText(QString::number(Value)); connect(Editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); @@ -503,8 +478,8 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyString: { - QLineEdit *editor = new QLineEdit(parent); - QString value = item->data(0, PropertyValueRole).toString(); + QLineEdit *editor = new QLineEdit(Parent); + QString value = Item->data(0, PropertyValueRole).toString(); editor->setText(value); @@ -515,19 +490,19 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyStringList: { - QComboBox* editor = new QComboBox(parent); + QComboBox* editor = new QComboBox(Parent); - if (item == mCameraProjectionItem) + if (Item == mCameraProjectionItem) { editor->addItems( { tr("Perspective"), tr("Orthographic") } ); } - else if (item == mLightTypeItem) + else if (Item == mLightTypeItem) { for (int LightTypeIndex = 0; LightTypeIndex < static_cast(lcLightType::Count); LightTypeIndex++) editor->addItem(lcLight::GetLightTypeString(static_cast(LightTypeIndex))); } - int value = item->data(0, PropertyValueRole).toInt(); + int value = Item->data(0, PropertyValueRole).toInt(); editor->setCurrentIndex(value); connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); @@ -537,7 +512,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyLightFormat: { - QComboBox *editor = new QComboBox(parent); + QComboBox *editor = new QComboBox(Parent); editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); editor->setMinimumContentsLength(1); @@ -546,7 +521,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) for (int i = 0; i < formats.size(); i++) editor->addItem(formats.at(i), QVariant::fromValue(i)); - int value = item->data(0, PropertyValueRole).toInt(); + int value = Item->data(0, PropertyValueRole).toInt(); editor->setCurrentIndex(value); connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); @@ -556,7 +531,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyLightShape: { - QComboBox *editor = new QComboBox(parent); + QComboBox *editor = new QComboBox(Parent); editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); editor->setMinimumContentsLength(1); @@ -565,7 +540,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) for (int i = 0; i < shapes.size(); i++) editor->addItem(shapes.at(i), QVariant::fromValue(i)); - int value = item->data(0, PropertyValueRole).toInt(); + int value = Item->data(0, PropertyValueRole).toInt(); editor->setCurrentIndex(value); connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); @@ -575,8 +550,8 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyColor: { - QPushButton *Editor = new QPushButton(parent); - QColor Value = item->data(0, PropertyValueRole).value(); + QPushButton *Editor = new QPushButton(Parent); + QColor Value = Item->data(0, PropertyValueRole).value(); UpdateLightColorEditor(Editor, Value); @@ -587,8 +562,8 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyPieceColor: { - QPushButton *editor = new QPushButton(parent); - int value = item->data(0, PropertyValueRole).toInt(); + QPushButton *editor = new QPushButton(Parent); + int value = Item->data(0, PropertyValueRole).toInt(); updateColorEditor(editor, value); @@ -599,7 +574,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) case PropertyPart: { - QComboBox *editor = new QComboBox(parent); + QComboBox *editor = new QComboBox(Parent); editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); editor->setMinimumContentsLength(1); @@ -627,7 +602,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) for (PieceInfo* Info : SortedPieces) editor->addItem(Info->m_strDescription, QVariant::fromValue((void*)Info)); - PieceInfo *info = (PieceInfo*)item->data(0, PropertyValueRole).value(); + PieceInfo *info = (PieceInfo*)Item->data(0, PropertyValueRole).value(); editor->setCurrentIndex(editor->findData(QVariant::fromValue((void*)info))); connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); @@ -900,6 +875,24 @@ void lcQPropertiesTree::slotReturnPressed() // // Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); } + else if (Item == mLightSpotConeAngleItem) + { + float Value = lcParseValueLocalized(Editor->text()); + + Model->SetSpotLightConeAngle(Light, Value); + } + else if (Item == mLightSpotPenumbraAngleItem) + { + float Value = lcParseValueLocalized(Editor->text()); + + Model->SetSpotLightPenumbraAngle(Light, Value); + } + else if (Item == mLightSpotTightnessItem) + { + float Value = lcParseValueLocalized(Editor->text()); + + Model->SetSpotLightTightness(Light, Value); + } else if (Item == lightFactorA || Item == lightFactorB) { float Value = lcParseValueLocalized(Editor->text()); @@ -934,25 +927,6 @@ void lcQPropertiesTree::slotReturnPressed() Model->UpdateLight(Light, Props, LC_LIGHT_CUTOFF); } - else if (Item == lightSpotSize) - { - Props.mSpotSize = lcParseValueLocalized(Editor->text()); - - Model->UpdateLight(Light, Props, LC_LIGHT_SPOT_SIZE); - } - - else if (Item == lightSpotFalloff) - { - Props.mSpotFalloff = lcParseValueLocalized(Editor->text()); - - Model->UpdateLight(Light, Props, LC_LIGHT_SPOT_FALLOFF); - } - else if (Item == lightSpotTightness) - { - Props.mSpotTightness = lcParseValueLocalized(Editor->text()); - - Model->UpdateLight(Light, Props, LC_LIGHT_SPOT_TIGHTNESS); - } else if (Item == lightAreaGridRows || Item == lightAreaGridColumns) { float Value = lcParseValueLocalized(Editor->text()); @@ -1195,15 +1169,15 @@ void lcQPropertiesTree::SetEmpty() lightFactorA = nullptr; lightFactorB = nullptr; mLightNameItem = nullptr; - lightSpotSize = nullptr; + mLightSpotConeAngleItem = nullptr; + mLightSpotPenumbraAngleItem = nullptr; + mLightSpotTightnessItem = nullptr; lightShape = nullptr; lightFormat = nullptr; mLightCastShadowItem = nullptr; lightAreaGridRows = nullptr; lightAreaGridColumns = nullptr; - lightSpotFalloff = nullptr; - lightSpotTightness = nullptr; - + mWidgetMode = LC_PROPERTY_WIDGET_EMPTY; mFocus = nullptr; } @@ -1437,13 +1411,10 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) QString Name = tr("Light"); QString ExponentLabel = tr("Exponent"); QString FactorALabel = QLatin1String("FactorA"); - QString Format, Shape, SpotSizeToolTip, ExponentToolTip, FactorAToolTip, FactorBToolTip; + QString Format, Shape, ExponentToolTip, FactorAToolTip, FactorBToolTip; lcLightType LightType = lcLightType::Point; lcLightShape ShapeIndex = LC_LIGHT_SHAPE_UNDEFINED; int FormatIndex = 0; - float SpotSize = 0.0f; - float SpotFalloff = 0.0f; - float SpotTightness = 0.0f; float Diffuse = 0.0f; float Specular = 0.0f; float Cutoff = 0.0f; @@ -1452,10 +1423,10 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) bool POVRayLight = false; bool CastShadow = true; PropertyType TargetProperty = PropertyFloat; - PropertyType SpotSizeProperty = PropertyFloatLightSpotSize; lcVector3 Position(0.0f, 0.0f, 0.0f); lcVector3 Target(0.0f, 0.0f, 0.0f); QColor Color(Qt::white); + float SpotConeAngle = 0.0f, SpotPenumbraAngle = 0.0f, SpotTightness = 0.0f; lcVector2 Factor(0.0f, 0.0f); lcVector2 AreaGrid(0.0f, 0.0f); @@ -1471,6 +1442,9 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Position = Light->GetPosition(); // Target = Light->mTargetPosition; Color = lcQColorFromVector3(Light->GetColor()); + SpotConeAngle = Light->GetSpotConeAngle(); + SpotPenumbraAngle = Light->GetSpotPenumbraAngle(); + Factor = Light->mLightFactor; LightType = Light->GetLightType(); @@ -1489,15 +1463,11 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) { FactorALabel = tr("Radius (°)"); FactorAToolTip = tr("The angle between the \"hot-spot\" edge at the beam center and the center line."); - SpotSizeToolTip = tr("Angle of the spotlight beam - Read only."); - Factor[0] = Light->mSpotSize - Light->mSpotFalloff; - SpotSizeProperty = PropertyFloatReadOnly; } else { FactorALabel = tr("Radius (m)"); FactorAToolTip = tr("Shadow soft size - Light size in metres for shadow sampling."); - SpotSizeToolTip = tr("Angle of the spotlight beam."); } break; case lcLightType::Directional: @@ -1564,9 +1534,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Cutoff = Light->mSpotCutoff; EnableCutoff = Light->mEnableCutoff; TargetProperty = LightType != lcLightType::Point ? PropertyFloat : PropertyFloatReadOnly; - SpotSize = Light->mSpotSize; - SpotFalloff = Light->mSpotFalloff; - SpotTightness = Light->mSpotTightness; + SpotTightness = Light->GetSpotTightness(); AreaGrid = Light->mAreaGrid; } @@ -1581,25 +1549,24 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightColorItem = addProperty(mLightAttributesItem, tr("Color"), PropertyColor); mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); + if (LightType == lcLightType::Spot) + { + mLightSpotConeAngleItem = addProperty(mLightAttributesItem, tr("Spot Cone Angle"), PropertyFloat); + mLightSpotConeAngleItem->setToolTip(1, tr("The angle (in degrees) of the spot light's beam.")); + + mLightSpotPenumbraAngleItem = addProperty(mLightAttributesItem, tr("Spot Penumbra Angle"), PropertyFloat); + mLightSpotPenumbraAngleItem->setToolTip(1, tr("The angle (in degrees) over which the intensity of the spot light falls off to zero.")); + + mLightSpotTightnessItem = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat); + mLightSpotTightnessItem->setToolTip(1, tr("Additional exponential spotlight edge softening (POV-Ray only).")); + } + lightExponent = addProperty(mLightAttributesItem, ExponentLabel, PropertyFloat); if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloat); - if (LightType == lcLightType::Spot) - { - lightSpotSize = addProperty(mLightAttributesItem, tr("Spot Size (°)"), SpotSizeProperty); - lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloatLightSpotSize); - - if (!POVRayLight) - lightFactorB = addProperty(mLightAttributesItem, tr("Spot Blend"), PropertyFloat); - else - { - lightSpotFalloff = addProperty(mLightAttributesItem, tr("Spot Falloff (°)"), PropertyFloatLightSpotFalloff); - lightSpotTightness = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat); - } - } - else if (LightType == lcLightType::Area) + if (LightType == lcLightType::Area) { lightShape = addProperty(mLightAttributesItem, tr("Shape"), PropertyLightShape); lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloat); @@ -1735,30 +1702,17 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) } else if (LightType == lcLightType::Spot) { - lightSpotSize->setText(1, lcFormatValueLocalized(SpotSize)); - lightSpotSize->setData(0, PropertyValueRole, SpotSize); - lightSpotSize->setToolTip(1, SpotSizeToolTip); - - lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); - lightFactorA->setData(0, PropertyValueRole, Factor[0]); - lightFactorA->setToolTip(1, FactorAToolTip); + mLightSpotConeAngleItem->setText(1, lcFormatValueLocalized(SpotConeAngle)); + mLightSpotConeAngleItem->setData(0, PropertyValueRole, SpotConeAngle); + mLightSpotConeAngleItem->setData(0, PropertyRangeRole, QPointF(1.0, 180.0)); - if (!POVRayLight) - { - lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); - lightFactorB->setData(0, PropertyValueRole, Factor[1]); - lightFactorB->setToolTip(1, FactorBToolTip); - } - else - { - lightSpotFalloff->setText(1, lcFormatValueLocalized(SpotFalloff)); - lightSpotFalloff->setData(0, PropertyValueRole, SpotFalloff); - lightSpotFalloff->setToolTip(1, tr("The angle between the spot beam edge and center line.")); + mLightSpotPenumbraAngleItem->setText(1, lcFormatValueLocalized(SpotPenumbraAngle)); + mLightSpotPenumbraAngleItem->setData(0, PropertyValueRole, SpotPenumbraAngle); + mLightSpotPenumbraAngleItem->setData(0, PropertyRangeRole, QPointF(0.0, 180.0)); - lightSpotTightness->setText(1, lcFormatValueLocalized(SpotTightness)); - lightSpotTightness->setData(0, PropertyValueRole, SpotTightness); - lightSpotTightness->setToolTip(1, tr("Additional exponential spotlight edge softening.")); - } + mLightSpotTightnessItem->setText(1, lcFormatValueLocalized(SpotTightness)); + mLightSpotTightnessItem->setData(0, PropertyValueRole, SpotTightness); + mLightSpotTightnessItem->setData(0, PropertyRangeRole, QPointF(0.0, 100.0)); } if (!POVRayLight) diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 4e8a352b..be8242bb 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -36,7 +36,8 @@ class lcQPropertiesTree : public QTreeWidget enum { PropertyTypeRole = Qt::UserRole, - PropertyValueRole + PropertyValueRole, + PropertyRangeRole }; enum PropertyType @@ -45,8 +46,6 @@ class lcQPropertiesTree : public QTreeWidget PropertyBool, PropertyFloat, PropertyFloatReadOnly, - PropertyFloatLightSpotSize, - PropertyFloatLightSpotFalloff, PropertyStep, PropertyString, PropertyStringList, @@ -143,7 +142,9 @@ protected slots: QTreeWidgetItem* lightEnableCutoff; QTreeWidgetItem* lightExponent; QTreeWidgetItem* mLightTypeItem; - QTreeWidgetItem* lightSpotSize; + QTreeWidgetItem* mLightSpotConeAngleItem; + QTreeWidgetItem* mLightSpotPenumbraAngleItem; + QTreeWidgetItem* mLightSpotTightnessItem; QTreeWidgetItem* lightShape; QTreeWidgetItem* lightFactorA; QTreeWidgetItem* lightFactorB; @@ -152,8 +153,6 @@ protected slots: QTreeWidgetItem* mLightCastShadowItem; QTreeWidgetItem* lightAreaGridRows; QTreeWidgetItem* lightAreaGridColumns; - QTreeWidgetItem* lightSpotFalloff; - QTreeWidgetItem* lightSpotTightness; }; class lcQPropertiesTreeDelegate : public QItemDelegate From 59c1930b832b33a2a9175bf1aad38966a20781e8 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 17 Sep 2023 10:40:23 -0700 Subject: [PATCH 31/42] Added support for area size key frames. --- common/lc_global.h | 1 + common/lc_model.cpp | 41 +++++--- common/lc_model.h | 2 + common/light.cpp | 196 +++++++++++++++++++------------------ common/light.h | 51 ++++++---- common/project.cpp | 18 +++- qt/lc_qpropertiestree.cpp | 201 +++++++++++++++++++------------------- qt/lc_qpropertiestree.h | 7 +- 8 files changed, 278 insertions(+), 239 deletions(-) diff --git a/common/lc_global.h b/common/lc_global.h index 48a3b33e..53335edb 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -76,6 +76,7 @@ class lcPiece; class lcCamera; class lcLight; enum class lcLightType; +enum class lcLightAreaShape; class lcGroup; class PieceInfo; typedef std::map> lcPartsList; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 1085028d..f9710522 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3163,7 +3163,9 @@ void lcModel::SetCameraName(lcCamera* Camera, const QString& Name) void lcModel::SetLightType(lcLight* Light, lcLightType LightType) { - Light->SetLightType(LightType); + if (!Light->SetLightType(LightType)) + return; + Light->UpdatePosition(mCurrentStep); SaveCheckpoint(tr("Changing Light Type")); @@ -3173,9 +3175,6 @@ void lcModel::SetLightType(lcLight* Light, lcLightType LightType) void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color) { - if (Light->GetColor() == Color) - return; - Light->SetColor(Color, mCurrentStep, gMainWindow->GetAddKeys()); Light->UpdatePosition(mCurrentStep); @@ -3186,9 +3185,6 @@ void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color) void lcModel::SetSpotLightConeAngle(lcLight* Light, float Angle) { - if (Light->GetSpotConeAngle() == Angle) - return; - Light->SetSpotConeAngle(Angle, mCurrentStep, gMainWindow->GetAddKeys()); Light->UpdatePosition(mCurrentStep); @@ -3199,9 +3195,6 @@ void lcModel::SetSpotLightConeAngle(lcLight* Light, float Angle) void lcModel::SetSpotLightPenumbraAngle(lcLight* Light, float Angle) { - if (Light->GetSpotPenumbraAngle() == Angle) - return; - Light->SetSpotPenumbraAngle(Angle, mCurrentStep, gMainWindow->GetAddKeys()); Light->UpdatePosition(mCurrentStep); @@ -3212,9 +3205,6 @@ void lcModel::SetSpotLightPenumbraAngle(lcLight* Light, float Angle) void lcModel::SetSpotLightTightness(lcLight* Light, float Tightness) { - if (Light->GetSpotTightness() == Tightness) - return; - Light->SetSpotTightness(Tightness, mCurrentStep, gMainWindow->GetAddKeys()); Light->UpdatePosition(mCurrentStep); @@ -3223,12 +3213,33 @@ void lcModel::SetSpotLightTightness(lcLight* Light, float Tightness) UpdateAllViews(); } +void lcModel::SetAreaLightShape(lcLight* Light, lcLightAreaShape LightAreaShape) +{ + if (!Light->SetAreaShape(LightAreaShape)) + return; + + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Area Light Shape")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + +void lcModel::SetAreaLightSize(lcLight* Light, lcVector2 LightAreaSize) +{ + Light->SetAreaSize(LightAreaSize, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Area Light Size")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetLightCastShadow(lcLight* Light, bool CastShadow) { - if (Light->GetCastShadow() == CastShadow) + if (!Light->SetCastShadow(CastShadow)) return; - Light->SetCastShadow(CastShadow); Light->UpdatePosition(mCurrentStep); SaveCheckpoint(tr("Changing Light Shadow")); diff --git a/common/lc_model.h b/common/lc_model.h index 0adcc909..32ae4869 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -373,6 +373,8 @@ class lcModel void SetSpotLightConeAngle(lcLight* Light, float Angle); void SetSpotLightPenumbraAngle(lcLight* Light, float Angle); void SetSpotLightTightness(lcLight* Light, float Tightness); + void SetAreaLightShape(lcLight* Light, lcLightAreaShape LightAreaShape); + void SetAreaLightSize(lcLight* Light, lcVector2 LightAreaSize); void SetLightCastShadow(lcLight* Light, bool CastShadow); void SetLightName(lcLight* Light, const QString& Name); void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); diff --git a/common/light.cpp b/common/light.cpp index 334e0bbb..9f24777d 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -18,6 +18,7 @@ #define LC_LIGHT_POSITION_EDGE 7.5f static const std::array(lcLightType::Count)> gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") }; +static const std::array(lcLightAreaShape::Count)> gLightAreaShapes = { QLatin1String("RECTANGLE"), QLatin1String("SQUARE"), QLatin1String("DISK"), QLatin1String("ELLIPSE") }; lcLight::lcLight(const lcVector3& Position, lcLightType LightType) : lcObject(lcObjectType::Light), mLightType(LightType) @@ -35,15 +36,14 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mPOVRayExponent = 1.0f; mSpotCutoff = LightType != lcLightType::Directional ? 40.0f : 0.0f; mAreaGrid = lcVector2(10.0f, 10.0f); - mAreaSize = lcVector2(200.0f, 200.0f); - mLightShape = LC_LIGHT_SHAPE_SQUARE; - + mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true); mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); mColorKeys.ChangeKey(mColor, 1, true); mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); + mAreaSizeKeys.ChangeKey(mAreaSize, 1, true); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); mLightFactorKeys.ChangeKey(mLightFactor, 1, true); @@ -56,7 +56,7 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) UpdatePosition(1); } -QString lcLight::GetLightTypeString(lcLightType LightType) +QString lcLight::GetTypeString(lcLightType LightType) { switch (LightType) { @@ -79,6 +79,29 @@ QString lcLight::GetLightTypeString(lcLightType LightType) return QString(); } +QString lcLight::GetAreaShapeString(lcLightAreaShape LightAreaShape) +{ + switch (LightAreaShape) + { + case lcLightAreaShape::Rectangle: + return QT_TRANSLATE_NOOP("Light Shapes", "Rectangle"); + + case lcLightAreaShape::Square: + return QT_TRANSLATE_NOOP("Light Shapes", "Square"); + + case lcLightAreaShape::Disk: + return QT_TRANSLATE_NOOP("Light Shapes", "Disk"); + + case lcLightAreaShape::Ellipse: + return QT_TRANSLATE_NOOP("Light Shapes", "Ellipse"); + + case lcLightAreaShape::Count: + break; + } + + return QString(); +} + void lcLight::SaveLDraw(QTextStream& Stream) const { const QLatin1String LineEnding("\r\n"); @@ -167,10 +190,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const else Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_TIGHTNESS ") << mSpotTightness << LineEnding; - if (mPOVRayLight) - { - } - else + if (!mPOVRayLight) { if (mLightFactorKeys.GetSize() > 1) mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); @@ -202,44 +222,13 @@ void lcLight::SaveLDraw(QTextStream& Stream) const else Stream << QLatin1String("0 !LEOCAD LIGHT AREA_ROWS ") << mAreaGrid[0] << QLatin1String(" AREA_COLUMNS ") << mAreaGrid[1] << LineEnding; } - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); - else - { - if (mPOVRayLight) - { - Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mAreaSize[0] << QLatin1String(" HEIGHT ") << mAreaSize[1] << LineEnding; - } - else - { - if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE || mLightFactor[1] > 0) - Stream << QLatin1String("0 !LEOCAD LIGHT WIDTH ") << mLightFactor[0] << QLatin1String(" HEIGHT ") << mLightFactor[1] << LineEnding; - else - Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mLightFactor[0] << LineEnding; - } - } - - Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE "); - - QString Shape = QLatin1String("UNDEFINED "); - switch (mLightShape) - { - case LC_LIGHT_SHAPE_SQUARE: - Shape = QLatin1String("SQUARE "); - break; - case LC_LIGHT_SHAPE_DISK: - Shape = QLatin1String("DISK "); - break; - case LC_LIGHT_SHAPE_RECTANGLE: - Shape = QLatin1String("RECTANGLE "); - break; - case LC_LIGHT_SHAPE_ELLIPSE: - Shape = QLatin1String("ELLIPSE "); - break; - } + Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE ") << gLightAreaShapes[static_cast(mAreaShape)] << LineEnding; - Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE ") << Shape << LineEnding; + if (mAreaSizeKeys.GetSize() > 1) + mAreaSizeKeys.SaveKeysLDraw(Stream, "LIGHT AREA_SIZE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT AREA_SIZE ") << mAreaSize[0] << mAreaSize[1] << LineEnding; break; } @@ -379,6 +368,28 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if (Token == QLatin1String("SPOT_TIGHTNESS_KEY")) mSpotTightnessKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SHAPE")) + { + QString AreaShape; + Stream >> AreaShape; + + for (size_t ShapeIndex = 0; ShapeIndex < gLightAreaShapes.size(); ShapeIndex++) + { + if (AreaShape == gLightAreaShapes[ShapeIndex]) + { + mAreaShape = static_cast(ShapeIndex); + break; + } + } + } + else if (Token == QLatin1String("AREA_SIZE")) + { + Stream >> mAreaSize[0] >> mAreaSize[1]; + mAreaSizeKeys.ChangeKey(mAreaSize, 1, true); + } + else if (Token == QLatin1String("AREA_SIZE_KEY")) + mAreaSizeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) { if (mPOVRayLight) @@ -392,25 +403,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); } } - else if (Token == QLatin1String("RADIUS") || Token == QLatin1String("SIZE") || Token == QLatin1String("WIDTH") || (mHeightSet = Token == QLatin1String("HEIGHT")) || (mSpotBlendSet = Token == QLatin1String("SPOT_BLEND")) || (mAngleSet = Token == QLatin1String("ANGLE"))) - { - if (mPOVRayLight) - { - if (Token == QLatin1String("WIDTH")) - Stream >> mAreaSize[0]; - else if (Token == QLatin1String("HEIGHT")) - Stream >> mAreaSize[1]; - mLightFactorKeys.ChangeKey(mAreaSize, 1, true); - } - else - { - if(Token == QLatin1String("HEIGHT") || Token == QLatin1String("SPOT_BLEND")) - Stream >> mLightFactor[1]; - else - Stream >> mLightFactor[0]; - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); - } - } else if (Token == QLatin1String("AREA_ROWS")) { mPOVRayLight = true; @@ -423,21 +415,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) Stream >> mAreaGrid[1]; mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); } - else if (Token == QLatin1String("SHAPE")) - { - QString Shape; - Stream >> Shape; - Shape.replace("\"", ""); - - if (Shape == QLatin1String("SQUARE")) - mLightShape = LC_LIGHT_SHAPE_SQUARE; - else if (Shape == QLatin1String("DISK") || Shape == QLatin1String("CIRCLE")) - mLightShape = LC_LIGHT_SHAPE_DISK; - else if (Shape == QLatin1String("RECTANGLE")) - mLightShape = LC_LIGHT_SHAPE_RECTANGLE; - else if (Shape == QLatin1String("ELLIPSE")) - mLightShape = LC_LIGHT_SHAPE_ELLIPSE; - } else if (Token == QLatin1String("DIFFUSE")) { Stream >>mLightDiffuse; @@ -522,14 +499,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) break; case lcLightType::Area: - if (mLightShape == LC_LIGHT_SHAPE_RECTANGLE || mLightShape == LC_LIGHT_SHAPE_ELLIPSE) - { - if (!mHeightSet) - { - mLightFactor[1] = 0.25f; - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); - } - } break; case lcLightType::Count: @@ -557,9 +526,6 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) { switch(Property) { - case LC_LIGHT_SHAPE: - mLightShape = Props.mLightShape; - break; case LC_LIGHT_FACTOR: if (Props.mPOVRayLight && mLightType == lcLightType::Area) { @@ -755,12 +721,18 @@ void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, SetRotation(NewLocalToWorldMatrix, Step, AddKey); } -void lcLight::SetLightType(lcLightType LightType) +bool lcLight::SetLightType(lcLightType LightType) { if (static_cast(LightType) < 0 || LightType >= lcLightType::Count) - return; + return false; - mLightType = LightType; + if (mLightType != LightType) + { + mLightType = LightType; + return true; + } + + return false; } void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey) @@ -783,9 +755,37 @@ void lcLight::SetSpotTightness(float Tightness, lcStep Step, bool AddKey) mSpotTightnessKeys.ChangeKey(Tightness, Step, AddKey); } -void lcLight::SetCastShadow(bool CastShadow) +bool lcLight::SetAreaShape(lcLightAreaShape AreaShape) +{ + if (static_cast(AreaShape) < 0 || AreaShape >= lcLightAreaShape::Count) + return false; + + if (mAreaShape != AreaShape) + { + mAreaShape = AreaShape; + return true; + } + + return false; +} + +void lcLight::SetAreaSize(lcVector2 AreaSize, lcStep Step, bool AddKey) +{ + if (mAreaShape == lcLightAreaShape::Square || mAreaShape == lcLightAreaShape::Disk) + AreaSize[1] = AreaSize[0]; + + mAreaSizeKeys.ChangeKey(AreaSize, Step, AddKey); +} + +bool lcLight::SetCastShadow(bool CastShadow) { - mCastShadow = CastShadow; + if (mCastShadow != CastShadow) + { + mCastShadow = CastShadow; + return true; + } + + return false; } void lcLight::InsertTime(lcStep Start, lcStep Time) @@ -796,6 +796,7 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mSpotConeAngleKeys.InsertTime(Start, Time); mSpotPenumbraAngleKeys.InsertTime(Start, Time); mSpotTightnessKeys.InsertTime(Start, Time); + mAreaSizeKeys.InsertTime(Start, Time); mAttenuationKeys.InsertTime(Start, Time); mLightFactorKeys.InsertTime(Start, Time); @@ -814,6 +815,7 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mSpotConeAngleKeys.RemoveTime(Start, Time); mSpotPenumbraAngleKeys.RemoveTime(Start, Time); mSpotTightnessKeys.RemoveTime(Start, Time); + mAreaSizeKeys.RemoveTime(Start, Time); mAttenuationKeys.RemoveTime(Start, Time); mLightFactorKeys.RemoveTime(Start, Time); @@ -843,6 +845,7 @@ void lcLight::UpdatePosition(lcStep Step) mSpotConeAngle = mSpotConeAngleKeys.CalculateKey(Step); mSpotPenumbraAngle = mSpotPenumbraAngleKeys.CalculateKey(Step); mSpotTightness = mSpotTightnessKeys.CalculateKey(Step); + mAreaSize = mAreaSizeKeys.CalculateKey(Step); mAttenuation = mAttenuationKeys.CalculateKey(Step); mLightFactor = mLightFactorKeys.CalculateKey(Step); @@ -946,7 +949,7 @@ void lcLight::DrawAreaLight(lcContext* Context) const { SetupLightMatrix(Context); - if (mLightShape == LC_LIGHT_SHAPE_SQUARE || mLightShape == LC_LIGHT_SHAPE_RECTANGLE) + if (mAreaShape == lcLightAreaShape::Square || mAreaShape == lcLightAreaShape::Rectangle) { float Verts[4 * 3]; float* CurVert = Verts; @@ -1271,6 +1274,9 @@ void lcLight::RemoveKeyFrames() mSpotTightnessKeys.RemoveAll(); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); + mAreaSizeKeys.RemoveAll(); + mAreaSizeKeys.ChangeKey(mAreaSize, 1, true); + mAttenuationKeys.RemoveAll(); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); diff --git a/common/light.h b/common/light.h index eeb67feb..93ce91af 100644 --- a/common/light.h +++ b/common/light.h @@ -25,20 +25,17 @@ enum class lcLightType Count }; -enum lcLightShape +enum class lcLightAreaShape { - LC_LIGHT_SHAPE_UNDEFINED = -1, - LC_LIGHT_SHAPE_SQUARE, - LC_LIGHT_SHAPE_DISK, - LC_LIGHT_SHAPE_RECTANGLE, - LC_LIGHT_SHAPE_ELLIPSE + Rectangle, + Square, + Disk, + Ellipse, + Count }; enum lcLightProperty { - LC_LIGHT_NONE, - LC_LIGHT_SHAPE, - LC_LIGHT_TYPE, LC_LIGHT_FACTOR, LC_LIGHT_DIFFUSE, LC_LIGHT_SPECULAR, @@ -59,7 +56,6 @@ struct lcLightProperties float mSpotCutoff; bool mEnableCutoff; bool mPOVRayLight; - int mLightShape; }; class lcLight : public lcObject @@ -73,7 +69,8 @@ class lcLight : public lcObject lcLight& operator=(const lcLight&) = delete; lcLight& operator=(lcLight&&) = delete; - static QString GetLightTypeString(lcLightType LightType); + static QString GetTypeString(lcLightType LightType); + static QString GetAreaShapeString(lcLightAreaShape LightAreaShape); bool IsPointLight() const { @@ -100,11 +97,11 @@ class lcLight : public lcObject return mLightType; } - void SetLightType(lcLightType LightType); + bool SetLightType(lcLightType LightType); - int GetLightShape() const + lcLightAreaShape GetLightShape() const { - return mLightShape; + return mAreaShape; } bool IsSelected() const override @@ -282,7 +279,21 @@ class lcLight : public lcObject return mSpotTightness; } - void SetCastShadow(bool CastShadow); + bool SetAreaShape(lcLightAreaShape LightAreaShape); + + lcLightAreaShape GetAreaShape() const + { + return mAreaShape; + } + + void SetAreaSize(lcVector2 AreaSize, lcStep Step, bool AddKey); + + lcVector2 GetAreaSize() const + { + return mAreaSize; + } + + bool SetCastShadow(bool CastShadow); bool GetCastShadow() const { @@ -306,6 +317,7 @@ class lcLight : public lcObject bool Setup(int LightIndex); void CreateName(const lcArray& Lights); void UpdateLight(lcStep Step, lcLightProperties Props, int Property); + lcLightProperties GetLightProperties() const { lcLightProperties props; @@ -317,7 +329,6 @@ class lcLight : public lcObject props.mPOVRayLight = mPOVRayLight; props.mEnableCutoff = mEnableCutoff; props.mAreaGrid = mAreaGrid; - props.mLightShape = mLightShape; return props; } @@ -326,11 +337,9 @@ class lcLight : public lcObject lcVector3 mAttenuation; lcVector2 mLightFactor; lcVector2 mAreaGrid; - lcVector2 mAreaSize; bool mAngleSet; bool mSpotBlendSet; bool mSpotCutoffSet; - bool mHeightSet; bool mEnableCutoff; bool mPOVRayLight; float mLightDiffuse; @@ -353,20 +362,22 @@ class lcLight : public lcObject void DrawCone(lcContext* Context, float TargetDistance) const; quint32 mState = 0; - lcLightType mLightType; + lcLightType mLightType = lcLightType::Point; bool mCastShadow = true; lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); float mSpotConeAngle = 80.0f; float mSpotPenumbraAngle = 0.0f; float mSpotTightness = 0.0f; + lcLightAreaShape mAreaShape = lcLightAreaShape::Rectangle; + lcVector2 mAreaSize = lcVector2(200.0f, 200.0f); - int mLightShape; lcObjectKeyArray mPositionKeys; lcObjectKeyArray mRotationKeys; lcObjectKeyArray mColorKeys; lcObjectKeyArray mSpotConeAngleKeys; lcObjectKeyArray mSpotPenumbraAngleKeys; lcObjectKeyArray mSpotTightnessKeys; + lcObjectKeyArray mAreaSizeKeys; lcObjectKeyArray mAttenuationKeys; lcObjectKeyArray mLightFactorKeys; diff --git a/common/project.cpp b/common/project.cpp index 67ed8583..c67713db 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2177,23 +2177,31 @@ bool Project::ExportPOVRay(const QString& FileName) const lcVector3 LightPosition = Light->GetPosition(); const lcVector3 LightTarget = LightPosition + Light->GetDirection(); const lcVector3 LightColor = Light->GetColor(); - const QString LightName = QString(Light->mName).replace(" ","_"); + const QString LightName = QString(Light->mName).replace(" ", "_"); LightType = Light->GetLightType(); Shadowless = Light->GetCastShadow() ? 0 : 1; Power = Light->mPOVRayExponent; - switch(LightType) + switch (LightType) { + case lcLightType::Point: + break; + case lcLightType::Spot: SpotFalloff = Light->GetSpotConeAngle() / 2.0f; SpotRadius = SpotFalloff - Light->GetSpotPenumbraAngle(); break; + + case lcLightType::Directional: + break; + case lcLightType::Area: - AreaCircle = Light->GetLightShape() == LC_LIGHT_SHAPE_DISK ? 1 : 0; - AreaSize = Light->mAreaSize; + AreaCircle = (Light->GetLightShape() == lcLightAreaShape::Disk || Light->GetLightShape() == lcLightAreaShape::Ellipse) ? 1 : 0; + AreaSize = Light->GetAreaSize(); AreaGrid = Light->mAreaGrid; break; - default: + + case lcLightType::Count: break; } diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 4d248702..5f13f0cf 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -499,7 +499,12 @@ QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) else if (Item == mLightTypeItem) { for (int LightTypeIndex = 0; LightTypeIndex < static_cast(lcLightType::Count); LightTypeIndex++) - editor->addItem(lcLight::GetLightTypeString(static_cast(LightTypeIndex))); + editor->addItem(lcLight::GetTypeString(static_cast(LightTypeIndex))); + } + else if (Item == mLightAreaShapeItem) + { + for (int LightAreaShapeIndex = 0; LightAreaShapeIndex < static_cast(lcLightAreaShape::Count); LightAreaShapeIndex++) + editor->addItem(lcLight::GetAreaShapeString(static_cast(LightAreaShapeIndex))); } int value = Item->data(0, PropertyValueRole).toInt(); @@ -529,25 +534,6 @@ QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) return editor; } - case PropertyLightShape: - { - QComboBox *editor = new QComboBox(Parent); - - editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); - editor->setMinimumContentsLength(1); - - QStringList shapes = { tr("Square"), tr("Disk"), tr("Rectangle"), tr("Ellipse") }; - for (int i = 0; i < shapes.size(); i++) - editor->addItem(shapes.at(i), QVariant::fromValue(i)); - - int value = Item->data(0, PropertyValueRole).toInt(); - editor->setCurrentIndex(value); - - connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); - - return editor; - } - case PropertyColor: { QPushButton *Editor = new QPushButton(Parent); @@ -893,13 +879,25 @@ void lcQPropertiesTree::slotReturnPressed() Model->SetSpotLightTightness(Light, Value); } - else if (Item == lightFactorA || Item == lightFactorB) + else if (Item == mLightAreaSizeXItem) + { + lcVector2 Value = Light->GetAreaSize(); + Value[0] = lcParseValueLocalized(Editor->text()); + + Model->SetAreaLightSize(Light, Value); + } + else if (Item == mLightAreaSizeYItem) + { + lcVector2 Value = Light->GetAreaSize(); + Value[1] = lcParseValueLocalized(Editor->text()); + + Model->SetAreaLightSize(Light, Value); + } + else if (Item == lightFactorA) { float Value = lcParseValueLocalized(Editor->text()); if (Item == lightFactorA) Props.mLightFactor[0] = Value; - else if (Item == lightFactorB) - Props.mLightFactor[1] = Value; Model->UpdateLight(Light, Props, LC_LIGHT_FACTOR); } @@ -937,7 +935,6 @@ void lcQPropertiesTree::slotReturnPressed() Model->UpdateLight(Light, Props, LC_LIGHT_AREA_GRID); } - else if (Item == mLightNameItem) { QString Value = Editor->text(); @@ -1004,10 +1001,9 @@ void lcQPropertiesTree::slotSetValue(int Value) { Model->SetLightType(Light, static_cast(Value)); } - else if (Item == lightShape) + else if (Item == mLightAreaShapeItem) { - Props.mLightShape = static_cast(Value); - Model->UpdateLight(Light, Props, LC_LIGHT_SHAPE); + Model->SetAreaLightShape(Light, static_cast(Value)); } else if (Item == lightFormat) { @@ -1167,12 +1163,13 @@ void lcQPropertiesTree::SetEmpty() lightExponent = nullptr; mLightTypeItem = nullptr; lightFactorA = nullptr; - lightFactorB = nullptr; mLightNameItem = nullptr; mLightSpotConeAngleItem = nullptr; mLightSpotPenumbraAngleItem = nullptr; mLightSpotTightnessItem = nullptr; - lightShape = nullptr; + mLightAreaShapeItem = nullptr; + mLightAreaSizeXItem = nullptr; + mLightAreaSizeYItem = nullptr; lightFormat = nullptr; mLightCastShadowItem = nullptr; lightAreaGridRows = nullptr; @@ -1411,9 +1408,10 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) QString Name = tr("Light"); QString ExponentLabel = tr("Exponent"); QString FactorALabel = QLatin1String("FactorA"); - QString Format, Shape, ExponentToolTip, FactorAToolTip, FactorBToolTip; + QString Format, ExponentToolTip, FactorAToolTip, FactorBToolTip; lcLightType LightType = lcLightType::Point; - lcLightShape ShapeIndex = LC_LIGHT_SHAPE_UNDEFINED; + lcLightAreaShape LightAreaShape = lcLightAreaShape::Rectangle; + lcVector2 LightAreaSize(0.0f, 0.0f); int FormatIndex = 0; float Diffuse = 0.0f; float Specular = 0.0f; @@ -1447,14 +1445,17 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Factor = Light->mLightFactor; LightType = Light->GetLightType(); + LightAreaShape = Light->GetAreaShape(); + LightAreaSize = Light->GetAreaSize(); - switch(LightType) + switch (LightType) { case lcLightType::Point: FactorALabel = tr("Radius (m)"); FactorAToolTip = tr("The light size for shadow sampling in metres."); ExponentLabel = tr("Exponent"); break; + case lcLightType::Spot: FactorBToolTip = tr("The softness of the spotlight edge."); ExponentLabel = tr("Power"); @@ -1470,51 +1471,20 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) FactorAToolTip = tr("Shadow soft size - Light size in metres for shadow sampling."); } break; + case lcLightType::Directional: FactorALabel = tr("Angle (°)"); FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth."); ExponentLabel = tr("Strength"); break; + case lcLightType::Area: ExponentLabel = tr("Power"); - - if (POVRayLight) - { - Factor = Light->mAreaSize; - FactorALabel = tr("Width"); - FactorAToolTip = tr("The width (X direction) of the area light."); - FactorBToolTip = tr("The height (Y direction) of the area light."); - } - else - { - FactorALabel = tr("Width"); - FactorAToolTip = tr("The width (X direction) of the area light."); - FactorBToolTip = tr("The height (Y direction) of the area light."); - } break; default: break; } - ShapeIndex = static_cast(Light->GetLightType()); - - switch(ShapeIndex) - { - case LC_LIGHT_SHAPE_SQUARE: - Shape = tr("Square"); - break; - case LC_LIGHT_SHAPE_DISK: - Shape = POVRayLight ? tr("Circle") : tr("Disk"); - break; - case LC_LIGHT_SHAPE_RECTANGLE: - Shape = tr("Rectangle"); - break; - case LC_LIGHT_SHAPE_ELLIPSE: - Shape = tr("Ellipse"); - break; - default: - break; - } Diffuse = Light->mLightDiffuse; Specular = Light->mLightSpecular; @@ -1538,7 +1508,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) AreaGrid = Light->mAreaGrid; } - if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType || mLightShape != ShapeIndex || mPOVRayLight != POVRayLight) + if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType || mLightAreaShape != LightAreaShape || mPOVRayLight != POVRayLight) { SetEmpty(); @@ -1549,40 +1519,72 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightColorItem = addProperty(mLightAttributesItem, tr("Color"), PropertyColor); mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); - if (LightType == lcLightType::Spot) + switch (LightType) { - mLightSpotConeAngleItem = addProperty(mLightAttributesItem, tr("Spot Cone Angle"), PropertyFloat); - mLightSpotConeAngleItem->setToolTip(1, tr("The angle (in degrees) of the spot light's beam.")); + case lcLightType::Point: + break; - mLightSpotPenumbraAngleItem = addProperty(mLightAttributesItem, tr("Spot Penumbra Angle"), PropertyFloat); - mLightSpotPenumbraAngleItem->setToolTip(1, tr("The angle (in degrees) over which the intensity of the spot light falls off to zero.")); + case lcLightType::Spot: + { + mLightSpotConeAngleItem = addProperty(mLightAttributesItem, tr("Spot Cone Angle"), PropertyFloat); + mLightSpotConeAngleItem->setToolTip(1, tr("The angle (in degrees) of the spot light's beam.")); - mLightSpotTightnessItem = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat); - mLightSpotTightnessItem->setToolTip(1, tr("Additional exponential spotlight edge softening (POV-Ray only).")); - } + mLightSpotPenumbraAngleItem = addProperty(mLightAttributesItem, tr("Spot Penumbra Angle"), PropertyFloat); + mLightSpotPenumbraAngleItem->setToolTip(1, tr("The angle (in degrees) over which the intensity of the spot light falls off to zero.")); - lightExponent = addProperty(mLightAttributesItem, ExponentLabel, PropertyFloat); + mLightSpotTightnessItem = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat); + mLightSpotTightnessItem->setToolTip(1, tr("Additional exponential spot light edge softening (POV-Ray only).")); + } + break; - if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) - lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloat); + case lcLightType::Directional: + break; - if (LightType == lcLightType::Area) - { - lightShape = addProperty(mLightAttributesItem, tr("Shape"), PropertyLightShape); - lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloat); + case lcLightType::Area: + { + mLightAreaShapeItem = addProperty(mLightAttributesItem, tr("Area Shape"), PropertyStringList); + mLightAreaShapeItem->setToolTip(1, tr("The shape of the area light.")); - if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE || POVRayLight) - lightFactorB = addProperty(mLightAttributesItem, tr("Height"), PropertyFloat); - else - FactorAToolTip = tr("The size of the area light grid."); + switch (LightAreaShape) + { + case lcLightAreaShape::Rectangle: + case lcLightAreaShape::Ellipse: + mLightAreaSizeXItem = addProperty(mLightAttributesItem, tr("Area Width"), PropertyFloat); + mLightAreaSizeXItem->setToolTip(1, tr("The width (X direction) of the area light.")); - if (POVRayLight) - { - lightAreaGridRows = addProperty(mLightAttributesItem, tr("Grid Rows"), PropertyFloat); - lightAreaGridColumns = addProperty(mLightAttributesItem, tr("Grid Columns"), PropertyFloat); + mLightAreaSizeYItem = addProperty(mLightAttributesItem, tr("Area Height"), PropertyFloat); + mLightAreaSizeYItem->setToolTip(1, tr("The height (Y direction) of the area light.")); + break; + + case lcLightAreaShape::Square: + case lcLightAreaShape::Disk: + mLightAreaSizeXItem = addProperty(mLightAttributesItem, tr("Area Size"), PropertyFloat); + mLightAreaSizeXItem->setToolTip(1, tr("The size of the area light.")); + + mLightAreaSizeYItem = nullptr; + break; + + case lcLightAreaShape::Count: + break; + } + + if (POVRayLight) + { + lightAreaGridRows = addProperty(mLightAttributesItem, tr("Grid Rows"), PropertyFloat); + lightAreaGridColumns = addProperty(mLightAttributesItem, tr("Grid Columns"), PropertyFloat); + } } + break; + + case lcLightType::Count: + break; } + lightExponent = addProperty(mLightAttributesItem, ExponentLabel, PropertyFloat); + + if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) + lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloat); + if (!POVRayLight) { if (LightType != lcLightType::Directional) @@ -1616,7 +1618,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mWidgetMode = LC_PROPERTY_WIDGET_LIGHT; mLightType = LightType; - mLightShape = ShapeIndex; + mLightAreaShape = LightAreaShape; mPOVRayLight = POVRayLight; } @@ -1656,7 +1658,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightFormat->setText(1, Format); lightFormat->setData(0, PropertyValueRole, FormatIndex); - mLightTypeItem->setText(1, lcLight::GetLightTypeString(LightType)); + mLightTypeItem->setText(1, lcLight::GetTypeString(LightType)); mLightTypeItem->setData(0, PropertyValueRole, static_cast(LightType)); mLightCastShadowItem->setCheckState(1, CastShadow ? Qt::Checked : Qt::Unchecked); @@ -1674,19 +1676,16 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) } else if (LightType == lcLightType::Area) { - lightShape->setText(1, Shape); - lightShape->setData(0, PropertyValueRole, ShapeIndex); - lightShape->setToolTip(1, tr("Suggested shape of the arealight.")); + mLightAreaShapeItem->setText(1, lcLight::GetAreaShapeString(LightAreaShape)); + mLightAreaShapeItem->setData(0, PropertyValueRole, static_cast(LightAreaShape)); - lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); - lightFactorA->setData(0, PropertyValueRole, Factor[0]); - lightFactorA->setToolTip(1, FactorAToolTip); + mLightAreaSizeXItem->setText(1, lcFormatValueLocalized(LightAreaSize[0])); + mLightAreaSizeXItem->setData(0, PropertyValueRole, LightAreaSize[0]); - if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE || POVRayLight) + if (mLightAreaSizeYItem) { - lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); - lightFactorB->setData(0, PropertyValueRole, Factor[1]); - lightFactorB->setToolTip(1, FactorBToolTip); + mLightAreaSizeYItem->setText(1, lcFormatValueLocalized(LightAreaSize[1])); + mLightAreaSizeYItem->setData(0, PropertyValueRole, LightAreaSize[1]); } if (POVRayLight) diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index be8242bb..f4910b73 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -50,7 +50,6 @@ class lcQPropertiesTree : public QTreeWidget PropertyString, PropertyStringList, PropertyLightFormat, - PropertyLightShape, PropertyColor, PropertyPieceColor, PropertyPart @@ -79,7 +78,7 @@ protected slots: void SetMultiple(); lcLightType mLightType; - int mLightShape; + lcLightAreaShape mLightAreaShape; bool mPOVRayLight; lcPropertyWidgetMode mWidgetMode; @@ -145,7 +144,9 @@ protected slots: QTreeWidgetItem* mLightSpotConeAngleItem; QTreeWidgetItem* mLightSpotPenumbraAngleItem; QTreeWidgetItem* mLightSpotTightnessItem; - QTreeWidgetItem* lightShape; + QTreeWidgetItem* mLightAreaShapeItem; + QTreeWidgetItem* mLightAreaSizeXItem; + QTreeWidgetItem* mLightAreaSizeYItem; QTreeWidgetItem* lightFactorA; QTreeWidgetItem* lightFactorB; QTreeWidgetItem* mLightNameItem; From 177c1b82d7ba93e03c9f68af6c9e68977bcf1318 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 17 Sep 2023 11:45:14 -0700 Subject: [PATCH 32/42] Support Blender light sizes for all types of lights. --- common/lc_model.cpp | 6 +- common/lc_model.h | 2 +- common/light.cpp | 172 +++++++++++++++-------------------- common/light.h | 27 ++---- common/project.cpp | 6 +- qt/lc_qpropertiestree.cpp | 187 +++++++++++++++++--------------------- qt/lc_qpropertiestree.h | 6 +- 7 files changed, 172 insertions(+), 234 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index f9710522..befc1420 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3225,12 +3225,12 @@ void lcModel::SetAreaLightShape(lcLight* Light, lcLightAreaShape LightAreaShape) UpdateAllViews(); } -void lcModel::SetAreaLightSize(lcLight* Light, lcVector2 LightAreaSize) +void lcModel::SetLightSize(lcLight* Light, lcVector2 LightAreaSize) { - Light->SetAreaSize(LightAreaSize, mCurrentStep, gMainWindow->GetAddKeys()); + Light->SetSize(LightAreaSize, mCurrentStep, gMainWindow->GetAddKeys()); Light->UpdatePosition(mCurrentStep); - SaveCheckpoint(tr("Changing Area Light Size")); + SaveCheckpoint(tr("Changing Light Size")); gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); } diff --git a/common/lc_model.h b/common/lc_model.h index 32ae4869..fe8423bd 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -374,7 +374,7 @@ class lcModel void SetSpotLightPenumbraAngle(lcLight* Light, float Angle); void SetSpotLightTightness(lcLight* Light, float Tightness); void SetAreaLightShape(lcLight* Light, lcLightAreaShape LightAreaShape); - void SetAreaLightSize(lcLight* Light, lcVector2 LightAreaSize); + void SetLightSize(lcLight* Light, lcVector2 LightAreaSize); void SetLightCastShadow(lcLight* Light, bool CastShadow); void SetLightName(lcLight* Light, const QString& Name); void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); diff --git a/common/light.cpp b/common/light.cpp index 9f24777d..8d0f2028 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -28,8 +28,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mPOVRayLight = false; mEnableCutoff = false; mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); - mLightFactor[0] = LightType == lcLightType::Directional ? 11.4f : 0.25f; - mLightFactor[1] = LightType == lcLightType::Area ? 0.25f : LightType == lcLightType::Spot ? 0.150f : 0.0f; mLightDiffuse = 1.0f; mLightSpecular = 1.0f; mSpotExponent = 10.0f; @@ -37,16 +35,16 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mSpotCutoff = LightType != lcLightType::Directional ? 40.0f : 0.0f; mAreaGrid = lcVector2(10.0f, 10.0f); + UpdateLightType(); + mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true); mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); mColorKeys.ChangeKey(mColor, 1, true); mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); - mAreaSizeKeys.ChangeKey(mAreaSize, 1, true); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); @@ -56,7 +54,36 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) UpdatePosition(1); } -QString lcLight::GetTypeString(lcLightType LightType) +void lcLight::UpdateLightType() +{ + mSizeKeys.RemoveAll(); + + switch (mLightType) + { + case lcLightType::Point: + mSize = lcVector2(0.0f, 0.0f); + break; + + case lcLightType::Spot: + mSize = lcVector2(0.0f, 0.0f); + break; + + case lcLightType::Directional: + mSize = lcVector2(0.00918f * LC_DTOR, 0.0f); + break; + + case lcLightType::Area: + mSize = lcVector2(200.0f, 200.0f); + break; + + case lcLightType::Count: + break; + } + + mSizeKeys.ChangeKey(mSize, 1, true); +} + +QString lcLight::GetLightTypeString(lcLightType LightType) { switch (LightType) { @@ -133,6 +160,11 @@ void lcLight::SaveLDraw(QTextStream& Stream) const else Stream << QLatin1String("0 !LEOCAD LIGHT COLOR ") << mColor[0] << ' ' << mColor[1] << ' ' << mColor[2] << LineEnding; + if (mSizeKeys.GetSize() > 1) + mSizeKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); + else + Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mSize[0] << mSize[1] << LineEnding; + if (!mPOVRayLight) { if (mLightDiffuseKeys.GetSize() > 1) @@ -162,16 +194,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const switch (mLightType) { case lcLightType::Count: - break; - case lcLightType::Point: - if (!mPOVRayLight) - { - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; - } break; case lcLightType::Spot: @@ -190,16 +213,6 @@ void lcLight::SaveLDraw(QTextStream& Stream) const else Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_TIGHTNESS ") << mSpotTightness << LineEnding; - if (!mPOVRayLight) - { - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT RADIUS_AND_SPOT_BLEND_KEY "); - else - { - Stream << QLatin1String("0 !LEOCAD LIGHT RADIUS ") << mLightFactor[0] << LineEnding; - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_BLEND ") << mLightFactor[1] << LineEnding; - } - } break; case lcLightType::Directional: @@ -208,10 +221,6 @@ void lcLight::SaveLDraw(QTextStream& Stream) const else Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << mSpotExponent << LineEnding; - if (mLightFactorKeys.GetSize() > 1) - mLightFactorKeys.SaveKeysLDraw(Stream, "LIGHT ANGLE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT ANGLE ") << mLightFactor[0] << LineEnding; break; case lcLightType::Area: @@ -223,12 +232,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD LIGHT AREA_ROWS ") << mAreaGrid[0] << QLatin1String(" AREA_COLUMNS ") << mAreaGrid[1] << LineEnding; } - Stream << QLatin1String("0 !LEOCAD LIGHT SHAPE ") << gLightAreaShapes[static_cast(mAreaShape)] << LineEnding; - - if (mAreaSizeKeys.GetSize() > 1) - mAreaSizeKeys.SaveKeysLDraw(Stream, "LIGHT AREA_SIZE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT AREA_SIZE ") << mAreaSize[0] << mAreaSize[1] << LineEnding; + Stream << QLatin1String("0 !LEOCAD LIGHT AREA_SHAPE ") << gLightAreaShapes[static_cast(mAreaShape)] << LineEnding; break; } @@ -368,7 +372,7 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if (Token == QLatin1String("SPOT_TIGHTNESS_KEY")) mSpotTightnessKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SHAPE")) + else if (Token == QLatin1String("AREA_SHAPE")) { QString AreaShape; Stream >> AreaShape; @@ -382,13 +386,13 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } } } - else if (Token == QLatin1String("AREA_SIZE")) + else if (Token == QLatin1String("SIZE")) { - Stream >> mAreaSize[0] >> mAreaSize[1]; - mAreaSizeKeys.ChangeKey(mAreaSize, 1, true); + Stream >> mSize[0] >> mSize[1]; + mSizeKeys.ChangeKey(mSize, 1, true); } - else if (Token == QLatin1String("AREA_SIZE_KEY")) - mAreaSizeKeys.LoadKeysLDraw(Stream); + else if (Token == QLatin1String("SIZE_KEY")) + mSizeKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) { @@ -455,8 +459,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) mSpotExponentKeys.LoadKeysLDraw(Stream); - else if ((Token == QLatin1String("ANGLE_KEY")) || (Token == QLatin1String("RADIUS_KEY")) || (Token == QLatin1String("SIZE_KEY")) || (Token == QLatin1String("RADIUS_AND_SPOT_BLEND_KEY"))) - mLightFactorKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("AREA_GRID_KEY")) mAreaGridKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("DIFFUSE_KEY")) @@ -474,23 +476,10 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) switch (mLightType) { case lcLightType::Point: - break; - case lcLightType::Spot: - if (!mSpotBlendSet) - { - mLightFactor[1] = 0.15f; - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); - } break; case lcLightType::Directional: - if (!mAngleSet) - { - mLightFactor[0] = 11.4f; - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); - } - if (!mSpotCutoffSet) { mSpotCutoff = 0.0f; @@ -499,8 +488,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) break; case lcLightType::Area: - break; - case lcLightType::Count: break; } @@ -526,18 +513,6 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) { switch(Property) { - case LC_LIGHT_FACTOR: - if (Props.mPOVRayLight && mLightType == lcLightType::Area) - { - mAreaSize = Props.mLightFactor; - mLightFactorKeys.ChangeKey(mAreaSize, 1, true); - } - else - { - mLightFactor = Props.mLightFactor; - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); - } - break; case LC_LIGHT_DIFFUSE: mLightDiffuse = Props.mLightDiffuse; mLightDiffuseKeys.ChangeKey(mLightDiffuse, Step, false); @@ -621,7 +596,7 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const float x = lcDot(IntersectionDirection, XAxis); float y = lcDot(IntersectionDirection, YAxis); - if (fabsf(x) < mAreaSize.x / 2.0f && fabsf(y) < mAreaSize.y / 2.0f) + if (fabsf(x) < mSize.x / 2.0f && fabsf(y) < mSize.y / 2.0f) { float Distance = lcLength(Intersection - ObjectRayTest.Start); @@ -726,13 +701,14 @@ bool lcLight::SetLightType(lcLightType LightType) if (static_cast(LightType) < 0 || LightType >= lcLightType::Count) return false; - if (mLightType != LightType) - { - mLightType = LightType; - return true; - } + if (mLightType == LightType) + return false; - return false; + mLightType = LightType; + + UpdateLightType(); + + return true; } void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey) @@ -769,12 +745,12 @@ bool lcLight::SetAreaShape(lcLightAreaShape AreaShape) return false; } -void lcLight::SetAreaSize(lcVector2 AreaSize, lcStep Step, bool AddKey) +void lcLight::SetSize(lcVector2 Size, lcStep Step, bool AddKey) { - if (mAreaShape == lcLightAreaShape::Square || mAreaShape == lcLightAreaShape::Disk) - AreaSize[1] = AreaSize[0]; + if (mLightType == lcLightType::Area && (mAreaShape == lcLightAreaShape::Square || mAreaShape == lcLightAreaShape::Disk)) + Size[1] = Size[0]; - mAreaSizeKeys.ChangeKey(AreaSize, Step, AddKey); + mSizeKeys.ChangeKey(Size, Step, AddKey); } bool lcLight::SetCastShadow(bool CastShadow) @@ -796,10 +772,9 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mSpotConeAngleKeys.InsertTime(Start, Time); mSpotPenumbraAngleKeys.InsertTime(Start, Time); mSpotTightnessKeys.InsertTime(Start, Time); - mAreaSizeKeys.InsertTime(Start, Time); + mSizeKeys.InsertTime(Start, Time); mAttenuationKeys.InsertTime(Start, Time); - mLightFactorKeys.InsertTime(Start, Time); mLightDiffuseKeys.InsertTime(Start, Time); mLightSpecularKeys.InsertTime(Start, Time); mSpotCutoffKeys.InsertTime(Start, Time); @@ -815,10 +790,9 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mSpotConeAngleKeys.RemoveTime(Start, Time); mSpotPenumbraAngleKeys.RemoveTime(Start, Time); mSpotTightnessKeys.RemoveTime(Start, Time); - mAreaSizeKeys.RemoveTime(Start, Time); + mSizeKeys.RemoveTime(Start, Time); mAttenuationKeys.RemoveTime(Start, Time); - mLightFactorKeys.RemoveTime(Start, Time); mLightDiffuseKeys.RemoveTime(Start, Time); mLightSpecularKeys.RemoveTime(Start, Time); mSpotCutoffKeys.RemoveTime(Start, Time); @@ -845,10 +819,9 @@ void lcLight::UpdatePosition(lcStep Step) mSpotConeAngle = mSpotConeAngleKeys.CalculateKey(Step); mSpotPenumbraAngle = mSpotPenumbraAngleKeys.CalculateKey(Step); mSpotTightness = mSpotTightnessKeys.CalculateKey(Step); - mAreaSize = mAreaSizeKeys.CalculateKey(Step); + mSize = mSizeKeys.CalculateKey(Step); mAttenuation = mAttenuationKeys.CalculateKey(Step); - mLightFactor = mLightFactorKeys.CalculateKey(Step); mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); mLightSpecular = mLightSpecularKeys.CalculateKey(Step); mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); @@ -954,20 +927,20 @@ void lcLight::DrawAreaLight(lcContext* Context) const float Verts[4 * 3]; float* CurVert = Verts; - *CurVert++ = -mAreaSize.x / 2.0f; - *CurVert++ = -mAreaSize.y / 2.0f; + *CurVert++ = -mSize.x / 2.0f; + *CurVert++ = -mSize.y / 2.0f; *CurVert++ = 0.0f; - *CurVert++ = mAreaSize.x / 2.0f; - *CurVert++ = -mAreaSize.y / 2.0f; + *CurVert++ = mSize.x / 2.0f; + *CurVert++ = -mSize.y / 2.0f; *CurVert++ = 0.0f; - *CurVert++ = mAreaSize.x / 2.0f; - *CurVert++ = mAreaSize.y / 2.0f; + *CurVert++ = mSize.x / 2.0f; + *CurVert++ = mSize.y / 2.0f; *CurVert++ = 0.0f; - *CurVert++ = -mAreaSize.x / 2.0f; - *CurVert++ = mAreaSize.y / 2.0f; + *CurVert++ = -mSize.x / 2.0f; + *CurVert++ = mSize.y / 2.0f; *CurVert++ = 0.0f; Context->SetVertexBufferPointer(Verts); @@ -992,8 +965,8 @@ void lcLight::DrawAreaLight(lcContext* Context) const for (int EdgeIndex = 0; EdgeIndex < CircleEdges; EdgeIndex++) { - float c = cosf((float)EdgeIndex / CircleEdges * LC_2PI) * mAreaSize.x / 2.0f; - float s = sinf((float)EdgeIndex / CircleEdges * LC_2PI) * mAreaSize.y / 2.0f; + float c = cosf((float)EdgeIndex / CircleEdges * LC_2PI) * mSize.x / 2.0f; + float s = sinf((float)EdgeIndex / CircleEdges * LC_2PI) * mSize.y / 2.0f; *CurVert++ = c; *CurVert++ = s; @@ -1274,15 +1247,12 @@ void lcLight::RemoveKeyFrames() mSpotTightnessKeys.RemoveAll(); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); - mAreaSizeKeys.RemoveAll(); - mAreaSizeKeys.ChangeKey(mAreaSize, 1, true); + mSizeKeys.RemoveAll(); + mSizeKeys.ChangeKey(mSize, 1, true); mAttenuationKeys.RemoveAll(); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); - mLightFactorKeys.RemoveAll(); - mLightFactorKeys.ChangeKey(mLightFactor, 1, true); - mLightDiffuseKeys.RemoveAll(); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); diff --git a/common/light.h b/common/light.h index 93ce91af..b8aeb9cb 100644 --- a/common/light.h +++ b/common/light.h @@ -36,7 +36,6 @@ enum class lcLightAreaShape enum lcLightProperty { - LC_LIGHT_FACTOR, LC_LIGHT_DIFFUSE, LC_LIGHT_SPECULAR, LC_LIGHT_EXPONENT, @@ -48,7 +47,6 @@ enum lcLightProperty struct lcLightProperties { - lcVector2 mLightFactor; lcVector2 mAreaGrid; float mLightDiffuse; float mLightSpecular; @@ -69,7 +67,7 @@ class lcLight : public lcObject lcLight& operator=(const lcLight&) = delete; lcLight& operator=(lcLight&&) = delete; - static QString GetTypeString(lcLightType LightType); + static QString GetLightTypeString(lcLightType LightType); static QString GetAreaShapeString(lcLightAreaShape LightAreaShape); bool IsPointLight() const @@ -99,11 +97,6 @@ class lcLight : public lcObject bool SetLightType(lcLightType LightType); - lcLightAreaShape GetLightShape() const - { - return mAreaShape; - } - bool IsSelected() const override { return (mState & LC_LIGHT_SELECTION_MASK) != 0; @@ -286,11 +279,11 @@ class lcLight : public lcObject return mAreaShape; } - void SetAreaSize(lcVector2 AreaSize, lcStep Step, bool AddKey); + void SetSize(lcVector2 Size, lcStep Step, bool AddKey); - lcVector2 GetAreaSize() const + lcVector2 GetSize() const { - return mAreaSize; + return mSize; } bool SetCastShadow(bool CastShadow); @@ -321,7 +314,6 @@ class lcLight : public lcObject lcLightProperties GetLightProperties() const { lcLightProperties props; - props.mLightFactor = mLightFactor; props.mLightDiffuse = mLightDiffuse; props.mLightSpecular = mLightSpecular; props.mSpotExponent = mSpotExponent; @@ -335,9 +327,7 @@ class lcLight : public lcObject lcMatrix44 mWorldMatrix; lcVector3 mAttenuation; - lcVector2 mLightFactor; lcVector2 mAreaGrid; - bool mAngleSet; bool mSpotBlendSet; bool mSpotCutoffSet; bool mEnableCutoff; @@ -347,9 +337,10 @@ class lcLight : public lcObject float mSpotCutoff; float mSpotExponent; float mPOVRayExponent; - QString mName; protected: + void UpdateLightType(); + void DrawPointLight(lcContext* Context) const; void DrawSpotLight(lcContext* Context) const; void DrawDirectionalLight(lcContext* Context) const; @@ -361,26 +352,26 @@ class lcLight : public lcObject void DrawTarget(lcContext* Context, float TargetDistance) const; void DrawCone(lcContext* Context, float TargetDistance) const; + QString mName; quint32 mState = 0; lcLightType mLightType = lcLightType::Point; bool mCastShadow = true; lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); + lcVector2 mSize = lcVector2(0.0f, 0.0f); float mSpotConeAngle = 80.0f; float mSpotPenumbraAngle = 0.0f; float mSpotTightness = 0.0f; lcLightAreaShape mAreaShape = lcLightAreaShape::Rectangle; - lcVector2 mAreaSize = lcVector2(200.0f, 200.0f); lcObjectKeyArray mPositionKeys; lcObjectKeyArray mRotationKeys; lcObjectKeyArray mColorKeys; + lcObjectKeyArray mSizeKeys; lcObjectKeyArray mSpotConeAngleKeys; lcObjectKeyArray mSpotPenumbraAngleKeys; lcObjectKeyArray mSpotTightnessKeys; - lcObjectKeyArray mAreaSizeKeys; lcObjectKeyArray mAttenuationKeys; - lcObjectKeyArray mLightFactorKeys; lcObjectKeyArray mAreaGridKeys; lcObjectKeyArray mLightSpecularKeys; lcObjectKeyArray mLightDiffuseKeys; diff --git a/common/project.cpp b/common/project.cpp index c67713db..e5d102fc 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2177,7 +2177,7 @@ bool Project::ExportPOVRay(const QString& FileName) const lcVector3 LightPosition = Light->GetPosition(); const lcVector3 LightTarget = LightPosition + Light->GetDirection(); const lcVector3 LightColor = Light->GetColor(); - const QString LightName = QString(Light->mName).replace(" ", "_"); + const QString LightName = QString(Light->GetName()).replace(" ", "_"); LightType = Light->GetLightType(); Shadowless = Light->GetCastShadow() ? 0 : 1; Power = Light->mPOVRayExponent; @@ -2196,8 +2196,8 @@ bool Project::ExportPOVRay(const QString& FileName) break; case lcLightType::Area: - AreaCircle = (Light->GetLightShape() == lcLightAreaShape::Disk || Light->GetLightShape() == lcLightAreaShape::Ellipse) ? 1 : 0; - AreaSize = Light->GetAreaSize(); + AreaCircle = (Light->GetAreaShape() == lcLightAreaShape::Disk || Light->GetAreaShape() == lcLightAreaShape::Ellipse) ? 1 : 0; + AreaSize = Light->GetSize(); AreaGrid = Light->mAreaGrid; break; diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 5f13f0cf..643d869e 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -499,7 +499,7 @@ QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) else if (Item == mLightTypeItem) { for (int LightTypeIndex = 0; LightTypeIndex < static_cast(lcLightType::Count); LightTypeIndex++) - editor->addItem(lcLight::GetTypeString(static_cast(LightTypeIndex))); + editor->addItem(lcLight::GetLightTypeString(static_cast(LightTypeIndex))); } else if (Item == mLightAreaShapeItem) { @@ -879,27 +879,19 @@ void lcQPropertiesTree::slotReturnPressed() Model->SetSpotLightTightness(Light, Value); } - else if (Item == mLightAreaSizeXItem) + else if (Item == mLightSizeXItem) { - lcVector2 Value = Light->GetAreaSize(); + lcVector2 Value = Light->GetSize(); Value[0] = lcParseValueLocalized(Editor->text()); - Model->SetAreaLightSize(Light, Value); + Model->SetLightSize(Light, Value); } - else if (Item == mLightAreaSizeYItem) + else if (Item == mLightSizeYItem) { - lcVector2 Value = Light->GetAreaSize(); + lcVector2 Value = Light->GetSize(); Value[1] = lcParseValueLocalized(Editor->text()); - Model->SetAreaLightSize(Light, Value); - } - else if (Item == lightFactorA) - { - float Value = lcParseValueLocalized(Editor->text()); - if (Item == lightFactorA) - Props.mLightFactor[0] = Value; - - Model->UpdateLight(Light, Props, LC_LIGHT_FACTOR); + Model->SetLightSize(Light, Value); } else if (Item == lightDiffuse) { @@ -1162,14 +1154,13 @@ void lcQPropertiesTree::SetEmpty() lightEnableCutoff = nullptr; lightExponent = nullptr; mLightTypeItem = nullptr; - lightFactorA = nullptr; mLightNameItem = nullptr; mLightSpotConeAngleItem = nullptr; mLightSpotPenumbraAngleItem = nullptr; mLightSpotTightnessItem = nullptr; mLightAreaShapeItem = nullptr; - mLightAreaSizeXItem = nullptr; - mLightAreaSizeYItem = nullptr; + mLightSizeXItem = nullptr; + mLightSizeYItem = nullptr; lightFormat = nullptr; mLightCastShadowItem = nullptr; lightAreaGridRows = nullptr; @@ -1411,7 +1402,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) QString Format, ExponentToolTip, FactorAToolTip, FactorBToolTip; lcLightType LightType = lcLightType::Point; lcLightAreaShape LightAreaShape = lcLightAreaShape::Rectangle; - lcVector2 LightAreaSize(0.0f, 0.0f); + lcVector2 LightSize(0.0f, 0.0f); int FormatIndex = 0; float Diffuse = 0.0f; float Specular = 0.0f; @@ -1425,7 +1416,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lcVector3 Target(0.0f, 0.0f, 0.0f); QColor Color(Qt::white); float SpotConeAngle = 0.0f, SpotPenumbraAngle = 0.0f, SpotTightness = 0.0f; - lcVector2 Factor(0.0f, 0.0f); lcVector2 AreaGrid(0.0f, 0.0f); if (Light) @@ -1443,38 +1433,22 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) SpotConeAngle = Light->GetSpotConeAngle(); SpotPenumbraAngle = Light->GetSpotPenumbraAngle(); - Factor = Light->mLightFactor; LightType = Light->GetLightType(); LightAreaShape = Light->GetAreaShape(); - LightAreaSize = Light->GetAreaSize(); + LightSize = Light->GetSize(); switch (LightType) { case lcLightType::Point: - FactorALabel = tr("Radius (m)"); - FactorAToolTip = tr("The light size for shadow sampling in metres."); ExponentLabel = tr("Exponent"); break; case lcLightType::Spot: FactorBToolTip = tr("The softness of the spotlight edge."); ExponentLabel = tr("Power"); - - if (POVRayLight) - { - FactorALabel = tr("Radius (°)"); - FactorAToolTip = tr("The angle between the \"hot-spot\" edge at the beam center and the center line."); - } - else - { - FactorALabel = tr("Radius (m)"); - FactorAToolTip = tr("Shadow soft size - Light size in metres for shadow sampling."); - } break; case lcLightType::Directional: - FactorALabel = tr("Angle (°)"); - FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth."); ExponentLabel = tr("Strength"); break; @@ -1522,57 +1496,60 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) switch (LightType) { case lcLightType::Point: + mLightSizeXItem = addProperty(mLightAttributesItem, tr("Radius"), PropertyFloat); + mLightSizeXItem->setToolTip(1, tr("Shadow soft size (Blender only).")); break; case lcLightType::Spot: - { - mLightSpotConeAngleItem = addProperty(mLightAttributesItem, tr("Spot Cone Angle"), PropertyFloat); - mLightSpotConeAngleItem->setToolTip(1, tr("The angle (in degrees) of the spot light's beam.")); + mLightSpotConeAngleItem = addProperty(mLightAttributesItem, tr("Spot Cone Angle"), PropertyFloat); + mLightSpotConeAngleItem->setToolTip(1, tr("The angle (in degrees) of the spot light's beam.")); - mLightSpotPenumbraAngleItem = addProperty(mLightAttributesItem, tr("Spot Penumbra Angle"), PropertyFloat); - mLightSpotPenumbraAngleItem->setToolTip(1, tr("The angle (in degrees) over which the intensity of the spot light falls off to zero.")); + mLightSpotPenumbraAngleItem = addProperty(mLightAttributesItem, tr("Spot Penumbra Angle"), PropertyFloat); + mLightSpotPenumbraAngleItem->setToolTip(1, tr("The angle (in degrees) over which the intensity of the spot light falls off to zero.")); - mLightSpotTightnessItem = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat); - mLightSpotTightnessItem->setToolTip(1, tr("Additional exponential spot light edge softening (POV-Ray only).")); - } + mLightSpotTightnessItem = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat); + mLightSpotTightnessItem->setToolTip(1, tr("Additional exponential spot light edge softening (POV-Ray only).")); + + mLightSizeXItem = addProperty(mLightAttributesItem, tr("Radius"), PropertyFloat); + mLightSizeXItem->setToolTip(1, tr("Shadow soft size (Blender only).")); break; case lcLightType::Directional: + mLightSizeXItem = addProperty(mLightAttributesItem, tr("Angle"), PropertyFloat); + mLightSizeXItem->setToolTip(1, tr("Angular diameter of the light (Blender only).")); break; case lcLightType::Area: - { - mLightAreaShapeItem = addProperty(mLightAttributesItem, tr("Area Shape"), PropertyStringList); - mLightAreaShapeItem->setToolTip(1, tr("The shape of the area light.")); + mLightAreaShapeItem = addProperty(mLightAttributesItem, tr("Area Shape"), PropertyStringList); + mLightAreaShapeItem->setToolTip(1, tr("The shape of the area light.")); - switch (LightAreaShape) - { - case lcLightAreaShape::Rectangle: - case lcLightAreaShape::Ellipse: - mLightAreaSizeXItem = addProperty(mLightAttributesItem, tr("Area Width"), PropertyFloat); - mLightAreaSizeXItem->setToolTip(1, tr("The width (X direction) of the area light.")); + switch (LightAreaShape) + { + case lcLightAreaShape::Rectangle: + case lcLightAreaShape::Ellipse: + mLightSizeXItem = addProperty(mLightAttributesItem, tr("Area Width"), PropertyFloat); + mLightSizeXItem->setToolTip(1, tr("The width (X direction) of the area light.")); - mLightAreaSizeYItem = addProperty(mLightAttributesItem, tr("Area Height"), PropertyFloat); - mLightAreaSizeYItem->setToolTip(1, tr("The height (Y direction) of the area light.")); - break; + mLightSizeYItem = addProperty(mLightAttributesItem, tr("Area Height"), PropertyFloat); + mLightSizeYItem->setToolTip(1, tr("The height (Y direction) of the area light.")); + break; - case lcLightAreaShape::Square: - case lcLightAreaShape::Disk: - mLightAreaSizeXItem = addProperty(mLightAttributesItem, tr("Area Size"), PropertyFloat); - mLightAreaSizeXItem->setToolTip(1, tr("The size of the area light.")); + case lcLightAreaShape::Square: + case lcLightAreaShape::Disk: + mLightSizeXItem = addProperty(mLightAttributesItem, tr("Area Size"), PropertyFloat); + mLightSizeXItem->setToolTip(1, tr("The size of the area light.")); - mLightAreaSizeYItem = nullptr; - break; + mLightSizeYItem = nullptr; + break; - case lcLightAreaShape::Count: - break; - } + case lcLightAreaShape::Count: + break; + } - if (POVRayLight) - { - lightAreaGridRows = addProperty(mLightAttributesItem, tr("Grid Rows"), PropertyFloat); - lightAreaGridColumns = addProperty(mLightAttributesItem, tr("Grid Columns"), PropertyFloat); - } + if (POVRayLight) + { + lightAreaGridRows = addProperty(mLightAttributesItem, tr("Grid Rows"), PropertyFloat); + lightAreaGridColumns = addProperty(mLightAttributesItem, tr("Grid Columns"), PropertyFloat); } break; @@ -1582,9 +1559,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightExponent = addProperty(mLightAttributesItem, ExponentLabel, PropertyFloat); - if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) - lightFactorA = addProperty(mLightAttributesItem, FactorALabel, PropertyFloat); - if (!POVRayLight) { if (LightType != lcLightType::Directional) @@ -1658,35 +1632,50 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightFormat->setText(1, Format); lightFormat->setData(0, PropertyValueRole, FormatIndex); - mLightTypeItem->setText(1, lcLight::GetTypeString(LightType)); + mLightTypeItem->setText(1, lcLight::GetLightTypeString(LightType)); mLightTypeItem->setData(0, PropertyValueRole, static_cast(LightType)); mLightCastShadowItem->setCheckState(1, CastShadow ? Qt::Checked : Qt::Unchecked); mLightCastShadowItem->setData(0, PropertyValueRole, CastShadow); + mLightSizeXItem->setText(1, lcFormatValueLocalized(LightSize[0])); + mLightSizeXItem->setData(0, PropertyValueRole, LightSize[0]); + + if (mLightSizeYItem) + { + mLightSizeYItem->setText(1, lcFormatValueLocalized(LightSize[1])); + mLightSizeYItem->setData(0, PropertyValueRole, LightSize[1]); + } + lightExponent->setText(1, lcFormatValueLocalized(Exponent)); lightExponent->setData(0, PropertyValueRole, Exponent); lightExponent->setToolTip(1, ExponentToolTip); - if ((LightType == lcLightType::Point || LightType == lcLightType::Directional) && !POVRayLight) - { - lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); - lightFactorA->setData(0, PropertyValueRole, Factor[0]); - lightFactorA->setToolTip(1, FactorAToolTip); - } - else if (LightType == lcLightType::Area) + switch (LightType) { - mLightAreaShapeItem->setText(1, lcLight::GetAreaShapeString(LightAreaShape)); - mLightAreaShapeItem->setData(0, PropertyValueRole, static_cast(LightAreaShape)); + case lcLightType::Point: + break; - mLightAreaSizeXItem->setText(1, lcFormatValueLocalized(LightAreaSize[0])); - mLightAreaSizeXItem->setData(0, PropertyValueRole, LightAreaSize[0]); + case lcLightType::Spot: + mLightSpotConeAngleItem->setText(1, lcFormatValueLocalized(SpotConeAngle)); + mLightSpotConeAngleItem->setData(0, PropertyValueRole, SpotConeAngle); + mLightSpotConeAngleItem->setData(0, PropertyRangeRole, QPointF(1.0, 180.0)); - if (mLightAreaSizeYItem) - { - mLightAreaSizeYItem->setText(1, lcFormatValueLocalized(LightAreaSize[1])); - mLightAreaSizeYItem->setData(0, PropertyValueRole, LightAreaSize[1]); - } + mLightSpotPenumbraAngleItem->setText(1, lcFormatValueLocalized(SpotPenumbraAngle)); + mLightSpotPenumbraAngleItem->setData(0, PropertyValueRole, SpotPenumbraAngle); + mLightSpotPenumbraAngleItem->setData(0, PropertyRangeRole, QPointF(0.0, 180.0)); + + mLightSpotTightnessItem->setText(1, lcFormatValueLocalized(SpotTightness)); + mLightSpotTightnessItem->setData(0, PropertyValueRole, SpotTightness); + mLightSpotTightnessItem->setData(0, PropertyRangeRole, QPointF(0.0, 100.0)); + break; + + case lcLightType::Directional: + break; + + case lcLightType::Area: + mLightAreaShapeItem->setText(1, lcLight::GetAreaShapeString(LightAreaShape)); + mLightAreaShapeItem->setData(0, PropertyValueRole, static_cast(LightAreaShape)); if (POVRayLight) { @@ -1698,20 +1687,10 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightAreaGridColumns->setData(0, PropertyValueRole, AreaGrid[1]); lightAreaGridColumns->setToolTip(1, tr("The number of sample columns in the area light.")); } - } - else if (LightType == lcLightType::Spot) - { - mLightSpotConeAngleItem->setText(1, lcFormatValueLocalized(SpotConeAngle)); - mLightSpotConeAngleItem->setData(0, PropertyValueRole, SpotConeAngle); - mLightSpotConeAngleItem->setData(0, PropertyRangeRole, QPointF(1.0, 180.0)); - - mLightSpotPenumbraAngleItem->setText(1, lcFormatValueLocalized(SpotPenumbraAngle)); - mLightSpotPenumbraAngleItem->setData(0, PropertyValueRole, SpotPenumbraAngle); - mLightSpotPenumbraAngleItem->setData(0, PropertyRangeRole, QPointF(0.0, 180.0)); + break; - mLightSpotTightnessItem->setText(1, lcFormatValueLocalized(SpotTightness)); - mLightSpotTightnessItem->setData(0, PropertyValueRole, SpotTightness); - mLightSpotTightnessItem->setData(0, PropertyRangeRole, QPointF(0.0, 100.0)); + case lcLightType::Count: + break; } if (!POVRayLight) diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index f4910b73..1c7428dd 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -145,10 +145,8 @@ protected slots: QTreeWidgetItem* mLightSpotPenumbraAngleItem; QTreeWidgetItem* mLightSpotTightnessItem; QTreeWidgetItem* mLightAreaShapeItem; - QTreeWidgetItem* mLightAreaSizeXItem; - QTreeWidgetItem* mLightAreaSizeYItem; - QTreeWidgetItem* lightFactorA; - QTreeWidgetItem* lightFactorB; + QTreeWidgetItem* mLightSizeXItem; + QTreeWidgetItem* mLightSizeYItem; QTreeWidgetItem* mLightNameItem; QTreeWidgetItem* lightFormat; QTreeWidgetItem* mLightCastShadowItem; From a27694a5947f95059d89bd1ca2076c807fe594e8 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 23 Sep 2023 18:38:03 -0700 Subject: [PATCH 33/42] Support dragging light targets to rotate. --- common/lc_mainwindow.cpp | 12 ++-- common/lc_model.cpp | 37 ++++++++----- common/lc_model.h | 7 ++- common/lc_view.cpp | 2 +- common/light.cpp | 116 ++++++++++++++++++++++++++------------- common/light.h | 110 ++++++++++++++++++------------------- common/piece.h | 2 + 7 files changed, 170 insertions(+), 116 deletions(-) diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 80a596f0..148647ea 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -2901,32 +2901,32 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) case LC_PIECE_MOVE_PLUSX: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, true); break; case LC_PIECE_MOVE_MINUSX: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, true); break; case LC_PIECE_MOVE_PLUSY: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, true); break; case LC_PIECE_MOVE_MINUSY: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, true); break; case LC_PIECE_MOVE_PLUSZ: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, true); break; case LC_PIECE_MOVE_MINUSZ: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, true); break; case LC_PIECE_ROTATE_PLUSX: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index befc1420..d6bdf293 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2705,7 +2705,7 @@ bool lcModel::RemoveSelectedObjects() return RemovedPiece || RemovedCamera || RemovedLight; } -void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint) +void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove) { bool Moved = false; lcMatrix33 RelativeRotation; @@ -2745,16 +2745,6 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector Moved = true; } } - - for (lcLight* Light : mLights) - { - if (Light->IsSelected()) - { - Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedPieceDistance); - Light->UpdatePosition(mCurrentStep); - Moved = true; - } - } } } @@ -2771,13 +2761,25 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector Moved = true; } } + + for (lcLight* Light : mLights) + { + if (Light->IsSelected()) + { + Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedObjectDistance, FirstMove); + Light->UpdatePosition(mCurrentStep); + Moved = true; + } + } } if (Moved && Update) { UpdateAllViews(); + if (Checkpoint) SaveCheckpoint(tr("Moving")); + gMainWindow->UpdateSelectedObjects(false); } } @@ -2951,11 +2953,11 @@ void lcModel::TransformSelectedObjects(lcTransformType TransformType, const lcVe switch (TransformType) { case lcTransformType::AbsoluteTranslation: - MoveSelectedObjects(Transform, false, false, true, true); + MoveSelectedObjects(Transform, false, false, true, true, true); break; case lcTransformType::RelativeTranslation: - MoveSelectedObjects(Transform, true, false, true, true); + MoveSelectedObjects(Transform, true, false, true, true, true); break; case lcTransformType::AbsoluteRotation: @@ -4214,6 +4216,7 @@ void lcModel::RedoAction() void lcModel::BeginMouseTool() { mMouseToolDistance = lcVector3(0.0f, 0.0f, 0.0f); + mMouseToolFirstMove = true; } void lcModel::EndMouseTool(lcTool Tool, bool Accept) @@ -4335,6 +4338,7 @@ void lcModel::BeginCameraTool(const lcVector3& Position, const lcVector3& Target mCameras.Add(Camera); mMouseToolDistance = Position; + mMouseToolFirstMove = false; ClearSelectionAndSetFocus(Camera, LC_CAMERA_SECTION_TARGET, false); } @@ -4347,6 +4351,7 @@ void lcModel::UpdateCameraTool(const lcVector3& Position) Camera->UpdatePosition(1); mMouseToolDistance = Position; + mMouseToolFirstMove = false; gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); @@ -4357,8 +4362,10 @@ void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool const lcVector3 PieceDistance = SnapPosition(Distance) - SnapPosition(mMouseToolDistance); const lcVector3 ObjectDistance = Distance - mMouseToolDistance; - MoveSelectedObjects(PieceDistance, ObjectDistance, AllowRelative, AlternateButtonDrag, true, false); + MoveSelectedObjects(PieceDistance, ObjectDistance, AllowRelative, AlternateButtonDrag, true, false, mMouseToolFirstMove); + mMouseToolDistance = Distance; + mMouseToolFirstMove = false; gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); @@ -4368,7 +4375,9 @@ void lcModel::UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag { const lcVector3 Delta = SnapRotation(Angles) - SnapRotation(mMouseToolDistance); RotateSelectedObjects(Delta, true, AlternateButtonDrag, false, false); + mMouseToolDistance = Angles; + mMouseToolFirstMove = false; gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); diff --git a/common/lc_model.h b/common/lc_model.h index fe8423bd..71fb0e5b 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -348,12 +348,12 @@ class lcModel void ZoomExtents(lcCamera* Camera, float Aspect); void Zoom(lcCamera* Camera, float Amount); - void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint) + void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove) { - MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Update, Checkpoint); + MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Update, Checkpoint, FirstMove); } - void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint); + void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove); void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint); void ScaleSelectedPieces(const float Scale, bool Update, bool Checkpoint); void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform); @@ -409,6 +409,7 @@ class lcModel bool mActive; lcStep mCurrentStep; lcVector3 mMouseToolDistance; + bool mMouseToolFirstMove; lcArray mPieces; lcArray mCameras; diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 13aeabb6..3cfe1a53 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2054,7 +2054,7 @@ void lcView::UpdateTrackTool() break; case lcTool::AreaLight: - NewTrackTool = lcTrackTool::AreaLight;; + NewTrackTool = lcTrackTool::AreaLight; break; case lcTool::Camera: diff --git a/common/light.cpp b/common/light.cpp index 8d0f2028..53d28909 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -9,7 +9,7 @@ #include "lc_context.h" #define LC_LIGHT_SPHERE_RADIUS 5.0f -#define LC_LIGHT_TARGET_EDGE 2.0f +#define LC_LIGHT_TARGET_RADIUS 2.5f #define LC_LIGHT_SPOT_CONE_HEIGHT 10.0f #define LC_LIGHT_SPOT_CONE_RADIUS 7.5f #define LC_LIGHT_DIRECTIONAL_RADIUS 5.0f @@ -627,6 +627,16 @@ void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const ObjectRayTest.PieceInfoRayTest.Plane = Plane; } } + + if (IsSelected()) + { + if (lcSphereRayMinIntersectDistance(lcMul31(lcVector3(0,0,-mTargetDistance), mWorldMatrix), LC_LIGHT_TARGET_RADIUS, ObjectRayTest.Start, ObjectRayTest.End, &Distance) && (Distance < ObjectRayTest.Distance)) + { + ObjectRayTest.ObjectSection.Object = const_cast(this); + ObjectRayTest.ObjectSection.Section = LC_LIGHT_SECTION_TARGET; + ObjectRayTest.Distance = Distance; + } + } } void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const @@ -659,9 +669,11 @@ void lcLight::BoxTest(lcObjectBoxTest& ObjectBoxTest) const } } -void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance) +void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance, bool FirstMove) { - if (IsSelected(LC_LIGHT_SECTION_POSITION)) + const quint32 Section = GetFocusSection(); + + if (Section == LC_LIGHT_SECTION_POSITION || Section == LC_LIGHT_SECTION_INVALID) { const lcVector3 Position = mWorldMatrix.GetTranslation() + Distance; @@ -669,6 +681,26 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance) mWorldMatrix.SetTranslation(Position); } + else + { + if (FirstMove) + mTargetMovePosition = lcMul31(lcVector3(0.0f, 0.0f, -mTargetDistance), mWorldMatrix); + + mTargetMovePosition += Distance; + + lcVector3 CurrentDirection = -lcNormalize(mTargetMovePosition - mWorldMatrix.GetTranslation()); + lcMatrix33 WorldMatrix; + + WorldMatrix.r[0] = lcCross(lcVector3(mWorldMatrix.r[1]), CurrentDirection); + WorldMatrix.r[1] = lcCross(CurrentDirection, WorldMatrix.r[0]); + WorldMatrix.r[2] = CurrentDirection; + + WorldMatrix.Orthonormalize(); + + SetRotation(WorldMatrix, Step, AddKey); + + mWorldMatrix = lcMatrix44(WorldMatrix, mWorldMatrix.GetTranslation()); + } } void lcLight::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame) @@ -861,7 +893,7 @@ void lcLight::DrawPointLight(lcContext* Context) const { SetupLightMatrix(Context); - DrawSphere(Context, LC_LIGHT_SPHERE_RADIUS); + DrawSphere(Context, lcVector3(0.0f, 0.0f, 0.0f), LC_LIGHT_SPHERE_RADIUS); } void lcLight::DrawSpotLight(lcContext* Context) const @@ -899,12 +931,11 @@ void lcLight::DrawSpotLight(lcContext* Context) const Context->DrawIndexedPrimitives(GL_LINES, (ConeEdges + 4) * 2, GL_UNSIGNED_SHORT, 0); - const float TargetDistance = 250.0f; - - DrawTarget(Context, TargetDistance); - if (IsSelected()) - DrawCone(Context, TargetDistance); + { + DrawCone(Context, mTargetDistance); + DrawTarget(Context); + } } void lcLight::DrawDirectionalLight(lcContext* Context) const @@ -913,9 +944,8 @@ void lcLight::DrawDirectionalLight(lcContext* Context) const DrawCylinder(Context, LC_LIGHT_DIRECTIONAL_RADIUS, LC_LIGHT_DIRECTIONAL_HEIGHT); - const float TargetDistance = 25.0f; - - DrawTarget(Context, TargetDistance); + if (IsSelected()) + DrawTarget(Context); } void lcLight::DrawAreaLight(lcContext* Context) const @@ -988,9 +1018,8 @@ void lcLight::DrawAreaLight(lcContext* Context) const Context->DrawIndexedPrimitives(GL_LINES, (CircleEdges + 2) * 2, GL_UNSIGNED_SHORT, 0); } - const float TargetDistance = 25.0f; - - DrawTarget(Context, TargetDistance); + if (IsSelected()) + DrawTarget(Context); } void lcLight::SetupLightMatrix(lcContext* Context) const @@ -1021,7 +1050,7 @@ void lcLight::SetupLightMatrix(lcContext* Context) const } } -void lcLight::DrawSphere(lcContext* Context, float Radius) const +void lcLight::DrawSphere(lcContext* Context, const lcVector3& Center, float Radius) const { constexpr int Slices = 6; constexpr int NumIndices = 3 * Slices + 6 * Slices * (Slices - 2) + 3 * Slices; @@ -1032,7 +1061,7 @@ void lcLight::DrawSphere(lcContext* Context, float Radius) const lcVector3* Vertex = Vertices; quint16* Index = Indices; - *Vertex++ = lcVector3(0, 0, Radius); + *Vertex++ = Center + lcVector3(0, 0, Radius); for (int i = 1; i < Slices; i++) { @@ -1044,11 +1073,11 @@ void lcLight::DrawSphere(lcContext* Context, float Radius) const const float x0 = r0 * sinf(j * (LC_2PI / Slices)); const float y0 = r0 * cosf(j * (LC_2PI / Slices)); - *Vertex++ = lcVector3(x0, y0, z0); + *Vertex++ = Center + lcVector3(x0, y0, z0); } } - *Vertex++ = lcVector3(0, 0, -Radius); + *Vertex++ = Center + lcVector3(0, 0, -Radius); for (quint16 i = 0; i < Slices - 1; i++) { @@ -1138,37 +1167,50 @@ void lcLight::DrawCylinder(lcContext* Context, float Radius, float Height) const Context->DrawIndexedPrimitives(GL_LINES, 48, GL_UNSIGNED_SHORT, 0); } -void lcLight::DrawTarget(lcContext* Context, float TargetDistance) const +void lcLight::DrawTarget(lcContext* Context) const { - float Verts[10 * 3]; + float Verts[2 * 3]; float* CurVert = Verts; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - TargetDistance; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - TargetDistance; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - TargetDistance; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE - TargetDistance; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - TargetDistance; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - TargetDistance; - *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - TargetDistance; - *CurVert++ = LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE; *CurVert++ = -LC_LIGHT_TARGET_EDGE - TargetDistance; - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f; - *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -TargetDistance; + *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -mTargetDistance; Context->SetVertexBufferPointer(Verts); Context->SetVertexFormatPosition(3); - const GLushort Indices[(12 + 1) * 2] = + const GLushort Indices[2] = { - 0, 1, 1, 2, 2, 3, 3, 0, - 4, 5, 5, 6, 6, 7, 7, 4, - 0, 4, 1, 5, 2, 6, 3, 7, - 8, 9 + 0, 1 }; Context->SetIndexBufferPointer(Indices); - Context->DrawIndexedPrimitives(GL_LINES, (12 + 1) * 2, GL_UNSIGNED_SHORT, 0); + Context->DrawIndexedPrimitives(GL_LINES, 2, GL_UNSIGNED_SHORT, 0); + + const lcPreferences& Preferences = lcGetPreferences(); + const float LineWidth = Preferences.mLineWidth; + + if (IsSelected(LC_LIGHT_SECTION_TARGET)) + { + const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); + const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); + + Context->SetLineWidth(2.0f * LineWidth); + + if (IsFocused(LC_LIGHT_SECTION_TARGET)) + Context->SetColor(FocusedColor); + else + Context->SetColor(SelectedColor); + } + else + { + const lcVector4 LightColor = lcVector4FromColor(Preferences.mLightColor); + + Context->SetLineWidth(LineWidth); + Context->SetColor(LightColor); + } + + DrawSphere(Context, lcVector3(0.0f, 0.0f, -mTargetDistance), LC_LIGHT_TARGET_RADIUS); } void lcLight::DrawCone(lcContext* Context, float TargetDistance) const diff --git a/common/light.h b/common/light.h index b8aeb9cb..2b2e1e4e 100644 --- a/common/light.h +++ b/common/light.h @@ -5,15 +5,12 @@ #define LC_LIGHT_HIDDEN 0x0001 #define LC_LIGHT_DISABLED 0x0002 -#define LC_LIGHT_POSITION_SELECTED 0x0010 -#define LC_LIGHT_POSITION_FOCUSED 0x0020 -#define LC_LIGHT_SELECTION_MASK LC_LIGHT_POSITION_SELECTED -#define LC_LIGHT_FOCUS_MASK LC_LIGHT_POSITION_FOCUSED - -enum lcLightSection +enum lcLightSection : quint32 { - LC_LIGHT_SECTION_POSITION + LC_LIGHT_SECTION_INVALID = ~0U, + LC_LIGHT_SECTION_POSITION = 0, + LC_LIGHT_SECTION_TARGET }; enum class lcLightType @@ -99,77 +96,58 @@ class lcLight : public lcObject bool IsSelected() const override { - return (mState & LC_LIGHT_SELECTION_MASK) != 0; + return mSelected; } bool IsSelected(quint32 Section) const override { - switch (Section) - { - case LC_LIGHT_SECTION_POSITION: - return (mState & LC_LIGHT_POSITION_SELECTED) != 0; - break; - } + Q_UNUSED(Section); - return false; + return mSelected; } void SetSelected(bool Selected) override { - if (Selected) - mState |= LC_LIGHT_POSITION_SELECTED; - else - mState &= ~(LC_LIGHT_SELECTION_MASK | LC_LIGHT_FOCUS_MASK); + mSelected = Selected; + + if (!Selected) + mFocusedSection = LC_LIGHT_SECTION_INVALID; } void SetSelected(quint32 Section, bool Selected) override { - switch (Section) - { - case LC_LIGHT_SECTION_POSITION: - if (Selected) - mState |= LC_LIGHT_POSITION_SELECTED; - else - mState &= ~(LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED); - break; - } + Q_UNUSED(Section); + + mSelected = Selected; + + if (!Selected) + mFocusedSection = LC_LIGHT_SECTION_INVALID; } bool IsFocused() const override { - return (mState & LC_LIGHT_FOCUS_MASK) != 0; + return mFocusedSection != LC_LIGHT_SECTION_INVALID; } bool IsFocused(quint32 Section) const override { - switch (Section) - { - case LC_LIGHT_SECTION_POSITION: - return (mState & LC_LIGHT_POSITION_FOCUSED) != 0; - } - - return false; + return mFocusedSection == Section; } void SetFocused(quint32 Section, bool Focused) override { - switch (Section) + if (Focused) { - case LC_LIGHT_SECTION_POSITION: - if (Focused) - mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED; - else - mState &= ~(LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED); - break; + mFocusedSection = Section; + mSelected = true; } + else + mFocusedSection = LC_LIGHT_SECTION_INVALID; } quint32 GetFocusSection() const override { - if (mState & LC_LIGHT_POSITION_FOCUSED) - return LC_LIGHT_SECTION_POSITION; - - return ~0U; + return mFocusedSection; } quint32 GetAllowedTransforms() const override @@ -179,9 +157,12 @@ class lcLight : public lcObject const quint32 Section = GetFocusSection(); - if (Section == LC_LIGHT_SECTION_POSITION) + if (Section == LC_LIGHT_SECTION_POSITION || Section == LC_LIGHT_SECTION_INVALID) return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ; + if (Section == LC_LIGHT_SECTION_TARGET) + return LC_OBJECT_TRANSFORM_MOVE_XYZ; + return 0; } @@ -197,9 +178,13 @@ class lcLight : public lcObject lcVector3 GetSectionPosition(quint32 Section) const override { - Q_UNUSED(Section); + if (Section == LC_LIGHT_SECTION_POSITION) + return mWorldMatrix.GetTranslation(); - return mWorldMatrix.GetTranslation(); + if (Section == LC_LIGHT_SECTION_TARGET) + return lcMul31(lcVector3(0.0f, 0.0f, -mTargetDistance), mWorldMatrix); + + return lcVector3(0.0f, 0.0f, 0.0f); } void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey) @@ -214,7 +199,16 @@ class lcLight : public lcObject lcVector3 GetRotationCenter() const { - return mWorldMatrix.GetTranslation(); + const quint32 Section = GetFocusSection(); + + if (Section == LC_LIGHT_SECTION_POSITION || Section == LC_LIGHT_SECTION_INVALID) + { + return mWorldMatrix.GetTranslation(); + } + else + { + return lcMul31(lcVector3(0.0f, 0.0f, -mTargetDistance), mWorldMatrix); + } } lcVector3 GetPosition() const @@ -305,7 +299,7 @@ class lcLight : public lcObject void CompareBoundingBox(lcVector3& Min, lcVector3& Max); void UpdatePosition(lcStep Step); - void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance); + void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance, bool FirstMove); void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame); bool Setup(int LightIndex); void CreateName(const lcArray& Lights); @@ -347,13 +341,12 @@ class lcLight : public lcObject void DrawAreaLight(lcContext* Context) const; void SetupLightMatrix(lcContext* Context) const; - void DrawSphere(lcContext* Context, float Radius) const; + void DrawSphere(lcContext* Context, const lcVector3& Center, float Radius) const; void DrawCylinder(lcContext* Context, float Radius, float Height) const; - void DrawTarget(lcContext* Context, float TargetDistance) const; + void DrawTarget(lcContext* Context) const; void DrawCone(lcContext* Context, float TargetDistance) const; QString mName; - quint32 mState = 0; lcLightType mLightType = lcLightType::Point; bool mCastShadow = true; lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); @@ -363,6 +356,11 @@ class lcLight : public lcObject float mSpotTightness = 0.0f; lcLightAreaShape mAreaShape = lcLightAreaShape::Rectangle; + quint32 mState = 0; + bool mSelected = false; + quint32 mFocusedSection = LC_LIGHT_SECTION_INVALID; + lcVector3 mTargetMovePosition = lcVector3(0.0f, 0.0f, 0.0f); + lcObjectKeyArray mPositionKeys; lcObjectKeyArray mRotationKeys; lcObjectKeyArray mColorKeys; @@ -377,4 +375,6 @@ class lcLight : public lcObject lcObjectKeyArray mLightDiffuseKeys; lcObjectKeyArray mSpotCutoffKeys; lcObjectKeyArray mSpotExponentKeys; + + static constexpr float mTargetDistance = 50.0f; }; diff --git a/common/piece.h b/common/piece.h index ff714fee..a139d890 100644 --- a/common/piece.h +++ b/common/piece.h @@ -48,6 +48,7 @@ class lcPiece : public lcObject void SetSelected(bool Selected) override { mSelected = Selected; + if (!Selected) mFocusedSection = LC_PIECE_SECTION_INVALID; } @@ -57,6 +58,7 @@ class lcPiece : public lcObject Q_UNUSED(Section); mSelected = Selected; + if (!Selected) mFocusedSection = LC_PIECE_SECTION_INVALID; } From 96523c39b9324e7b324126d7360cb4394a244854 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 1 Oct 2023 12:49:35 -0700 Subject: [PATCH 34/42] Show light rotation in properties. --- qt/lc_qpropertiestree.cpp | 251 ++++++++++++++++---------------------- qt/lc_qpropertiestree.h | 26 ++-- 2 files changed, 116 insertions(+), 161 deletions(-) diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 643d869e..a648a179 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -667,50 +667,54 @@ void lcQPropertiesTree::slotReturnPressed() QTreeWidgetItem* Item = mDelegate->editedItem(); lcModel* Model = gMainWindow->GetActiveModel(); - if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE) + lcPiece* Piece = (mFocus && mFocus->IsPiece()) ? (lcPiece*)mFocus : nullptr; + lcLight* Light = (mFocus && mFocus->IsLight()) ? (lcLight*)mFocus : nullptr; + + if (Item == mPositionXItem || Item == mPositionYItem || Item == mPositionZItem) { - lcPiece* Piece = (mFocus && mFocus->IsPiece()) ? (lcPiece*)mFocus : nullptr; + lcVector3 Center; + lcMatrix33 RelativeRotation; + Model->GetMoveRotateTransform(Center, RelativeRotation); + lcVector3 Position = Center; + float Value = lcParseValueLocalized(Editor->text()); + + if (Item == mPositionXItem) + Position[0] = Value; + else if (Item == mPositionYItem) + Position[1] = Value; + else if (Item == mPositionZItem) + Position[2] = Value; + + lcVector3 Distance = Position - Center; + + Model->MoveSelectedObjects(Distance, Distance, false, true, true, true); + } + else if (Item == mRotationXItem || Item == mRotationYItem || Item == mRotationZItem) + { + lcVector3 InitialRotation(0.0f, 0.0f, 0.0f); - if (Item == partPositionX || Item == partPositionY || Item == partPositionZ) - { - lcVector3 Center; - lcMatrix33 RelativeRotation; - Model->GetMoveRotateTransform(Center, RelativeRotation); - lcVector3 Position = Center; - float Value = lcParseValueLocalized(Editor->text()); - - if (Item == partPositionX) - Position[0] = Value; - else if (Item == partPositionY) - Position[1] = Value; - else if (Item == partPositionZ) - Position[2] = Value; - - lcVector3 Distance = Position - Center; - - Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); - } - else if (Item == partRotationX || Item == partRotationY || Item == partRotationZ) - { - lcVector3 InitialRotation; - if (Piece) - InitialRotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD; - else - InitialRotation = lcVector3(0.0f, 0.0f, 0.0f); - lcVector3 Rotation = InitialRotation; + if (Piece) + InitialRotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD; + else if (Light) + InitialRotation = lcMatrix44ToEulerAngles(Light->mWorldMatrix) * LC_RTOD; - float Value = lcParseValueLocalized(Editor->text()); + lcVector3 Rotation = InitialRotation; - if (Item == partRotationX) - Rotation[0] = Value; - else if (Item == partRotationY) - Rotation[1] = Value; - else if (Item == partRotationZ) - Rotation[2] = Value; + float Value = lcParseValueLocalized(Editor->text()); - Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, true); - } - else if (Item == partShow) + if (Item == mRotationXItem) + Rotation[0] = Value; + else if (Item == mRotationYItem) + Rotation[1] = Value; + else if (Item == mRotationZItem) + Rotation[2] = Value; + + Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, true); + } + + if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE) + { + if (Item == partShow) { bool Ok = false; lcStep Step = Editor->text().toUInt(&Ok); @@ -819,49 +823,11 @@ void lcQPropertiesTree::slotReturnPressed() } else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) { - lcLight* Light = (mFocus && mFocus->IsLight()) ? (lcLight*)mFocus : nullptr; - if (Light) { lcLightProperties Props = Light->GetLightProperties(); - QString Name = Light->GetName(); - - if (Item == lightPositionX || Item == lightPositionY || Item == lightPositionZ) - { - lcVector3 Center = Light->GetPosition(); - lcVector3 Position = Center; - - float Value = lcParseValueLocalized(Editor->text()); - - if (Item == lightPositionX) - Position[0] = Value; - else if (Item == lightPositionY) - Position[1] = Value; - else if (Item == lightPositionZ) - Position[2] = Value; - - lcVector3 Distance = Position - Center; - - Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); - } - else if (Item == lightTargetX || Item == lightTargetY || Item == lightTargetZ) - { -// lcVector3 Center = Light->mTargetPosition; -// lcVector3 Position = Center; -// float Value = lcParseValueLocalized(Editor->text()); -// if (Item == lightTargetX) -// Position[0] = Value; -// else if (Item == lightTargetY) -// Position[1] = Value; -// else if (Item == lightTargetZ) -// Position[2] = Value; -// -// lcVector3 Distance = Position - Center; -// -// Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); - } - else if (Item == mLightSpotConeAngleItem) + if (Item == mLightSpotConeAngleItem) { float Value = lcParseValueLocalized(Editor->text()); @@ -1103,14 +1069,6 @@ void lcQPropertiesTree::SetEmpty() clear(); mPieceAttributesItem = nullptr; - partPosition = nullptr; - partPositionX = nullptr; - partPositionY = nullptr; - partPositionZ = nullptr; - partRotation = nullptr; - partRotationX = nullptr; - partRotationY = nullptr; - partRotationZ = nullptr; partVisibility = nullptr; partShow = nullptr; partHide = nullptr; @@ -1138,14 +1096,6 @@ void lcQPropertiesTree::SetEmpty() mCameraNameItem = nullptr; lightConfiguration = nullptr; - lightPosition = nullptr; - lightPositionX = nullptr; - lightPositionY = nullptr; - lightPositionZ = nullptr; - lightTarget = nullptr; - lightTargetX = nullptr; - lightTargetY = nullptr; - lightTargetZ = nullptr; mLightColorItem = nullptr; mLightAttributesItem = nullptr; lightDiffuse = nullptr; @@ -1166,6 +1116,15 @@ void lcQPropertiesTree::SetEmpty() lightAreaGridRows = nullptr; lightAreaGridColumns = nullptr; + mPositionItem = nullptr; + mPositionXItem = nullptr; + mPositionYItem = nullptr; + mPositionZItem = nullptr; + mRotationItem = nullptr; + mRotationXItem = nullptr; + mRotationYItem = nullptr; + mRotationZItem = nullptr; + mWidgetMode = LC_PROPERTY_WIDGET_EMPTY; mFocus = nullptr; } @@ -1184,15 +1143,15 @@ void lcQPropertiesTree::SetPiece(const lcArray& Selection, lcObject* partShow = addProperty(partVisibility, tr("Show"), PropertyStep); partHide = addProperty(partVisibility, tr("Hide"), PropertyStep); - partPosition = addProperty(nullptr, tr("Position"), PropertyGroup); - partPositionX = addProperty(partPosition, tr("X"), PropertyFloat); - partPositionY = addProperty(partPosition, tr("Y"), PropertyFloat); - partPositionZ = addProperty(partPosition, tr("Z"), PropertyFloat); + mPositionItem = addProperty(nullptr, tr("Position"), PropertyGroup); + mPositionXItem = addProperty(mPositionItem, tr("X"), PropertyFloat); + mPositionYItem = addProperty(mPositionItem, tr("Y"), PropertyFloat); + mPositionZItem = addProperty(mPositionItem, tr("Z"), PropertyFloat); - partRotation = addProperty(nullptr, tr("Rotation"), PropertyGroup); - partRotationX = addProperty(partRotation, tr("X"), PropertyFloat); - partRotationY = addProperty(partRotation, tr("Y"), PropertyFloat); - partRotationZ = addProperty(partRotation, tr("Z"), PropertyFloat); + mRotationItem = addProperty(nullptr, tr("Rotation"), PropertyGroup); + mRotationXItem = addProperty(mRotationItem, tr("X"), PropertyFloat); + mRotationYItem = addProperty(mRotationItem, tr("Y"), PropertyFloat); + mRotationZItem = addProperty(mRotationItem, tr("Z"), PropertyFloat); mWidgetMode = LC_PROPERTY_WIDGET_PIECE; } @@ -1203,25 +1162,29 @@ void lcQPropertiesTree::SetPiece(const lcArray& Selection, lcObject* lcVector3 Position; lcMatrix33 RelativeRotation; + Model->GetMoveRotateTransform(Position, RelativeRotation); - partPositionX->setText(1, lcFormatValueLocalized(Position[0])); - partPositionX->setData(0, PropertyValueRole, Position[0]); - partPositionY->setText(1, lcFormatValueLocalized(Position[1])); - partPositionY->setData(0, PropertyValueRole, Position[1]); - partPositionZ->setText(1, lcFormatValueLocalized(Position[2])); - partPositionZ->setData(0, PropertyValueRole, Position[2]); + + mPositionXItem->setText(1, lcFormatValueLocalized(Position[0])); + mPositionXItem->setData(0, PropertyValueRole, Position[0]); + mPositionYItem->setText(1, lcFormatValueLocalized(Position[1])); + mPositionYItem->setData(0, PropertyValueRole, Position[1]); + mPositionZItem->setText(1, lcFormatValueLocalized(Position[2])); + mPositionZItem->setData(0, PropertyValueRole, Position[2]); lcVector3 Rotation; + if (Piece) Rotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD; else Rotation = lcVector3(0.0f, 0.0f, 0.0f); - partRotationX->setText(1, lcFormatValueLocalized(Rotation[0])); - partRotationX->setData(0, PropertyValueRole, Rotation[0]); - partRotationY->setText(1, lcFormatValueLocalized(Rotation[1])); - partRotationY->setData(0, PropertyValueRole, Rotation[1]); - partRotationZ->setText(1, lcFormatValueLocalized(Rotation[2])); - partRotationZ->setData(0, PropertyValueRole, Rotation[2]); + + mRotationXItem->setText(1, lcFormatValueLocalized(Rotation[0])); + mRotationXItem->setData(0, PropertyValueRole, Rotation[0]); + mRotationYItem->setText(1, lcFormatValueLocalized(Rotation[1])); + mRotationYItem->setData(0, PropertyValueRole, Rotation[1]); + mRotationZItem->setText(1, lcFormatValueLocalized(Rotation[2])); + mRotationZItem->setData(0, PropertyValueRole, Rotation[2]); lcStep Show = 0; lcStep Hide = 0; @@ -1411,9 +1374,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) bool EnableCutoff = false; bool POVRayLight = false; bool CastShadow = true; - PropertyType TargetProperty = PropertyFloat; lcVector3 Position(0.0f, 0.0f, 0.0f); - lcVector3 Target(0.0f, 0.0f, 0.0f); QColor Color(Qt::white); float SpotConeAngle = 0.0f, SpotPenumbraAngle = 0.0f, SpotTightness = 0.0f; lcVector2 AreaGrid(0.0f, 0.0f); @@ -1428,7 +1389,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) CastShadow = Light->GetCastShadow(); Position = Light->GetPosition(); -// Target = Light->mTargetPosition; Color = lcQColorFromVector3(Light->GetColor()); SpotConeAngle = Light->GetSpotConeAngle(); SpotPenumbraAngle = Light->GetSpotPenumbraAngle(); @@ -1477,12 +1437,11 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) ExponentLabel = LightType == lcLightType::Directional ? tr("Strength") : tr("Power"); Cutoff = Light->mSpotCutoff; EnableCutoff = Light->mEnableCutoff; - TargetProperty = LightType != lcLightType::Point ? PropertyFloat : PropertyFloatReadOnly; SpotTightness = Light->GetSpotTightness(); AreaGrid = Light->mAreaGrid; } - if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType || mLightAreaShape != LightAreaShape || mPOVRayLight != POVRayLight) + if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType || mPOVRayLight != POVRayLight) { SetEmpty(); @@ -1575,44 +1534,48 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightConfiguration = addProperty(nullptr, tr("Configuration"), PropertyGroup); lightFormat = addProperty(lightConfiguration, tr("Format"), PropertyLightFormat); - // Position - lightPosition = addProperty(nullptr, tr("Position"), PropertyGroup); - lightPositionX = addProperty(lightPosition, tr("X"), PropertyFloat); - lightPositionY = addProperty(lightPosition, tr("Y"), PropertyFloat); - lightPositionZ = addProperty(lightPosition, tr("Z"), PropertyFloat); + mPositionItem = addProperty(nullptr, tr("Position"), PropertyGroup); + mPositionXItem = addProperty(mPositionItem, tr("X"), PropertyFloat); + mPositionYItem = addProperty(mPositionItem, tr("Y"), PropertyFloat); + mPositionZItem = addProperty(mPositionItem, tr("Z"), PropertyFloat); - // Target Position - if (LightType != lcLightType::Point && !(LightType == lcLightType::Area && POVRayLight)) + if (LightType != lcLightType::Point) { - lightTarget = addProperty(nullptr, tr("Target"), PropertyGroup); - lightTargetX = addProperty(lightTarget, tr("X"), TargetProperty); - lightTargetY = addProperty(lightTarget, tr("Y"), TargetProperty); - lightTargetZ = addProperty(lightTarget, tr("Z"), TargetProperty); + mRotationItem = addProperty(nullptr, tr("Rotation"), PropertyGroup); + mRotationXItem = addProperty(mRotationItem, tr("X"), PropertyFloat); + mRotationYItem = addProperty(mRotationItem, tr("Y"), PropertyFloat); + mRotationZItem = addProperty(mRotationItem, tr("Z"), PropertyFloat); } mWidgetMode = LC_PROPERTY_WIDGET_LIGHT; mLightType = LightType; - mLightAreaShape = LightAreaShape; mPOVRayLight = POVRayLight; } mFocus = Light; - lightPositionX->setText(1, lcFormatValueLocalized(Position[0])); - lightPositionX->setData(0, PropertyValueRole, Position[0]); - lightPositionY->setText(1, lcFormatValueLocalized(Position[1])); - lightPositionY->setData(0, PropertyValueRole, Position[1]); - lightPositionZ->setText(1, lcFormatValueLocalized(Position[2])); - lightPositionZ->setData(0, PropertyValueRole, Position[2]); + mPositionXItem->setText(1, lcFormatValueLocalized(Position[0])); + mPositionXItem->setData(0, PropertyValueRole, Position[0]); + mPositionYItem->setText(1, lcFormatValueLocalized(Position[1])); + mPositionYItem->setData(0, PropertyValueRole, Position[1]); + mPositionZItem->setText(1, lcFormatValueLocalized(Position[2])); + mPositionZItem->setData(0, PropertyValueRole, Position[2]); - if (LightType != lcLightType::Point && !(LightType == lcLightType::Area && POVRayLight)) + if (LightType != lcLightType::Point) { - lightTargetX->setText(1, lcFormatValueLocalized(Target[0])); - lightTargetX->setData(0, PropertyValueRole, Target[0]); - lightTargetY->setText(1, lcFormatValueLocalized(Target[1])); - lightTargetY->setData(0, PropertyValueRole, Target[1]); - lightTargetZ->setText(1, lcFormatValueLocalized(Target[2])); - lightTargetZ->setData(0, PropertyValueRole, Target[2]); + lcVector3 Rotation; + + if (Light) + Rotation = lcMatrix44ToEulerAngles(Light->mWorldMatrix) * LC_RTOD; + else + Rotation = lcVector3(0.0f, 0.0f, 0.0f); + + mRotationXItem->setText(1, lcFormatValueLocalized(Rotation[0])); + mRotationXItem->setData(0, PropertyValueRole, Rotation[0]); + mRotationYItem->setText(1, lcFormatValueLocalized(Rotation[1])); + mRotationYItem->setData(0, PropertyValueRole, Rotation[1]); + mRotationZItem->setText(1, lcFormatValueLocalized(Rotation[2])); + mRotationZItem->setData(0, PropertyValueRole, Rotation[2]); } QImage ColorImage(16, 16, QImage::Format_ARGB32); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 1c7428dd..e63d6474 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -78,7 +78,6 @@ protected slots: void SetMultiple(); lcLightType mLightType; - lcLightAreaShape mLightAreaShape; bool mPOVRayLight; lcPropertyWidgetMode mWidgetMode; @@ -90,14 +89,6 @@ protected slots: QIcon m_uncheckedIcon; QTreeWidgetItem* mPieceAttributesItem; - QTreeWidgetItem* partPosition; - QTreeWidgetItem* partPositionX; - QTreeWidgetItem* partPositionY; - QTreeWidgetItem* partPositionZ; - QTreeWidgetItem* partRotation; - QTreeWidgetItem* partRotationX; - QTreeWidgetItem* partRotationY; - QTreeWidgetItem* partRotationZ; QTreeWidgetItem* partVisibility; QTreeWidgetItem* partShow; QTreeWidgetItem* partHide; @@ -125,14 +116,6 @@ protected slots: QTreeWidgetItem* mCameraNameItem; QTreeWidgetItem* lightConfiguration; - QTreeWidgetItem* lightPosition; - QTreeWidgetItem* lightPositionX; - QTreeWidgetItem* lightPositionY; - QTreeWidgetItem* lightPositionZ; - QTreeWidgetItem* lightTarget; - QTreeWidgetItem* lightTargetX; - QTreeWidgetItem* lightTargetY; - QTreeWidgetItem* lightTargetZ; QTreeWidgetItem* mLightColorItem; QTreeWidgetItem* mLightAttributesItem; QTreeWidgetItem* lightDiffuse; @@ -152,6 +135,15 @@ protected slots: QTreeWidgetItem* mLightCastShadowItem; QTreeWidgetItem* lightAreaGridRows; QTreeWidgetItem* lightAreaGridColumns; + + QTreeWidgetItem* mPositionItem; + QTreeWidgetItem* mPositionXItem; + QTreeWidgetItem* mPositionYItem; + QTreeWidgetItem* mPositionZItem; + QTreeWidgetItem* mRotationItem; + QTreeWidgetItem* mRotationXItem; + QTreeWidgetItem* mRotationYItem; + QTreeWidgetItem* mRotationZItem; }; class lcQPropertiesTreeDelegate : public QItemDelegate From 5430dd6170ba938889ec4d7289c132c8c42c60ae Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 1 Oct 2023 13:16:26 -0700 Subject: [PATCH 35/42] Added light power attribute. --- common/lc_model.cpp | 10 ++++++++++ common/lc_model.h | 1 + common/light.cpp | 12 ++++++++++++ common/light.h | 9 +++++++++ qt/lc_qpropertiestree.cpp | 27 +++++++++++++++++++-------- qt/lc_qpropertiestree.h | 2 +- 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index d6bdf293..37836427 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3237,6 +3237,16 @@ void lcModel::SetLightSize(lcLight* Light, lcVector2 LightAreaSize) UpdateAllViews(); } +void lcModel::SetLightPower(lcLight* Light, float Power) +{ + Light->SetPower(Power, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Light Power")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetLightCastShadow(lcLight* Light, bool CastShadow) { if (!Light->SetCastShadow(CastShadow)) diff --git a/common/lc_model.h b/common/lc_model.h index 71fb0e5b..7ec1349b 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -375,6 +375,7 @@ class lcModel void SetSpotLightTightness(lcLight* Light, float Tightness); void SetAreaLightShape(lcLight* Light, lcLightAreaShape LightAreaShape); void SetLightSize(lcLight* Light, lcVector2 LightAreaSize); + void SetLightPower(lcLight* Light, float Power); void SetLightCastShadow(lcLight* Light, bool CastShadow); void SetLightName(lcLight* Light, const QString& Name); void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); diff --git a/common/light.cpp b/common/light.cpp index 53d28909..db09a6f2 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -40,6 +40,7 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true); mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); mColorKeys.ChangeKey(mColor, 1, true); + mPowerKeys.ChangeKey(mPower, 1, true); mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); @@ -785,6 +786,11 @@ void lcLight::SetSize(lcVector2 Size, lcStep Step, bool AddKey) mSizeKeys.ChangeKey(Size, Step, AddKey); } +void lcLight::SetPower(float Power, lcStep Step, bool AddKey) +{ + mPowerKeys.ChangeKey(Power, Step, AddKey); +} + bool lcLight::SetCastShadow(bool CastShadow) { if (mCastShadow != CastShadow) @@ -805,6 +811,7 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mSpotPenumbraAngleKeys.InsertTime(Start, Time); mSpotTightnessKeys.InsertTime(Start, Time); mSizeKeys.InsertTime(Start, Time); + mPowerKeys.InsertTime(Start, Time); mAttenuationKeys.InsertTime(Start, Time); mLightDiffuseKeys.InsertTime(Start, Time); @@ -823,6 +830,7 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mSpotPenumbraAngleKeys.RemoveTime(Start, Time); mSpotTightnessKeys.RemoveTime(Start, Time); mSizeKeys.RemoveTime(Start, Time); + mPowerKeys.RemoveTime(Start, Time); mAttenuationKeys.RemoveTime(Start, Time); mLightDiffuseKeys.RemoveTime(Start, Time); @@ -852,6 +860,7 @@ void lcLight::UpdatePosition(lcStep Step) mSpotPenumbraAngle = mSpotPenumbraAngleKeys.CalculateKey(Step); mSpotTightness = mSpotTightnessKeys.CalculateKey(Step); mSize = mSizeKeys.CalculateKey(Step); + mPower = mPowerKeys.CalculateKey(Step); mAttenuation = mAttenuationKeys.CalculateKey(Step); mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); @@ -1292,6 +1301,9 @@ void lcLight::RemoveKeyFrames() mSizeKeys.RemoveAll(); mSizeKeys.ChangeKey(mSize, 1, true); + mPowerKeys.RemoveAll(); + mPowerKeys.ChangeKey(mPower, 1, true); + mAttenuationKeys.RemoveAll(); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); diff --git a/common/light.h b/common/light.h index 2b2e1e4e..7646e29f 100644 --- a/common/light.h +++ b/common/light.h @@ -280,6 +280,13 @@ class lcLight : public lcObject return mSize; } + void SetPower(float Power, lcStep Step, bool AddKey); + + float GetPower() const + { + return mPower; + } + bool SetCastShadow(bool CastShadow); bool GetCastShadow() const @@ -351,6 +358,7 @@ class lcLight : public lcObject bool mCastShadow = true; lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); lcVector2 mSize = lcVector2(0.0f, 0.0f); + float mPower = 1.0f; float mSpotConeAngle = 80.0f; float mSpotPenumbraAngle = 0.0f; float mSpotTightness = 0.0f; @@ -365,6 +373,7 @@ class lcLight : public lcObject lcObjectKeyArray mRotationKeys; lcObjectKeyArray mColorKeys; lcObjectKeyArray mSizeKeys; + lcObjectKeyArray mPowerKeys; lcObjectKeyArray mSpotConeAngleKeys; lcObjectKeyArray mSpotPenumbraAngleKeys; lcObjectKeyArray mSpotTightnessKeys; diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index a648a179..bf1c2046 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -447,9 +447,6 @@ QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) return Editor; } - case PropertyFloatReadOnly: - return nullptr; - case PropertyStep: { QLineEdit* Editor = new QLineEdit(Parent); @@ -859,6 +856,12 @@ void lcQPropertiesTree::slotReturnPressed() Model->SetLightSize(Light, Value); } + else if (Item == mLightPowerItem) + { + float Value = lcParseValueLocalized(Editor->text()); + + Model->SetLightPower(Light, Value); + } else if (Item == lightDiffuse) { Props.mLightDiffuse = lcParseValueLocalized(Editor->text()); @@ -1049,10 +1052,7 @@ QTreeWidgetItem *lcQPropertiesTree::addProperty(QTreeWidgetItem *parent, const Q newItem = new QTreeWidgetItem(this, QStringList(label)); newItem->setData(0, PropertyTypeRole, QVariant(propertyType)); - - if (propertyType != PropertyFloatReadOnly) - newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); - + newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); newItem->setExpanded(true); if (propertyType == PropertyGroup) @@ -1097,6 +1097,7 @@ void lcQPropertiesTree::SetEmpty() lightConfiguration = nullptr; mLightColorItem = nullptr; + mLightPowerItem = nullptr; mLightAttributesItem = nullptr; lightDiffuse = nullptr; lightSpecular = nullptr; @@ -1366,6 +1367,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lcLightType LightType = lcLightType::Point; lcLightAreaShape LightAreaShape = lcLightAreaShape::Rectangle; lcVector2 LightSize(0.0f, 0.0f); + float Power = 0.0f; int FormatIndex = 0; float Diffuse = 0.0f; float Specular = 0.0f; @@ -1390,6 +1392,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) CastShadow = Light->GetCastShadow(); Position = Light->GetPosition(); Color = lcQColorFromVector3(Light->GetColor()); + Power = Light->GetPower(); SpotConeAngle = Light->GetSpotConeAngle(); SpotPenumbraAngle = Light->GetSpotPenumbraAngle(); @@ -1419,7 +1422,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) break; } - Diffuse = Light->mLightDiffuse; Specular = Light->mLightSpecular; @@ -1449,7 +1451,13 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightAttributesItem = addProperty(nullptr, tr("Light Attributes"), PropertyGroup); mLightNameItem = addProperty(mLightAttributesItem, tr("Name"), PropertyString); mLightTypeItem = addProperty(mLightAttributesItem, tr("Type"), PropertyStringList); + mLightColorItem = addProperty(mLightAttributesItem, tr("Color"), PropertyColor); + mLightColorItem->setToolTip(1, tr("Color of the emitted light.")); + + mLightPowerItem = addProperty(mLightAttributesItem, tr("Power"), PropertyFloat); + mLightPowerItem->setToolTip(1, tr("Power of the light in Watts (Blender only).")); + mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); switch (LightType) @@ -1592,6 +1600,9 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightColorItem->setText(1, Color.name().toUpper()); mLightColorItem->setData(0, PropertyValueRole, Color); + mLightPowerItem->setText(1, lcFormatValueLocalized(Power)); + mLightPowerItem->setData(0, PropertyValueRole, Power); + lightFormat->setText(1, Format); lightFormat->setData(0, PropertyValueRole, FormatIndex); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index e63d6474..2bdd490b 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -45,7 +45,6 @@ class lcQPropertiesTree : public QTreeWidget PropertyGroup, PropertyBool, PropertyFloat, - PropertyFloatReadOnly, PropertyStep, PropertyString, PropertyStringList, @@ -117,6 +116,7 @@ protected slots: QTreeWidgetItem* lightConfiguration; QTreeWidgetItem* mLightColorItem; + QTreeWidgetItem* mLightPowerItem; QTreeWidgetItem* mLightAttributesItem; QTreeWidgetItem* lightDiffuse; QTreeWidgetItem* lightSpecular; From ff313d4675f1b8c3155642900117631cb95c0ae7 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Fri, 29 Sep 2023 21:49:00 +0200 Subject: [PATCH 36/42] Blender LDraw Render - revert smooth_type default to edge_split --- common/lc_blenderpreferences.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index ea83d777..56553dfb 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -242,7 +242,7 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM /* 53/01 LBL_COLOUR_SCHEME_MM */ {"usecolourscheme", "lgeo", QObject::tr("Colour Scheme"), QObject::tr("Colour scheme options - Realistic (lgeo), Original (LDConfig), Alternate (LDCfgalt), Custom (User Defined)")}, /* 54/02 LBL_COLOUR_STRATEGY */ {"colorstrategy", "material", QObject::tr("How To Color Parts"), QObject::tr("Colour strategy options - Material (Default - use if exporting), Vertex colors (slightly quicker to import)")}, /* 55/03 LBL_RESOLUTION_MM */ {"resolution", "Standard", QObject::tr("Resolution"), QObject::tr("Resolution of part primitives, ie. how much geometry they have")}, - /* 56/04 LBL_SMOOTH_TYPE */ {"smoothtype", "bmesh_split",QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")} + /* 56/04 LBL_SMOOTH_TYPE */ {"smoothtype", "edge_split", QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")} }; lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO_ITEMS_MM] = @@ -252,7 +252,7 @@ lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO /* 01 LBL_COLOUR_SCHEME_MM */ {"lgeo|ldraw|alt|custom", QObject::tr("Realistic Colours|Original LDraw Colours|Alternate LDraw Colours|Custom Colours")}, /* 02 LBL_COLOUR_STRATEGY */ {"material|vertex_colors", QObject::tr("Material|Vertex Colors")}, /* 03 LBL_RESOLUTION_MM */ {"Low|Standard|High", QObject::tr("Low Resolution Primitives|Standard Primitives|High Resolution Primitives")}, - /* 04 LBL_SMOOTH_TYPE */ {"bmesh_split|edge_split|auto_smooth", QObject::tr("Split during initial mesh processing|Smooth part faces with edge split modifier|Auto-smooth part faces")} + /* 04 LBL_SMOOTH_TYPE */ {"edge_split|auto_smooth|bmesh_split", QObject::tr("Smooth part faces with edge split modifier|Auto-smooth part faces|Split during initial mesh processing")} }; lcBlenderPreferences* gAddonPreferences; From c2199eb6b02ebca4975a932a97ef8937cdcee782 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 1 Oct 2023 16:24:42 -0700 Subject: [PATCH 37/42] Added serialization helper functions. --- common/camera.cpp | 46 ++++----------- common/light.cpp | 142 +++++++++++++--------------------------------- common/object.cpp | 115 ++++++++++++++++++++++--------------- common/object.h | 9 ++- common/piece.cpp | 4 +- 5 files changed, 128 insertions(+), 188 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index ae8a0a15..ca820514 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -142,20 +142,9 @@ void lcCamera::SaveLDraw(QTextStream& Stream) const Stream << QLatin1String("0 !LEOCAD CAMERA FOV ") << m_fovy << QLatin1String(" ZNEAR ") << m_zNear << QLatin1String(" ZFAR ") << m_zFar << LineEnding; - if (mPositionKeys.GetSize() > 1) - mPositionKeys.SaveKeysLDraw(Stream, "CAMERA POSITION_KEY "); - else - Stream << QLatin1String("0 !LEOCAD CAMERA POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding; - - if (mTargetPositionKeys.GetSize() > 1) - mTargetPositionKeys.SaveKeysLDraw(Stream, "CAMERA TARGET_POSITION_KEY "); - else - Stream << QLatin1String("0 !LEOCAD CAMERA TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding; - - if (mUpVectorKeys.GetSize() > 1) - mUpVectorKeys.SaveKeysLDraw(Stream, "CAMERA UP_VECTOR_KEY "); - else - Stream << QLatin1String("0 !LEOCAD CAMERA UP_VECTOR ") << mUpVector[0] << ' ' << mUpVector[1] << ' ' << mUpVector[2] << LineEnding; + SaveAttribute(Stream, mPosition, mPositionKeys, "CAMERA", "POSITION"); + SaveAttribute(Stream, mTargetPosition, mTargetPositionKeys, "CAMERA", "TARGET_POSITION"); + SaveAttribute(Stream, mUpVector, mUpVectorKeys, "CAMERA", "UP_VECTOR"); Stream << QLatin1String("0 !LEOCAD CAMERA "); @@ -176,7 +165,7 @@ bool lcCamera::ParseLDrawLine(QTextStream& Stream) Stream >> Token; if (Token == QLatin1String("HIDDEN")) - SetHidden(true); + SetHidden(true); else if (Token == QLatin1String("ORTHOGRAPHIC")) SetOrtho(true); else if (Token == QLatin1String("FOV")) @@ -185,27 +174,12 @@ bool lcCamera::ParseLDrawLine(QTextStream& Stream) Stream >> m_zNear; else if (Token == QLatin1String("ZFAR")) Stream >> m_zFar; - else if (Token == QLatin1String("POSITION")) - { - Stream >> mPosition[0] >> mPosition[1] >> mPosition[2]; - mPositionKeys.ChangeKey(mPosition, 1, true); - } - else if (Token == QLatin1String("TARGET_POSITION")) - { - Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; - mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true); - } - else if (Token == QLatin1String("UP_VECTOR")) - { - Stream >> mUpVector[0] >> mUpVector[1] >> mUpVector[2]; - mUpVectorKeys.ChangeKey(mUpVector, 1, true); - } - else if (Token == QLatin1String("POSITION_KEY")) - mPositionKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("TARGET_POSITION_KEY")) - mTargetPositionKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("UP_VECTOR_KEY")) - mUpVectorKeys.LoadKeysLDraw(Stream); + else if (LoadAttribute(Stream, Token, mPosition, mPositionKeys, "POSITION")) + continue; + else if (LoadAttribute(Stream, Token, mTargetPosition, mTargetPositionKeys, "TARGET_POSITION")) + continue; + else if (LoadAttribute(Stream, Token, mUpVector, mUpVectorKeys, "UP_VECTOR")) + continue; else if (Token == QLatin1String("NAME")) { mName = Stream.readAll().trimmed(); diff --git a/common/light.cpp b/common/light.cpp index db09a6f2..0f3fe33f 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -144,52 +144,33 @@ void lcLight::SaveLDraw(QTextStream& Stream) const const float Numbers[12] = { Matrix[12], -Matrix[14], Matrix[13], Matrix[0], -Matrix[8], Matrix[4], -Matrix[2], Matrix[10], -Matrix[6], Matrix[1], -Matrix[9], Matrix[5] }; if (mPositionKeys.GetSize() > 1) - mPositionKeys.SaveKeysLDraw(Stream, "LIGHT POSITION_KEY "); + mPositionKeys.SaveKeysLDraw(Stream, "LIGHT", "POSITION"); else Stream << QLatin1String("0 !LEOCAD LIGHT POSITION ") << Numbers[0] << ' ' << Numbers[1] << ' ' << Numbers[2] << LineEnding; if (!IsPointLight()) { if (mRotationKeys.GetSize() > 1) - mRotationKeys.SaveKeysLDraw(Stream, "LIGHT ROTATION_KEY "); + mRotationKeys.SaveKeysLDraw(Stream, "LIGHT", "ROTATION"); else Stream << QLatin1String("0 !LEOCAD LIGHT ROTATION ") << Numbers[3] << ' ' << Numbers[4] << ' ' << Numbers[5] << ' ' << Numbers[6] << ' ' << Numbers[7] << ' ' << Numbers[8] << ' ' << Numbers[9] << ' ' << Numbers[10] << ' ' << Numbers[11] << LineEnding; } - if (mColorKeys.GetSize() > 1) - mColorKeys.SaveKeysLDraw(Stream, "LIGHT COLOR_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT COLOR ") << mColor[0] << ' ' << mColor[1] << ' ' << mColor[2] << LineEnding; - - if (mSizeKeys.GetSize() > 1) - mSizeKeys.SaveKeysLDraw(Stream, "LIGHT SIZE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SIZE ") << mSize[0] << mSize[1] << LineEnding; + SaveAttribute(Stream, mColor, mColorKeys, "LIGHT", "COLOR"); + SaveAttribute(Stream, mSize, mSizeKeys, "LIGHT", "SIZE"); + SaveAttribute(Stream, mPower, mPowerKeys, "LIGHT", "POWER"); if (!mPOVRayLight) { - if (mLightDiffuseKeys.GetSize() > 1) - mLightDiffuseKeys.SaveKeysLDraw(Stream, "LIGHT DIFFUSE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT DIFFUSE ") << mLightDiffuse << LineEnding; - - if (mLightSpecularKeys.GetSize() > 1) - mLightSpecularKeys.SaveKeysLDraw(Stream, "LIGHT SPECULAR_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPECULAR ") << mLightSpecular << LineEnding; + SaveAttribute(Stream, mLightDiffuse, mLightDiffuseKeys, "LIGHT", "DIFFUSE"); + SaveAttribute(Stream, mLightSpecular, mLightSpecularKeys, "LIGHT", "SPECULAR"); } - if (mSpotExponentKeys.GetSize() > 1) - mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT POWER_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT POWER ") << (mPOVRayLight ? mPOVRayExponent : mSpotExponent) << LineEnding; +// SaveAttribute(Stream, (mPOVRayLight ? mPOVRayExponent : mSpotExponent), mSpotExponentKeys, "LIGHT", "POWER"); if (mEnableCutoff && !mPOVRayLight) { - if (mSpotCutoffKeys.GetSize() > 1) - mSpotCutoffKeys.SaveKeysLDraw(Stream, "LIGHT CUTOFF_DISTANCE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT CUTOFF_DISTANCE ") << mSpotCutoff << LineEnding; + SaveAttribute(Stream, mSpotCutoff, mSpotCutoffKeys, "LIGHT", "CUTOFF_DISTANCE"); } switch (mLightType) @@ -199,39 +180,18 @@ void lcLight::SaveLDraw(QTextStream& Stream) const break; case lcLightType::Spot: - if (mSpotConeAngleKeys.GetSize() > 1) - mSpotConeAngleKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_CONE_ANGLE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_CONE_ANGLE ") << mSpotConeAngle << LineEnding; - - if (mSpotPenumbraAngleKeys.GetSize() > 1) - mSpotPenumbraAngleKeys.SaveKeysLDraw(Stream, "LIGHT SPOT_PENUMBRA_ANGLE_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_PENUMBRA_ANGLE ") << mSpotPenumbraAngle << LineEnding; - - if (mSpotTightnessKeys.GetSize() > 1) - mSpotTightnessKeys.SaveKeysLDraw(Stream, "SPOT_TIGHTNESS_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT SPOT_TIGHTNESS ") << mSpotTightness << LineEnding; - + SaveAttribute(Stream, mSpotConeAngle, mSpotConeAngleKeys, "LIGHT", "SPOT_CONE_ANGLE"); + SaveAttribute(Stream, mSpotPenumbraAngle, mSpotPenumbraAngleKeys, "LIGHT", "SPOT_PENUMBRA_ANGLE"); + SaveAttribute(Stream, mSpotTightness, mSpotTightnessKeys, "LIGHT", "SPOT_TIGHTNESS"); break; case lcLightType::Directional: - if (mSpotExponentKeys.GetSize() > 1) - mSpotExponentKeys.SaveKeysLDraw(Stream, "LIGHT STRENGTH_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT STRENGTH ") << mSpotExponent << LineEnding; - + SaveAttribute(Stream, mSpotExponent, mSpotExponentKeys, "LIGHT", "STRENGTH"); break; case lcLightType::Area: if (mPOVRayLight) - { - if (mAreaGridKeys.GetSize() > 1) - mAreaGridKeys.SaveKeysLDraw(Stream, "LIGHT AREA_GRID_KEY "); - else - Stream << QLatin1String("0 !LEOCAD LIGHT AREA_ROWS ") << mAreaGrid[0] << QLatin1String(" AREA_COLUMNS ") << mAreaGrid[1] << LineEnding; - } + SaveAttribute(Stream, mAreaGrid, mAreaGridKeys, "LIGHT", "AREA_GRID"); Stream << QLatin1String("0 !LEOCAD LIGHT AREA_SHAPE ") << gLightAreaShapes[static_cast(mAreaShape)] << LineEnding; @@ -344,35 +304,18 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if (Token == QLatin1String("ROTATION_KEY")) mRotationKeys.LoadKeysLDraw(Stream); // todo: convert from ldraw - else if (Token == QLatin1String("COLOR")) - { - Stream >> mColor[0] >> mColor[1] >> mColor[2]; - mColorKeys.ChangeKey(mColor, 1, true); - } - else if (Token == QLatin1String("COLOR_KEY")) - mColorKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SPOT_CONE_ANGLE")) - { - Stream >> mSpotConeAngle; - mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); - } - else if (Token == QLatin1String("SPOT_CONE_ANGLE_KEY")) - mSpotConeAngleKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SPOT_PENUMBRA_ANGLE")) - { - Stream >> mSpotPenumbraAngle; - mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); - } - else if (Token == QLatin1String("SPOT_PENUMBRA_ANGLE_KEY")) - mSpotPenumbraAngleKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SPOT_TIGHTNESS")) - { - mPOVRayLight = true; - Stream >> mSpotTightness; - mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); - } - else if (Token == QLatin1String("SPOT_TIGHTNESS_KEY")) - mSpotTightnessKeys.LoadKeysLDraw(Stream); + else if (LoadAttribute(Stream, Token, mColor, mColorKeys, "COLOR")) + continue; + else if (LoadAttribute(Stream, Token, mSize, mSizeKeys, "SIZE")) + continue; + else if (LoadAttribute(Stream, Token, mPower, mPowerKeys, "POWER")) + continue; + else if (LoadAttribute(Stream, Token, mSpotConeAngle, mSpotConeAngleKeys, "SPOT_CONE_ANGLE")) + continue; + else if (LoadAttribute(Stream, Token, mSpotPenumbraAngle, mSpotPenumbraAngleKeys, "SPOT_PENUMBRA_ANGLE")) + continue; + else if (LoadAttribute(Stream, Token, mSpotTightness, mSpotTightnessKeys, "SPOT_TIGHTNESS")) + continue; else if (Token == QLatin1String("AREA_SHAPE")) { QString AreaShape; @@ -387,27 +330,20 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } } } - else if (Token == QLatin1String("SIZE")) - { - Stream >> mSize[0] >> mSize[1]; - mSizeKeys.ChangeKey(mSize, 1, true); - } - else if (Token == QLatin1String("SIZE_KEY")) - mSizeKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) - { - if (mPOVRayLight) - { - Stream >> mPOVRayExponent; - mSpotExponentKeys.ChangeKey(mPOVRayExponent, 1, true); - } - else - { - Stream >> mSpotExponent; - mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); - } - } +// else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) +// { +// if (mPOVRayLight) +// { +// Stream >> mPOVRayExponent; +// mSpotExponentKeys.ChangeKey(mPOVRayExponent, 1, true); +// } +// else +// { +// Stream >> mSpotExponent; +// mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); +// } +// } else if (Token == QLatin1String("AREA_ROWS")) { mPOVRayLight = true; diff --git a/common/object.cpp b/common/object.cpp index c8eedc93..fefc71f6 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -1,6 +1,22 @@ #include "lc_global.h" #include "object.h" +#define LC_OBJECT_ATTRIBUTE(T) \ + template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* ObjectName, const char* VariableName) const; \ + template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); \ + template const T& lcObjectKeyArray::CalculateKey(lcStep Step) const; \ + template void lcObjectKeyArray::ChangeKey(const T& Value, lcStep Step, bool AddKey); \ + template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); \ + template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); \ + template void lcObject::SaveAttribute(QTextStream& Stream, const T& Variable, const lcObjectKeyArray& Keys, const char* ObjectName, const char* VariableName) const; \ + template bool lcObject::LoadAttribute(QTextStream& Stream, const QString& Token, T& Variable, lcObjectKeyArray& Keys, const char* VariableName) + +LC_OBJECT_ATTRIBUTE(float); +LC_OBJECT_ATTRIBUTE(lcVector2); +LC_OBJECT_ATTRIBUTE(lcVector3); +LC_OBJECT_ATTRIBUTE(lcVector4); +LC_OBJECT_ATTRIBUTE(lcMatrix33); + lcObject::lcObject(lcObjectType ObjectType) : mObjectType(ObjectType) { @@ -10,59 +26,32 @@ lcObject::~lcObject() { } -template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; -template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); -template const float& lcObjectKeyArray::CalculateKey(lcStep Step) const; -template void lcObjectKeyArray::ChangeKey(const float& Value, lcStep Step, bool AddKey); -template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); -template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); - -template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; -template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); -template const lcVector3& lcObjectKeyArray::CalculateKey(lcStep Step) const; -template void lcObjectKeyArray::ChangeKey(const lcVector3& Value, lcStep Step, bool AddKey); -template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); -template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); - -template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; -template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); -template const lcVector4& lcObjectKeyArray::CalculateKey(lcStep Step) const; -template void lcObjectKeyArray::ChangeKey(const lcVector4& Value, lcStep Step, bool AddKey); -template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); -template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); - -template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; -template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); -template const lcMatrix33& lcObjectKeyArray::CalculateKey(lcStep Step) const; -template void lcObjectKeyArray::ChangeKey(const lcMatrix33& Value, lcStep Step, bool AddKey); -template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); -template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); - -template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; -template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); -template const int& lcObjectKeyArray::CalculateKey(lcStep Step) const; -template void lcObjectKeyArray::ChangeKey(const int& Value, lcStep Step, bool AddKey); -template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); -template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); - -template void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; -template void lcObjectKeyArray::LoadKeysLDraw(QTextStream& Stream); -template const lcVector2& lcObjectKeyArray::CalculateKey(lcStep Step) const; -template void lcObjectKeyArray::ChangeKey(const lcVector2& Value, lcStep Step, bool AddKey); -template void lcObjectKeyArray::InsertTime(lcStep Start, lcStep Time); -template void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time); +template +static void SaveFloatValue(QTextStream& Stream, const T& Value) +{ + constexpr int Count = sizeof(T) / sizeof(float); + + for (int ValueIndex = 0; ValueIndex < Count; ValueIndex++) + Stream << ((const float*)&Value)[ValueIndex] << ' '; +} template -void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const +static void LoadFloatValue(QTextStream& Stream, T& Value) { constexpr int Count = sizeof(T) / sizeof(float); + for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++) + Stream >> ((float*)&Value)[ValueIdx]; +} + +template +void lcObjectKeyArray::SaveKeysLDraw(QTextStream& Stream, const char* ObjectName, const char* VariableName) const +{ for (const lcObjectKey& Key : mKeys) { - Stream << QLatin1String("0 !LEOCAD ") << KeyName << Key.Step << ' '; + Stream << QLatin1String("0 !LEOCAD ") << ObjectName << ' ' << VariableName << "_KEY " << Key.Step << ' '; - for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++) - Stream << ((float*)&Key.Value)[ValueIdx] << ' '; + SaveFloatValue(Stream, Key.Value); Stream << QLatin1String("\r\n"); } @@ -182,3 +171,39 @@ void lcObjectKeyArray::RemoveTime(lcStep Start, lcStep Time) KeyIt++; } } + +template +void lcObject::SaveAttribute(QTextStream& Stream, const T& Variable, const lcObjectKeyArray& Keys, const char* ObjectName, const char* VariableName) const +{ + if (Keys.GetSize() == 1) + { + Stream << QLatin1String("0 !LEOCAD ") << ObjectName << ' ' << VariableName << ' '; + + SaveFloatValue(Stream, Variable); + + Stream << QLatin1String("\r\n"); + } + else + Keys.SaveKeysLDraw(Stream, ObjectName, VariableName); +} + +template +bool lcObject::LoadAttribute(QTextStream& Stream, const QString& Token, T& Variable, lcObjectKeyArray& Keys, const char* VariableName) +{ + if (Token == VariableName) + { + LoadFloatValue(Stream, Variable); + Keys.ChangeKey(Variable, 1, true); + + return true; + } + + if (Token.endsWith(QLatin1String("_KEY")) && Token.leftRef(Token.size() - 4) == VariableName) + { + Keys.LoadKeysLDraw(Stream); + + return true; + } + + return false; +} diff --git a/common/object.h b/common/object.h index d4694f10..92af6cd2 100644 --- a/common/object.h +++ b/common/object.h @@ -36,7 +36,7 @@ class lcObjectKeyArray mKeys.clear(); } - void SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const; + void SaveKeysLDraw(QTextStream& Stream, const char* ObjectName, const char* VariableName) const; void LoadKeysLDraw(QTextStream& Stream); const T& CalculateKey(lcStep Step) const; void ChangeKey(const T& Value, lcStep Step, bool AddKey); @@ -141,7 +141,12 @@ class lcObject virtual void RemoveKeyFrames() = 0; virtual QString GetName() const = 0; +protected: + template + void SaveAttribute(QTextStream& Stream, const T& Variable, const lcObjectKeyArray& Keys, const char* ObjectName, const char* VariableName) const; + template + bool LoadAttribute(QTextStream& Stream, const QString& Token, T& Variable, lcObjectKeyArray& Keys, const char* VariableName); + private: lcObjectType mObjectType; }; - diff --git a/common/piece.cpp b/common/piece.cpp index 6c392d72..89cee77e 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -125,10 +125,10 @@ void lcPiece::SaveLDraw(QTextStream& Stream) const } if (mPositionKeys.GetSize() > 1) - mPositionKeys.SaveKeysLDraw(Stream, "PIECE POSITION_KEY "); + mPositionKeys.SaveKeysLDraw(Stream, "PIECE", "POSITION"); if (mRotationKeys.GetSize() > 1) - mRotationKeys.SaveKeysLDraw(Stream, "PIECE ROTATION_KEY "); + mRotationKeys.SaveKeysLDraw(Stream, "PIECE", "ROTATION"); Stream << "1 " << mColorCode << ' '; From 0a48e30ec0931e393e7fc36e59fc273d914cb49a Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 22 Oct 2023 18:48:08 -0700 Subject: [PATCH 38/42] Changed POV area lights to take the x/y vectors correctly. --- common/light.cpp | 30 ------------------------------ common/light.h | 10 +++++----- common/project.cpp | 14 ++++++++------ qt/lc_qpropertiestree.cpp | 31 ------------------------------- qt/lc_qpropertiestree.h | 2 -- 5 files changed, 13 insertions(+), 74 deletions(-) diff --git a/common/light.cpp b/common/light.cpp index 0f3fe33f..d1fb7fd7 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -33,7 +33,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mSpotExponent = 10.0f; mPOVRayExponent = 1.0f; mSpotCutoff = LightType != lcLightType::Directional ? 40.0f : 0.0f; - mAreaGrid = lcVector2(10.0f, 10.0f); UpdateLightType(); @@ -50,7 +49,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); - mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); UpdatePosition(1); } @@ -190,11 +188,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const break; case lcLightType::Area: - if (mPOVRayLight) - SaveAttribute(Stream, mAreaGrid, mAreaGridKeys, "LIGHT", "AREA_GRID"); - Stream << QLatin1String("0 !LEOCAD LIGHT AREA_SHAPE ") << gLightAreaShapes[static_cast(mAreaShape)] << LineEnding; - break; } @@ -344,18 +338,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) // mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); // } // } - else if (Token == QLatin1String("AREA_ROWS")) - { - mPOVRayLight = true; - Stream >> mAreaGrid[0]; - mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); - } - else if (Token == QLatin1String("AREA_COLUMNS")) - { - mPOVRayLight = true; - Stream >> mAreaGrid[1]; - mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); - } else if (Token == QLatin1String("DIFFUSE")) { Stream >>mLightDiffuse; @@ -396,8 +378,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) mSpotExponentKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("AREA_GRID_KEY")) - mAreaGridKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("DIFFUSE_KEY")) mLightDiffuseKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("SPECULAR_KEY")) @@ -470,10 +450,6 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) mSpotExponentKeys.ChangeKey(mSpotExponent, Step, false); } break; - case LC_LIGHT_AREA_GRID: - mAreaGrid = Props.mAreaGrid; - mAreaGridKeys.ChangeKey(mAreaGrid, Step, false); - break; case LC_LIGHT_CUTOFF: mSpotCutoff = Props.mSpotCutoff; mSpotCutoffKeys.ChangeKey(mSpotCutoff, Step, false); @@ -754,7 +730,6 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mLightSpecularKeys.InsertTime(Start, Time); mSpotCutoffKeys.InsertTime(Start, Time); mSpotExponentKeys.InsertTime(Start, Time); - mAreaGridKeys.InsertTime(Start, Time); } void lcLight::RemoveTime(lcStep Start, lcStep Time) @@ -773,7 +748,6 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mLightSpecularKeys.RemoveTime(Start, Time); mSpotCutoffKeys.RemoveTime(Start, Time); mSpotExponentKeys.RemoveTime(Start, Time); - mAreaGridKeys.RemoveTime(Start, Time); } void lcLight::UpdatePosition(lcStep Step) @@ -803,7 +777,6 @@ void lcLight::UpdatePosition(lcStep Step) mLightSpecular = mLightSpecularKeys.CalculateKey(Step); mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); mSpotExponent = mSpotExponentKeys.CalculateKey(Step); - mAreaGrid = mAreaGridKeys.CalculateKey(Step); } void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const @@ -1254,9 +1227,6 @@ void lcLight::RemoveKeyFrames() mSpotExponentKeys.RemoveAll(); mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); - - mAreaGridKeys.RemoveAll(); - mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); } bool lcLight::Setup(int LightIndex) diff --git a/common/light.h b/common/light.h index 7646e29f..2dc73b04 100644 --- a/common/light.h +++ b/common/light.h @@ -36,7 +36,6 @@ enum lcLightProperty LC_LIGHT_DIFFUSE, LC_LIGHT_SPECULAR, LC_LIGHT_EXPONENT, - LC_LIGHT_AREA_GRID, LC_LIGHT_CUTOFF, LC_LIGHT_USE_CUTOFF, LC_LIGHT_POVRAY @@ -44,7 +43,6 @@ enum lcLightProperty struct lcLightProperties { - lcVector2 mAreaGrid; float mLightDiffuse; float mLightSpecular; float mSpotExponent; @@ -221,6 +219,11 @@ class lcLight : public lcObject return -lcVector3(mWorldMatrix[2]); } + const lcMatrix44& GetWorldMatrix() const + { + return mWorldMatrix; + } + void SaveLDraw(QTextStream& Stream) const; bool ParseLDrawLine(QTextStream& Stream); @@ -321,14 +324,12 @@ class lcLight : public lcObject props.mSpotCutoff = mSpotCutoff; props.mPOVRayLight = mPOVRayLight; props.mEnableCutoff = mEnableCutoff; - props.mAreaGrid = mAreaGrid; return props; } lcMatrix44 mWorldMatrix; lcVector3 mAttenuation; - lcVector2 mAreaGrid; bool mSpotBlendSet; bool mSpotCutoffSet; bool mEnableCutoff; @@ -379,7 +380,6 @@ class lcLight : public lcObject lcObjectKeyArray mSpotTightnessKeys; lcObjectKeyArray mAttenuationKeys; - lcObjectKeyArray mAreaGridKeys; lcObjectKeyArray mLightSpecularKeys; lcObjectKeyArray mLightDiffuseKeys; lcObjectKeyArray mSpotCutoffKeys; diff --git a/common/project.cpp b/common/project.cpp index e5d102fc..5e77ad7a 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2139,7 +2139,8 @@ bool Project::ExportPOVRay(const QString& FileName) (CameraName.isEmpty() ? "Camera" : CameraName.toLatin1().constData())); POVFile.WriteLine(Line); - lcVector2 AreaSize(200.0f, 200.0f), AreaGrid(10.0f, 10.0f); + lcVector3 AreaX(1.0f, 0.0f, 0.0f), AreaY(0.0f, 1.0f, 0.0f); + lcVector2 AreaSize(200.0f, 200.0f); int AreaCircle = 0, Shadowless = 0; lcLightType LightType = lcLightType::Area; float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0; @@ -2157,7 +2158,7 @@ bool Project::ExportPOVRay(const QString& FileName) for (int Idx = 0; Idx < 4; Idx++) { Power = Idx < 2 ? 0.75f : 0.5f; - sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, %i, %i, %i, %i)\n#end\n\n", + sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", Idx, LightType, Shadowless, @@ -2166,7 +2167,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightColor[0], LightColor[1], LightColor[2], Power, SpotRadius, SpotFalloff, SpotTightness, - AreaCircle, (int)AreaSize[0], (int)AreaSize[1], (int)AreaGrid[0], (int)AreaGrid[1]); + AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], (int)AreaSize[0], (int)AreaSize[1]); POVFile.WriteLine(Line); } } @@ -2198,14 +2199,15 @@ bool Project::ExportPOVRay(const QString& FileName) case lcLightType::Area: AreaCircle = (Light->GetAreaShape() == lcLightAreaShape::Disk || Light->GetAreaShape() == lcLightAreaShape::Ellipse) ? 1 : 0; AreaSize = Light->GetSize(); - AreaGrid = Light->mAreaGrid; + AreaX = lcVector3(Light->GetWorldMatrix()[0]); + AreaY = lcVector3(Light->GetWorldMatrix()[1]); break; case lcLightType::Count: break; } - sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, %i, %i, %i, %i)\n#end\n\n", + sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", LightName.toLatin1().constData(), LightType, Shadowless, @@ -2214,7 +2216,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightColor[0], LightColor[1], LightColor[2], Power, SpotRadius, SpotFalloff, SpotTightness, - AreaCircle, (int)AreaSize[0], (int)AreaSize[1], (int)AreaGrid[0], (int)AreaGrid[1]); + AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], (int)AreaSize[0], (int)AreaSize[1]); POVFile.WriteLine(Line); } } diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index bf1c2046..c4a07d32 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -886,16 +886,6 @@ void lcQPropertiesTree::slotReturnPressed() Model->UpdateLight(Light, Props, LC_LIGHT_CUTOFF); } - else if (Item == lightAreaGridRows || Item == lightAreaGridColumns) - { - float Value = lcParseValueLocalized(Editor->text()); - if (Item == lightAreaGridRows) - Props.mAreaGrid[0] = Value; - else if (Item == lightAreaGridColumns) - Props.mAreaGrid[1] = Value; - - Model->UpdateLight(Light, Props, LC_LIGHT_AREA_GRID); - } else if (Item == mLightNameItem) { QString Value = Editor->text(); @@ -1114,8 +1104,6 @@ void lcQPropertiesTree::SetEmpty() mLightSizeYItem = nullptr; lightFormat = nullptr; mLightCastShadowItem = nullptr; - lightAreaGridRows = nullptr; - lightAreaGridColumns = nullptr; mPositionItem = nullptr; mPositionXItem = nullptr; @@ -1379,7 +1367,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lcVector3 Position(0.0f, 0.0f, 0.0f); QColor Color(Qt::white); float SpotConeAngle = 0.0f, SpotPenumbraAngle = 0.0f, SpotTightness = 0.0f; - lcVector2 AreaGrid(0.0f, 0.0f); if (Light) { @@ -1440,7 +1427,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Cutoff = Light->mSpotCutoff; EnableCutoff = Light->mEnableCutoff; SpotTightness = Light->GetSpotTightness(); - AreaGrid = Light->mAreaGrid; } if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType || mPOVRayLight != POVRayLight) @@ -1512,12 +1498,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) case lcLightAreaShape::Count: break; } - - if (POVRayLight) - { - lightAreaGridRows = addProperty(mLightAttributesItem, tr("Grid Rows"), PropertyFloat); - lightAreaGridColumns = addProperty(mLightAttributesItem, tr("Grid Columns"), PropertyFloat); - } break; case lcLightType::Count: @@ -1650,17 +1630,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) case lcLightType::Area: mLightAreaShapeItem->setText(1, lcLight::GetAreaShapeString(LightAreaShape)); mLightAreaShapeItem->setData(0, PropertyValueRole, static_cast(LightAreaShape)); - - if (POVRayLight) - { - lightAreaGridRows->setText(1, lcFormatValueLocalized(AreaGrid[0])); - lightAreaGridRows->setData(0, PropertyValueRole, AreaGrid[0]); - lightAreaGridRows->setToolTip(1, tr("The number of sample rows in the area light.")); - - lightAreaGridColumns->setText(1, lcFormatValueLocalized(AreaGrid[1])); - lightAreaGridColumns->setData(0, PropertyValueRole, AreaGrid[1]); - lightAreaGridColumns->setToolTip(1, tr("The number of sample columns in the area light.")); - } break; case lcLightType::Count: diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 2bdd490b..d6d1e8f2 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -133,8 +133,6 @@ protected slots: QTreeWidgetItem* mLightNameItem; QTreeWidgetItem* lightFormat; QTreeWidgetItem* mLightCastShadowItem; - QTreeWidgetItem* lightAreaGridRows; - QTreeWidgetItem* lightAreaGridColumns; QTreeWidgetItem* mPositionItem; QTreeWidgetItem* mPositionXItem; From 0e74aea5fa484d9dede13a18ed2a2b2c41f4a424 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 19 Nov 2023 18:05:43 -0800 Subject: [PATCH 39/42] Fixed POV-Ray area light grid. --- common/lc_math.h | 15 ++++++++++++ common/lc_model.cpp | 14 ++++++++++- common/lc_model.h | 3 ++- common/light.cpp | 17 ++++++++++++++ common/light.h | 9 +++++++ common/object.cpp | 1 + common/project.cpp | 12 +++++----- qt/lc_qpropertiestree.cpp | 49 ++++++++++++++++++++++++++++++++++++++- qt/lc_qpropertiestree.h | 3 +++ 9 files changed, 114 insertions(+), 9 deletions(-) diff --git a/common/lc_math.h b/common/lc_math.h index 4e2e7090..fb89a6b3 100644 --- a/common/lc_math.h +++ b/common/lc_math.h @@ -51,6 +51,21 @@ inline T lcClamp(const T& Value, const T& Min, const T& Max) return Value; } +class lcVector2i +{ +public: + lcVector2i() + { + } + + constexpr lcVector2i(const int _x, const int _y) + : x(_x), y(_y) + { + } + + int x, y; +}; + class lcVector2 { public: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 37836427..cb339a65 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3215,7 +3215,7 @@ void lcModel::SetSpotLightTightness(lcLight* Light, float Tightness) UpdateAllViews(); } -void lcModel::SetAreaLightShape(lcLight* Light, lcLightAreaShape LightAreaShape) +void lcModel::SetLightAreaShape(lcLight* Light, lcLightAreaShape LightAreaShape) { if (!Light->SetAreaShape(LightAreaShape)) return; @@ -3227,6 +3227,18 @@ void lcModel::SetAreaLightShape(lcLight* Light, lcLightAreaShape LightAreaShape) UpdateAllViews(); } +void lcModel::SetLightAreaGrid(lcLight* Light, lcVector2i AreaGrid) +{ + if (!Light->SetAreaGrid(AreaGrid, mCurrentStep, gMainWindow->GetAddKeys())) + return; + + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Area Light Size")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetLightSize(lcLight* Light, lcVector2 LightAreaSize) { Light->SetSize(LightAreaSize, mCurrentStep, gMainWindow->GetAddKeys()); diff --git a/common/lc_model.h b/common/lc_model.h index 7ec1349b..dd99f74c 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -373,7 +373,8 @@ class lcModel void SetSpotLightConeAngle(lcLight* Light, float Angle); void SetSpotLightPenumbraAngle(lcLight* Light, float Angle); void SetSpotLightTightness(lcLight* Light, float Tightness); - void SetAreaLightShape(lcLight* Light, lcLightAreaShape LightAreaShape); + void SetLightAreaShape(lcLight* Light, lcLightAreaShape LightAreaShape); + void SetLightAreaGrid(lcLight* Light, lcVector2i AreaGrid); void SetLightSize(lcLight* Light, lcVector2 LightAreaSize); void SetLightPower(lcLight* Light, float Power); void SetLightCastShadow(lcLight* Light, bool CastShadow); diff --git a/common/light.cpp b/common/light.cpp index d1fb7fd7..ccb8819b 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -43,6 +43,7 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); + mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); mAttenuationKeys.ChangeKey(mAttenuation, 1, true); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); @@ -189,6 +190,7 @@ void lcLight::SaveLDraw(QTextStream& Stream) const case lcLightType::Area: Stream << QLatin1String("0 !LEOCAD LIGHT AREA_SHAPE ") << gLightAreaShapes[static_cast(mAreaShape)] << LineEnding; + SaveAttribute(Stream, mAreaGrid, mAreaGridKeys, "LIGHT", "AREA_GRID"); break; } @@ -324,6 +326,8 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } } } + else if (LoadAttribute(Stream, Token, mAreaGrid, mAreaGridKeys, "AREA_GRID")) + continue; // else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) // { @@ -690,6 +694,13 @@ bool lcLight::SetAreaShape(lcLightAreaShape AreaShape) return false; } +bool lcLight::SetAreaGrid(lcVector2i AreaGrid, lcStep Step, bool AddKey) +{ + mAreaGridKeys.ChangeKey(AreaGrid, Step, AddKey); + + return true; +} + void lcLight::SetSize(lcVector2 Size, lcStep Step, bool AddKey) { if (mLightType == lcLightType::Area && (mAreaShape == lcLightAreaShape::Square || mAreaShape == lcLightAreaShape::Disk)) @@ -722,6 +733,7 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mSpotConeAngleKeys.InsertTime(Start, Time); mSpotPenumbraAngleKeys.InsertTime(Start, Time); mSpotTightnessKeys.InsertTime(Start, Time); + mAreaGridKeys.InsertTime(Start, Time); mSizeKeys.InsertTime(Start, Time); mPowerKeys.InsertTime(Start, Time); @@ -740,6 +752,7 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mSpotConeAngleKeys.RemoveTime(Start, Time); mSpotPenumbraAngleKeys.RemoveTime(Start, Time); mSpotTightnessKeys.RemoveTime(Start, Time); + mAreaGridKeys.RemoveTime(Start, Time); mSizeKeys.RemoveTime(Start, Time); mPowerKeys.RemoveTime(Start, Time); @@ -769,6 +782,7 @@ void lcLight::UpdatePosition(lcStep Step) mSpotConeAngle = mSpotConeAngleKeys.CalculateKey(Step); mSpotPenumbraAngle = mSpotPenumbraAngleKeys.CalculateKey(Step); mSpotTightness = mSpotTightnessKeys.CalculateKey(Step); + mAreaGrid = mAreaGridKeys.CalculateKey(Step); mSize = mSizeKeys.CalculateKey(Step); mPower = mPowerKeys.CalculateKey(Step); @@ -1207,6 +1221,9 @@ void lcLight::RemoveKeyFrames() mSpotTightnessKeys.RemoveAll(); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); + mAreaGridKeys.RemoveAll(); + mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); + mSizeKeys.RemoveAll(); mSizeKeys.ChangeKey(mSize, 1, true); diff --git a/common/light.h b/common/light.h index 2dc73b04..3f4faf68 100644 --- a/common/light.h +++ b/common/light.h @@ -276,6 +276,13 @@ class lcLight : public lcObject return mAreaShape; } + bool SetAreaGrid(lcVector2i AreaGrid, lcStep Step, bool AddKey); + + lcVector2i GetAreaGrid() const + { + return mAreaGrid; + } + void SetSize(lcVector2 Size, lcStep Step, bool AddKey); lcVector2 GetSize() const @@ -364,6 +371,7 @@ class lcLight : public lcObject float mSpotPenumbraAngle = 0.0f; float mSpotTightness = 0.0f; lcLightAreaShape mAreaShape = lcLightAreaShape::Rectangle; + lcVector2i mAreaGrid = lcVector2i(2, 2); quint32 mState = 0; bool mSelected = false; @@ -378,6 +386,7 @@ class lcLight : public lcObject lcObjectKeyArray mSpotConeAngleKeys; lcObjectKeyArray mSpotPenumbraAngleKeys; lcObjectKeyArray mSpotTightnessKeys; + lcObjectKeyArray mAreaGridKeys; lcObjectKeyArray mAttenuationKeys; lcObjectKeyArray mLightSpecularKeys; diff --git a/common/object.cpp b/common/object.cpp index fefc71f6..4eed9443 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -12,6 +12,7 @@ template bool lcObject::LoadAttribute(QTextStream& Stream, const QString& Token, T& Variable, lcObjectKeyArray& Keys, const char* VariableName) LC_OBJECT_ATTRIBUTE(float); +LC_OBJECT_ATTRIBUTE(lcVector2i); LC_OBJECT_ATTRIBUTE(lcVector2); LC_OBJECT_ATTRIBUTE(lcVector3); LC_OBJECT_ATTRIBUTE(lcVector4); diff --git a/common/project.cpp b/common/project.cpp index 5e77ad7a..d8a6a64c 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2140,7 +2140,7 @@ bool Project::ExportPOVRay(const QString& FileName) POVFile.WriteLine(Line); lcVector3 AreaX(1.0f, 0.0f, 0.0f), AreaY(0.0f, 1.0f, 0.0f); - lcVector2 AreaSize(200.0f, 200.0f); + lcVector2i AreaGrid(1, 1); int AreaCircle = 0, Shadowless = 0; lcLightType LightType = lcLightType::Area; float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0; @@ -2167,7 +2167,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightColor[0], LightColor[1], LightColor[2], Power, SpotRadius, SpotFalloff, SpotTightness, - AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], (int)AreaSize[0], (int)AreaSize[1]); + AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], AreaGrid.x, AreaGrid.y); POVFile.WriteLine(Line); } } @@ -2198,9 +2198,9 @@ bool Project::ExportPOVRay(const QString& FileName) case lcLightType::Area: AreaCircle = (Light->GetAreaShape() == lcLightAreaShape::Disk || Light->GetAreaShape() == lcLightAreaShape::Ellipse) ? 1 : 0; - AreaSize = Light->GetSize(); - AreaX = lcVector3(Light->GetWorldMatrix()[0]); - AreaY = lcVector3(Light->GetWorldMatrix()[1]); + AreaX = lcVector3(Light->GetWorldMatrix()[0]) * Light->GetSize().x; + AreaY = lcVector3(Light->GetWorldMatrix()[1]) * Light->GetSize().y; + AreaGrid = Light->GetAreaGrid(); break; case lcLightType::Count: @@ -2216,7 +2216,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightColor[0], LightColor[1], LightColor[2], Power, SpotRadius, SpotFalloff, SpotTightness, - AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], (int)AreaSize[0], (int)AreaSize[1]); + AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], AreaGrid.x, AreaGrid.y); POVFile.WriteLine(Line); } } diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index c4a07d32..24ff25bb 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -447,6 +447,20 @@ QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) return Editor; } + case PropertyInteger: + { + QLineEdit* Editor = new QLineEdit(Parent); + int Value = Item->data(0, PropertyValueRole).toInt(); + QPoint Range = Item->data(0, PropertyRangeRole).toPoint(); + + Editor->setValidator(Range.isNull() ? new QIntValidator(Editor) : new QIntValidator(Range.x(), Range.y(), Editor)); + Editor->setText(QString::number(Value)); + + connect(Editor, &QLineEdit::returnPressed, this, &lcQPropertiesTree::slotReturnPressed); + + return Editor; + } + case PropertyStep: { QLineEdit* Editor = new QLineEdit(Parent); @@ -842,6 +856,20 @@ void lcQPropertiesTree::slotReturnPressed() Model->SetSpotLightTightness(Light, Value); } + else if (Item == mLightAreaGridXItem) + { + lcVector2i AreaGrid = Light->GetAreaGrid(); + AreaGrid.x = Editor->text().toInt(); + + Model->SetLightAreaGrid(Light, AreaGrid); + } + else if (Item == mLightAreaGridYItem) + { + lcVector2i AreaGrid = Light->GetAreaGrid(); + AreaGrid.y = Editor->text().toInt(); + + Model->SetLightAreaGrid(Light, AreaGrid); + } else if (Item == mLightSizeXItem) { lcVector2 Value = Light->GetSize(); @@ -954,7 +982,7 @@ void lcQPropertiesTree::slotSetValue(int Value) } else if (Item == mLightAreaShapeItem) { - Model->SetAreaLightShape(Light, static_cast(Value)); + Model->SetLightAreaShape(Light, static_cast(Value)); } else if (Item == lightFormat) { @@ -1100,6 +1128,8 @@ void lcQPropertiesTree::SetEmpty() mLightSpotPenumbraAngleItem = nullptr; mLightSpotTightnessItem = nullptr; mLightAreaShapeItem = nullptr; + mLightAreaGridXItem = nullptr; + mLightAreaGridYItem = nullptr; mLightSizeXItem = nullptr; mLightSizeYItem = nullptr; lightFormat = nullptr; @@ -1355,6 +1385,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lcLightType LightType = lcLightType::Point; lcLightAreaShape LightAreaShape = lcLightAreaShape::Rectangle; lcVector2 LightSize(0.0f, 0.0f); + lcVector2i AreaGrid(2, 2); float Power = 0.0f; int FormatIndex = 0; float Diffuse = 0.0f; @@ -1386,6 +1417,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) LightType = Light->GetLightType(); LightAreaShape = Light->GetAreaShape(); LightSize = Light->GetSize(); + AreaGrid = Light->GetAreaGrid(); switch (LightType) { @@ -1498,6 +1530,15 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) case lcLightAreaShape::Count: break; } + + mLightAreaGridXItem = addProperty(mLightAttributesItem, tr("Area Grid X"), PropertyInteger); + mLightAreaGridXItem->setToolTip(1, tr("Number of point sources along the X axis (POV-Ray only).")); + mLightAreaGridXItem->setData(0, PropertyRangeRole, QPointF(1, INT_MAX)); + + mLightAreaGridYItem = addProperty(mLightAttributesItem, tr("Area Grid Y"), PropertyInteger); + mLightAreaGridYItem->setToolTip(1, tr("Number of point sources along the Y axis (POV-Ray only).")); + mLightAreaGridYItem->setData(0, PropertyRangeRole, QPointF(1, INT_MAX)); + break; case lcLightType::Count: @@ -1630,6 +1671,12 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) case lcLightType::Area: mLightAreaShapeItem->setText(1, lcLight::GetAreaShapeString(LightAreaShape)); mLightAreaShapeItem->setData(0, PropertyValueRole, static_cast(LightAreaShape)); + + mLightAreaGridXItem->setText(1, QString::number(AreaGrid.x)); + mLightAreaGridXItem->setData(0, PropertyValueRole, AreaGrid.x); + + mLightAreaGridYItem->setText(1, QString::number(AreaGrid.y)); + mLightAreaGridYItem->setData(0, PropertyValueRole, AreaGrid.y); break; case lcLightType::Count: diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index d6d1e8f2..148d3244 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -45,6 +45,7 @@ class lcQPropertiesTree : public QTreeWidget PropertyGroup, PropertyBool, PropertyFloat, + PropertyInteger, PropertyStep, PropertyString, PropertyStringList, @@ -128,6 +129,8 @@ protected slots: QTreeWidgetItem* mLightSpotPenumbraAngleItem; QTreeWidgetItem* mLightSpotTightnessItem; QTreeWidgetItem* mLightAreaShapeItem; + QTreeWidgetItem* mLightAreaGridXItem; + QTreeWidgetItem* mLightAreaGridYItem; QTreeWidgetItem* mLightSizeXItem; QTreeWidgetItem* mLightSizeYItem; QTreeWidgetItem* mLightNameItem; From d52159087c2b8ce519f908a51ecacd407937ebf0 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 17 Dec 2023 11:37:11 -0800 Subject: [PATCH 40/42] Added light attenuation settings. --- common/lc_model.cpp | 20 ++++++++++++++++++++ common/lc_model.h | 2 ++ common/light.cpp | 36 +++++++++++++++++++++++++++++------- common/light.h | 20 ++++++++++++++++++-- common/project.cpp | 18 ++++++++++++++---- qt/lc_qpropertiestree.cpp | 34 +++++++++++++++++++++++++++++++++- qt/lc_qpropertiestree.h | 2 ++ 7 files changed, 118 insertions(+), 14 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index cb339a65..407b1344 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3185,6 +3185,26 @@ void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color) UpdateAllViews(); } +void lcModel::SetLightAttenuationDistance(lcLight* Light, float Distance) +{ + Light->SetAttenuationDistance(Distance, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Light Attenuation Distance")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + +void lcModel::SetLightAttenuationPower(lcLight* Light, float Power) +{ + Light->SetAttenuationPower(Power, mCurrentStep, gMainWindow->GetAddKeys()); + Light->UpdatePosition(mCurrentStep); + + SaveCheckpoint(tr("Changing Light Attenuation Power")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); +} + void lcModel::SetSpotLightConeAngle(lcLight* Light, float Angle) { Light->SetSpotConeAngle(Angle, mCurrentStep, gMainWindow->GetAddKeys()); diff --git a/common/lc_model.h b/common/lc_model.h index dd99f74c..144ee9f8 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -370,6 +370,8 @@ class lcModel void SetLightType(lcLight* Light, lcLightType LightType); void SetLightColor(lcLight* Light, const lcVector3& Color); + void SetLightAttenuationDistance(lcLight* Light, float Distance); + void SetLightAttenuationPower(lcLight* Light, float Power); void SetSpotLightConeAngle(lcLight* Light, float Angle); void SetSpotLightPenumbraAngle(lcLight* Light, float Angle); void SetSpotLightTightness(lcLight* Light, float Tightness); diff --git a/common/light.cpp b/common/light.cpp index ccb8819b..f57f7583 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -27,7 +27,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mPOVRayLight = false; mEnableCutoff = false; - mAttenuation = lcVector3(1.0f, 0.0f, 0.0f); mLightDiffuse = 1.0f; mLightSpecular = 1.0f; mSpotExponent = 10.0f; @@ -40,12 +39,13 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mRotationKeys.ChangeKey(lcMatrix33(mWorldMatrix), 1, true); mColorKeys.ChangeKey(mColor, 1, true); mPowerKeys.ChangeKey(mPower, 1, true); + mAttenuationDistanceKeys.ChangeKey(mAttenuationDistance, 1, true); + mAttenuationPowerKeys.ChangeKey(mAttenuationPower, 1, true); mSpotConeAngleKeys.ChangeKey(mSpotConeAngle, 1, true); mSpotPenumbraAngleKeys.ChangeKey(mSpotPenumbraAngle, 1, true); mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); - mAttenuationKeys.ChangeKey(mAttenuation, 1, true); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); @@ -158,6 +158,8 @@ void lcLight::SaveLDraw(QTextStream& Stream) const SaveAttribute(Stream, mColor, mColorKeys, "LIGHT", "COLOR"); SaveAttribute(Stream, mSize, mSizeKeys, "LIGHT", "SIZE"); SaveAttribute(Stream, mPower, mPowerKeys, "LIGHT", "POWER"); + SaveAttribute(Stream, mAttenuationDistance, mAttenuationDistanceKeys, "LIGHT", "ATTENUATION_DISTANCE"); + SaveAttribute(Stream, mAttenuationPower, mAttenuationPowerKeys, "LIGHT", "ATTENUATION_POWER"); if (!mPOVRayLight) { @@ -306,6 +308,10 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) continue; else if (LoadAttribute(Stream, Token, mPower, mPowerKeys, "POWER")) continue; + else if (LoadAttribute(Stream, Token, mAttenuationDistance, mAttenuationDistanceKeys, "ATTENUATION_DISTANCE")) + continue; + else if (LoadAttribute(Stream, Token, mAttenuationPower, mAttenuationPowerKeys, "ATTENUATION_POWER")) + continue; else if (LoadAttribute(Stream, Token, mSpotConeAngle, mSpotConeAngleKeys, "SPOT_CONE_ANGLE")) continue; else if (LoadAttribute(Stream, Token, mSpotPenumbraAngle, mSpotPenumbraAngleKeys, "SPOT_PENUMBRA_ANGLE")) @@ -665,6 +671,16 @@ void lcLight::SetColor(const lcVector3& Color, lcStep Step, bool AddKey) mColorKeys.ChangeKey(Color, Step, AddKey); } +void lcLight::SetAttenuationDistance(float Distance, lcStep Step, bool AddKey) +{ + mAttenuationDistanceKeys.ChangeKey(Distance, Step, AddKey); +} + +void lcLight::SetAttenuationPower(float Power, lcStep Step, bool AddKey) +{ + mAttenuationPowerKeys.ChangeKey(Power, Step, AddKey); +} + void lcLight::SetSpotConeAngle(float Angle, lcStep Step, bool AddKey) { mSpotConeAngleKeys.ChangeKey(Angle, Step, AddKey); @@ -736,8 +752,9 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mAreaGridKeys.InsertTime(Start, Time); mSizeKeys.InsertTime(Start, Time); mPowerKeys.InsertTime(Start, Time); + mAttenuationDistanceKeys.InsertTime(Start, Time); + mAttenuationPowerKeys.InsertTime(Start, Time); - mAttenuationKeys.InsertTime(Start, Time); mLightDiffuseKeys.InsertTime(Start, Time); mLightSpecularKeys.InsertTime(Start, Time); mSpotCutoffKeys.InsertTime(Start, Time); @@ -755,8 +772,9 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mAreaGridKeys.RemoveTime(Start, Time); mSizeKeys.RemoveTime(Start, Time); mPowerKeys.RemoveTime(Start, Time); + mAttenuationDistanceKeys.RemoveTime(Start, Time); + mAttenuationPowerKeys.RemoveTime(Start, Time); - mAttenuationKeys.RemoveTime(Start, Time); mLightDiffuseKeys.RemoveTime(Start, Time); mLightSpecularKeys.RemoveTime(Start, Time); mSpotCutoffKeys.RemoveTime(Start, Time); @@ -785,8 +803,9 @@ void lcLight::UpdatePosition(lcStep Step) mAreaGrid = mAreaGridKeys.CalculateKey(Step); mSize = mSizeKeys.CalculateKey(Step); mPower = mPowerKeys.CalculateKey(Step); + mAttenuationDistance = mAttenuationDistanceKeys.CalculateKey(Step); + mAttenuationPower = mAttenuationPowerKeys.CalculateKey(Step); - mAttenuation = mAttenuationKeys.CalculateKey(Step); mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); mLightSpecular = mLightSpecularKeys.CalculateKey(Step); mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); @@ -1230,8 +1249,11 @@ void lcLight::RemoveKeyFrames() mPowerKeys.RemoveAll(); mPowerKeys.ChangeKey(mPower, 1, true); - mAttenuationKeys.RemoveAll(); - mAttenuationKeys.ChangeKey(mAttenuation, 1, true); + mAttenuationDistanceKeys.RemoveAll(); + mAttenuationDistanceKeys.ChangeKey(mAttenuationDistance, 1, true); + + mAttenuationPowerKeys.RemoveAll(); + mAttenuationPowerKeys.ChangeKey(mAttenuationPower, 1, true); mLightDiffuseKeys.RemoveAll(); mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); diff --git a/common/light.h b/common/light.h index 3f4faf68..b70435ea 100644 --- a/common/light.h +++ b/common/light.h @@ -248,6 +248,20 @@ class lcLight : public lcObject return mColor; } + void SetAttenuationDistance(float Distance, lcStep Step, bool AddKey); + + float GetAttenuationDistance() const + { + return mAttenuationDistance; + } + + void SetAttenuationPower(float Power, lcStep Step, bool AddKey); + + float GetAttenuationPower() const + { + return mAttenuationPower; + } + void SetSpotConeAngle(float Angle, lcStep Step, bool AddKey); float GetSpotConeAngle() const @@ -336,7 +350,6 @@ class lcLight : public lcObject lcMatrix44 mWorldMatrix; - lcVector3 mAttenuation; bool mSpotBlendSet; bool mSpotCutoffSet; bool mEnableCutoff; @@ -367,6 +380,8 @@ class lcLight : public lcObject lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f); lcVector2 mSize = lcVector2(0.0f, 0.0f); float mPower = 1.0f; + float mAttenuationDistance = 0.0f; + float mAttenuationPower = 0.0f; float mSpotConeAngle = 80.0f; float mSpotPenumbraAngle = 0.0f; float mSpotTightness = 0.0f; @@ -383,12 +398,13 @@ class lcLight : public lcObject lcObjectKeyArray mColorKeys; lcObjectKeyArray mSizeKeys; lcObjectKeyArray mPowerKeys; + lcObjectKeyArray mAttenuationDistanceKeys; + lcObjectKeyArray mAttenuationPowerKeys; lcObjectKeyArray mSpotConeAngleKeys; lcObjectKeyArray mSpotPenumbraAngleKeys; lcObjectKeyArray mSpotTightnessKeys; lcObjectKeyArray mAreaGridKeys; - lcObjectKeyArray mAttenuationKeys; lcObjectKeyArray mLightSpecularKeys; lcObjectKeyArray mLightDiffuseKeys; lcObjectKeyArray mSpotCutoffKeys; diff --git a/common/project.cpp b/common/project.cpp index d8a6a64c..c83c9a4f 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2007,7 +2007,7 @@ bool Project::ExportPOVRay(const QString& FileName) sprintf(Line, "#ifndef (SkipWriteLightMacro)\n" - "#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n" + "#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n" " #local PointLight = %i;\n" " #local Spotlight = %i;\n" " #local DirectionalLight = %i;\n" @@ -2018,6 +2018,12 @@ bool Project::ExportPOVRay(const QString& FileName) " #if (Shadowless > 0)\n" " shadowless\n" " #end\n" + " #if (FadeDistance > 0)\n" + " fade_distance FadeDistance\n" + " #end\n" + " #if (FadePower > 0)\n" + " fade_power FadePower\n" + " #end\n" " #if (Type = Spotlight)\n" " spotlight\n" " radius SpotRadius\n" @@ -2143,7 +2149,7 @@ bool Project::ExportPOVRay(const QString& FileName) lcVector2i AreaGrid(1, 1); int AreaCircle = 0, Shadowless = 0; lcLightType LightType = lcLightType::Area; - float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0; + float Power = 0.0f, FadeDistance = 0.0f, FadePower = 0.0f, SpotRadius = 0.0f, SpotFalloff = 0.0f, SpotTightness = 0.0f; if (Lights.IsEmpty()) { @@ -2158,7 +2164,7 @@ bool Project::ExportPOVRay(const QString& FileName) for (int Idx = 0; Idx < 4; Idx++) { Power = Idx < 2 ? 0.75f : 0.5f; - sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", + sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", Idx, LightType, Shadowless, @@ -2166,6 +2172,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightTarget[0], LightTarget[1], LightTarget[2], LightColor[0], LightColor[1], LightColor[2], Power, + FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], AreaGrid.x, AreaGrid.y); POVFile.WriteLine(Line); @@ -2182,6 +2189,8 @@ bool Project::ExportPOVRay(const QString& FileName) LightType = Light->GetLightType(); Shadowless = Light->GetCastShadow() ? 0 : 1; Power = Light->mPOVRayExponent; + FadeDistance = Light->GetAttenuationDistance(); + FadePower = Light->GetAttenuationPower(); switch (LightType) { @@ -2207,7 +2216,7 @@ bool Project::ExportPOVRay(const QString& FileName) break; } - sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", + sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", LightName.toLatin1().constData(), LightType, Shadowless, @@ -2215,6 +2224,7 @@ bool Project::ExportPOVRay(const QString& FileName) LightTarget[1], LightTarget[0], LightTarget[2], LightColor[0], LightColor[1], LightColor[2], Power, + FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], AreaGrid.x, AreaGrid.y); POVFile.WriteLine(Line); diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index 24ff25bb..cf46027b 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -838,7 +838,19 @@ void lcQPropertiesTree::slotReturnPressed() { lcLightProperties Props = Light->GetLightProperties(); - if (Item == mLightSpotConeAngleItem) + if (Item == mLightAttenuationDistanceItem) + { + float Value = lcParseValueLocalized(Editor->text()); + + Model->SetLightAttenuationDistance(Light, Value); + } + else if (Item == mLightAttenuationPowerItem) + { + float Value = lcParseValueLocalized(Editor->text()); + + Model->SetLightAttenuationPower(Light, Value); + } + else if (Item == mLightSpotConeAngleItem) { float Value = lcParseValueLocalized(Editor->text()); @@ -1124,6 +1136,8 @@ void lcQPropertiesTree::SetEmpty() lightExponent = nullptr; mLightTypeItem = nullptr; mLightNameItem = nullptr; + mLightAttenuationDistanceItem = nullptr; + mLightAttenuationPowerItem = nullptr; mLightSpotConeAngleItem = nullptr; mLightSpotPenumbraAngleItem = nullptr; mLightSpotTightnessItem = nullptr; @@ -1387,6 +1401,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lcVector2 LightSize(0.0f, 0.0f); lcVector2i AreaGrid(2, 2); float Power = 0.0f; + float AttenuationDistance = 0.0f; + float AttenuationPower = 0.0f; int FormatIndex = 0; float Diffuse = 0.0f; float Specular = 0.0f; @@ -1411,6 +1427,8 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) Position = Light->GetPosition(); Color = lcQColorFromVector3(Light->GetColor()); Power = Light->GetPower(); + AttenuationDistance = Light->GetAttenuationDistance(); + AttenuationPower = Light->GetAttenuationPower(); SpotConeAngle = Light->GetSpotConeAngle(); SpotPenumbraAngle = Light->GetSpotPenumbraAngle(); @@ -1478,6 +1496,12 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); + mLightAttenuationDistanceItem = addProperty(mLightAttributesItem, tr("Attenuation Distance"), PropertyFloat); + mLightAttenuationDistanceItem->setToolTip(1, tr("The distance at which the full light intensity arrives (POV-Ray only).")); + + mLightAttenuationPowerItem = addProperty(mLightAttributesItem, tr("Attenuation Power"), PropertyFloat); + mLightAttenuationPowerItem->setToolTip(1, tr("Light falloff rate (POV-Ray only).")); + switch (LightType) { case lcLightType::Point: @@ -1624,6 +1648,14 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightPowerItem->setText(1, lcFormatValueLocalized(Power)); mLightPowerItem->setData(0, PropertyValueRole, Power); + mLightAttenuationDistanceItem->setText(1, lcFormatValueLocalized(AttenuationDistance)); + mLightAttenuationDistanceItem->setData(0, PropertyValueRole, AttenuationDistance); + mLightAttenuationDistanceItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX)); + + mLightAttenuationPowerItem->setText(1, lcFormatValueLocalized(AttenuationPower)); + mLightAttenuationPowerItem->setData(0, PropertyValueRole, AttenuationPower); + mLightAttenuationPowerItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX)); + lightFormat->setText(1, Format); lightFormat->setData(0, PropertyValueRole, FormatIndex); diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 148d3244..1eabd9ef 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -125,6 +125,8 @@ protected slots: QTreeWidgetItem* lightEnableCutoff; QTreeWidgetItem* lightExponent; QTreeWidgetItem* mLightTypeItem; + QTreeWidgetItem* mLightAttenuationDistanceItem; + QTreeWidgetItem* mLightAttenuationPowerItem; QTreeWidgetItem* mLightSpotConeAngleItem; QTreeWidgetItem* mLightSpotPenumbraAngleItem; QTreeWidgetItem* mLightSpotTightnessItem; From 321b9389ede4d6f03e7eea0c929bc7c3867c0483 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 17 Dec 2023 12:16:32 -0800 Subject: [PATCH 41/42] Removed unused light options. Specular is EEVEE only and Diffuse/Cutoff are unknown. --- common/light.cpp | 93 --------------------------------------- common/light.h | 21 --------- qt/lc_qpropertiestree.cpp | 74 +------------------------------ qt/lc_qpropertiestree.h | 4 -- 4 files changed, 2 insertions(+), 190 deletions(-) diff --git a/common/light.cpp b/common/light.cpp index f57f7583..17d3cef6 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -26,12 +26,8 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mWorldMatrix = lcMatrix44Translation(Position); mPOVRayLight = false; - mEnableCutoff = false; - mLightDiffuse = 1.0f; - mLightSpecular = 1.0f; mSpotExponent = 10.0f; mPOVRayExponent = 1.0f; - mSpotCutoff = LightType != lcLightType::Directional ? 40.0f : 0.0f; UpdateLightType(); @@ -46,9 +42,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); - mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); - mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); - mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); UpdatePosition(1); @@ -161,19 +154,8 @@ void lcLight::SaveLDraw(QTextStream& Stream) const SaveAttribute(Stream, mAttenuationDistance, mAttenuationDistanceKeys, "LIGHT", "ATTENUATION_DISTANCE"); SaveAttribute(Stream, mAttenuationPower, mAttenuationPowerKeys, "LIGHT", "ATTENUATION_POWER"); - if (!mPOVRayLight) - { - SaveAttribute(Stream, mLightDiffuse, mLightDiffuseKeys, "LIGHT", "DIFFUSE"); - SaveAttribute(Stream, mLightSpecular, mLightSpecularKeys, "LIGHT", "SPECULAR"); - } - // SaveAttribute(Stream, (mPOVRayLight ? mPOVRayExponent : mSpotExponent), mSpotExponentKeys, "LIGHT", "POWER"); - if (mEnableCutoff && !mPOVRayLight) - { - SaveAttribute(Stream, mSpotCutoff, mSpotCutoffKeys, "LIGHT", "CUTOFF_DISTANCE"); - } - switch (mLightType) { case lcLightType::Count: @@ -348,22 +330,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) // mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); // } // } - else if (Token == QLatin1String("DIFFUSE")) - { - Stream >>mLightDiffuse; - mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); - } - else if (Token == QLatin1String("SPECULAR")) - { - Stream >>mLightSpecular; - mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); - } - else if ((mSpotCutoffSet = Token == QLatin1String("CUTOFF_DISTANCE"))) - { - mEnableCutoff = true; - Stream >> mSpotCutoff; - mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); - } else if (Token == QLatin1String("TYPE")) { QString Type; @@ -388,37 +354,11 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) mSpotExponentKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("DIFFUSE_KEY")) - mLightDiffuseKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("SPECULAR_KEY")) - mLightSpecularKeys.LoadKeysLDraw(Stream); - else if (Token == QLatin1String("CUTOFF_DISTANCE_KEY")) - mSpotCutoffKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("NAME")) { mName = Stream.readAll().trimmed(); mName.replace("\"", ""); - // Set default settings per light type - switch (mLightType) - { - case lcLightType::Point: - case lcLightType::Spot: - break; - - case lcLightType::Directional: - if (!mSpotCutoffSet) - { - mSpotCutoff = 0.0f; - mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); - } - break; - - case lcLightType::Area: - case lcLightType::Count: - break; - } - return true; } } @@ -440,14 +380,6 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) { switch(Property) { - case LC_LIGHT_DIFFUSE: - mLightDiffuse = Props.mLightDiffuse; - mLightDiffuseKeys.ChangeKey(mLightDiffuse, Step, false); - break; - case LC_LIGHT_SPECULAR: - mLightSpecular = Props.mLightSpecular; - mLightSpecularKeys.ChangeKey(mLightSpecular, Step, false); - break; case LC_LIGHT_EXPONENT: if (Props.mPOVRayLight) { @@ -460,13 +392,6 @@ void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) mSpotExponentKeys.ChangeKey(mSpotExponent, Step, false); } break; - case LC_LIGHT_CUTOFF: - mSpotCutoff = Props.mSpotCutoff; - mSpotCutoffKeys.ChangeKey(mSpotCutoff, Step, false); - break; - case LC_LIGHT_USE_CUTOFF: - mEnableCutoff = Props.mEnableCutoff; - break; case LC_LIGHT_POVRAY: mPOVRayLight = Props.mPOVRayLight; break; @@ -755,9 +680,6 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mAttenuationDistanceKeys.InsertTime(Start, Time); mAttenuationPowerKeys.InsertTime(Start, Time); - mLightDiffuseKeys.InsertTime(Start, Time); - mLightSpecularKeys.InsertTime(Start, Time); - mSpotCutoffKeys.InsertTime(Start, Time); mSpotExponentKeys.InsertTime(Start, Time); } @@ -775,9 +697,6 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mAttenuationDistanceKeys.RemoveTime(Start, Time); mAttenuationPowerKeys.RemoveTime(Start, Time); - mLightDiffuseKeys.RemoveTime(Start, Time); - mLightSpecularKeys.RemoveTime(Start, Time); - mSpotCutoffKeys.RemoveTime(Start, Time); mSpotExponentKeys.RemoveTime(Start, Time); } @@ -806,9 +725,6 @@ void lcLight::UpdatePosition(lcStep Step) mAttenuationDistance = mAttenuationDistanceKeys.CalculateKey(Step); mAttenuationPower = mAttenuationPowerKeys.CalculateKey(Step); - mLightDiffuse = mLightDiffuseKeys.CalculateKey(Step); - mLightSpecular = mLightSpecularKeys.CalculateKey(Step); - mSpotCutoff = mSpotCutoffKeys.CalculateKey(Step); mSpotExponent = mSpotExponentKeys.CalculateKey(Step); } @@ -1255,15 +1171,6 @@ void lcLight::RemoveKeyFrames() mAttenuationPowerKeys.RemoveAll(); mAttenuationPowerKeys.ChangeKey(mAttenuationPower, 1, true); - mLightDiffuseKeys.RemoveAll(); - mLightDiffuseKeys.ChangeKey(mLightDiffuse, 1, true); - - mLightSpecularKeys.RemoveAll(); - mLightSpecularKeys.ChangeKey(mLightSpecular, 1, true); - - mSpotCutoffKeys.RemoveAll(); - mSpotCutoffKeys.ChangeKey(mSpotCutoff, 1, true); - mSpotExponentKeys.RemoveAll(); mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); } diff --git a/common/light.h b/common/light.h index b70435ea..14d598a4 100644 --- a/common/light.h +++ b/common/light.h @@ -33,21 +33,13 @@ enum class lcLightAreaShape enum lcLightProperty { - LC_LIGHT_DIFFUSE, - LC_LIGHT_SPECULAR, LC_LIGHT_EXPONENT, - LC_LIGHT_CUTOFF, - LC_LIGHT_USE_CUTOFF, LC_LIGHT_POVRAY }; struct lcLightProperties { - float mLightDiffuse; - float mLightSpecular; float mSpotExponent; - float mSpotCutoff; - bool mEnableCutoff; bool mPOVRayLight; }; @@ -339,24 +331,14 @@ class lcLight : public lcObject lcLightProperties GetLightProperties() const { lcLightProperties props; - props.mLightDiffuse = mLightDiffuse; - props.mLightSpecular = mLightSpecular; props.mSpotExponent = mSpotExponent; - props.mSpotCutoff = mSpotCutoff; props.mPOVRayLight = mPOVRayLight; - props.mEnableCutoff = mEnableCutoff; return props; } lcMatrix44 mWorldMatrix; - bool mSpotBlendSet; - bool mSpotCutoffSet; - bool mEnableCutoff; bool mPOVRayLight; - float mLightDiffuse; - float mLightSpecular; - float mSpotCutoff; float mSpotExponent; float mPOVRayExponent; @@ -405,9 +387,6 @@ class lcLight : public lcObject lcObjectKeyArray mSpotTightnessKeys; lcObjectKeyArray mAreaGridKeys; - lcObjectKeyArray mLightSpecularKeys; - lcObjectKeyArray mLightDiffuseKeys; - lcObjectKeyArray mSpotCutoffKeys; lcObjectKeyArray mSpotExponentKeys; static constexpr float mTargetDistance = 50.0f; diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index cf46027b..a5ebc50c 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -658,13 +658,7 @@ void lcQPropertiesTree::slotToggled(bool Value) if (Light) { - if (Item == lightEnableCutoff) - { - lcLightProperties Props = Light->GetLightProperties(); - Props.mEnableCutoff = Value; - Model->UpdateLight(Light, Props, LC_LIGHT_USE_CUTOFF); - } - else if (Item == mLightCastShadowItem) + if (Item == mLightCastShadowItem) { Model->SetLightCastShadow(Light, Value); } @@ -902,30 +896,12 @@ void lcQPropertiesTree::slotReturnPressed() Model->SetLightPower(Light, Value); } - else if (Item == lightDiffuse) - { - Props.mLightDiffuse = lcParseValueLocalized(Editor->text()); - - Model->UpdateLight(Light, Props, LC_LIGHT_DIFFUSE); - } - else if (Item == lightSpecular) - { - Props.mLightSpecular = lcParseValueLocalized(Editor->text()); - - Model->UpdateLight(Light, Props, LC_LIGHT_SPECULAR); - } else if (Item == lightExponent) { Props.mSpotExponent = lcParseValueLocalized(Editor->text()); Model->UpdateLight(Light, Props, LC_LIGHT_EXPONENT); } - else if (Item == lightCutoff) - { - Props.mSpotCutoff = lcParseValueLocalized(Editor->text()); - - Model->UpdateLight(Light, Props, LC_LIGHT_CUTOFF); - } else if (Item == mLightNameItem) { QString Value = Editor->text(); @@ -1129,10 +1105,6 @@ void lcQPropertiesTree::SetEmpty() mLightColorItem = nullptr; mLightPowerItem = nullptr; mLightAttributesItem = nullptr; - lightDiffuse = nullptr; - lightSpecular = nullptr; - lightCutoff = nullptr; - lightEnableCutoff = nullptr; lightExponent = nullptr; mLightTypeItem = nullptr; mLightNameItem = nullptr; @@ -1394,8 +1366,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) QString Name = tr("Light"); QString ExponentLabel = tr("Exponent"); - QString FactorALabel = QLatin1String("FactorA"); - QString Format, ExponentToolTip, FactorAToolTip, FactorBToolTip; + QString Format, ExponentToolTip; lcLightType LightType = lcLightType::Point; lcLightAreaShape LightAreaShape = lcLightAreaShape::Rectangle; lcVector2 LightSize(0.0f, 0.0f); @@ -1404,8 +1375,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) float AttenuationDistance = 0.0f; float AttenuationPower = 0.0f; int FormatIndex = 0; - float Diffuse = 0.0f; - float Specular = 0.0f; float Cutoff = 0.0f; float Exponent = 0.0f; bool EnableCutoff = false; @@ -1444,7 +1413,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) break; case lcLightType::Spot: - FactorBToolTip = tr("The softness of the spotlight edge."); ExponentLabel = tr("Power"); break; @@ -1459,9 +1427,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) break; } - Diffuse = Light->mLightDiffuse; - Specular = Light->mLightSpecular; - if (POVRayLight) { Exponent = Light->mPOVRayExponent; @@ -1474,8 +1439,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) } ExponentLabel = LightType == lcLightType::Directional ? tr("Strength") : tr("Power"); - Cutoff = Light->mSpotCutoff; - EnableCutoff = Light->mEnableCutoff; SpotTightness = Light->GetSpotTightness(); } @@ -1571,18 +1534,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lightExponent = addProperty(mLightAttributesItem, ExponentLabel, PropertyFloat); - if (!POVRayLight) - { - if (LightType != lcLightType::Directional) - { - lightEnableCutoff = addProperty(mLightAttributesItem, tr("Cutoff"), PropertyBool); - lightCutoff = addProperty(mLightAttributesItem, tr("Cutoff Distance"), PropertyFloat); - } - - lightDiffuse = addProperty(mLightAttributesItem, tr("Diffuse"), PropertyFloat); - lightSpecular = addProperty(mLightAttributesItem, tr("Specular"), PropertyFloat); - } - // Configuration lightConfiguration = addProperty(nullptr, tr("Configuration"), PropertyGroup); lightFormat = addProperty(lightConfiguration, tr("Format"), PropertyLightFormat); @@ -1715,27 +1666,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) break; } - if (!POVRayLight) - { - if (LightType != lcLightType::Directional) - { - lightEnableCutoff->setCheckState(1, EnableCutoff ? Qt::Checked : Qt::Unchecked); - lightEnableCutoff->setData(0, PropertyValueRole, EnableCutoff); - - lightCutoff->setText(1, lcFormatValueLocalized(Cutoff)); - lightCutoff->setData(0, PropertyValueRole, Cutoff); - lightCutoff->setToolTip(1, tr("Distance at which the light influence will be set to 0.")); - } - - lightDiffuse->setText(1, lcFormatValueLocalized(Diffuse)); - lightDiffuse->setData(0, PropertyValueRole, Diffuse); - lightDiffuse->setToolTip(1, tr("Diffuse reflection multiplier factor.")); - - lightSpecular->setText(1, lcFormatValueLocalized(Specular)); - lightSpecular->setData(0, PropertyValueRole, Specular); - lightSpecular->setToolTip(1, tr("Specular reflection multiplier factor.")); - } - mLightNameItem->setText(1, Name); mLightNameItem->setData(0, PropertyValueRole, QVariant::fromValue(Name)); } diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 1eabd9ef..25eae636 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -119,10 +119,6 @@ protected slots: QTreeWidgetItem* mLightColorItem; QTreeWidgetItem* mLightPowerItem; QTreeWidgetItem* mLightAttributesItem; - QTreeWidgetItem* lightDiffuse; - QTreeWidgetItem* lightSpecular; - QTreeWidgetItem* lightCutoff; - QTreeWidgetItem* lightEnableCutoff; QTreeWidgetItem* lightExponent; QTreeWidgetItem* mLightTypeItem; QTreeWidgetItem* mLightAttenuationDistanceItem; From 6774b17051d847844a9f4bbc76837746d3d160d9 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Wed, 20 Dec 2023 16:42:00 -0800 Subject: [PATCH 42/42] Merged POV-Ray and Blender light power. --- common/lc_global.h | 1 - common/lc_model.cpp | 9 ---- common/lc_model.h | 1 - common/light.cpp | 64 ------------------------ common/light.h | 27 ---------- common/project.cpp | 2 +- qt/lc_qpropertiestree.cpp | 102 ++------------------------------------ qt/lc_qpropertiestree.h | 5 -- 8 files changed, 4 insertions(+), 207 deletions(-) diff --git a/common/lc_global.h b/common/lc_global.h index 53335edb..33fbfa04 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -107,7 +107,6 @@ struct lcMeshSection; struct lcRenderMesh; struct lcObjectSection; struct lcPieceInfoRayTest; -struct lcLightProperties; class lcTexture; class lcScene; class lcViewManipulator; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 407b1344..6cb9e210 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3092,15 +3092,6 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) } } -void lcModel::UpdateLight(lcLight* Light, const lcLightProperties Props, int Property) -{ - Light->UpdateLight(mCurrentStep, Props, Property); - - SaveCheckpoint(tr("Update Light")); - UpdateAllViews(); - gMainWindow->UpdateSelectedObjects(false); -} - void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) { if (Camera->IsOrtho() == Ortho) diff --git a/common/lc_model.h b/common/lc_model.h index 144ee9f8..59bee78c 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -381,7 +381,6 @@ class lcModel void SetLightPower(lcLight* Light, float Power); void SetLightCastShadow(lcLight* Light, bool CastShadow); void SetLightName(lcLight* Light, const QString& Name); - void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); void ShowPropertiesDialog(); void ShowSelectByNameDialog(); diff --git a/common/light.cpp b/common/light.cpp index 17d3cef6..82ed4288 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -25,10 +25,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) { mWorldMatrix = lcMatrix44Translation(Position); - mPOVRayLight = false; - mSpotExponent = 10.0f; - mPOVRayExponent = 1.0f; - UpdateLightType(); mPositionKeys.ChangeKey(mWorldMatrix.GetTranslation(), 1, true); @@ -42,8 +38,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mSpotTightnessKeys.ChangeKey(mSpotTightness, 1, true); mAreaGridKeys.ChangeKey(mAreaGrid, 1, true); - mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); - UpdatePosition(1); } @@ -126,9 +120,6 @@ void lcLight::SaveLDraw(QTextStream& Stream) const { const QLatin1String LineEnding("\r\n"); - if (mPOVRayLight) - Stream << QLatin1String("0 !LEOCAD LIGHT POV_RAY") << LineEnding; - if (!mCastShadow) Stream << QLatin1String("0 !LEOCAD LIGHT SHADOWLESS") << LineEnding; @@ -154,8 +145,6 @@ void lcLight::SaveLDraw(QTextStream& Stream) const SaveAttribute(Stream, mAttenuationDistance, mAttenuationDistanceKeys, "LIGHT", "ATTENUATION_DISTANCE"); SaveAttribute(Stream, mAttenuationPower, mAttenuationPowerKeys, "LIGHT", "ATTENUATION_POWER"); -// SaveAttribute(Stream, (mPOVRayLight ? mPOVRayExponent : mSpotExponent), mSpotExponentKeys, "LIGHT", "POWER"); - switch (mLightType) { case lcLightType::Count: @@ -169,7 +158,6 @@ void lcLight::SaveLDraw(QTextStream& Stream) const break; case lcLightType::Directional: - SaveAttribute(Stream, mSpotExponent, mSpotExponentKeys, "LIGHT", "STRENGTH"); break; case lcLightType::Area: @@ -316,20 +304,6 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } else if (LoadAttribute(Stream, Token, mAreaGrid, mAreaGridKeys, "AREA_GRID")) continue; - -// else if (Token == QLatin1String("POWER") || Token == QLatin1String("STRENGTH")) -// { -// if (mPOVRayLight) -// { -// Stream >> mPOVRayExponent; -// mSpotExponentKeys.ChangeKey(mPOVRayExponent, 1, true); -// } -// else -// { -// Stream >> mSpotExponent; -// mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); -// } -// } else if (Token == QLatin1String("TYPE")) { QString Type; @@ -344,16 +318,10 @@ bool lcLight::ParseLDrawLine(QTextStream& Stream) } } } - else if (Token == QLatin1String("POV_RAY")) - { - mPOVRayLight = true; - } else if (Token == QLatin1String("SHADOWLESS")) { mCastShadow = false; } - else if ((Token == QLatin1String("POWER_KEY")) || (Token == QLatin1String("STRENGTH_KEY"))) - mSpotExponentKeys.LoadKeysLDraw(Stream); else if (Token == QLatin1String("NAME")) { mName = Stream.readAll().trimmed(); @@ -376,29 +344,6 @@ void lcLight::CompareBoundingBox(lcVector3& Min, lcVector3& Max) Max = lcMax(Point, Max); } -void lcLight::UpdateLight(lcStep Step, lcLightProperties Props, int Property) -{ - switch(Property) - { - case LC_LIGHT_EXPONENT: - if (Props.mPOVRayLight) - { - mPOVRayExponent = Props.mSpotExponent; - mSpotExponentKeys.ChangeKey(mPOVRayExponent, Step, false); - } - else - { - mSpotExponent = Props.mSpotExponent; - mSpotExponentKeys.ChangeKey(mSpotExponent, Step, false); - } - break; - case LC_LIGHT_POVRAY: - mPOVRayLight = Props.mPOVRayLight; - break; - } - UpdatePosition(Step); -} - void lcLight::RayTest(lcObjectRayTest& ObjectRayTest) const { if (IsPointLight()) @@ -679,8 +624,6 @@ void lcLight::InsertTime(lcStep Start, lcStep Time) mPowerKeys.InsertTime(Start, Time); mAttenuationDistanceKeys.InsertTime(Start, Time); mAttenuationPowerKeys.InsertTime(Start, Time); - - mSpotExponentKeys.InsertTime(Start, Time); } void lcLight::RemoveTime(lcStep Start, lcStep Time) @@ -696,8 +639,6 @@ void lcLight::RemoveTime(lcStep Start, lcStep Time) mPowerKeys.RemoveTime(Start, Time); mAttenuationDistanceKeys.RemoveTime(Start, Time); mAttenuationPowerKeys.RemoveTime(Start, Time); - - mSpotExponentKeys.RemoveTime(Start, Time); } void lcLight::UpdatePosition(lcStep Step) @@ -724,8 +665,6 @@ void lcLight::UpdatePosition(lcStep Step) mPower = mPowerKeys.CalculateKey(Step); mAttenuationDistance = mAttenuationDistanceKeys.CalculateKey(Step); mAttenuationPower = mAttenuationPowerKeys.CalculateKey(Step); - - mSpotExponent = mSpotExponentKeys.CalculateKey(Step); } void lcLight::DrawInterface(lcContext* Context, const lcScene& Scene) const @@ -1170,9 +1109,6 @@ void lcLight::RemoveKeyFrames() mAttenuationPowerKeys.RemoveAll(); mAttenuationPowerKeys.ChangeKey(mAttenuationPower, 1, true); - - mSpotExponentKeys.RemoveAll(); - mSpotExponentKeys.ChangeKey(mSpotExponent, 1, true); } bool lcLight::Setup(int LightIndex) diff --git a/common/light.h b/common/light.h index 14d598a4..32d80a0a 100644 --- a/common/light.h +++ b/common/light.h @@ -31,18 +31,6 @@ enum class lcLightAreaShape Count }; -enum lcLightProperty -{ - LC_LIGHT_EXPONENT, - LC_LIGHT_POVRAY -}; - -struct lcLightProperties -{ - float mSpotExponent; - bool mPOVRayLight; -}; - class lcLight : public lcObject { public: @@ -326,22 +314,9 @@ class lcLight : public lcObject void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame); bool Setup(int LightIndex); void CreateName(const lcArray& Lights); - void UpdateLight(lcStep Step, lcLightProperties Props, int Property); - - lcLightProperties GetLightProperties() const - { - lcLightProperties props; - props.mSpotExponent = mSpotExponent; - props.mPOVRayLight = mPOVRayLight; - return props; - } lcMatrix44 mWorldMatrix; - bool mPOVRayLight; - float mSpotExponent; - float mPOVRayExponent; - protected: void UpdateLightType(); @@ -387,7 +362,5 @@ class lcLight : public lcObject lcObjectKeyArray mSpotTightnessKeys; lcObjectKeyArray mAreaGridKeys; - lcObjectKeyArray mSpotExponentKeys; - static constexpr float mTargetDistance = 50.0f; }; diff --git a/common/project.cpp b/common/project.cpp index c83c9a4f..56b8c528 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2188,7 +2188,7 @@ bool Project::ExportPOVRay(const QString& FileName) const QString LightName = QString(Light->GetName()).replace(" ", "_"); LightType = Light->GetLightType(); Shadowless = Light->GetCastShadow() ? 0 : 1; - Power = Light->mPOVRayExponent; + Power = Light->GetPower(); FadeDistance = Light->GetAttenuationDistance(); FadePower = Light->GetAttenuationPower(); diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index a5ebc50c..c1b89b5e 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -526,25 +526,6 @@ QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) return editor; } - case PropertyLightFormat: - { - QComboBox *editor = new QComboBox(Parent); - - editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); - editor->setMinimumContentsLength(1); - - QStringList formats = { QLatin1String("Blender"), QLatin1String("POVRay") }; - for (int i = 0; i < formats.size(); i++) - editor->addItem(formats.at(i), QVariant::fromValue(i)); - - int value = Item->data(0, PropertyValueRole).toInt(); - editor->setCurrentIndex(value); - - connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); - - return editor; - } - case PropertyColor: { QPushButton *Editor = new QPushButton(Parent); @@ -830,8 +811,6 @@ void lcQPropertiesTree::slotReturnPressed() { if (Light) { - lcLightProperties Props = Light->GetLightProperties(); - if (Item == mLightAttenuationDistanceItem) { float Value = lcParseValueLocalized(Editor->text()); @@ -896,12 +875,6 @@ void lcQPropertiesTree::slotReturnPressed() Model->SetLightPower(Light, Value); } - else if (Item == lightExponent) - { - Props.mSpotExponent = lcParseValueLocalized(Editor->text()); - - Model->UpdateLight(Light, Props, LC_LIGHT_EXPONENT); - } else if (Item == mLightNameItem) { QString Value = Editor->text(); @@ -962,8 +935,6 @@ void lcQPropertiesTree::slotSetValue(int Value) if (Light) { - lcLightProperties Props = Light->GetLightProperties(); - if (Item == mLightTypeItem) { Model->SetLightType(Light, static_cast(Value)); @@ -972,11 +943,6 @@ void lcQPropertiesTree::slotSetValue(int Value) { Model->SetLightAreaShape(Light, static_cast(Value)); } - else if (Item == lightFormat) - { - Props.mPOVRayLight = Value; - Model->UpdateLight(Light, Props, LC_LIGHT_POVRAY); - } } } } @@ -1101,11 +1067,9 @@ void lcQPropertiesTree::SetEmpty() cameraFar = nullptr; mCameraNameItem = nullptr; - lightConfiguration = nullptr; mLightColorItem = nullptr; mLightPowerItem = nullptr; mLightAttributesItem = nullptr; - lightExponent = nullptr; mLightTypeItem = nullptr; mLightNameItem = nullptr; mLightAttenuationDistanceItem = nullptr; @@ -1118,7 +1082,6 @@ void lcQPropertiesTree::SetEmpty() mLightAreaGridYItem = nullptr; mLightSizeXItem = nullptr; mLightSizeYItem = nullptr; - lightFormat = nullptr; mLightCastShadowItem = nullptr; mPositionItem = nullptr; @@ -1365,8 +1328,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; QString Name = tr("Light"); - QString ExponentLabel = tr("Exponent"); - QString Format, ExponentToolTip; lcLightType LightType = lcLightType::Point; lcLightAreaShape LightAreaShape = lcLightAreaShape::Rectangle; lcVector2 LightSize(0.0f, 0.0f); @@ -1374,11 +1335,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) float Power = 0.0f; float AttenuationDistance = 0.0f; float AttenuationPower = 0.0f; - int FormatIndex = 0; - float Cutoff = 0.0f; - float Exponent = 0.0f; - bool EnableCutoff = false; - bool POVRayLight = false; bool CastShadow = true; lcVector3 Position(0.0f, 0.0f, 0.0f); QColor Color(Qt::white); @@ -1388,10 +1344,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) { Name = Light->GetName(); - POVRayLight = Light->mPOVRayLight; - FormatIndex = static_cast(POVRayLight); - Format = POVRayLight ? QLatin1String("POVRay") : QLatin1String("Blender"); - CastShadow = Light->GetCastShadow(); Position = Light->GetPosition(); Color = lcQColorFromVector3(Light->GetColor()); @@ -1400,49 +1352,15 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) AttenuationPower = Light->GetAttenuationPower(); SpotConeAngle = Light->GetSpotConeAngle(); SpotPenumbraAngle = Light->GetSpotPenumbraAngle(); + SpotTightness = Light->GetSpotTightness(); LightType = Light->GetLightType(); LightAreaShape = Light->GetAreaShape(); LightSize = Light->GetSize(); AreaGrid = Light->GetAreaGrid(); - - switch (LightType) - { - case lcLightType::Point: - ExponentLabel = tr("Exponent"); - break; - - case lcLightType::Spot: - ExponentLabel = tr("Power"); - break; - - case lcLightType::Directional: - ExponentLabel = tr("Strength"); - break; - - case lcLightType::Area: - ExponentLabel = tr("Power"); - break; - default: - break; - } - - if (POVRayLight) - { - Exponent = Light->mPOVRayExponent; - ExponentToolTip = tr("Intensity of the light with typical range of 0 to 1.0."); - } - else - { - Exponent = Light->mSpotExponent; - ExponentToolTip = tr("Intensity of the light in watts."); - } - - ExponentLabel = LightType == lcLightType::Directional ? tr("Strength") : tr("Power"); - SpotTightness = Light->GetSpotTightness(); } - if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType || mPOVRayLight != POVRayLight) + if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType) { SetEmpty(); @@ -1455,7 +1373,7 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightColorItem->setToolTip(1, tr("Color of the emitted light.")); mLightPowerItem = addProperty(mLightAttributesItem, tr("Power"), PropertyFloat); - mLightPowerItem->setToolTip(1, tr("Power of the light in Watts (Blender only).")); + mLightPowerItem->setToolTip(1, tr("Power of the light (Watts in Blender).")); mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool); @@ -1532,12 +1450,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) break; } - lightExponent = addProperty(mLightAttributesItem, ExponentLabel, PropertyFloat); - - // Configuration - lightConfiguration = addProperty(nullptr, tr("Configuration"), PropertyGroup); - lightFormat = addProperty(lightConfiguration, tr("Format"), PropertyLightFormat); - mPositionItem = addProperty(nullptr, tr("Position"), PropertyGroup); mPositionXItem = addProperty(mPositionItem, tr("X"), PropertyFloat); mPositionYItem = addProperty(mPositionItem, tr("Y"), PropertyFloat); @@ -1553,7 +1465,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mWidgetMode = LC_PROPERTY_WIDGET_LIGHT; mLightType = LightType; - mPOVRayLight = POVRayLight; } mFocus = Light; @@ -1607,9 +1518,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightAttenuationPowerItem->setData(0, PropertyValueRole, AttenuationPower); mLightAttenuationPowerItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX)); - lightFormat->setText(1, Format); - lightFormat->setData(0, PropertyValueRole, FormatIndex); - mLightTypeItem->setText(1, lcLight::GetLightTypeString(LightType)); mLightTypeItem->setData(0, PropertyValueRole, static_cast(LightType)); @@ -1625,10 +1533,6 @@ void lcQPropertiesTree::SetLight(lcObject* Focus) mLightSizeYItem->setData(0, PropertyValueRole, LightSize[1]); } - lightExponent->setText(1, lcFormatValueLocalized(Exponent)); - lightExponent->setData(0, PropertyValueRole, Exponent); - lightExponent->setToolTip(1, ExponentToolTip); - switch (LightType) { case lcLightType::Point: diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 25eae636..80f75486 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -49,7 +49,6 @@ class lcQPropertiesTree : public QTreeWidget PropertyStep, PropertyString, PropertyStringList, - PropertyLightFormat, PropertyColor, PropertyPieceColor, PropertyPart @@ -78,7 +77,6 @@ protected slots: void SetMultiple(); lcLightType mLightType; - bool mPOVRayLight; lcPropertyWidgetMode mWidgetMode; lcObject* mFocus; @@ -115,11 +113,9 @@ protected slots: QTreeWidgetItem* cameraFar; QTreeWidgetItem* mCameraNameItem; - QTreeWidgetItem* lightConfiguration; QTreeWidgetItem* mLightColorItem; QTreeWidgetItem* mLightPowerItem; QTreeWidgetItem* mLightAttributesItem; - QTreeWidgetItem* lightExponent; QTreeWidgetItem* mLightTypeItem; QTreeWidgetItem* mLightAttenuationDistanceItem; QTreeWidgetItem* mLightAttenuationPowerItem; @@ -132,7 +128,6 @@ protected slots: QTreeWidgetItem* mLightSizeXItem; QTreeWidgetItem* mLightSizeYItem; QTreeWidgetItem* mLightNameItem; - QTreeWidgetItem* lightFormat; QTreeWidgetItem* mLightCastShadowItem; QTreeWidgetItem* mPositionItem;