File: show_sh.lpr

package info (click to toggle)
castle-game-engine 6.4%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 194,520 kB
  • sloc: pascal: 364,585; ansic: 8,606; java: 2,851; objc: 2,601; cpp: 1,412; xml: 851; makefile: 725; sh: 563; php: 26
file content (139 lines) | stat: -rw-r--r-- 3,758 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
{
  Copyright 2008-2017 Michalis Kamburelis.

  This file is part of "Castle Game Engine".

  "Castle Game Engine" is free software; see the file COPYING.txt,
  included in this distribution, for details about the copyright.

  "Castle Game Engine" is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  ----------------------------------------------------------------------------
}

{ Show Spherical harmonics function basis.
  Single SH function is shown on a sphere, yellow indicates positive values,
  blue negative values.

  Navigate with mouse or keyboard (like view3dscene in Examine mode).
}

program show_sh;

uses Classes, CastleFrustum,
  CastleVectors, CastleBoxes, CastleWindow, CastleUIControls,
  CastleClassUtils, CastleUtils, SysUtils, CastleFilesUtils, CastleControls,
  CastleGLUtils, CastleCameras, Math, CastleSphereSampling, CastleSphericalHarmonics,
  CastleSceneManager, CastleScene, X3DNodes, CastleShapes, Castle3D,
  CastleStringUtils, CastleKeysMouse, CastleColors;

var
  Window: TCastleWindow;

  LM: Cardinal = 0;

  MinSHValue, MaxSHValue: Float;

procedure Render(Container: TUIContainer);
var
  L: Cardinal;
  M: Integer;
begin
  LMDecode(LM, L, M);
  UIFont.Print(10, 10, Yellow,
    Format('Spherical harmonic number %d. (L, M) = (%d, %d). Results in range (%f, %f)',
    [LM, L, M, MinSHValue, MaxSHValue]));
end;

type
  TMyScene = class(TCastleScene)
  private
    procedure VertexColor(var Color: TVector3;
      Shape: TShape; const VertexPosition: TVector3;
      VertexIndex: Integer);
  public
    constructor Create(AOwner: TComponent); override;
    procedure LocalRender(const Params: TRenderParams); override;
  end;

procedure TMyScene.VertexColor(var Color: TVector3;
  Shape: TShape; const VertexPosition: TVector3;
  VertexIndex: Integer);
var
  SH: Float;
begin
  SH := SHBasis(LM, XYZToPhiTheta(VertexPosition));
  if SH > MaxSHValue then MaxSHValue := SH;
  if SH < MinSHValue then MinSHValue := SH;

  if SH >= 0 then
    Color := Vector3(SH, SH, 0) else
    Color := Vector3(0, 0, -SH);
end;

constructor TMyScene.Create(AOwner: TComponent);
var
  Root: TX3DRootNode;
  Shape: TShapeNode;
  SphereNode: TSphereNode;
begin
  inherited;

  Attributes.OnVertexColor := @VertexColor;

  SphereNode := TSphereNode.Create;

  Shape := TShapeNode.Create;
  Shape.FdGeometry.Value := SphereNode;

  Root := TX3DRootNode.Create;
  Root.AddChildren(Shape);

  Load(Root, true);
end;

procedure TMyScene.LocalRender(const Params: TRenderParams);
begin
  if (not Params.Transparent) and Params.ShadowVolumesReceivers then
  begin
    { before every rendering clear Min/MaxSHValue, so that VertexColor can set them }
    MinSHValue :=  MaxFloat;
    MaxSHValue := -MaxFloat;
  end;
  inherited;
end;

procedure MenuClick(Container: TUIContainer; Item: TMenuItem);
begin
  case Item.IntData of
    10: LM := ChangeIntCycle(LM, -1, MaxSHBasis - 1);
    20: LM := ChangeIntCycle(LM, +1, MaxSHBasis - 1);
    else Exit;
  end;
  Window.Invalidate;
end;

var
  M: TMenu;
begin
  Window := TCastleWindow.Create(Application);

  DefaultTriangulationSlices := 60;
  DefaultTriangulationStacks := 60;

  Window.MainMenu := TMenu.Create('Main menu');
  M := TMenu.Create('_Program');
    M.Append(TMenuItem.Create('_Previous basis', 10, 'p'));
    M.Append(TMenuItem.Create('_Next basis', 20, 'n'));
    Window.MainMenu.Append(M);

  Window.SceneManager.MainScene := TMyScene.Create(Application);
  Window.SceneManager.Items.Add(Window.SceneManager.MainScene);

  Window.OnMenuClick := @MenuClick;
  Window.OnRender := @Render;
  Window.SetDemoOptions(K_F11, CharEscape, true);
  Window.OpenAndRun;
end.