Here is cleaner version of same thing:
const heightroadaboveterrain : single = 0.1;
function anglefromdelta2d( const delta : TVector2 ) : single;
begin
Result := arctan2(delta.y,delta.x);
end;
procedure calcstartcorners( const p : TVector2;
angle, w2 : single;
var L, R : TVector3 );
{ given a point, an angle and a distance, calculate
the cornerpoints 90deg from the angle at that distance
p is vector2, returns L and R which are vector 3 without Y set}
var sina, cosa : single;
dx, dy : single;
begin
sincos( angle, sina, cosa );
dx := cosa * w2;
dy := sina * w2;
L := Vector3( p.x + dx, 0, p.y + dy );
R := Vector3( p.x - dx, 0, p.y - dy );
end;
procedure addtexture( Shape : TShapeNode;
turl : string );
var Texture : TImageTextureNode;
begin
Shape.Appearance := TAppearanceNode.Create;
Texture := TImageTextureNode.Create;
Texture.SetUrl([turl]);
Shape.Appearance.Texture := Texture;
end;
procedure TRoadGraphic.buildx3dgraphic( const P1, P2 : TVector2;
width : single;
terrainheight : THeightAboveTerrainEvent;
TextureUrl : string = '' );
var Points : TVector3SingleList;
TextureCoordinates : TVector2SingleList;
procedure addsquare( const pL0, pR0, pL1, pR1 : TVector3;
t0, t1 : single );
{ add the 4 point square as two cw triangles }
begin
Points.Add( pR0 );
Points.Add( pL0 );
Points.Add( pR1 );
TextureCoordinates.Add(Vector2(t0, 0));
TextureCoordinates.Add(Vector2(t0, 1));
TextureCoordinates.Add(Vector2(t1, 0));
Points.Add( pR1 );
Points.Add( pL0 );
Points.Add( pL1 );
TextureCoordinates.Add(Vector2(t1, 0));
TextureCoordinates.Add(Vector2(t0, 1));
TextureCoordinates.Add(Vector2(t1, 1));
end;
var x3dRootNode : TX3DRootNode;
angle, distance, w2 : single;
i, n : integer;
delta : TVector2;
pL, pR, lastpL, lastpR : TVector3;
TrianglesNode : TTriangleSetNode;
CoordinateNode : TCoordinateNode;
TextureCoordinateNode: TTextureCoordinateNode;
Shape : TShapeNode;
TextureScale, TexPct, LastTexPct, TexDelta : single;
begin
w2 := width * 0.5;
distance := PointsDistance( P1, P2 );
textureScale := distance / width;
{ split the road in to n>=1 number of segments about a world unit each}
n := trunc( distance ) + 1;
Delta := ( p2 - p1 );
angle := anglefromdelta2d( Delta );
Delta := Delta / n;
texpct := 0;
texdelta := TextureScale / n;
{ determine left and right corner points at start point }
calcstartcorners( p1, angle + Pi/2 { 90 deg }, w2, pL, pR );
{ no need to initialize these but keeps compiler from complaning }
LastpR := Vector3(0,0,0);
LastpL := LastPr;
LastTexPct := 0;
{ initalize a triangle set node}
TrianglesNode := TTriangleSetNode.CreateWithShape(Shape);
CoordinateNode := TCoordinateNode.Create;
Points := TVector3SingleList.Create;
TextureCoordinateNode := TTextureCoordinateNode.Create;
TextureCoordinates := TVector2SingleList.Create;
{ step through n road segments, adding the side points to the triangle set }
for i := 0 to n do
begin
{ set heights from terrain }
terrainheight( pL, pL.Y );
terrainheight( pR, pR.Y );
{ raise the points to not be coplaner with terrain }
pr.y := pr.y + heightroadaboveterrain;
pl.y := pl.y + heightroadaboveterrain;
if i > 0 then
AddSquare( LastPl, LastPr, PL, PR, lasttexpct, texpct );
lastPl := Pl;
LastPr := PR;
lasttexpct := texpct;
{ walk all the values to the next set of points }
pL.x := pL.x + delta.x;
pL.z := pL.z + delta.y;
pR.x := pR.x + delta.x;
pR.z := pR.z + delta.y;
texpct := texpct + texdelta;
end;
CoordinateNode.SetPoint(Points);
TrianglesNode.Coord := CoordinateNode;
TextureCoordinateNode.SetPoint(TextureCoordinates);
TrianglesNode.TexCoord := TextureCoordinateNode;
if TextureUrl <> '' then
AddTexture( Shape, TextureUrl );
x3dRootNode := TX3DRootNode.Create;
x3dRootNode.AddChildren( Shape );
Load(x3dRootNode, true);
PreciseCollisions := true;
end;