Your Home Digital Twin: Interactive floor 3d plan

Hello @mytasker, thanks for sharing, it saves me a little time.
Be advised that the Text feature is not working as expected when you use the glb models exported from Sweethome3d. At least in my case this is not working in my test models.
I’m trying to troubleshoot, as announced earlier and on github , glb is still highly experimental and I cannot guarantee that the glb will work as the obj format.

1 Like

Thanks to you both. However, it’s still not working for me, not with .glb or with .obj files (the code for the latter pasted below):

path: /local/garage-obj/garage-obj/
name: Home
objfile: home.obj
shadow: 'yes'
globalLightPower: '0.8'
header: 'no'
camera_position:
  x: 609.3072605703628
  'y': 905.5330092468828
  z: 376.66437610591277
camera_rotate:
  x: -1.0930244719682243
  'y': 0.5200808414019678
  z: 0.7648717152512469
camera_target:
  x: 37.36890424945437
  'y': 18.64464320782064
  z: -82.55051697031719
entities:
  - entity: switch.shelly_25_garage_light
    type3d: light
    object_id: <gl>
    light:
      shadow: 'yes'
      vertical_alignment: bottom
      color: Khaki
      distance: '325'
      lumens: '700'
      decay: '1.7'
  - entity: sensor.beach_air_temp
    type3d: text
    text:
      font: arial black
      span: '100'
      textbgcolor: yellow
      textfgcolor: black
    action: more-info
    object_id: cabnet2_ec_cover_4
object_groups:
  - object_group: gl
    objects:
      - object_id: '1_15'
      - object_id: '1_2'
      - object_id: '1_3'
      - object_id: '1_4'
      - object_id: '1_5'
      - object_id: '1_6'
      - object_id: '1_7'
zoom_areas:
  - zoom: ''
mtlfile: home.mtl

(By the way, the .glb renderings are much more smooth, as the pictures show, with .glb at the bottom. Not especially the car’s headlights and wheels. The assigned object that should show temperature is the yellow utility box.)

Hey @adizanni

It is working with glb :pray:

I converted my obj to glb as per instructions on the github page

I got it working in an inverted way :upside_down_face:

To fix it, we need to change object settings in SweetHome3D, like this:
Set Location to: Mirrored shape
Orientation: Y axi = 180
image

Now we have it working with glb:

I didn’t change anything my configuration card for it to work:

type: custom:floor3d-card
path: /local/3DHome_lights_v2.3.2
name: Home
objfile: home.glb
shadow: 'yes'
globalLightPower: sensor.global_light_power
header: 'no'
entities:
  - entity: light.livingroom_left
    type3d: light
    action: default
    object_id: livingroom_Light_01
    light:
      lumens: '1000'
  - entity: light.livingroom_right
    type3d: light
    action: default
    object_id: livingroom_Light_02
    light:
      lumens: '1000'
  - entity: light.bulblight_celing_livingroom_01
    type3d: light
    action: default
    object_id: livingroom_Light_03
    light:
      lumens: '1200'
  - entity: light.led_strip_01
    type3d: light
    action: default
    object_id: LED_kitchen_Painting_light
    light:
      lumens: '800'
  - entity: light.light
    type3d: light
    action: default
    object_id: Dining_Light_02
    light:
      lumens: '900'
  - entity: switch.smartplug_bd1_socket
    type3d: light
    action: default
    object_id: BD_G02_Little_lamp
    light:
      lumens: '800'
  - entity: sensor.bedroom_temp_pedro_temperature
    type3d: text
    text:
      font: arial black
      span: '100'
      textbgcolor: transparent
      textfgcolor: black
    action: more-info
    object_id: BD_G02_show_temp_1
  - entity: sensor.bedroom_temp_master_temperature
    type3d: text
    action: more-info
    object_id: BD_master_show_temp_1
    text:
      font: arial black
      span: '100'
      textbgcolor: transparent
      textfgcolor: black
  - entity: sensor.temperature
    type3d: text
    text:
      font: arial black
      span: '75'
      textbgcolor: transparent
      textfgcolor: black
    action: more-info
    object_id: Livingroom_show_temp_1
  - entity: media_player.living_room_tv
    type3d: text
    object_id: Livingroom_Wal_TV_2
    text:
      font: verdana
      span: '75'
      textbgcolor: blue
      textfgcolor: white
      attribute: app_name
    action: more-info
object_groups: []
zoom_areas: []
sky: 'yes'
overlay: 'yes'
extralightmode: 'yes'
show_axes: 'no'
mtlfile: home.mtl
objectlist: home.json
backgroundColor: black
camera_position:
  x: -11.984304091969593
  'y': 1495.5400888589684
  z: 667.1305469670244
camera_rotate:
  x: -1.033797258213751
  'y': -0.0010626773387391617
  z: -0.0017849369731443151
camera_target:
  x: -10.232956403128757
  'y': 79.45558333922764
  z: -175.94629833558608
click: 'yes'
north:
  x: 0.01
  z: null

@FortranFour
Try this:
Instead of using a object group, try to use one part of the object - just the panel where you want to display the info.

This should help you guys.

Cheers

Very happy with the results.

I had to re-do my lights as glb doesn’t like this light source:
image

I added this one and hided all the parts leaving only be bulb visibled:
image

I wil test more things Andy.
But for now, I’m happy with what is already working.

cheers :wink:

Very well spotted and brillant workaround. I think I need to solve it in the code to be sure I get to a iso experience between obj and glb at least for the model generation flows that I support (plugin to obj to glb).

Yes @FortranFour, @mytasker suggestion is correct. You need to stick a frame object on top of the box and bind the “text” entity to the frame. If you bind it to the box, the face where the text is written is unpredictable.

1 Like

Hello @FortranFour,

I suggest you test everything first with obj before moving to glb. If it works in glb it will work also in obj, viceversa is not always true. Also there are some object renaming when converting to glb using the method I have described causing additional collateral effects.

  • Overlays is a feature that I will probably discontinue in future releases. I cannot make it work smoothly and it come quite ugly.

  • Text: as explained in previous posts if you use obj, be careful to use a plane object (like a frame) on top of the object where you want the text to appear. If you use the glb, for the moment you need to apply the workaraound described by @mytasker

  • Rotate: never tested in glb. In obj you may have some problem to identify the hinge object (it is the object whose center axis is rotating)

  • Cover: never tested in glb. In obj I have seen some roller shutters in SweetHome3d not working because of the way they where composed and grouped. Your cover entity moving up and down should work

I will do some more testing and troubeshooting next week-end. I had a busy schedule latetly…

But thanks to your encouragement I will try to find some spare time.

1 Like

Hey Andy,
I tested Rotate with glb and I can resume saying it is working.

Just some tips:

In this picture
Door 1: Open and close - when the Aquara door sensor is triggered to open, it changes its color to Red, if close it goes back to the iroginal color (or whatever color you want - I love this option in the card)

Windows 2 an 3: It is sliding up and set it to Red that represents it is open (I can’t find the proper window with SweetHome3D - I had to improvise a mix of windows to get the job done)

Door 4: ahh door four- it was fun to discover this:
Door 4 has the hinge to rotate “no problem”, but it is made of a single frame that covers 2 doors and a non movable panel using the same entity name. When trying to open the 2 doors and having the hinges set correctly (like door 1), everything rotates.
This is not a problem with obj or glb. But, the object is using a single frame for everyting. I hope it makes sense.

Look from the top:
Yellow: not supposed to move
Purple: the door(s)
Both share the same frame name: Livingroom_Triple_French_window_1_2


Even if the frame was diffent, you would find another problem with the glasses as they share the same name: Livingroom_Triple_French_window_1
Again, this isn’t a limitation with Andy’s AWESOME job by exporting and importing obj or glb.
Exporting obj or glb, both keeps the object properties no changes found
This is the object properties limitation?!?!?! I guess!?!?!
I will choose a different door. Not a problem for me at all.
But I thought it would be nice to share it here.
Don’t get furstrate, just think out of the box and do it again - Better!

For the garage door, I just slid it down:
image image
Aaaand garage door sorted.
If you guys have any sugestion for a good site to download object that we can: open, close, roll and all the bits and bobs you know. Please share with us.

Do you have any example of “overlay” that I could test Andy?

I will keep test what I can on my side.
Once again, Thanks a lot for this awesome card.

PS: my previous post, you can see which windows I was using and they have the same issue as the door, the single frame (painted in green for you guys to have an idea) and glass

Cheers :wink:

I had a problem with the hinges. The way I have solved it is by defining in SH3D a pair of overlapping windows, one open and one closed, for each of the 2 windows I have on the roof.

In next picture there are 2 closed windows (say Velux1Closed# and Velux2Closed#)

In next picture there are 2 open windows (Velux1Open# and Velux2Open#)

          - entity: binary_sensor.sensor_velux_1
            type3d: hide
            object_id: Velux1Closed
            hide:
              state: 'on'
          - entity: binary_sensor.sensor_velux_1
            type3d: hide
            object_id: Velux1Open
            hide:
              state: 'off'
          - entity: binary_sensor.sensor_velux_2
            type3d: hide
            object_id: Velux2Closed
            hide:
              state: 'on'
          - entity: binary_sensor.sensor_velux_2
            type3d: hide
            object_id: Velux2Open
            hide:
              state: 'off'

Hope that helps.
Cheers,
us

3 Likes

Andy,

Eventually, yesterday evening, I’ve done some glb tests on my house.
I am speechless.
The rendering time drops down from 10 seconds for obj format, to something under 1 second for glb. Almost instantly.
I could even see it on my phone where obj was impossible to use.
I will collect some old tablets around the house and check them.

So far I could see some problems, but nothing critically:

  1. Object name is different in glb vs obj, for example:
    SH3D object name, say, LivingLight#
    obj object name LivingLight
    glb object name LivingLight_1_1

  2. SH3D invisibleBox doesn’t work with glb.
    It can be replaced using various tricks, though.

  3. I reckon this one is a bug. The image appears dark.
    globalLightPower doesn’t seem to work with glb.

  4. To preserve shiness use --specularGlossiness flag when convert from obj to glb, as in:
    obj2gltf --checkTransparency --specularGlossiness -i home.obj -o home.glb

I’ll do further testing.

Cheers,
us

Hello @uss thanks again for testing. I think that the only way for supporting glb correctly will be to either integrate the conversion in the ExportToHASS plugin or to make a significant change in the card, having a post-loader function specific for glb. The 2 solutions I can only afford when I will start working in v2.0 (I’m still stuck, only branched the code and done some modelling work on paper).

The problem 1 is known and I think it is the same as described in this issue Grouped/Nested Objects positioned wrong · Issue #110 · adizanni/floor3d-card · GitHub. The use case is different but it raised the fact that, in glb, objects with different material cannot be grouped.

Problem 2 is new for me.

Problem 3 is a known one and I do not know how to make the globalLightPower act on glb (the ambient is working but not the torchlight).

Point 4, thanks I will check that option.

Andy.

I may be totally wrong or maybe I did not get your problem, but I have the impression that based on the name of the objects you are still not using the SweetHome3D plugin GitHub - adizanni/ExportToHASS: Sweethome3D Plugin for Home Assistant Export . If you use the plugin you should end up with different object names for each of the components and using the object groups you should be able to separate the moving parts from the static parts…

I started to put a gallery of objects in this repo GitHub - adizanni/3DResources but I did not really have time to make it better. There are a lot of free catalog of objects (.obj) in the net.

Hope that I’m not frustrating you, because I have not loaded fix since a while. The work on glb seems to be daunting and I’m pushing it to v2.0, but I have not yet really started

1 Like

I think Andy had advised giving all the objects in SH3D unique names, so I just serially numbered all the objects, as integers. The numbers are preserved when rendered either as .obj or .glb (with the exception of one or two multicomponent pieces of furniture), so that, for the most part, I didn’t have to change anything moving back and forth between the two formats.

I did confirm that my problem with the text was not using a frame, but instead incorrectly expecting that any planar surface would work.

I still haven’t got ceiling fans to rotate though. I’ve used both fan models that come with SH3D and tried each of the components (in .obj) as a hinge. The moving parts simply disappear when conditionally switched on. If you happen to have a working example, that’d be great.

As far as I can tell the name difference in glb vs obj has nothing to do with the name itself. The fact that you have numbers instead of letters doesn’t change anything.

@adizanni
From the experiments I have done, I came to following conclusions:

  1. obj2gltf sometimes appends _1 or _1_1 to objects sometimes not. I might be wrong, but It looks like objects with a single material doesn’t get suffix, objects with more than one material get.
    On the other hand, the loading in Floor3D itself appends a suffix.

  2. The problem with invisibleBox is a obj2gltf bug;

  3. I manage to get an acceptable view (not ideal) by adding the line:

        this._renderer.outputEncoding = THREE.sRGBEncoding;

here

      } else if (fileExt == "glb") {
        //glb format
        this._renderer.outputEncoding = THREE.sRGBEncoding;
        const loader = new GLTFLoader().setPath( path );
        loader.load(
          this._config.objfile,
          this._onLoadedGLTF3DModel.bind(this),
          this._onloadedGLTF3DProgress.bind(this),
          function (error: ErrorEvent): void {
            throw new Error(error.error);
          },
        );
        this._modeltype = ModelSource.GLB;
      }

but this is not quite right. I need to read more.

Important note:
I gave up using obj2gltf due to bugs shown. Instead I use Online 3D Viewer to convert to glb. It produces objects names without suffix and there’s no transparentBox bug.
The import and export routines are not three’s but written ones.
But once glb loaded in Floor3D objects names get a suffix
Btw., the obj and glb images are identical in Online 3D Viewer.

us

Hello @adizanni! Loving this card, great job! I am, however, having issues with the gesture type. I’ve seen comments here using that functionality and my configs are similar, if not equal. Yet, I can’t get any of my integrated devices or even scripts to toggle when clicking objects on the model. I’ve tried with .obg/.mtl and .glb versions of my floor plan, with no positive results. Any idea what it could be?

Here’s my test config, using the default model:

type: custom:floor3d-card
path: /local/community/floor3d-card/
name: Home
objfile: home.glb
shadow: 'yes'
globalLightPower: '0.8'
header: 'no'
camera_position:
  x: 609.3072605703628
  'y': 905.5330092468828
  z: 376.66437610591277
camera_rotate:
  x: -1.0930244719682243
  'y': 0.5200808414019678
  z: 0.7648717152512469
camera_target:
  x: 37.36890424945437
  'y': 18.64464320782064
  z: -82.55051697031719
object_groups:
  - object_group: RoundTable
    objects:
      - object_id: Round_table_1
      - object_id: Round_table_2
      - object_id: Round_table_3
  - object_group: EntranceDoor
    objects:
      - object_id: Door_9
      - object_id: Door_7
      - object_id: Door_5
entities:
  - entity: switch.wall_switch_932f
    type3d: gesture
    object_id: Bed_140x190_10
    gesture:
      domain: switch
      service: toggle
zoom_areas:
  - zoom: ''

My previous issue with windows rotating on the axis was a user error :smiley:
I had previously removed from doors and windows the “#” inside SWhome3D.
But, that especifc door and windows was exported as a group for some reason (again my mistake).
No exporting it corrcetly I can move/select each item.
About what USS said, here is an example
On the left is an glb file exported via obj2gltf and it append an extra _1 after the name.
On the right is an obj exported via Andy’s inside SWhome3D and it does not have the extra _1.

I have 4x chair on my dinning table, each one set to be grouped by the character "#. I didn’t border to change the name and left it just as “chair”

coverting obj via obj2gltf, the glb file will name treat each chair as an individual object by naming it with the exta _4, _5, _6 and _7. It does not expose all parts of the chair and keep it grouped, but it adds the extra numbers to identify each objet.

obj: on the other side, exposes only one “chair”.

So, I don’t think it is a bug, but just how the export was writen to treat each object parts.

@uss, I got this windows working as we wanted:

image

As long we don’t export the objet grouped by the character “#” (I know, you know that, but important to remember any new user reading this, and I made this mistake in my previous post)

You can try this:
Set the hinge to be these selected object id:
in my case I renamed the window to Turnwindow01
So, my hinge object id is: Turnwindow01_5
As you can see per picutre, 10% is enough to open it nicely.

  - entity: binary_sensor.doorsensor_01_contact
    type3d: door
    door:
      doortype: swing
      pane: Turnwindow01_9
      hinge: Turnwindow01_5
      direction: outer
      degrees: '10'
    object_id: <tun-windowdoor_01>

  - object_group: tun-windowdoor_01
    objects:
      - object_id: Turnwindow01_5
      - object_id: Turnwindow01_6
      - object_id: Turnwindow01_7
      - object_id: Turnwindow01_8
      - object_id: Turnwindow01_9

I hope this work for you as well.
And I got my double doors fixed :wink:

1 Like

@mytasker
Thank you for your example.

I have roughly 1500 # objects in my house model.
The original version of the house took more than 40 seconds to load as obj. And that is on a supercomputer.
Thus I try to keep each object to a minimum. I had to redesign most of the objects.As an example, all my windows have no frame.
With this and other tricks, I managed to go down to less than 11 seconds to load obj model.
With glb it goes further down to under 1 second, almost instantly.
Of course, rasterize time.
That is why I am very interested in glb.
With more than 40 lights, 25 HVAC controllers, 30 cameras and 50 door/window sensors (to name just the important ones) it is difficult to change the object to entity link when object names change.

If one imports obj in Online 3D Viewer and exports it as glb, opening the exported glb in Online 3D Viewer shows the object names (meshes names) preserved (btw. all of my objects are #).
Let apart the loading time I could see no difference between obj and glb, neither in names or aspects of the objects, nor in colors, with a single exception, glossiness is lost.
That means there is no reason for any suffix to be appended.

Digging further into Online 3D Viewer import code shows the imports are done programmatically.
Not as in Andy’s Floor3D where GLTF loader is imported from ‘three/examples/jsm/loaders/GLTFLoader’.
Now, in order to insure having unique node names (and not only node names), THREE GLTFLoader uses the following function:

createUniqueName( originalName ) {
	const sanitizedName = PropertyBinding.sanitizeNodeName( originalName || '' );
	let name = sanitizedName;
	for ( let i = 1; this.nodeNamesUsed[ name ]; ++ i ) {
		name = sanitizedName + '_' + i;
	}
	this.nodeNamesUsed[ name ] = true;
	return name;
}

That’s why Floor3D appends those ‘_x’ suffixes.

us

PS:
obj2gltf has the following function used when reads obj file:

function setDefaultNames(items, defaultName, usedNames) {
  const itemsLength = items.length;
  for (let i = 0; i < itemsLength; ++i) {
    const item = items[i];
    let name = defaultValue(item.name, defaultName);
    const occurrences = usedNames[name];
    if (defined(occurrences)) {
      usedNames[name]++;
      name = name + "_" + occurrences;
    } else {
      usedNames[name] = 1;
    }
    item.name = name;
  }
}
2 Likes

Hello @BIMMS-JGraca, I have tested right now and it is working for me in any condition. When you do not specify click: ‘yes’ in the parameter, the gesture action is triggered by double-click.

Hello @uss,

it could be a good idea to use the Online Viewer (at least the loader libraries) for the card v2.0.
On the other hand it creates and additional dependency not sure if it is actively maintained.
I’m trying to use the libraries developed in https://github.com/oguzhancevik/obj2gltf to add a gltf exporter in the Sweethome plugin but it is significant effort.

I renew my proposal to co-work to this card as I’m reaching my limits in terms of time and skills.

Andy