Suspected typos (low priority)

Hello!

castle-engine\src\images\castleimages.pas

acSimpleYesNo = acBlending deprecated 'use acTest';

wrong value?

Actually there was a number of comments-obly typos that i already forgot. But this one seems to hatch into the code and made me log into the forum :slight_smile: Those were mistakes like a letter missed or changed or inserted into some ID. Perhaps one could make word statistics gatherer for CGE sources, stupir words counter with matcher for words used <= 5 times. If it is ever worth it…


https://castle-engine.io/x3d_implementation_geometry2d.php#section_example_pascal

Supported nodes

Missed TTriangleFanNode, also no link to TLineSetNode, also no example of setting coords to Triangles-based nodes.
The OutlineGeometry.Coord := OutlineCoords; from the example won’t work on them. Hopefully would TriangleSetNode.CoordField.Value := OutlineCoords; - but it takes some time to find it in sources.

For some hopefully simple yet realistic possible example.

function DiagShape(const Source: RAnglesDiagram; const baseZ: single;
  clOutline, clInner: TCastleColor;
  const AlphaOutline: single = 1;
  const AlphaInner:   single = 0.5): TX3DRootNode;

I want to render a rotatable sensor, with RAnglesDiagram basically being an array of {angle, radius} pairs and an interpolation method. In the end i want a rotating polar-coord chart with translucent inner filling and opaque or less translucent outline.

Here is it rendered with usual LCL TImage for example, not translucent, not rotatable and not having other objects in the scene

I am NOT asking to implement it, just maybe giving you a good idea for a demo/tutorial, maybe not.

In general, that example created to demonstrate 2D uses almost exclusively 3D nodes. Basically twi chapters of the page deny one another.

Could’ve showcase TAppearanceNode and TUnlitMaterialNode.

Also, space missed in //Scene.Rotation := in WindowUpdate


In general, most nodes like triangles have a “mirror class” - Txxxx and TIndexedXXX - and your demos seem to prefer the latter. It is somewhat confusing, would be good if the intended difference between those would be outlined somewhere. Why there should be both, what are usecases favoring one or another.


Also, maybe it is personal, when i read through tutorials i always feel myself shaky, as there is no mention of memory/object ownership. Tutorials seem to be of “create and keep until program exit” type. Some tutorials of “delete and recreate” kind would feel nice ro have, perhaps.

Actually feel puzzled here… The comments in the source strongly suggest to make an explicit Appearanvce node… Okay.

  Result := nil;
  xn := nil;

  c2s := DiagShape(Source, scale, 1);
  c3s_i := DiagShapeTriag(c2s, baseZ - 0.5);
  c3s_o := DiagShape(c2s, baseZ + 0.5);
  c2s := nil;

  try
    xn := TX3DRootNode.Create;

    Transform := TTransformNode.Create;
    xn.AddChildren(Transform);

    InFill := TTriangleSetNode.CreateWithShape(OutlineShape);

    OutlineCoords := TCoordinateNode.Create;
    OutlineCoords.SetPoint(c3s_i);
    InFill.CoordField.Value := OutlineCoords;

    Material := TUnlitMaterialNode.Create;
    Material.EmissiveColor := clInner.XYZ;
    Material.Transparency := 1 - AlphaInner;
    OutlineShape.Material := Material;
//    OutlineShape.Appearance := TAppearanceNode.Create;
//    OutlineShape.Appearance.AlphaChannel := acBlending;

    Transform.AddChildren(OutlineShape);

    OutlineCoords := TCoordinateNode.Create;
    OutlineCoords.SetPoint(c3s_o);

    OutlineGeometry := TLineSetNode.CreateWithShape(OutlineShape);
    OutlineGeometry.Coord := OutlineCoords;
    OutlineGeometry.SetVertexCount([OutlineCoords.FdPoint.Count]);

    Material := TUnlitMaterialNode.Create;
    Material.EmissiveColor := clOutline.XYZ;
    Material.Transparency := 1 - AlphaOutline;
    OutlineShape.Material := Material;

    Transform.AddChildren(OutlineShape);

    Result := xn;
    xn := nil;
  finally
    xn.Free;
  end;

Would i uncomment the Appearance lines - and the inner field is white instead of colours!
Without those lines it seems to work fine.

Perhaps i did something stupid, but was copy-pasting from tutporials and hoiping upon defaults.

Win7 x64 integrated Radeon 4250 (760G ?)

Okay, i WAS doing a stupid thing, but CGE seems inconsistent… Maybe, there is a method to this inconsistency, but for a tutorials copy-pasting newb it is one trap…

    OutlineGeometry := TLineSetNode.CreateWithShape(OutlineShape);

    //    OutlineShape.Appearance := TAppearanceNode.Create;
    appNode := OutlineShape.Appearance;
    appNode.AlphaChannel := acBlending;

Explicitly creating the node here not just is redundant, but outright “kills the mood”.

    appNode.LineProperties := TLinePropertiesNode.Create;
    appNode.LineProperties.LinewidthScaleFactor := 0;

yet here we MUST do it, despite the previous example taught us not to.

I don’t know if getter-as-constructor can be applied here, but feels inconsistent.

https://castle-engine.io/apidoc/html/CastleControls.TCastleLabel.html

weirdly, no linke to .Border property nor TB order type on the pagem despite PasDoc presen in a deep ancestor TCastleUserInterface

Could it be because of redirection TBorder = CastleVectors.TBorder; ?..

…but probably bad choice anyway, since i wanted them to be placed under the transplucent TTrianglesSetNode :slight_smile:

no any examples or tutorials for TCastleText :-/

for example i want that TCastleControl with 2D settings with both coords span -10K to +10K

now i want by mouse click position a TCastleText there. Seems easy-peasy, but somethign does not work and no clues what to check…

Text and fonts | Manual | Castle Game Engine suggests the examples\fonts\text_tests, but that is a “create by editor” example, and there is no “create by code” which should showcase the minimal bootstrapping.

Also, this tutorial, if it is required doc, could be lionked from the TCastleText/TCastleEdit/TCastleLabel class documentation pages, it is not.

Maybe i should’ve set the component size, or manually created even the most basic font, but… I just don’t know - and seem to have no way to know.

    tc := TCastleScene.Create(Self);
    try
      tt := TCastleText.Create(Self);
      tt.Caption := IntToStr(row);
      tt.Color := cl;
      tt.ColorPersistent;

//      tt.BorderColor := cl;
//      tt.Border.AllSides := 2;
//      tt.Padding := 6;

      tc.Add(tt);

      tc.TranslationXY := coord;
      Vehicles[row] := tc;
      tc := nil;
    finally
      tc.Free;
    end;
    Viewport.Items.Add(Vehicles[row]);

Then TCastleControl.OnPress moves them fine - but renders none…

  1. Customizing font. You can add and configure fonts…
    …
    You can also assign font to TCastleText.CustomFont

“Can” means it is not required, if you only needs most basic things. And i only needed 1/2/3

  1. Deprecated … To make it easy, one global instance of this class is already created for you: UIFont

Oh, great! Except i had to read into Deprecated section. But… won’t even compile

Error: Incompatible type for arg no. 1: Got “TCastleAbstractFont”, expected “TCastleFont”

And DefaultUIFont is not even mentioned there in the tutorial. Neither is FallbackFont(), nor is there some hypothetical FallbackFont(small) to expose DefaultUIFont.Small to user code;

Anyway, adding tt.CustomFont := FallbackFont(); did not fix things…

tt.Size := 200 (300, 400) did a trick, but was it mentioned? And how to calculate?
tt.CustomFont.OptimalSize := 30; gives a pretty nil^ AV

      tt.CustomFont := FallbackFont;
      tt.CustomFont.OptimalSize := 30;

…gives another exception about missing FreeType library, but it was not advertized it would be needed (for the bare bones stuff).

How should i offset it to position it’s center under the mouse click?

    MouPos := ViewPort.PositionTo2DWorld(Event.Position, True);
    Vehicles[i].TranslationXY := MouPos;

Or in another terms, where is the text rendered from the local zero point, and how to make it centered?

tt.Center.XY; this gave nothing, okay, it was abuse, but it was named so nicely.

tt.TranslationXY := - tt.BoundingBox.Center.XY; did the trick it seems, yet i am not sure it was intended/optimal way, perhaps the text components better be auto-centering? At least, no clues i found in tutorial or the class doc.

Thank you for the comments, there are a lot of useful conclusions in this thread that I now applied – changes to engine and/or docs.

But note: Please try to separate reports into a few threads – one long thread talking about many things is hard to answer, and we’re doomed to generate a long thread talking about many things at once :slight_smile: I prefer a few small threads, that can be “solved” one by one, then a long-running thread.

For now I have addressed things until TCastleLabel comments – I will read and answer them later, for now I’m falling asleep :slight_smile: Answers below:

Thank you, fixed!

TTriangleFanNode and TLineSetNode are documented on Rendering component | Castle Game Engine .

I agree these nodes could be grouped better. For now this organization (sections like “Geometry2D”, “Geometry3D”, “Rendering”) follows X3D specification Extensible 3D (X3D), ISO/IEC 19775-1:202x, Contents , which is “friendly” only to people familiar with X3D. I want to rearrange most of these docs to be more friendly to people new to CGE (who may not know, or even care, about X3D). That’s a larger TODO for some time.

It works, it’s mostly the same.

Geometry.Coord := Coord;

is OK when Geometry is of TTriangleSetNode type.

I added TTriangleSetNode and TTriangleFanSetNode examples to Rendering component | Castle Game Engine .

Both indexed and non-indexed make sense.

The “indexed” versions allow to refer to the same vertex (on the Coord list) multiple times, since you specify the vertex once in TCoordinateNode, and then can use the same index multiple times e.g. in TIndexedTriangleSetNode.SetIndex.

Good point that this needs to be documented better. I added a longer explanation to Rendering component | Castle Game Engine .

The X3D nodes have a reference-counting mechanism. The node is freed when the reference count of it changes from non-zero to zero.

Again good point that this needs to be documented better.

I added a longer explanation to Scene graph (X3D) | Castle Game Engine (section " 2.1. X3D node instance lifetime in Pascal"). I also improved the API docs of KeepExistingBegin, KeepExistingEnd mentioned there (the API docs Castle Game Engine: X3DNodes: Class TX3DNode ).

You’re not the first to report confusion about this.

I consider it a mistake to add TShapeNode.Material shortcut, that automatically creates and sets TShapeNode.Appearance and then sets TAppearanceNode.Material.

I should have deprecated it, and remove from docs, long time ago… Done now.

( I will nuke some remaining usage of it in CGE tomorrow. )

Not using this shortcut (and always creating and assigning TAppearanceNode explicitly to Shape.Appearance, then assigning material to Appearance.Material := ...) is much less error-prone (even if it looks a bit more verbose).

Well, sure, it was a “road movie” as i was scrambling some time for a long postponed project :slight_smile:

i am still struglging to internalize bs2D sorting and blending though.
Spent a lot of time on unstable sort - until i realized that i had to z-translate the “root” scenes, which i used as mere logical container and rotation/translation joint, so they all had zero Z, and the real Z had the objects within them. This hit me later when i got to bed, after i wasted like 3 hours trying different combinations of everything i could think of :frowning:

I would later re-read bs2D description and think if this could be made more digestable by newbs.

Also, sorry, would read the rest of your reply later too, no time right now :slight_smile:

When i did just that it ruined my rendering. I assume the default values from TAppearanceNode.Create were not all set up as TShapeNode expected them, or something.

Perhaps consider adding explicit API like procedure TShapeNode.CreateDefaultAppearance or function TShapeNode.CreateDefault(nodeclass): TObject - that could more or less uniformly be added to all the nodes? Something that would blend mere calling consturctor with ad hoc properties assignment both of creator and of the created node?

See, i am talking standing in a noob hat wearing noob boots. I can’t into Google.

I see the specific, 2D tutorial page.
This specific tutorial page goes at lengths to introduce me to a whola lot of classes…

…just to immediately disregard them and use some mysteriuous LineSet instead.

With no reasoning why.

It’s puzzling… And the lack of the immediate, here and now linke to the LineSet class (with at least some explanation what it was the beast) contributes.

Personally, after a tedious digging through low-level sources i ended up with

    InFill := TTriangleSetNode.CreateWithShape(OutlineShape);

    OutlineCoords := TCoordinateNode.Create;
    OutlineCoords.SetPoint(c3s_i);
    InFill.CoordField.Value := OutlineCoords;

Meanwhile OutlineGeometry := TLineSetNode.Create... and while it can receive coordinates array, it can not be assigned to the TTriangleSetNode instance, or i failed to find in the tutorial.

Another low-key thing i am somewhat striggling is forcing anti-aliasing upon the outline. Giving it Alpha=0.99 makes it smooth, but is an ugly hack. Making it opaque immediately makes it segmented again. Now, the ball here is in my park, but maybe a tutorial could be a bit proactive here.
Actually, perhaps tutorials could “pass the bucket” linking to one another, as the problems/topics are expected to be tangential.

    OutlineGeometry.Coord := OutlineCoords;
    OutlineGeometry.SetVertexCount([OutlineCoords.FdPoint.Count]);

This tutorial part also looks very redundant and fragile. Why the second line is even required? Can’t the property setter just do it?..

Google found me a TCastleWindow.AntiAliasing - which TCastelControl is sadly lacking.

Now i wonder if xxxx.MultiSampling can actually be anything but the very same thing by any other name (like its description and comments seem to vaguely imply). However i can witness, that searching for “antialiasing” is comes easier, than for “multisampling”.

If anything, MSAA is always full-screen(or full-window) and maybe there still are more local low hanging fruits

It would’ve been nice if TDisk2DNode.InnerRadius had been clearly marked as not-implemented, both in PasDoc and using something like deprecated or experimental