Menu

1 scene, multiple models

smo
2018-05-15
2018-05-21
  • smo

    smo - 2018-05-15

    Hello,

    I want to be able to load multiple models in 1 castlecontrol/scene. What is the best way to achieve this ?

    Sidenote:
    As far as I can see you have to create 1 "world", then you can add/import multiple models into this world ?

    Models are randomly chosen (with a dialogue box).

    The loaded models should stay "seperate". I mean, I want to create a treeview structure so I can set the visibility for each loaded model as needed (visible/not visible) with a checkbox.

    Models are x3d (or vrml). Models should be able to be placed in the world with differrent coördinates (x, y, z) by a dialogue box and rotation (for now Y- only). Also the possiblity to move/rotate the models after import.

    WORLD
    |
    |- - Model 1
    |
    |- - Model 2
    |
    |- - Model 3
    |
    | etc. ...

    So I hope this gives a more clear idea on what I will try to achieve, any thoughts/hints/tips ?

    Thanks

     
  • EugeneLoza

    EugeneLoza - 2018-05-15

    The simplest way to do this is to use TSwitchNodes:

    var
      Root: TX3DRootNode;
      Scene: TCastleScene;
      Models: array[0..5] of TSwitchNode;
    
    procedure LoadModelsAndBuildScene;
    begin
      Root := TX3DRootNode.Create;
      for i := 0 to 5 do
      begin
        Models[i] := TSwitchNode.Create.FdChildren.Add(Load3D(SomeModelURL[i]));
        Models[i].WhichChoice := 0;
        Root.Children.Add(Models[i]);
      end;
      Scene := TCastleScene.Create;
      Scene.Load(Root);
      CastleControl1.SceneManager.Add(Scene);
      CastleControl1.SceneManager.MainScene := Scene;
    end;
    
    procedure ToggleModelInVisible(ModelNumber: integer);
    begin
      Models[ModelNumber].WhichChoice := -1;
    end;
    
    procedure ToggleModelVisible(ModelNumber: integer);
    begin
      Models[ModelNumber].WhichChoice := 0;
    end;
    
     

    Last edit: EugeneLoza 2018-05-15
  • Michalis Kamburelis

    The Switch node is used to show one (at most) node from a number of children. It is a good solution when the number of your models is predefined at start, and you only want to show one (or none) at a given time.

    If you want to freely show/hide each model independently, and if you want to add/remove/transform models at runtime at zero cost, I would rather use a number of TCastleScene instances :)

    The code would look like the most basic example on https://castle-engine.io/manual_load_3d.php . You can just create as many instances of TCastleScene as you like, and add/remove them from the world by CastleControl1.SceneManager.Items.Add / Remove.

    procedure AddAnotherScene(const URL: string);
    var
      AnotherScene: TCastleScene;
    begin
      AnotherScene := TCastleScene.Create(Application);
      AnotherScene.Load(URL);
      AnotherScene.Spatial := [ssRendering, ssDynamicCollisions];
      AnotherScene.ProcessEvents := true;
      CastleControl1.SceneManager.Items.Add(AnotherScene);
    end;
    

    Note that each Scene may be trasformed (see the TCastleTransform properties like Translation, Rotation, Scale). Each Scene has Exists: boolean property to instantly hide/show it.

    See also https://castle-engine.io/manual_scene.php and https://castle-engine.io/apidoc/html/CastleTransform.TCastleTransform.html .

    A simple demo of this is on https://github.com/castle-engine/castle-engine/blob/master/examples/3d_rendering_processing/scene_manager_demos.lpr .

     
  • smo

    smo - 2018-05-16

    Thanks for helping out guys, loading multiple x3d's works fine !

    But, as expected, few additional questions:

    • How can such a multi-model be saved ?
      Save3d(CastleControl1.SceneManager.MainScene.RootNode, CastleSaveDialog1.URL); does not seem to work
    • Some bigger models take some time to load, and of course the multi model will take some time to save. Is there some feedback from the loading/saving procedure to assign to a progressbar (or something similar) ? Or does the castle engine has is own progressbar that can be configured ?
     
    • Michalis Kamburelis

      Save3d(CastleControl1.SceneManager.MainScene.RootNode, CastleSaveDialog1.URL);

      Indeed it should work, as Eugene writes. It can actually be shortened to "CastleControl1.SceneManager.MainScene.Save(CastleSaveDialog1.URL)".

      But note that it will only save one scene (the one set as MainScene). If you use the suggestion from my post (the one with AnotherScene), then you will have many scenes, so it will not be enough.

      We do not have any format for saving multiple scenes (yet -- we will introduce such format when creating CGE editor later this year :) ). To save multiple scenes, you have to save them yourself for now. You will probably just want to save URL, Translation, Rotation for each scene. You can invent any save format you like, e.g. txt file, xml file etc. and use standard FPC/Pascal utilities to write it. If you choose to write XML file, we have some helpers in CastleXMLUtils. We also have helpers to convert vectors from/to strings (like TVector3.ToString method, Vector3FromStr), these should be useful in case TXT or XML formats.

      Or does the castle engine has is own progressbar that can be configured ?

      Indeed we have our own progress bar UI, as Eugene writes. It is automatically used by some operations... but it's most comfortable when you use TCastleWindow. It's somewhat less useful with TCastleControl, in which case you need to create and manually control a TCastleProgressBar user-interface class.

      Since you will be controlling this progress bar yourself, you can as well just use any Lazarus control to display a progress.

       
  • EugeneLoza

    EugeneLoza - 2018-05-16

    Save3d(CastleControl1.SceneManager.MainScene.RootNode, CastleSaveDialog1.URL); does not seem to work

    Hmmm... strange, it should work. Does CastleSaveDialog1.URL contain a valid value?

    Is there some feedback from the loading/saving procedure to assign to a progressbar (or something similar)

    Try this one: https://castle-engine.io/apidoc/html/CastleProgress.TProgress.html and its output may be routed to https://castle-engine.io/apidoc/html/CastleControls.TCastleProgressBar.html

     
  • smo

    smo - 2018-05-16

    About the saving, if I try with one model, it gives an error:

    SIGSEGV: in file '...\src\x3d\castlescenecore.pas' at line 2795
    which refers to this:

    procedure TCastleSceneCore.Save(const AURL: string);
    begin
      if RootNode <> nil then
        Save3D(RootNode, AURL, ApplicationName);
      FURL := AURL;
    end;
    

    with this button to save:

    procedure TForm1.Button2Click(Sender: TObject);
    begin
      if CastleSaveDialog1.Execute then
        CastleControl1.SceneManager.MainScene.Save(CastleSaveDialog1.URL);
    end;
    
     
  • Michalis Kamburelis

    About the saving, if I try with one model, it gives an error:

    This probably means that the CastleControl1.SceneManager.MainScene is nil (it was not initialized, or the scene was freed later). Check CastleControl1.SceneManager.MainScene <> nil earlier. In general, we would have to see the whole code to tell why it is nil :)

    As my previous answer says, it is also possible that you don't want to save the contents of the scene. It really depends what you want to save. If you do not edit the scene contents, then calling Save3D or TCastleSceneCore.Save is not what you want. Instead, you want to save, for each scene, it's URL (string), Translation (TVector3), Rotation (TVector4) etc. -- to your own, custom save file.

     

    Last edit: Michalis Kamburelis 2018-05-16
  • Anonymous

    Anonymous - 2018-05-16

    Hello Michalis,

    Probably you are right about saving the link to model and transformations in a seperate file.
    I will have a look at that later this week.

     
  • smo

    smo - 2018-05-20

    A general question about the enigne's 'space specifications'. Just to understand the workflow better.

    The space in the engine is limitless ? (distances in X, Y Z are limitless ?)

    What "start" point uses the engine when you load a model ? Does it loads at xyz= 0,0,0 ? And does it centers the model ? Or does it take the coördinates (if included) of a model into account ?

     
  • Michalis Kamburelis

    The space in the engine is limitless ? (distances in X, Y Z are limitless ?)

    There are no special limits on distances placed by Castle Game Engine.

    That said, nothing is really "limitless" on existing computers with finite memory :) As we represent most distances using the Single type, your distances should fit within it's range, which is huge: 3.4 × 10^38 (see https://www.freepascal.org/docs-html/ref/refsu5.html , https://en.wikipedia.org/wiki/Single-precision_floating-point_format ). Moreover, be aware that these are floating points -- which, roughly speaking, means that calculations are always approximate, and they are more approximate when using larger numbers.

    Usually you do not worry about these limits, and can assume that things are limitless. There isn't much software that deals with larger distances anyway :)

    What "start" point uses the engine when you load a model ? Does it loads at xyz= 0,0,0 ? And does it centers the model ? Or does it take the coördinates (if included) of a model into account ?

    The TCastleScene.Translation and TCastleTransform.Translation is initially always 0,0,0. Loading a scene (using TCastleScene.Load) doesn't change the TCastleScene.Translation.

    You decide (when creating the model in Blender, Spine, etc.) how is the model placed with respect to the point 0,0,0. You can design the model centered around 0,0,0, or hovering over 0,0,0 -- it's all up to you, and every 3D/2D model designer will show you this.

    We do not shift the loaded contents in any way, we do not automatically recenter it. That would be unexpected for most use-cases. (You can always recenter it yourself, doing something like Scene.Translation := -Scene.LocalBoundingBox.Size / 2;).

     
  • smo

    smo - 2018-05-21

    Very clear, thanks for explaining :)

     

Anonymous
Anonymous

Add attachments
Cancel