[TOOL] DAEnerys - DAE Ship Editor

It sounds like you might be sending the vertex/index/etc data to the GL pipeline every time the render() call is made. If so, create a VBO/IBO and send the buffered info to the GL pipeline once, when the vertices/indicies are read/calculated/whatever else, and then you can “forget” about it. The only changes that then need to be called in the render() method is updated camera/light positions, and various other positional data.*

*I say all this with the knowledge that I might be completely off-base. It has been a “minute” since I last touched OGL rendering…

Some other points:

  • 50 FPS isn’t that bad (it’s technically all about frame time, or how long it takes to render a single frame [see this article]). What is your monitor refresh rate? Anything above that, and you start to skip rendered scenes.
  • Having not actually looked at your render code, I can only offer pointers, but make sure that everything in that render call is 100% necessary for rendering. The only example that currently comes to mind on things to look for:
  • Are you calling an update to the matrix for the camera in the render code, or is that being done as soon as the camera is updated?

Hope some of this helps…

1 Like

another thing is to tighten the inner loop of the rendering code so that things like setting up buffers and rendering modes are done as far outside of the loop as possible and iterating through meshes and verts/indexs is done with as little extra code as necessary, you may even want to group by rendermodes so that those can be iterated too.


I am doing that in my Update callback, the editor is event-based and not in a loop (due to the Form around it). I am now rewriting the renderer to only update the mesh data when it’s actually changed. Thanks for pointing that out.

60Hz, even without V-Sync, the framerate is horribly low.[quote=“radar3301, post:41, topic:540034”]
Are you calling an update to the matrix for the camera in the render code, or is that being done as soon as the camera is updated?

Another thing to optimize, I’ll fix that. :slight_smile:
Let’s see how much these optimizations help, especially sending the buffered data only if needed.

Good point, I’ll do that when updating the renderer to be able to use several shaders, thanks.


Okay, so here is the new version: Windows x86/x64

Added features

  • All editor visuals now get drawn in front of the ship.
  • Dockpaths now have their own tab with all of their information conveniently displayed.
  • Dockpaths are visualized by a 3d line showing their path and little spheres at the segment points.
  • Markers now have their own tab with a list of them and a checkbox to render them.
  • Added marker size slider.
  • Added clip distance slider.
  • Many internal things.


  • Much better performance (Thanks to @radar3301 and @EvilleJedi).
  • Transformations of nodes fixed, so all joints and other things should be correctly rotated and placed now.
  • Many little things.

Known bugs

  • Some mesh names don’t get loaded correctly.
  • The mouse sometimes goes to a random position after releasing the right mouse button.
  • There is some weird flickering on some meshes (with multiple materials applied to them I think) after I reworked the renderer. All homeworld meshes from the workshop examples I tested work.

Planned features

  • I thought of some 2D icons for displaying navlights and all the other stuff that homeworld ships have. Like these from Unity: image
  • Real-time previews of how dockpaths (and maybe other things) are going to look like in game.
  • Tolerance display of dockpath segments.
  • Lighting shader for navlight previews.
  • Better data display for all the other joints.
  • Troubleshooting help by showing you problems with your DAE. (And fixing them) Like @Xercodo suggested a while ago.
  • Bounding box calculations, in order to scale zoom speed etc. automatically.
  • Editing and exporting of ships.

Note: You won’t be able to see your navlights, engine burns and some other things for now. Because only joints (nodes starting with “JNT”) get displayed in the joints tab. They still get loaded internally though.

So once again, test your ships with this, give me feedback and let me know of your ideas.


Edit: Derp, I found zoom speed

  • I got a crash when trying to load a Nyx, looks like a zero length substring:

    ************** Exception Text **************
    System.ArgumentOutOfRangeException: Length cannot be less than zero.
    Parameter name: length
    at System.String.Substring(Int32 startIndex, Int32 length)
    at Homeworld_Editor.HWNode…ctor(Node node, HWNode parent) in D:\HomeworldEditor\Homeworld Editor\collada\HWNode.cs:line 69
    at Homeworld_Editor.HWNode…ctor(Node node, HWNode parent) in D:\HomeworldEditor\Homeworld Editor\collada\HWNode.cs:line 157
    at Homeworld_Editor.HWNode…ctor(Node node, HWNode parent) in D:\HomeworldEditor\Homeworld Editor\collada\HWNode.cs:line 157
    at Homeworld_Editor.HWNode…ctor(Node node, HWNode parent) in D:\HomeworldEditor\Homeworld Editor\collada\HWNode.cs:line 157
    at Homeworld_Editor.HWScene.LoadCollada(String path) in D:\HomeworldEditor\Homeworld Editor\collada\HWScene.cs:line 59
    at Homeworld_Editor.Main.buttonOpen_Click(Object sender, EventArgs e) in D:\HomeworldEditor\Homeworld Editor\Main.cs:line 115
    at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
    at System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
    at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
    at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
    at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
    at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
    at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
    at System.Windows.Forms.ToolStrip.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

1 Like

Looks like a node has an invalid name (or my importer just messes up on that particular one). Could you send me the .dae please? (without textures)

Also I found that whenever you close and re-open the settings the marker size gets multiplied by ten


  • Set marker size to 8.4x
  • Close settings
  • Reopen settings
  • Marker size is now at 84x

This means that setting a marker size of anything over 10 crashes on the slider being given a value that is outside of the min and max range defined for the control. :smirk:

Here’s the dae: https://www.dropbox.com/s/urfd9p4188ynj2g/gal_nyx.dae?dl=0

But it still has texture on it since I haven’t touched it in a while :neutral_face: Hope that won’t be too much of an inconvenience

Edit: Found that the 10x issue only happens when changing the value, opening and closing the setting window over and over does not change the value.

1 Like

Oops, a bit embarassing xD
I will look at these things tomorrow (4am here), thanks for your input. :slight_smile:
No problem with these textures, I just did not want you to have to upload them.

EDIT: That crash was because of ‘_’ underlines in DOCK node names, I rewrote the parser to handle that.

1 Like

I’m going to suggest something, and I just want to state clearly ahead of time I appreciate and respect work like this from programmers looking to help the community - I got my start in games due to similar work (NPherno’s Skin Tool and NPherno’s MD3 Compiler, etc).

So, some notes:

  • Editing DAE files directly seems easier for some tasks (minor tweaks to nodes, etc) - except that if you’re using Blender or Max, the native formats have data and structure that is lost going to DAE, and not recovered coming back from DAE. If you work in Max, then export to DAE, then edit more, you’re either losing work, forced to duplicate work, or delusional about what the process does to your data.

  • So in that respect, a DAE editor is maybe a mid-process tool for reviewing outputs, and for some people without access to these ‘better’ tools to do some work.

  • A MUCH more useful feature, I think, would be a DAE syntax/layout converter that can take RODOH and Max friendly DAE files and prep them for Blender, either by converting to FBX (I think people presently use some other tool) - or exporting a Blender-friendly DAE file (the details of which I don’t have).

  • The upcoming patch has support for ‘ship patching’ - which will allow DAE files to be generated that HODOR turns in to partial HOD files - things with just replacement textures, markers. The patching system also takes a text file with edits for joints - something that an editor like this would export/import/edit.
    – Imagine loading a ‘base’ DAE (the thing to be patched), and yes it will be possible to get a proxy DAE for any HWRM asset when the new tools are released shortly after the patch, and then loading your ‘patch’ DAE with edits to textures, joints, etc. An editor such as this can crawl the tree and export a ‘patch’ script file with the various differences/additions and let a user work almost entirely in a WYSIWYG manner.


Potentially also useful would be a tool to load a base DAE and an existing patch to sanity check the patch without loading the game.

1 Like

Indeed! And the format is not all that difficult… it is a really simple LUA file with very, very basic syntax. I’ll explain that once the patch itself is public…


I just want to second the notion that a DAE to FBX converter would be amazeballs.

1 Like

FBX->DAE and DAE->FBX, max seems like it handles FBX better in export (not sure about 2015 and newer)

Mainly I am going to use this similar to how I have used CFHOD, export the file from max, convert and then verify the joints and rotations all transitioned right. In this case the DAE and patch loading will allow a pre export check (since post export except for proxy will go away)


"Look at my balls, my balls are amazing…"
Sorry, couldn’t resist :joy:
(and for those afraid that I’ve totally lost my sanity, replace “balls” by “horse” and google it ^^)

1 Like

Glad to be of assistance!

Also, because I’m curious, how much did those changes affect your performance?

I might have a fix for that, if you’re interested. But, I don’t know what you’ve already tried to fix that.

1 Like

I would say about 80% more performance, but it’s still far from perfect, I found many code parts that are highly optimizable. But for now it’s enough. :slight_smile:

Well, I tried some things after I found that bug, but after some minutes I stopped, because it’s not that high on my to-do list.

At the frame when the right mouse button is starting to be pressed, I save the cursor position and hide it.
Then every frame the button is held down, I put it back to it’s starting position.
When the user stops pressing it, the cursor is made visible again.

I use the OpenTK Mouse class to set the cursor position, that method wants absolute pixel coordinates, but the method for getting the position gives me pixel coordinates relative to the GLControl area. So I just added the relative position with the coordinates that Windows Forms gives me. It works sometimes.

Silly question certainly, but why don’t you put it back to it’s starting position only when you make it visible again ? It would prevent updating it every frame, no ?

1 Like

It would hit the screen border, which would cause it to be unable to move, that would prevent you from rotating the camera further.

EDIT: Don’t bother with that too much, I will figure it out sometime.
EDIT 2: Or just let it stay visible and moveable, like in CFHodEd for example.

See, I knew my question was silly ^^
I didn’t think of that problem :slight_smile:

1 Like

The MouseDevice class has getters for absolute x and y positions:

Or use a function closer to the source:

1 Like