Print at Dec 19, 2025, 7:45:01 AM
Posted by sjb007 at Jun 17, 2022, 12:38:16 PM
Add "o" to OBJWriter output
https://sourceforge.net/p/sweethome3d/feature-requests/1084/

Could we please have a minor (I hope) change to the OBJWriter so we can have much cleaner imports into blender, and maybe other applications.

Simply needs a line at the start of each SH3D object in the export file:
o <name>

And that gives a single object in blender per object in SH3D, instead of the current situation where even a simple section of wall results in 6 seperate objects in blender.

Posted by sjb007 at Jun 17, 2022, 3:06:59 PM
Re: Add "o" to OBJWriter output
Oh, and I just checked the FreeCAD obj import, and that also can import "o" as individual objects.

Posted by Daniels118 at Jun 17, 2022, 4:07:04 PM
Re: Add "o" to OBJWriter output
the current situation where even a simple section of wall results in 6 seperate objects in blender.

For real? Which version of SH3D are you using?
I'm using 6.6a and I get no "o" lines in the exported object, so the whole home is seen as a single object when importing into blender. Am I missing something?

Posted by Keet at Jun 17, 2022, 10:35:54 PM
Re: Add "o" to OBJWriter output
If I'm not mistaking every "g" in the OBJ file is a separate object when importing into Blender. At least that is what I get when importing an object into Blender. SH3D OBJ exports have the g groupings.
According to the OBJ specifications:
Grouping:
g Group name
s Smoothing group
mg Merging group
o Object name

----------------------------------------
Dodecagon.nl
1300+ 3D models, manuals, and projects

Posted by Keet at Jun 17, 2022, 11:00:03 PM
Re: Add "o" to OBJWriter output
I did a little test by exporting a single wall. The OBJ file has 6 g groups, as it should, because you want to be able to apply a texture to each "side". A single piece of wall is just like a box.

Adding an o object name changes nothing when importing into Blender, the same 6 object parts remain the same.

The only way to get a single object into Blender would be to merge all g groupings into a single g group. I haven't tested this but I suspect that you loose the separate textures.

From my point of view a single object in Blender is virtually useless, you want things to be as separated as possible because it allows you to manipulate them individually.
----------------------------------------
Dodecagon.nl
1300+ 3D models, manuals, and projects

Posted by sjb007 at Jun 18, 2022, 12:50:00 AM
Re: Add "o" to OBJWriter output
Allow me to elaborate. Blender (I'm on 3.1) has options when importing obj files. (Gear cog, top right). There is an expander panel named "Geometry". These affect how the data is interpreted. You can select between Split, and Keep Vert Order.

The "Keep Vert Order" option will create a single object. If "Poly Groups" is on it will create vertex groups in the object based on the "v" labels that allow you to select parts of the mesh. This has some specific useful use case I read somewhere, but not very interesting for us SH3D users.

Under "Split" is the bit I/we are interested in.
If you only select "Split by Object", it will create a single blender mesh object per "o" label in the obj file.
The "Split by Group is maybe the default (I lost track as I've edited my blender importer python code.) On it's own you get blender objects based on "v" labels. If you combine it with "Split by Object" you will still get an object per "v" but the naming convention is "<o-label>_<v-label>".

All the above is observable with the example "with o" test file in the linked ticket.

Simply adding the "o <o-label>" will make SH3D and Blender work really nice together.

I'm currently trying to modify the blender import to add the option to have the best of both worlds:
"Split by Object" + new "Group to Vertex Groups" (yeah the name isn't great). The idea is that each "o" in the obj file create a seperate blender object, and each of the sub "v" groups create a blender vertex group under that object. This allows you to easily select or operate on the seperate parts of the mesh. Think of a bed, with the pillows and duvets as seperately selectable vertex groups. I'm kind of stuck at the moment because the vertex group code uses an array of vertices and indexes to reference them. Unfortunately when you "Split by Object" it appears the vertices indices change, so the vertex groups don't work.

I hope that cleared up any misunderstanding.

Posted by sjb007 at Jun 18, 2022, 12:53:46 AM
Re: Add "o" to OBJWriter output
the current situation where even a simple section of wall results in 6 seperate objects in blender.

For real? Which version of SH3D are you using?
I'm using 6.6a and I get no "o" lines in the exported object, so the whole home is seen as a single object when importing into blender. Am I missing something?


In case it wasn't clear I exported an obj file, and manually added the "o" to test the theory, and it works. Theree's an attachment in the linked ticket that has the "with o" test file I've been experimenting with.

If you get a single object, you need to examine the options as I mention in my previous comment. You likely have "Keep Vert Order" selected.

Posted by sjb007 at Jun 18, 2022, 1:25:00 AM
Re: Add "o" to OBJWriter output
A couple of other quick thoughts on possible additions to the blender obj importer to improve SH3D -> Blender:

  • A scale factor to resize the import, because SH3D and Blender use very different units, and I'm bored of resizing objects.
  • This one is really "out there" and I'm not sure I understand Blender well enough to implement... The "o" name could use a name with a "splitter character", and the split parts (except the last) could be used to create a nested collection tree. Then if SH3D set "o" to "<level-label><split-char><object-label>"... You could have objects divided up into levels in Blender.


Posted by Daniels118 at Jun 18, 2022, 8:12:45 AM
Re: Add "o" to OBJWriter output
@sjb007
(Gear cog, top right). There is an expander panel named "Geometry"

You're right! I did expand the gear button, but I didn't see the "geometry" accordion... my poor eyes!
Thank you!

I agree with you about having the "o" lines, splitting by geometry produces too many entries (even door handles gets separated), many of which have poor names.

P.S. after importing, all the imported objects are selected by default. Just type "s.01" and press enter to scale down 100 times (centimeters -> meters).

Posted by sjb007 at Jun 18, 2022, 3:29:54 PM
Re: Add "o" to OBJWriter output

P.S. after importing, all the imported objects are selected by default. Just type "s.01" and press enter to scale down 100 times (centimeters -> meters).

Oh, I know how to scale. That's five key presses! "Ain't nobody got time for that!"... more seriously, when you are doing the import 50 times trying to figure out how in the hell the importer works, it does get tedious.

Posted by sjb007 at Jun 19, 2022, 4:31:35 AM
Re: Add "o" to OBJWriter output
Just so no one else wastes time, I've added the vertex groups and scaling to the blender obj import. Limited tests, but looks good.

I've written a provisional, untested patch for SH3D that I think will do the "o" entry. I'm not a Java dev but can sort of understand it, so it looks correct. I don't yet have Eclipse/JDK installed in order to try building it. That's the next job.

After that (if can figure it out) I might try and implement the idea of putting imported objects into a tree of blender containers based on Level and furniture groups (idea 2 in my earlier message). No promises on that one though.

Posted by sjb007 at Jun 19, 2022, 10:13:00 PM
cool   Re: Add "o" to OBJWriter output
OK, so Java is horrible. Bloomin' strange lingo. My untested attempt did not work at all. Many iterations and tests later...

I have gotten furniture being named, and even prefixed by the level name, with the "|" character as a seperator. It imports into blender perfectly.

Walls and rooms still need attention to prefix with their level name in the same way. Additionally Rooms have names, so I'll add that. Maybe I should separate the walls and rooms into sub-collections of the level... might be nice for organisation.

I haven't yet started to look at the bit to get Blender to create collections based on the level name, and make the objects a child of the level/collection. That is Python (which I'm way better at than Java) so it will just be a bit of a dive trying to understand the Blender API.

And now a question for the people familiar (and, unlike me, competent) with the Java code: Is it possible to check/get the parent groups from a HomePieceOfFurniture? I'm thinking the group hierarchy could be also turned into sub-collections. i.e.
<kitchen-level>|<island-group>|<tall-chair-group>|<tall-chair-01>
<kitchen-level>|<island-group>|<tall-chair-group>|<tall-chair-02>
<kitchen-level>|<island-group>|<tall-chair-group>|<tall-chair-03>

I'm not decided whether the SH3D groups should become sub-collections or be done with parent objects. Parent Objects would behave more like SH3D.

Posted by Daniels118 at Jun 20, 2022, 9:45:26 AM
Re: Add "o" to OBJWriter output
Is it possible to check/get the parent groups from a HomePieceOfFurniture?

I'm quite sure you can't get the parent directly. However you can get the child from the parent, so you can iterate over all groups to build a child->parent map, and use it later to query the parent from the child.
Keep in mind that groups can be nested, so if you want to recreate the hierarchy you have to prepend the parent name in a loop until the object has no more ancestors.
Another approach could be to retrieve the objects using Home.getSelectableViewableItems(), which returns all the non-grouped objects + the groups, then you can itearate over the items and if you find a group dive into it using a recursive method.

Posted by sjb007 at Jun 20, 2022, 1:37:52 PM
Re: Add "o" to OBJWriter output
Is it possible to check/get the parent groups from a HomePieceOfFurniture?

I'm quite sure you can't get the parent directly. However you can get the child from the parent, so you can iterate over all groups to build a child->parent map, and use it later to query the parent from the child.
Keep in mind that groups can be nested, so if you want to recreate the hierarchy you have to prepend the parent name in a loop until the object has no more ancestors.
Another approach could be to retrieve the objects using Home.getSelectableViewableItems(), which returns all the non-grouped objects + the groups, then you can itearate over the items and if you find a group dive into it using a recursive method.

I was afraid of that, but good to have better eyes than mine confirm it. Guess I have to figure out more Java-isms. Ugh. At least the HomePane.OBJExporter class already has code to iterate through the objects using getSelectableViewableItems/getSelectedItems. Reading the code the structure looks flat, so there shouldn't need to be any recursion. Just create a HashMap child:parent, then loop over the hashmap to build the parent groups when creating the full "path". Nothing too complicated.

So when I get the SH3D bit finished, would you mind taking a look over it? It'll be pretty short as patches go, but I'm sure I've done some bits in bad way. (i.e. that there is a Javonic way, just like there is a Pythonic way, and I'm forcing Pythonic style into Java. biggrin )

Posted by sjb007 at Jun 20, 2022, 2:35:17 PM
Re: Add "o" to OBJWriter output
Reading the code the structure looks flat, so there shouldn't need to be any recursion. Just create a HashMap child:parent, then loop over the hashmap to build the parent groups when creating the full "path". Nothing too complicated.

Ha! Spoke too soon. That getAllFurniture does the descent for you, returning a flattened list of furniture, buggering up my first attempt at group nesting.

Posted by Daniels118 at Jun 20, 2022, 6:06:57 PM
Re: Add "o" to OBJWriter output
So when I get the SH3D bit finished, would you mind taking a look over it?

For sure. One question: are you planning to build a plugin or a derived version of the main program?

Posted by sjb007 at Jun 21, 2022, 1:37:33 AM
Re: Add "o" to OBJWriter output
So when I get the SH3D bit finished, would you mind taking a look over it?

For sure. One question: are you planning to build a plugin or a derived version of the main program?


I refer you to my previous comments regarding my lack of Java skills confused I now have it working perfectly, but I've done it by hacking on chunks of HomePane.java and OBJWriter.java.

I wouldn't know how to separate it to make a plugin, but I guess I can take a look at the guide. Maybe I can figure it out. I definitely wouldn't do a derived version as in my own version of SH3D, not for such a minor feature. I was thinking of submitting it as a patch to the ticket I raised in SF.

The only thing I can see to change now is to have rooms separate the floor and ceiling, otherwise you can't easily see the aerial view without messing around. That a nice to have, and first I have to get the collection division working in Blender. Back to lovely Python, ahhh... and the Blender API, AHHHHHGGGGHHHH!

Mostly this is scratching an itch I have. I need to get some planning grade diagrams. My path currently is going to be SH3D -> Blender (model finessing) -> FreeCAD (using the Technical Draw workbench for 1:50 scale plans, elevations and sections. I could use Blender further for the prettied up 3D renders.

If FreeCAD proves uncooperative I have the option of exporting from Blender to SketchUp, and holding my nose and Stumping up for the Pro version that includes Layout which also does good elevations, sections etc., but £235 per year is a bit rich just to get access to Layout.

Posted by sjb007 at Jun 21, 2022, 2:21:05 AM
Re: Add "o" to OBJWriter output
So if anyone wants to take a look or have a test, the first version is posted as a diff against the 6.6 source.

To be clear: This is only partially useful until I finish the Blender Python importer.

What this will do: All Walls, Rooms, and Furniture will get "o" entries.

The entries are "|" delimited which will (when I finish) give structure through collections in Python. i.e.
<levelheight-levelname>|<group_name>|...|<subgroup_n_name>|<item_name>

Where an item has multiple meshes "g" (very common) they can be optionally turned into blender vertex groups for easy selection.

Posted by Daniels118 at Jun 21, 2022, 11:08:53 AM
Re: Add "o" to OBJWriter output
The only thing I can see to change now is to have rooms separate the floor and ceiling, otherwise you can't easily see the aerial view without messing around

For anyone wondering, this can be wordarounded in Blender by simply turning on backface culling for the ceiling material.

An alternative could be to export each room 2 times as 2 separate objects, one with both ceiling and floors, and one with floor only (the Room3D constructor has a ignoreCeilingPart parameter that can be used for this purpose).

The third option is to use the second option, with the addition to select only the ceiling node:
Room3D room3D = new Room3D(room, home, false, true);
Node floor = room3D.getChild(0);
writer.writeNode(floor);
if (room.isCeilingVisible()) {
Node ceiling = room3D.getChild(1);
writer.writeNode(ceiling);
}


Posted by sjb007 at Jun 22, 2022, 4:55:16 PM
Re: Add "o" to OBJWriter output
For anyone wondering, this can be wordarounded in Blender by simply turning on backface culling for the ceiling material.

An alternative could be to export each room 2 times as 2 separate objects, one with both ceiling and floors, and one with floor only (the Room3D constructor has a ignoreCeilingPart parameter that can be used for this purpose).

The third option is to use the second option, with the addition to select only the ceiling node:
Room3D room3D = new Room3D(room, home, false, true);
Node floor = room3D.getChild(0);
writer.writeNode(floor);
if (room.isCeilingVisible()) {
Node ceiling = room3D.getChild(1);
writer.writeNode(ceiling);
}

Once again making a bid for Most Valued Player I see. wink

That was very helpful, although I've slightly modified the idea. Floors and Walls are entirely separate, and members of separate collections, so I can hide ceilings in one tap.

I've posted the first real proof of concept to the ticket in comment 1 of this thread. It all works perfectly on my 90 MB exported obj file. It would be useful if some others could give it a try and see if it works for them.

I just had the thought that the reverse could be done. Blender export to obj, and a special mode for SH3D to reimport. Roundtripping between the two. But I'm not think about that right now.

I am still thinking about the plugin idea, but I just don't know if I have the Java chops to be able to do that.

I'm noticing quite a few issues in Blender with flipped normals. This makes backface culling look quite bad, and tends to butcher the textures/smoothing. I'm not sure if this is poor quality models, the export, or the import. Whatever it is, it is not my code, because I'm not monkeying around with that stuff.

Posted by sjb007 at Jun 22, 2022, 4:57:00 PM
Re: Add "o" to OBJWriter output
@Daniels118 Oh, and if you could look at the java changes and tell me all the Java conventions I blew through, I'd appreciate it.

Posted by Daniels118 at Jul 9, 2022, 7:55:57 PM
Re: Add "o" to OBJWriter output
Sorry for late response. I looked at the changes and they seems ok, but you know it's up to Emmanuel to decide wether to merge or not into the main stream.
If you decide to make it a plugin you could consider to override the OBJWriter instead of duplicate the whole code. This is how I managed to obtain this result for another project I'm working on:
public class LDObjWriter extends OBJWriter {
private boolean firstNode = true;
private boolean separateObjects = false;

public boolean isSeparateObjects() {
return separateObjects;
}

public void setSeparateObjects(boolean separateObjects) {
this.separateObjects = separateObjects;
}

@Override
public void writeNode(Node node) throws IOException, InterruptedIOException {
writeNode(node, null);
}

@Override
public void writeNode(Node node, String nodeName) throws IOException, InterruptedIOException {
if (firstNode) {
super.writeNode(null, null);
firstNode = false;
}
if (separateObjects && nodeName != null && !nodeName.isEmpty()) {
this.out.write("o " + nodeName + "\n");
}
super.writeNode(node, nodeName);
}

public void newObject(String name) throws IOException {
if (firstNode) {
super.writeNode(null, null);
firstNode = false;
}
this.out.write("o " + name + "\n");
separateObjects = false;
}
}


Posted by Keet at Jul 9, 2022, 9:00:57 PM
Re: Add "o" to OBJWriter output
Last week I discovered the usefulness of the o line in an obj file. I had to bisect a complex set of objects and I couldn't do that because all of the g groups and no o object. So I added the line manually and it still didn't work until I flagged all g lines as remarks. That gave a single object in Blender but of course had the disadvantage of no more g groups.

Rereading the posts in this thread I went looking for the gear to change settings when importing and after I switched of groups just the o line was enough to allow selection of a single object, which I needed for bisecting and still retain the g groups.

Big vote here to add o line(s) to the obj export. I manage to create very complex furniture with just SH3D but there a few things it can't do that sometimes are needed.
----------------------------------------
Dodecagon.nl
1300+ 3D models, manuals, and projects

Posted by sjb007 at Dec 11, 2022, 8:33:09 PM
Re: Add "o" to OBJWriter output
@Daniels118 "Resurrectus threadius!"

I've picked this back up, got Eclipse installed, done the plugin tutorial, and have a vague idea how I can turn this into a plugin.

As I said <points at self> clueless Javamateur. I had a look at a couple of plugins, and I see yours looking all purty! You have a bunch of the boilerplate stuff all squared away. Can I ask your permission to shamelessly and liberally borrow that stuff and adapt it for my needs? It will save me a ton of time scratching my head that can be better spent getting the meat of the plugin to work.

Posted by Daniels118 at Dec 12, 2022, 10:01:58 PM
Re: Add "o" to OBJWriter output
Hi Stephen, all my plugins are licensed under GPL, so you are free to reuse all the code as long as you respect the terms (keep it open source, under GPL, and cite the author).