Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Swapping multiple scenes #53

Open
cancech opened this issue Oct 12, 2023 · 7 comments
Open

Question: Swapping multiple scenes #53

cancech opened this issue Oct 12, 2023 · 7 comments

Comments

@cancech
Copy link

cancech commented Oct 12, 2023

Greetings,

I am curious to know if it possible to swap between two (or more) 3D scenes, without needing to rebuild/recreate them on access? What I'm imagining is two different scenes, where each scene contains an interactive model. You can click things on the model, and the scene then updates in response (i.e.: click a door and the door opens). What I would like to be able to do,as an end user, is easily/quickly swap between these two scenes without needing to recreate them. For example:

  1. Load app with two scenes (neither scene is displayed)
  2. Access Scene 1, manipulate door (door can be seen open)
  3. Access Scene 2 (Scene 1 is hidden), manipulate window (window can be seen open)
  4. Return to Scene 1 (Scene 2 is hidden), Scene 1 is displayed with the door still open (no reloading of the scene/model is done)
  5. Hide both scenes (neither scene is displayed, but the scene/model is still "ready" to be shown in the future)

Could something of this sort be done? Given how the Viewer and Scene is separated in the example code I can see, I could foresee being doable (viewer.setScene(...)), or perhaps creating two Viewers (one for each scene) and then alternating which one is embedded into the page?

Thanks!

@simutaroman
Copy link
Collaborator

Hi
You can try something like this

<Viewer @ref="View3D1" Scene=scene1  />
...
private Scene scene1 = new Scene();
private Scene scene2 = new Scene();
...
// fill scene 1 and scene 2 with corresponding 3d objects
...
// bind viewer to the corresponding scene to make it visible
    private async Task OnButton1Click()
    {
      View3D1.Scene = scene1;
      await View3D1.UpdateScene();
    }

    private async Task OnButton2Click()
    {
      View3D1.Scene = scene2;
      await View3D1.UpdateScene();
    }

But I have to notice. At this moment Blazor 3D is in the early development stage, so it cannot support all the features of the THREE.js. There is no full synchronization between scene objects on JS side and .NET side. For more info see HomagGroup/Blazor3D#31

@cancech
Copy link
Author

cancech commented Oct 27, 2023

Thanks for the quick response!

Now that I've had the chance to finally sit down and try to play around with this, I'm realizing that I both over-complicated and oversimplified what I need to do. In my situation I need to be able to not "just" swap what scene is visible in the viewer at any given point in time, but rather be able to hide the 3D scene when I don't want/need it. Basically have it appear and disappear at the click of a button. In principle this is something that should be fairly easy to do, as shown in the following

@page "/hidden"
@using HomagGroup.Blazor3D.Viewers

<button @onclick="OnClickHide">@text</button>
<div style="border-style: solid;" hidden="@isHidden">
    <Viewer @ref="viewer" UseDefaultScene=@true></Viewer>
</div>

@code {
    private Viewer viewer = default!;
    private string text = "Hide";

    private bool isHidden = false;
    private void OnClickHide() {
        isHidden = !isHidden;
        text = isHidden ? "Show" : "Hide";
    }
}

And while this works in theory, in practice it only does half of the job. When I click to hide, then the div and contained Viewer are hidden, however when I click to show it again the div reappears but it is empty. The Viewer being either destroyed or at least not reappearing. Any thoughts on why this might be?

Getting to your comment about Blazor 3D being in early development, maybe you can help me understand to what extent it's current state would cover my needs. Ultimately what I'm looking for can be best described as a glorified model viewer:

  1. Display a model
  2. Navigate around the model (rotate / pan / zoom)
  3. Detect clicks on individual meshes within the model
  4. Update meshes in the model (show, hide, rotate, move,... that kind of thing)
  5. Trigger animations contained within the model

Would these kinds of capabilities be available, even if I need to turn to JavaScript to achieve them? So far I've only gotten as far as Example 2 to get my model to successfully appear in the scene (and the viewer in its default state already seems to accomplish most of 2. above).

Thanks again for your quick response, it's much appreciated!

@cancech
Copy link
Author

cancech commented Oct 27, 2023

I've been trying to look into 3. above (detect click on individual meshes within the model), and the closest I've been able to figure out would be to use Viewer.ObjectSelected, but that's only triggering when I click on the Group. I suppose by way of context:

I'm loading a Collada model which contains a group with a series of child meshes. The Group and all child meshes have a name, id, and sid. On import I can see everything (group with all child meshes), though OnObjectLoaded doesn't seem to acknowledge the child meshes? item.Children is empty and ObjectSelected only triggers for the Group. Internally it recognized the click on the child mesh as it produces a Uncaught TypeError: this.INTERSECTED.material.color is undefined but not much else. Strangely as I went to reproduce the exception clicking on one of the meshes made it turn green without the exception and ObjectSelected did get triggered, but that only went on for a few clicks before returning to throwing the exception. Any thoughts on this?

Thanks again!

@simutaroman
Copy link
Collaborator

Thanks for the quick response!

Now that I've had the chance to finally sit down and try to play around with this, I'm realizing that I both over-complicated and oversimplified what I need to do. In my situation I need to be able to not "just" swap what scene is visible in the viewer at any given point in time, but rather be able to hide the 3D scene when I don't want/need it. Basically have it appear and disappear at the click of a button. In principle this is something that should be fairly easy to do, as shown in the following

@page "/hidden"
@using HomagGroup.Blazor3D.Viewers

<button @onclick="OnClickHide">@text</button>
<div style="border-style: solid;" hidden="@isHidden">
    <Viewer @ref="viewer" UseDefaultScene=@true></Viewer>
</div>

@code {
    private Viewer viewer = default!;
    private string text = "Hide";

    private bool isHidden = false;
    private void OnClickHide() {
        isHidden = !isHidden;
        text = isHidden ? "Show" : "Hide";
    }
}

And while this works in theory, in practice it only does half of the job. When I click to hide, then the div and contained Viewer are hidden, however when I click to show it again the div reappears but it is empty. The Viewer being either destroyed or at least not reappearing. Any thoughts on why this might be?

Getting to your comment about Blazor 3D being in early development, maybe you can help me understand to what extent it's current state would cover my needs. Ultimately what I'm looking for can be best described as a glorified model viewer:

  1. Display a model
  2. Navigate around the model (rotate / pan / zoom)
  3. Detect clicks on individual meshes within the model
  4. Update meshes in the model (show, hide, rotate, move,... that kind of thing)
  5. Trigger animations contained within the model

Would these kinds of capabilities be available, even if I need to turn to JavaScript to achieve them? So far I've only gotten as far as Example 2 to get my model to successfully appear in the scene (and the viewer in its default state already seems to accomplish most of 2. above).

Thanks again for your quick response, it's much appreciated!

Hi.
Unfortunately, I have no time to test your code, probably you can see some errors in the browser console. This may help to understand the issue
Try something like this instead:

<div style="border-style: solid;">
@if (!isHidden)
{
    <Viewer @ref="viewer" UseDefaultScene=@true></Viewer>
}
</div>

probably you have to call StateHasChanged when state isHidden == false in your OnClickHide method

@simutaroman
Copy link
Collaborator

I've been trying to look into 3. above (detect click on individual meshes within the model), and the closest I've been able to figure out would be to use Viewer.ObjectSelected, but that's only triggering when I click on the Group. I suppose by way of context:

I'm loading a Collada model which contains a group with a series of child meshes. The Group and all child meshes have a name, id, and sid. On import I can see everything (group with all child meshes), though OnObjectLoaded doesn't seem to acknowledge the child meshes? item.Children is empty and ObjectSelected only triggers for the Group. Internally it recognized the click on the child mesh as it produces a Uncaught TypeError: this.INTERSECTED.material.color is undefined but not much else. Strangely as I went to reproduce the exception clicking on one of the meshes made it turn green without the exception and ObjectSelected did get triggered, but that only went on for a few clicks before returning to throwing the exception. Any thoughts on this?

Thanks again!

The problem is .NET part knows only about root node of imported object. You can find more information here HomagGroup/Blazor3D#31 (in the Examples repository)
Sorry, have no time to do something with this. seratechnl mentioned he would try to resolve this. but I do not know the current state of his work

@cancech
Copy link
Author

cancech commented Oct 30, 2023

Hi. Unfortunately, I have no time to test your code, probably you can see some errors in the browser console. This may help to understand the issue Try something like this instead:

<div style="border-style: solid;">
@if (!isHidden)
{
    <Viewer @ref="viewer" UseDefaultScene=@true></Viewer>
}
</div>

probably you have to call StateHasChanged when state isHidden == false in your OnClickHide method

Unfortunately no errors are raised, and calling StateHasChanged doesn't change anything. I tried what you provided, and while that does work, it triggers the destruction/recreation of the scene when hidden/shown, something that I was hoping to avoid. I have the suspicion/fear that what I'm trying to do is not possible with Three.js (and by extension Blazor 3D).

The problem is .NET part knows only about root node of imported object. You can find more information here HomagGroup/Blazor3D#31 (in the Examples repository)
Sorry, have no time to do something with this. seratechnl mentioned he would try to resolve this. but I do not know the current state of his work

Ok, thanks for the information! I had a hunch that that topic referenced the same issue (or at least was related), I'll look forward to whatever seratechnl comes up with.

@cancech
Copy link
Author

cancech commented Nov 15, 2023

Having some more time to come back and take a look at this, I've found out what the problem is. Everything is "working" in the important sense, however the canvas has a height of 0. When viewed through the Firefox Web Developer Tools Inspector, on initial load (when it can be seen properly) the relevant HTML section is

<div class="viewer3dContainer" id="example1" b-h6holr0slw="">
	<canvas style="display: block; width: 100%; height: 100%; touch-action: none;" data-engine="three.js r143" width="1270" height="635">
	</canvas>
</div>

after hiding and showing it the height is now 0

<div class="viewer3dContainer" id="example1" b-h6holr0slw="">
	<canvas style="display: block; width: 100%; height: 100%; touch-action: none;" data-engine="three.js r143" width="1287" height="0">
	</canvas>
</div>

If I change the height in the Inspector back to 635 is appears as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants