/usr/src/castle-game-engine-5.0.0/x3d/x3dnodes_elevationgrid.inc is in castle-game-engine-src 5.0.0-3.
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 | {
Copyright 2002-2014 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.
----------------------------------------------------------------------------
}
function TElevationGridNode.Proxy(var State: TX3DGraphTraverseState;
const OverTriangulate: boolean): TAbstractGeometryNode;
{ I initially rendered ElevationGrid directly, by GL_QUAD_STRIP
for each row. Fast, but has troubles:
- When colorPerVertex is different than normalPerVertex,
neither flat nor smooth shading is good.
- Normal generation was a pain. A code generating smooth-only normals
was implemented, and was already a pain to maintain (since with IndexedFaceSet,
we already had normal generation implemented).
creaseAngle was not supported, only all smooth or all flat was supported.
- Rendering by quads was sometimes not fully correct, as elevation grid
quads were not really planar. So with GPU performing any triangulation
it wants, results are undefined and not always the best.
Right now we triangulate ourselves along the shortest diagonal,
which improves the look much.
IndexedFaceSet is rendered through GL_TRIANGLES anyway.
Using proxy to render ElevationGrid solves above troubles.
Using proxy also makes simpler implementation than rendering,
and also it's used for triangulating.
}
var
Coords: TVector3SingleList;
CoordIndexes: TLongIntList;
{ Add to CoordIndexes a quad from given indexes.
Actually we add two triangles, looking at Coord to choose the best
triangulation. }
procedure Quad(const IndexNum, I1, I2, I3, I4: Integer);
begin
if PointsDistanceSqr(Coords.L[I1], Coords.L[I3]) <
PointsDistanceSqr(Coords.L[I2], Coords.L[I4]) then
begin
CoordIndexes.L[IndexNum ] := I1;
CoordIndexes.L[IndexNum + 1] := I2;
CoordIndexes.L[IndexNum + 2] := I3;
CoordIndexes.L[IndexNum + 3] := -1;
CoordIndexes.L[IndexNum + 4] := I3;
CoordIndexes.L[IndexNum + 5] := I4;
CoordIndexes.L[IndexNum + 6] := I1;
CoordIndexes.L[IndexNum + 7] := -1;
end else
begin
CoordIndexes.L[IndexNum ] := I1;
CoordIndexes.L[IndexNum + 1] := I2;
CoordIndexes.L[IndexNum + 2] := I4;
CoordIndexes.L[IndexNum + 3] := -1;
CoordIndexes.L[IndexNum + 4] := I2;
CoordIndexes.L[IndexNum + 5] := I3;
CoordIndexes.L[IndexNum + 6] := I4;
CoordIndexes.L[IndexNum + 7] := -1;
end;
end;
var
IFS: TIndexedFaceSetNode absolute Result;
XDimension, ZDimension: Integer; {< shortcuts for appropriate fields values }
TexCoordProvided: boolean;
I, J, NextIndex: Integer;
CoordNode: TCoordinateNode;
TexCoords: TVector2SingleList;
begin
IFS := TIndexedFaceSetNode.Create(NodeName, BaseUrl);
try
XDimension := FdXDimension.Value;
ZDimension := FdZDimension.Value;
if IsNotEmpty then
begin
CoordNode := TCoordinateNode.Create('', BaseUrl);
IFS.FdCoord.Value := CoordNode;
Coords := CoordNode.FdPoint.Items;
{ calculate TexCoordProvided, set IFS.FdTexCoord, maybe set TexCoords }
TexCoordProvided :=
(FdTexCoord.Value <> nil) and
(FdTexCoord.Value is TTextureCoordinateNode) and
(TTextureCoordinateNode(FdTexCoord.Value).FdPoint.Count >=
XDimension * ZDimension);
if TexCoordProvided then
IFS.FdTexCoord.Value := FdTexCoord.Value else
begin
IFS.FdTexCoord.Value := TTextureCoordinateNode.Create('', BaseUrl);
TexCoords := TTextureCoordinateNode(IFS.FdTexCoord.Value).FdPoint.Items;
end;
{ generate coords (and other per-vertex stuff: tex coords) }
Coords.Count := XDimension * ZDimension;
if not TexCoordProvided then
TexCoords.Count := XDimension * ZDimension;
for J := 0 to ZDimension - 1 do
for I := 0 to XDimension - 1 do
begin
Coords.L[I + J * XDimension] := Vector3Single(
FdXSpacing.Value * I,
FdHeight.Items.L[I + J * XDimension],
FdZSpacing.Value * J);
if not TexCoordProvided then
TexCoords.L[I + J * XDimension] := Vector2Single(
I / (XDimension - 1),
J / (ZDimension - 1));
end;
{ generate quads indexes }
CoordIndexes := IFS.CoordIndex.Items;
CoordIndexes.Count := (XDimension - 1) * (ZDimension - 1) * 8;
NextIndex := 0;
for J := 1 to ZDimension - 1 do
for I := 1 to XDimension - 1 do
begin
{ Vertices are ordered such that face is CCW from up
(i.e. looking from positive Y axis). }
Quad(NextIndex,
I + (J - 1) * XDimension,
I - 1 + (J - 1) * XDimension,
I - 1 + J * XDimension,
I + J * XDimension);
NextIndex += 8;
end;
Assert(NextIndex = CoordIndexes.Count);
end;
IFS.FdSolid.Value := FdSolid.Value;
IFS.FdCcw.Value := FdCcw.Value;
{ We order our coords such that we can simply copy normal/color nodes }
IFS.FdNormalPerVertex.Value := FdNormalPerVertex.Value;
IFS.FdNormal.Value := FdNormal.Value;
IFS.FdColorPerVertex.Value := FdColorPerVertex.Value;
IFS.FdColor.Value := FdColor.Value;
IFS.FdCreaseAngle.Value := FdCreaseAngle.Value;
IFS.FdFogCoord.Value := FdFogCoord.Value;
IFS.FdAttrib.AssignValue(FdAttrib);
except FreeAndNil(Result); raise end;
end;
function TElevationGridNode.ProxyUsesOverTriangulate: boolean;
begin
Result := false;
end;
|