| Description | Hierarchy | Fields | Methods | Properties |
type TVRMLFlatScene = class(TObject)
This class represents a VRML scene (that is, graph of VRML nodes rooted in RootNode) deconstructed to a list of TVRMLShapeState objects. The basic idea is to "have" at the same time hierarchical view of the scene (in RootNode) and a flattened view of the same scene (in ShapeStates list).
Unfortunately this means that things get a little more complicated if you want to dynamically change the scene. Although whole TVRMLNode class works very nicely and you can freely change any part of it, add, delete and move nodes around and change their properties, this is no longer so easy with TVRMLFlatScene. Basically you can just call ChangedAll after changing some things inside RootNode, but you should also take a look at other Changed* methods defined here.
In exchange, this class provides many functionality and most things work very quickly if the scene is more-or-less static. E.g. methods [Local]BoundingBox, Vertices/TrianglesCount cache their results so after the first call to TrianglesCount next calls to the same method will return instantly (assuming that scene did not changed much). And the ShapeStates list is the key to various processing of the scene, most important it's the key to write a flexible OpenGL renderer of the VRML scene.
Also, VRML2ActiveLights are magically updated for all states in ShapeStates list. This is crucial for lights rendering in VRML 2.0.
![]() |
constructor Create(ARootNode: TVRMLNode; AOwnsRootNode: boolean); |
![]() |
destructor Destroy; override; |
![]() |
function BoundingBox: TBox3d; |
![]() |
function VerticesCount(OverTriangulate: boolean): Cardinal; |
![]() |
function TrianglesCount(OverTriangulate: boolean): Cardinal; |
![]() |
procedure ChangedAll; virtual; |
![]() |
procedure ChangedShapeStateFields(ShapeStateNum: Integer); virtual; |
![]() |
procedure ChangedFields(Node: TVRMLNode); |
![]() |
function Info(InfoTriVertCounts, InfoBoundingBox: boolean): string; |
![]() |
procedure WritelnInfoNodes; |
![]() |
function CreateTriangleOctree(const ProgressTitle: string): TVRMLTriangleOctree; overload; |
![]() |
function CreateTriangleOctree(AMaxDepth, AMaxLeafItemsCount: integer; const ProgressTitle: string): TVRMLTriangleOctree; overload; |
![]() |
function CreateShapeStateOctree(const ProgressTitle: string): TVRMLShapeStateOctree; overload; |
![]() |
function CreateShapeStateOctree(AMaxDepth, AMaxLeafItemsCount: integer; const ProgressTitle: string): TVRMLShapeStateOctree; overload; |
![]() |
function GetViewpoint( out CamKind: TVRMLCameraKind; out CamPos, CamDir, CamUp, GravityUp: TVector3Single; const ViewpointDescription: string = ''): TNodeGeneralViewpoint; |
![]() |
function GetPerspectiveViewpoint( out CamPos, CamDir, CamUp, GravityUp: TVector3Single; const ViewpointDescription: string = ''): TNodeGeneralViewpoint; |
![]() |
procedure EnumerateViewpoints(ViewpointFunction: TViewpointFunction); |
![]() |
function FogNode: TNodeFog; |
![]() |
function FogDistanceScaling: Single; |
![]() |
function CreateTrianglesList(OverTriangulate: boolean): TDynTriangle3SingleArray; |
![]() |
function TrianglesList(OverTriangulate: boolean): TDynTriangle3SingleArray; |
![]() |
function ManifoldEdges: TDynManifoldEdgeArray; |
![]() |
function BorderEdges: TDynBorderEdgeArray; |
![]() |
procedure ShareManifoldAndBorderEdges( ManifoldShared: TDynManifoldEdgeArray; BorderShared: TDynBorderEdgeArray); |
![]() |
procedure FreeResources(Resources: TVRMLSceneFreeResources); |
![]() |
property ShapeStates: TVRMLShapeStatesList read FShapeStates; |
![]() |
property RootNode: TVRMLNode read FRootNode write FRootNode; |
![]() |
property OwnsRootNode: boolean read FOwnsRootNode write FOwnsRootNode; |
![]() |
property DefaultTriangleOctree: TVRMLTriangleOctree
read FDefaultTriangleOctree write FDefaultTriangleOctree; |
![]() |
property DefaultShapeStateOctree: TVRMLShapeStateOctree
read FDefaultShapeStateOctree write FDefaultShapeStateOctree; |
![]() |
property OwnsDefaultTriangleOctree: boolean
read FOwnsDefaultTriangleOctree write FOwnsDefaultTriangleOctree
default true; |
![]() |
property OwnsDefaultShapeStateOctree: boolean
read FOwnsDefaultShapeStateOctree write FOwnsDefaultShapeStateOctree
default true; |
![]() |
constructor Create(ARootNode: TVRMLNode; AOwnsRootNode: boolean); |
![]() |
destructor Destroy; override; |
![]() |
function BoundingBox: TBox3d; |
|
Calculate bounding box, number of triangls and vertexes of all shapa states. For detailed specification of what these functions do (and what does OverTriangulate mean) see appropriate VRMLNodes.TNodeGenaralShape methods. Here, we just sum results of TNodeGenaralShape methods for all shapes. | |
![]() |
function VerticesCount(OverTriangulate: boolean): Cardinal; |
![]() |
function TrianglesCount(OverTriangulate: boolean): Cardinal; |
![]() |
procedure ChangedAll; virtual; |
|
ta klasa zapamietuje sobie pewne przeliczone rzeczy w swoich polach, w zwiazku z czym musi byc powiadamiana gdy dokonasz jakichs zmian w strukturze RootNode. Wywolaj Wywolaj ChangedShapeStateFields(i) gdy zmieniles tylko zawartosci pol node'a ShapeList[i].ShapeNode, node'ow ShapeList[i].State.Last* i node'ow ShapeList[i].State.Active*. (i jestes PEWIEN ze node ktorego pole zmieniles nie wystepuje w innych ShapeState'ach). Wywolaj ChangedFields gdy zmieniles pola danego Node'a. Mozesz podac Node ktory jest lub ktorego nie ma w aktualnym grafie VRML'a zaczepionym w RootNode, moze byc w czesci aktywnej lub nieaktywnej (takiej do ktorej nie dociera Traverse) tego grafu, moze byc Node'm dowolnej klasy, moze byc takze jednym z Node'ow StateDefaultNodes ktory wziales z jakiegos State.LastNodes[] - to wszystko tutaj uwzglednimy i wywolanie ChangedFields rozlozy sie na wywolania innych Changed. To jest prawdopodobnie najwygodniejsze sposrod Changed*. Notka dla implementatorow podklas : jak widac | |
![]() |
procedure ChangedShapeStateFields(ShapeStateNum: Integer); virtual; |
![]() |
procedure ChangedFields(Node: TVRMLNode); |
![]() |
function Info(InfoTriVertCounts, InfoBoundingBox: boolean): string; |
|
Returns short information about the scene. This consists of a few lines, separated by KambiUtils.NL. Last line also ends with KambiUtils.NL. | |
![]() |
procedure WritelnInfoNodes; |
|
Write contents of all VRML "Info" nodes. Also write how many Info nodes there are in the scene. | |
![]() |
function CreateTriangleOctree(const ProgressTitle: string): TVRMLTriangleOctree; overload; |
|
Creates triangle octree and inits it with our BoundingBox and adds all triangles from our ShapeStates. (generated using ShapeNode.Triangulate(State, false, ...) (note : OverTriangulate = false because it's not necessary for collision detection)) If ProgressTitle <> '' then it uses Progress while building octree. Remember that such octree has a reference to Shape nodes inside RootNode vrml tree and to State objects inside our ShapeStates list. So you must not use this octree after freeing this object. Also you must rebuild such octree when this object changes. Note: remember that this is a function and it returns created octree object. It does *not* set value of property DefaultTriangleOctree. But of course you can use it (and you often will) in code like Scene.DefaultTriangleOctree := Scene.CreateTriangleOctree(...) | |
![]() |
function CreateTriangleOctree(AMaxDepth, AMaxLeafItemsCount: integer; const ProgressTitle: string): TVRMLTriangleOctree; overload; |
![]() |
function CreateShapeStateOctree(const ProgressTitle: string): TVRMLShapeStateOctree; overload; |
|
Creates shapestate octree and inits it with our BoundingBox and adds all our ShapeStates. If ProgressTitle <> '' then it uses Progress while building octree. Remember that such octree has a reference to our ShapeStates list. So you must not use this octree after freeing this object. Also you must rebuild such octree when this object changes. Note: remember that this is a function and it returns created octree object. It does *not* set value of property DefaultShapeStateOctree. But of course you can use it (and you often will) in code like Scene.DefaultShapeStateOctree := Scene.CreateShapeStateOctree(...) | |
![]() |
function CreateShapeStateOctree(AMaxDepth, AMaxLeafItemsCount: integer; const ProgressTitle: string): TVRMLShapeStateOctree; overload; |
![]() |
function GetViewpoint( out CamKind: TVRMLCameraKind; out CamPos, CamDir, CamUp, GravityUp: TVector3Single; const ViewpointDescription: string = ''): TNodeGeneralViewpoint; |
|
GetPerspectiveViewpoint omits OrthographicCamera. If ViewpointDescription = '', they return the first found Viewpoint. Otherwise, they look for Viewpoint with description field mathing given string. Jezeli VRML posiada node kamery zdefiniowany w aktywnej czesci swojego grafu to oblicza swoje zmienne "out" na podstawie tego node'a, wpp. zwraca domyslne ulozenia kamery w VRMLu, zgodnie ze specyfik. VRMLa (tzn. CamPos = (0, 0, 1), CamDir = (0, 0, -1), CamUp = GravityUp = (0, 1, 0), CamType = ctPerspective (ze domyslna kamera jest ctPerspective to juz sam sobie dopowiedzialem)). If camera properties were found in some node, it returns this node. Otherwise it returns nil. This way you can optionally extract some additional info from used viewpoint node, or do something special if default values were used. Often you will just ignore result of this function — after all, the most important feature of this function is that you don't have to care about details of dealing with camera node. Zwraca zawsze znormalizowane CamDir i CamUp i GravityUp — powody takie same jak dla TNodeGeneralViewpoint.GetCameraVectors. | |
![]() |
function GetPerspectiveViewpoint( out CamPos, CamDir, CamUp, GravityUp: TVector3Single; const ViewpointDescription: string = ''): TNodeGeneralViewpoint; |
![]() |
procedure EnumerateViewpoints(ViewpointFunction: TViewpointFunction); |
|
This enumerates all viewpoint nodes (Viewpoint (for VRML 2.0), PerspectiveCamera and OrthographicCamera (for VRML 1.0)) in scene graph. For each such node, it calls ViewpointFunction. Essentially, this is a trivial wrapper over RootNode.Traverse that returns only TNodeGeneralViewpoint. | |
![]() |
function FogNode: TNodeFog; |
|
FogDistanceScaling zwraca skalowanie tego node'a, wziete z transformacji w miejscu gdzie sie znajduje node Fog w hierarchii VRMLa. You should always multiply FogNode.FdVisibilityRange.Value by FogDistanceScaling when applying (rendering etc.) this fog node. Value of FogDistanceScaling is undefined if Wyniki tych funkcji sa "cachowane" wiec nie ma strachu - mozna uzywac tych funkcji czesto, dopoki nie bedziesz w miedzyczasie zmienial modelu VRMLa to te funkcje beda prosto zwracaly juz przeliczone wyniki, bez zadnej straty czasu. | |
![]() |
function FogDistanceScaling: Single; |
![]() |
function CreateTrianglesList(OverTriangulate: boolean): TDynTriangle3SingleArray; |
|
This returns an array of all triangles of this scene. I.e. it triangulates the scene, adding all non-degenerated (see IsValidTriangles) triangles to the list. It's your responsibility what to do with resulting object, when to free it etc. | |
![]() |
function TrianglesList(OverTriangulate: boolean): TDynTriangle3SingleArray; |
|
Just like CreateTrianglesList, but results of this function are cached, and returned object is read-only for you. Don't modify it, don't free it. | |
![]() |
function ManifoldEdges: TDynManifoldEdgeArray; |
|
Edges with more than two neighbors are allowed. If an edge has an odd number of neighbors, it will be placed in BorderEdges. Every other pair of neighbors will be "paired" and placed as one manifold edge inside Note that vertexes must be consistently ordered in triangles. For two neighboring triangles, if one triangle's edge has order V0, V1, then on the neighbor triangle the order must be reversed (V1, V0). This is true in almost all situations, for example if you have a closed solid object and all outside faces are ordered consistently (all CCW or all CW). Failure to order consistently will result in edges not being "paired", i.e. we will not recognize that some 2 edges are in fact one edge between two neighboring triangles — and this will result in more edges in BorderEdges. Both of these lists are calculated at once, i.e. when you call Results of these functions are cached, and are also owned by this object. So don't modify it, don't free it. This uses TrianglesList(false). | |
![]() |
function BorderEdges: TDynBorderEdgeArray; |
![]() |
procedure ShareManifoldAndBorderEdges( ManifoldShared: TDynManifoldEdgeArray; BorderShared: TDynBorderEdgeArray); |
|
This allows you to "share" ManifoldEdges and BorderEdges values between TVRMLFlatScene instances, to conserve memory and preparation time. The values set here will be returned by following ManifoldEdges and BorderEdges calls. The values passed here will not be owned by this object — you gave this, you're responsible for freeing it. This is handy if you know that this scene has the same ManifoldEdges and BorderEdges contents as some other scene. In particular, this is extremely handy in cases of animations in TVRMLGLAnimation, where all scenes actually need only a single instance of TDynManifoldEdgeArray and TDynBorderEdgeArray, this greatly speeds up TVRMLGLAnimation loading and reduces memory use. Note that passing here as values the same references that are already returned by ManifoldEdges / BorderEdges is always guaranteed to be a harmless operation. If ManifoldEdges / BorderEdges was owned by this object, it will remain owned in this case (while in normal sharing situation, values set here are assumed to be owned by something else). | |
![]() |
procedure FreeResources(Resources: TVRMLSceneFreeResources); |
![]() |
property ShapeStates: TVRMLShapeStatesList read FShapeStates; |
|
Note that the only place where | |
![]() |
property RootNode: TVRMLNode read FRootNode write FRootNode; |
|
This class can be viewed as a wrapper around specified As such it is allowed to change contents of This is useful for programs like view3dscene, that want to have one TVRMLFlatScene for all the lifetime and only replace That's why it is possible to change Always call ChangedAll when you changed Note that there is also a trick to conserve memory use. After you've done PrepareRender some things are precalculated here, and | |
![]() |
property OwnsRootNode: boolean read FOwnsRootNode write FOwnsRootNode; |
|
jezeli | |
![]() |
property DefaultTriangleOctree: TVRMLTriangleOctree
read FDefaultTriangleOctree write FDefaultTriangleOctree; |
|
Notes for both Everything in my units is done in the spirit that you can create as many octrees as you want for a given scene (both octrees based on triangles and based on shapestates). Also, in some special cases an octree may be constructed in some special way (not only using CreateShapeStateOctree or CreateTriangleOctree) so that it doesn't contain the whole scene from some TVRMLFlatScene object, or it contains the scene from many TVRMLFlatScene objects, or something else. What I want to say is that it's generally wrong to think of an octree as something that maps 1-1 to some TVRMLFlatScene object. Octrees, as implemented here, are a lot more flexible. That said, it's very often the case that you actually want to create exactly one octree of each kind (one TVRMLTriangleOctree and one TVRMLShapeStateOctree) for each scene. Properties below make it easier for you. Basically you can use them however you like. They can simply serve for you as some variables inside TVRMLFlatSceneGL that you can use however you like, so that you don't have to declare two additional variables like SceneTriangleOctree and SceneShapeStateOctree each time you define variable Scene: TVRMLFlatScene. Also, some methods in this class that take an octree from you as a parameter may have some overloaded versions that implicitly use octree objects stored in properties below, e.g. see TVRMLFlatSceneGL.RenderFrustumOctree. This class modifies these properties in *only* one case: if OwnsDefaultTriangleOctree is true (default value) then at destruction this class calls FreeAndNil( In any case, these properties are not managed by this object. E.g. these octrees are not automaticaly rebuild when you call ChangedAll. | |
![]() |
property DefaultShapeStateOctree: TVRMLShapeStateOctree
read FDefaultShapeStateOctree write FDefaultShapeStateOctree; |
![]() |
property OwnsDefaultTriangleOctree: boolean
read FOwnsDefaultTriangleOctree write FOwnsDefaultTriangleOctree
default true; |
![]() |
property OwnsDefaultShapeStateOctree: boolean
read FOwnsDefaultShapeStateOctree write FOwnsDefaultShapeStateOctree
default true; |