This file is indexed.

/usr/src/castle-game-engine-6.4/x3d/castlerenderingcamera.pas is in castle-game-engine-src 6.4+dfsg1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
{
  Copyright 2009-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.

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

{ @abstract(Current rendering camera (TRenderingCamera).)

  @bold(This is mostly an internal unit), normal applications should not access
  camera this way (instead use TCastleAbstractViewport.Camera).
  However, there are some valid uses for it (like querying
  @link(TRenderingCamera.Target) to selectively hide some stuff). }
unit CastleRenderingCamera;

{$I castleconf.inc}

interface

uses Generics.Collections,
  CastleUtils, CastleVectors, CastleFrustum, CastleCameras, X3DNodes;

type
  TRenderingCamera = class;

  TCameraChangedEvent = procedure (
    const RenderingCamera: TRenderingCamera;
    Viewpoint: TAbstractViewpointNode) of object;

  TCameraChangedEventList = class({$ifdef CASTLE_OBJFPC}specialize{$endif} TList<TCameraChangedEvent>)
  public
    { This calls all functions (all Items). }
    procedure ExecuteAll(const RenderingCamera: TRenderingCamera;
      const Viewpoint: TAbstractViewpointNode);
  end;

  TRenderTarget = (
    { Normal rendering. }
    rtScreen,
    { Rendering color buffer contents to normal single 2D texture. }
    rfOffScreen,
    { Rendering color buffer contents to cube map texture. }
    rtCubeMapEnvironment,
    { Rendering depth buffer contents to shadow map texture. }
    rtShadowMap,
    { Rendering with a special VSM shader to capture shadow map texture
      (in the normal color buffer). }
    rtVarianceShadowMap);

  { Current camera used for rendering, almost always accessed using
    @link(RenderingCamera) singleton.

    @bold(This is an internal class), normal applications should not access
    camera this way (instead use TCastleAbstractViewport.Camera). }
  TRenderingCamera = class
  strict private
    FOnChanged: TCameraChangedEventList;
    FTarget: TRenderTarget;
  public
    constructor Create;
    destructor Destroy; override;
  public
    { Current camera matrix. Transforms from world space (normal 3D space)
      to camera space (camera space is the space where you're always
      standing on zero point, looking in -Z, and so on).

      This is needed for various things, like
      TextureCoordinateGenerator.mode = "WORLDSPACE*" or generating
      Viewpoint.camera[Inverse]Matrix event.

      Always after changing this, change also all other camera
      fields, and then call @link(Changed). }
    Matrix: TMatrix4;

    { Inverse of @link(Matrix).

      Always call InverseMatrixNeeded before using it,
      InverseMatrixNeeded will check InverseMatrixDone
      and eventually will calculate inverse and set InverseMatrixDone to
      @true. }
    InverseMatrix: TMatrix4;
    InverseMatrixDone: boolean;

    { Camera rotation matrix. That is, this is like @link(Matrix) but
      it doesn't move the camera, only rotates it.

      It's guaranteed that this is actually only 3x3 matrix,
      the 4th row and 4th column are all zero except the lowest right item
      which is 1.0. }
    RotationMatrix: TMatrix4;

    { Use RotationMatrix as camera matrix for rendering. }
    RotationOnly: boolean;

    { Inverse of RotationMatrix.

      Always call RotationInverseMatrixNeeded before using it,
      RotationInverseMatrixNeeded will check RotationInverseMatrixDone
      and eventually will calculate inverse and set RotationInverseMatrixDone to
      @true. }
    RotationInverseMatrix: TMatrix4;
    RotationInverseMatrixDone: boolean;

    Frustum: TFrustum;

    procedure InverseMatrixNeeded;
    procedure RotationInverseMatrixNeeded;

    { Camera rotation matrix, as a 3x3 matrix. }
    function RotationMatrix3: TMatrix3;
    function RotationInverseMatrix3: TMatrix3;

    { Set all properties (except Target) from TCamera instance in ACamera.
      See @link(FromMatrix) for comments about @link(Target) property
      and Viewpoint parameter. }
    procedure FromCameraObject(const ACamera: TCamera;
      const Viewpoint: TAbstractViewpointNode);

    { Set all properties (except Target) from explict matrices.
      ProjectionMatrix is needed to calculate frustum.

      Remember that @link(Target) must be already set correctly when calling
      this, registered OnChanged callbacks may read it.

      Viewpoint is only passed to the Changed and OnChanged.
      It should be non-nil to indicate that the view comes from non-standard
      (not currently bound) VRML/X3D Viewpoint node. }
    procedure FromMatrix(const AMatrix, ARotationMatrix,
      ProjectionMatrix: TMatrix4;
      const Viewpoint: TAbstractViewpointNode);

    property Target: TRenderTarget read FTarget write FTarget;

    { Always called after camera changed.
      This will call all registered OnChanged events.
      Remember that @link(Target) must be already set correctly when calling
      this, registered OnChanged callbacks may read it. }
    procedure Changed(const Viewpoint: TAbstractViewpointNode);

    property OnChanged: TCameraChangedEventList read FOnChanged;
  end;

var
  { Current camera used for rendering.

    @bold(This is an internal information), normal applications should not access
    camera this way (instead use TCastleAbstractViewport.Camera). }
  RenderingCamera: TRenderingCamera;

implementation

uses SysUtils, CastleLog;

{ TCameraChangedEventList ------------------------------------------------ }

procedure TCameraChangedEventList.ExecuteAll(
  const RenderingCamera: TRenderingCamera;
  const Viewpoint: TAbstractViewpointNode);
var
  I: Integer;
begin
  for I := 0 to Count - 1 do
    Items[I](RenderingCamera, Viewpoint);
end;

{ TRenderingCamera --------------------------------------------------------------- }

constructor TRenderingCamera.Create;
begin
  inherited;
  FOnChanged := TCameraChangedEventList.Create;
end;

destructor TRenderingCamera.Destroy;
begin
  FreeAndNil(FOnChanged);
  inherited;
end;

procedure TRenderingCamera.Changed(const Viewpoint: TAbstractViewpointNode);
begin
  FOnChanged.ExecuteAll(Self, Viewpoint);
end;

procedure TRenderingCamera.InverseMatrixNeeded;
begin
  if not InverseMatrixDone then
  begin
    if not Matrix.TryInverse(InverseMatrix) then
    begin
      InverseMatrix := TMatrix4.Identity;
      if Log then
        WritelnLogMultiline('Camera', 'Camera matrix cannot be inverted, conversions between world and camera space will not be done. Camera matrix is: ' +
          Matrix.ToRawString('  '));
    end;
    InverseMatrixDone := true;
  end;
end;

procedure TRenderingCamera.RotationInverseMatrixNeeded;
begin
  if not RotationInverseMatrixDone then
  begin
    if not RotationMatrix.TryInverse(RotationInverseMatrix) then
    begin
      RotationInverseMatrix := TMatrix4.Identity;
      if Log then
        WritelnLogMultiline('Camera', 'Camera rotation matrix cannot be inverted, conversions between world and camera space will not be done. Camera matrix is: ' +
          RotationMatrix.ToRawString('  '));
    end;
    RotationInverseMatrixDone := true;
  end;
end;

function TRenderingCamera.RotationMatrix3: TMatrix3;
begin
  Move(RotationMatrix.Data[0], Result.Data[0], SizeOf(Single) * 3);
  Move(RotationMatrix.Data[1], Result.Data[1], SizeOf(Single) * 3);
  Move(RotationMatrix.Data[2], Result.Data[2], SizeOf(Single) * 3);
end;

function TRenderingCamera.RotationInverseMatrix3: TMatrix3;
begin
  Move(RotationInverseMatrix.Data[0], Result.Data[0], SizeOf(Single) * 3);
  Move(RotationInverseMatrix.Data[1], Result.Data[1], SizeOf(Single) * 3);
  Move(RotationInverseMatrix.Data[2], Result.Data[2], SizeOf(Single) * 3);
end;

procedure TRenderingCamera.FromCameraObject(const ACamera: TCamera;
  const Viewpoint: TAbstractViewpointNode);
begin
  Matrix := ACamera.Matrix;
  InverseMatrixDone := false;
  RotationMatrix := ACamera.RotationMatrix;
  RotationInverseMatrixDone := false;
  Frustum := ACamera.Frustum;
  Changed(Viewpoint);
end;

procedure TRenderingCamera.FromMatrix(
  const AMatrix, ARotationMatrix, ProjectionMatrix: TMatrix4;
  const Viewpoint: TAbstractViewpointNode);
begin
  Matrix := AMatrix;
  InverseMatrixDone := false;
  RotationMatrix := ARotationMatrix;
  RotationInverseMatrixDone := false;
  Frustum.Init(ProjectionMatrix, AMatrix);
  Changed(Viewpoint);
end;

initialization
  RenderingCamera := TRenderingCamera.Create;
finalization
  FreeAndNil(RenderingCamera);
end.