Unit X3DLoad

Description

Loading and saving nodes.

Almost every format is handled by converting it into VRML / X3D nodes graph. This allows to use nodes throughout the engine, for all rendering and processing.

Basic guide for adding a new format:

  • Particular formats are implemented inside various X3DLoadInternalXxx units. Implementation of this unit calls them. In the future, a mechanism that allows you to "register" an importer, without modifying this unit's implementation, may be done — report if needed.

  • Scene formats are also listed in the file filters constants: see LoadScene_FileFilters . Each format has a file filter to specifically choose this format, and also is added to the "All Scenes" filter.

  • Enable castle-model-viewer to associate with this file format on freedesktops (GNOME, and other following freedesktop.org specs). For this,

    1. Update castle-model-viewer MIME database. Simply add appopriate element to ../../../castle-model-viewer/freedesktop/castle-model-viewer.xml. Format of that MIME xml file is self-explanatory. It's good idea to google first to search for standard MIME type for your model format (e.g. wikipedia shows mime types for formats). If none is found, just use application/x-???, where ??? is some short name for your format.

    2. After adding to MIME database, you want to also add format to ../../../castle-model-viewer/freedesktop/castle-model-viewer.desktop, to indicate that castle-model-viewer handles this MIME type.

    3. Finally, also add this to ../../../castle-model-viewer/freedesktop/install_thumbnailer.sh, so that GNOME nautilus thumbnailers for this MIME types can be installed.

  • You probably also want to extend documentation. At least https://castle-engine.io/creating_data_model_formats.php , it lists all supported scene formats.

Uses

Overview

Classes, Interfaces, Objects and Records

Name Description
Class TModelFormat Information about a model format, used with RegisterModelFormat.

Functions and Procedures

function LoadNode(const Url: String): TX3DRootNode; overload;
function LoadNode(const Stream: TStream; BaseUrl: String; const MimeType: String): TX3DRootNode; overload;
procedure SaveNode(const Node: TX3DRootNode; const Url: String; const Generator: String = ''; const Source: String = ''); overload;
procedure SaveNode(const Node: TX3DRootNode; const Stream: TStream; const MimeType: String; const Generator: String = ''; const Source: String = ''); overload;
function LoadScene_FileFilters: String;
function SaveNode_FileFilters: String;
procedure RegisterModelFormat(const ModelFormat: TModelFormat);

Types

TModelLoadEvent = function (const Stream: TStream; const BaseUrl: String): TX3DRootNode;
TModelSaveEvent = procedure (const Node: TX3DRootNode; const Stream: TStream; const Generator: String; const Source: String);

Constants

DefaultBakedAnimationSmoothness = 1;

Variables

BakedAnimationSmoothness: Single = DefaultBakedAnimationSmoothness;

Description

Functions and Procedures

function LoadNode(const Url: String): TX3DRootNode; overload;

Load a scene as X3D node. Guesses scene format based on the URL extension. We load a large number of formats, see https://castle-engine.io/creating_data_model_formats.php .

All the scene formats are loaded as a graph of X3D nodes.

URL is downloaded using the CastleDownload unit, so it supports files, http resources and more. See https://castle-engine.io/manual_network.php about supported URL schemes. If you all you care about is loading normal files, then just pass a normal filename (absolute or relative to the current directory) as the URL parameter.

To actually display, animate and do many other things with the loaded model, you usually want to load it to TCastleScene, using the TCastleSceneCore.Load method. Like this:

var
  RootNode: TX3DRootNode;
  Scene: TCastleScene;
begin
  RootNode := LoadNode('my_model.x3d');
  Scene := TCastleScene.Create(Application);
  Scene.Load(RootNode, true);
  // The 2nd parameter of Load says that Scene owns RootNode
end;

Actually, in most cases you don't need to use LoadNode (and this unit, X3DLoad) at all, and you can simply load from an URL:

var
  Scene: TCastleScene;
begin
  Scene := TCastleScene.Create(Application);
  Scene.Load('my_model.x3d');
  // you can access Scene.RootNode after loading, if needed
end;

Note that usually you want to load models from the game data, so you would actually use 'castle-data:/my_model.x3d' URL instead of 'my_model.x3d'.

function LoadNode(const Stream: TStream; BaseUrl: String; const MimeType: String): TX3DRootNode; overload;

Load a scene as X3D node from TStream.

Takes a TStream instance with contents to load, and MimeType parameter determines the data content (e.g. X3D or glTF or Spine model).

In most cases, instead of this, you should use a simpler LoadNode overloaded version that just takes URL parameter without the explicit Stream or MimeType parameters. It will automatically create the stream and guess MIME type.

The BaseUrl parameter here is used to resolve relative URLs inside the model, e.g. references to textures from various 3D and 2D model formats are resolved relative to this base URL. It generally should be a URL from which you downloaded the model. If you don't know it, you can use the current directory (which can be conveniently expressed by BaseUrl = '', which is a relative empty URL implying current working dir). We do not use BaseUrl to determine file contents (e.g. we don't look at filename extension here) in this routine.

Note that some formats (like glTF) require a stream with free seeking capabilities. Call Download with soForceMemoryStream, or wrap the stream in TMemoryStream manually, if unsure. The overloaded LoadNode without explicit TStream uses soForceMemoryStream when necessary.

Note that this routine assumes that the stream is not gzip-compressed. The overloaded LoadNode without explicit TStream accounts for gzip-compressed streams in some cases.

procedure SaveNode(const Node: TX3DRootNode; const Url: String; const Generator: String = ''; const Source: String = ''); overload;

Save model to a file.

See SaveNode_FileFilters for all model formats that we can save.

If you provide explicit URL, it determines the output format. If you provide a Stream and MimeType, then MimeType determines the output format. E.g. use MimeType = 'model/x3d+vrml' to X3D classic encoding, or MimeType = 'model/x3d+xml' to X3D XML encoding.

Parameters
Generator
Optional name, or short description, of the application generating this file. This value is not interpreted in any way, it is simply a "metadata" information we may store in the resulting file.
Source
Optional name of the original file, if this file is a result of some conversion or transformation. This value is not interpreted in any way, it is simply a "metadata" information we may store in the resulting file.
procedure SaveNode(const Node: TX3DRootNode; const Stream: TStream; const MimeType: String; const Generator: String = ''; const Source: String = ''); overload;

This item has no description.

function LoadScene_FileFilters: String;

File filters for files loaded by TCastleSceneCore.Load and LoadNode. Suitable for TFileFilterList.AddFiltersFromString and TCastleWindow.FileDialog.

function SaveNode_FileFilters: String;

File filters for files saved by SaveNode. Suitable for TFileFilterList.AddFiltersFromString and TCastleWindow.FileDialog.

procedure RegisterModelFormat(const ModelFormat: TModelFormat);

Register given model format, to enable loading and/or saving it using LoadNode, SaveNode and all routines on top of them, like TCastleSceneCore.Load.

The ModelFormat instance given here becomes owned by the internal list in this unit. Do not free it, do not modify it after registering it.

Here's an example how to register a new model format, USD. This example assumes you want to register the new model format in the initialization section of a unit, which is the most common place, as it ensures that the format is registered for any future use in the application.

function LoadUSD(const Stream: TStream; const BaseUrl: String): TX3DRootNode;
begin
  Result := TX3DRootNode.Create;
  // TODO: Load USD here
end;

var
  ModelFormat: TModelFormat;
initialization
  ModelFormat := TModelFormat.Create;
  ModelFormat.OnLoad := {$ifdef FPC}@{$endif} LoadUSD;
  ModelFormat.MimeTypes.Add('model/vnd.usda');
  ModelFormat.MimeTypes.Add('model/vnd.usdz+zip');
  ModelFormat.FileFilterName := 'Universal Scene Description';
  ModelFormat.Extensions.Add('.usd');
  ModelFormat.Extensions.Add('.usda');
  ModelFormat.Extensions.Add('.usdc');
  ModelFormat.Extensions.Add('.usdz');
  RegisterModelFormat(ModelFormat);

  UriMimeExtensions['.usd'] := 'model/vnd.usda';
  UriMimeExtensions['.usda'] := 'model/vnd.usda';
  UriMimeExtensions['.usdc'] := 'model/vnd.usda';
  UriMimeExtensions['.usdz'] := 'model/vnd.usdz+zip';
end.

Types

TModelLoadEvent = function (const Stream: TStream; const BaseUrl: String): TX3DRootNode;

This item has no description.

TModelSaveEvent = procedure (const Node: TX3DRootNode; const Stream: TStream; const Generator: String; const Source: String);

This item has no description.

Constants

DefaultBakedAnimationSmoothness = 1;

This item has no description.

Variables

BakedAnimationSmoothness: Single = DefaultBakedAnimationSmoothness;

A smoothness value for "baked" animations loaded from castle-anim-frames files. This is multiplied by the scenes_per_time value recorded in castle-anim-frames file (30 by default), and determines the number of extra frames we add to the baked animation (between key frames).


Generated by PasDoc 0.16.0-snapshot.