Jump to content
The Dark Mod Forums

OrbWeaver

Active Developer
  • Posts

    8650
  • Joined

  • Last visited

  • Days Won

    67

Posts posted by OrbWeaver

  1. On 1/23/2023 at 7:27 PM, motorsep said:

    Is there an LWO exporter that works with Blender 3.4.1 ? 

    As far as I know the most up-to-date one is the script I maintain (there is a single tdm_export script which supports both ASE and LWO export). However I haven't specifically tested with the latest Blender 3.4 series, so it's possible that it will need an update.

    On 1/23/2023 at 7:53 PM, stgatilov said:

    As far as I remember, the engine drops smoothing information from LWO file and applies automatic determination of smooth groups depending on some hardcoded angle.
    So I'm not sure these smoothing settings will help in TDM or Doom 3.

    I believe this information is out of date. The problem of LWO losing smoothing information was caused by the Blender exporter itself ignoring object-specific data and enforcing a hard-coded smoothing angle. This is now fixed in my latest version, although the old behaviour is selectable at the time of export if you don't want to deal with object smooth groups. As far as I can recall, when I was testing this, the smoothing options did take effect in the engine (although I couldn't say whether they were 100% mathematically correct).

    • Like 1
  2. Would you be able to attach or upload the map (or any other map which shows the same issue, if you don't want to share a WIP)?

    Even if the map has become corrupted, we ought to be able to handle this more gracefully and perhaps recover whatever data we can read even if some is missing. Under no circumstances should we hard crash regardless of what sort of corruption is in the map file.

  3. 4 hours ago, stgatilov said:

    I think @OrbWeaver tried to load precompressed RGTC in TDM recently and failed, and after that we fixed something.

    This was the relevant SVN change:

    r9525 | orbweaver | 2021-07-30 21:17:43 +0100 (Fri, 30 Jul 2021) | 11 lines
    
    Use correct format for uploading precompressed ATI2 normal maps
    
    When the 'ATI2' FOURCC is seen in a precompressed DDS file, use the
    GL_COMPRESSED_RG_RGTC2 internal format (matching the behaviour of
    image_useNormalCompression on uncompressed source images). The legacy code was
    using GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT.
    
    This is enough to get plausible looking normal maps with DDS files exported in
    3Dc/BC5 format using the GIMP DDS plugin. Not tested with files exported from
    any other tools; it is conceivable that other FOURCCs might need handling too.

    Note in particular the comment about this only being tested with the GIMP DDS plugin, and that formats used by other tools might need additional changes.

  4. This exact behaviour can be created using a blendLight using the blend filter blend mode.

    The light becomes a volume which simply multiplies (darkens) its projected texture with the texture of contained objects, almost like a 3D volumetric decal.

    • Like 4
  5. The actual crash occurs on this line of LightInspector.cpp:

       85  	void LightInspector::shaderSelectionChanged()
       86  	{
       87  	    // Get the selected shader
    -> 88  	    auto ishader = _texSelector->getSelectedShader();

    The _texSelector member is still NULL here, so this is a segfault.

    The initialisation of _texSelector happens in setupTextureWidgets(), which is called unconditionally in the LightInspector constructor, so a missing method call is not the issue. However, the value of _texSelector is a newly-constructed MaterialSelector object, and this object takes a function pointer to the shaderSelectionChanged() in its constructor:

        _texSelector = new MaterialSelector(parent,
                                            std::bind(&LightInspector::shaderSelectionChanged, this),
                                            MaterialSelector::TextureFilter::Lights);

    It appears that this is creating a race condition: the constructor of MaterialSelector is able to call the shaderSelectionChanged callback (presumably as a result of selection changes during its Populate() method), but it isn't actually safe to call shaderSelectionChanged() until after the MaterialSelector is fully constructed and assigned to the _texSelector member.

    I think my preferred solution would be to remove the "selectionChanged" function parameter to the MaterialSelector constructor entirely, and replace it with a public signal_selectionChanged() which client code could connect to. This would have two advantages:

    1. No possibility of race condition, since you would have to construct the MaterialSelector before connecting to the signal.
    2. Signals are more powerful than manual std::function callbacks (e.g. they can auto-disconnect if the target object is destroyed) and are widely used throughout the codebase.

    However, if anything currently relies on receiving selectionChanged callbacks during the MaterialSelector construction, this would no longer work. @greebo what do you think?

    • Thanks 1
  6. On 11/16/2022 at 10:07 PM, stgatilov said:

    Why do you think so?

    Apple deprecated OpenGL but never removed it.
    I think they still support 4.1, which is enough for TDM currently.

    Looks like I jumped the gun slightly. It doesn't seem to have been completely removed, but has been deprecated for several versions. Knowing Apple, I will be very surprised if they don't eventually remove it altogether in a few versions time.

  7. On 11/4/2022 at 3:57 AM, greebo said:

    I would have assumed that the assertion wouldn't fire if existingIndex == -1 since that is also < tab count. At any rate, if existingIndex == -1 at this point in the code either the addControl or findControlIndexByName seem to have failed. Can you step through it and figure out what goes wrong? Is addControl failing?

    I've done more debugging, and it seems like it is FindPage() that is failing for reasons which are unclear. It even fails immediately after the page is added in addControl(), i.e.

        bool succ = AddPage(content, control->getDisplayName(), false, tabIconIndex);
        wxASSERT(succ); // succeeds
        wxASSERT(FindPage(content) != wxNOT_FOUND); // FAILS

    I guess this means one of two things:

    1. A bug in Ubuntu's wxWidgets 3.0.x package (it wouldn't be the first time), or the GTK wxWidgets build more generally.
    2. A false assumption in our code about when/how wxAuiNotebook::FindPage() is able to work. For example, perhaps it only works once the AUI interface has actually been displayed on the screen, rather than during the setup process.

    EDIT: I wonder if it is this bug: https://github.com/wxWidgets/wxWidgets/issues/15932

    I can armour restoreState() against passing an invalid index to GetPage() and friends, which avoids the assertion, but then I have multiple copies of every tab in the group widget. On the other hand, I can completely disable the contents of restoreState() and everything looks fine with all tabs present and correct (although I presume any changes to tab layout wouldn't be preserved), so I wonder if it's even necessary for restoreState() to add new tabs at all?

  8. 17 hours ago, greebo said:

    I would have assumed that the assertion wouldn't fire if existingIndex == -1 since that is also < tab count.

    It looks like GetPageCount() and GetPage() are working with size_t indices which (on Linux) are equivalent to unsigned int, so I guess this is wrap-around behaviour.

    17 hours ago, greebo said:

    At any rate, if existingIndex == -1 at this point in the code either the addControl or findControlIndexByName seem to have failed. Can you step through it and figure out what goes wrong? Is addControl failing?

    Yes, it's very strange that the index should be -1 immediately after the page was added — I'll do more debugging and see if I can find out which function call isn't working as expected.

    • Thanks 1
  9. I'm also seeing an assertion failure, although it doesn't seem to have anything in common with what other people have posted. This appears at startup before the main window is shown, and appears to be fatal (attempting to Continue just produces the same assertion again).

    ASSERT INFO:
    ../src/aui/auibook.cpp(2270): assert "page_idx < m_tabs.GetPageCount()" failed in GetPage().
    
    BACKTRACE:
    [1] wxAuiNotebook::GetPage(unsigned long) const
    [2] sigc::internal::signal_emit0<void, sigc::nil>::emit(sigc::internal::signal_impl*)
    [3] sigc::signal0<void, sigc::nil>::emit() const
    [4] module::ModuleRegistry::loadAndInitialiseModules()
    [5] radiant::Radiant::startup()
    [6] wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&)
    [7] wxEvtHandler::SearchDynamicEventTable(wxEvent&)
    [8] wxEvtHandler::TryHereOnly(wxEvent&)
    [9] wxEvtHandler::ProcessEventLocally(wxEvent&)
    [10] wxEvtHandler::ProcessEvent(wxEvent&)
    [11] wxEvtHandler::ProcessPendingEvents()
    [12] wxApp::DoIdle()
    [13] g_main_context_dispatch
    [14] g_main_loop_run
    [15] gtk_main
    [16] wxGUIEventLoop::DoRun()
    [17] wxEventLoopBase::Run()
    [18] wxAppConsoleBase::MainLoop()
    [19] wxEntry(int&, wchar_t**)
    [20] __libc_start_main
    
    

    More info from LLDB (since the built-in stacktrace seems to miss out a lot of function calls):

        frame #10: 0x00007ffff6a9eeca libwx_gtk3u_aui-3.0.so.0`wxAuiNotebook::GetPage(unsigned long) const + 106
        frame #11: 0x0000555555d4f768 darkradiant`ui::PropertyNotebook::restoreState(this=0x000055555611c490) at PropertyNotebook.cpp:264:34
        frame #12: 0x0000555555d3f7b6 darkradiant`ui::AuiLayout::restoreStateFromRegistry(this=0x0000555557179c10) at AuiLayout.cpp:654:36
        frame #13: 0x0000555555d46817 darkradiant`ui::MainFrame::construct(this=0x00005555560c53a0) at MainFrame.cpp:271:38
        frame #14: 0x0000555555d46680 darkradiant`ui::MainFrame::postModuleInitialisation(this=0x00005555560c53a0) at MainFrame.cpp:211:11
        frame #15: 0x0000555555d4c024 darkradiant`sigc::bound_mem_functor0<void, ui::MainFrame>::operator(this=0x0000555556cd1258)() const at mem_fun.h:1991:48
        frame #16: 0x0000555555d4ba80 darkradiant`sigc::adaptor_functor<sigc::bound_mem_functor0<void, ui::MainFrame> >::operator(this=0x0000555556cd1250)() const at adaptor_trait.h:256:20
        frame #17: 0x0000555555d4b22c darkradiant`sigc::internal::slot_call<sigc::bound_mem_functor0<void, ui::MainFrame>, void>::call_it(rep=0x0000555556cd1220) at slot.h:483:35
        frame #18: 0x0000555555aec9e2 darkradiant`sigc::internal::signal_emit0<void, sigc::nil>::emit(impl=0x0000555556a31300) at signal.h:798:79
        frame #19: 0x0000555555aee4a8 darkradiant`sigc::signal0<void, sigc::nil>::emit(this=0x0000555556163398) const at signal.h:2804:32
        frame #20: 0x00007fffeba2acfb libradiantcore.so`module::ModuleRegistry::loadAndInitialiseModules(this=0x0000555556163320) at ModuleRegistry.cpp:192:32
        frame #21: 0x00007fffeba8bc87 libradiantcore.so`radiant::Radiant::startup(this=0x00005555562af760) at Radiant.cpp:97:58
        frame #22: 0x0000555555be315f darkradiant`RadiantApp::onStartupEvent(this=0x00005555560a4660, ev=0x00005555562dc8d0) at RadiantApp.cpp:230:30

    This is the actual line of code which fails in PropertyNotebook.cpp. It seems that existingIndex is actually -1 here.

    assertion.png.1a36203343673e9c6487f7e92f422c43.png

  10. I don't see how DoF can possibly work in a game which isn't tracking your eyes. How does the game know what you are looking at? Your eyes could be focussed anywhere on screen, which might show objects at a variety of distances. If the depth is taken from the central aim point, that means that instead of just moving your eyes to look at something on screen, you'd also need to move the mouse to remove the artificial blur.

    DoF looks nice in photos, and as stgatilov says it might work in a VR simulation with eye tracking, but for a 2D image on a standard screen I can't see it adding any value.

    • Like 3
  11. On 10/27/2022 at 11:41 AM, Xolvix said:

    Just make sure it's rewritten using Rust, that's what all the cool kids are using these days apparently.

    I'm a big fan of Rust. It's an well-designed language with excellent tooling. But it doesn't have great GUI support yet (although there are a few toolkits available), and integrating it into a larger C++ application is non-trivial (although possible).

    Designing a new loader from scratch in Rust with an Electron-based front-end — that might actually be possible, although it would probably need somebody with more than my beginner-level Rust knowledge.

    • Like 1
  12. 7 hours ago, greebo said:
    • Feature: More customisable layout, all windows and panes can be dragged and arranged
    • Layouts like Embedded, Regular and Splitpane are superseded and have been removed

    An excellent step forward. After the recent discussion in one of the newbie threads about limitations of the dockable layout, I was actually wondering whether and when should look into this, but you're way ahead of me as usual.

    • Like 1
    • Thanks 1
  13. 22 hours ago, greebo said:

    Of course it's possible to fundamentally change the way DR is handling manipulations and selections, but for every such change you'll probably face differing opinions and/or resistance.

    I actually had a go at this myself once, but found it far too difficult. Personally I too hate the default input style, particularly the requirement to constantly hold down modifiers just to select things, but changing the defaults just breaks too much stuff because the selection system isn't designed to work that way.

    In order to allow "normal" selection rules, we would also need:

    • A different method to create a new brush (since left-drag is now a selection or manipulation operation), for example something like Blender's Shift+A shortcut.
    • A different way to resize brushes. Currently dragging anywhere outside the brush performs a resize, but if clicking/dragging on empty space is supposed to define a new selection, this will no longer work. So we would need something like traditional resize handles instead of the planar dragging approach.
    • The selection system to decide what operation is being performed after the initial click or drag starts (as Greebo already mentioned).
    • [Optional but almost certainly necessary] A system for setting up alternative keyboard profiles so people could choose between classic Radiant selection or the new system, since not everybody would agree with the changes.
  14. On 10/13/2022 at 6:11 PM, greebo said:

    About the drag-and-drop: this is another problem that seems to affect wxGTK only... in Windows, I can drag the layer to the top border of the view and it will deliver an empty target wxDataViewItem, which means make it toplevel - in wxGTK it doesn't seem to be possible to drag it to the top.

    The odd thing is that GTK itself can clearly distinguish the two cases, because I see different "drop destination lines" when dragging to the top of the view (one line above) versus dragging onto the first layer (one line above and one line below).

    On 10/13/2022 at 6:11 PM, greebo said:

    (*) Yes, there's a guard in the wxGTK event handler:

    wxDataViewItem item(GetOwner()->GTKPathToItem(path));
    if ( !item )
       return FALSE;

    this prevents any empty item from being forwarded to the event.

    So wxWidgets itself is actually swallowing up the event, even though it would actually be useful and consistent with the Windows behaviour, and the purpose of wxWidgets is for creating cross-platform UIs? I can't really see the logic of that, but I guess it was probably introduced to fix some bug without really considering the consequences.

    Quote

    Add a context menu item called "Make Top-Level"

    My suggested UI would be to add a couple of buttons (which are more discoverable than a context menu), perhaps next to the existing rename and delete buttons since the New button already has more than enough width. One button would move the selected layer up by 1 in the hierarchy, and the other would move it all the way to the top.

    • Like 1
  15. To be honest I can't remember ever using TAB to choose between items in a group. I certainly wasn't aware of it when writing the user guide, which is why the section on converting to func_static mentions using TAB, but the section on grouping doesn't. But it would certainly be useful and consistent behaviour.

×
×
  • Create New...