Code:
unit unit_glowinglines;
interface
uses
SvEngine;
procedure DrawGlowingLine(x1,y1,x2,y2: Single; color: cardinal; RenderState: Integer; texture: TsvTexture; DrawEnd1,DrawEnd2: Boolean; width: Single = 1);
implementation
uses
unit_vectors;
type
//
// TRGBA
//
TRGBA = packed record
case Integer of
0: (b,g,r,a: Byte);
1: (Value: Cardinal);
end;
//
// glowing line routines
//
function OffsetCoord(const ox,oy,x,y: Single; up,right: TVector2f): TVector2f;
// this function moves along the rotated space's up & right vectors by
// y and x respectively, and then translates it to ox,oy
begin
Result.x := ox + x * right.x + y * up.x;
Result.y := oy + x * right.y + y * up.y;
end;
procedure DrawGlowingLine(x1,y1,x2,y2: Single; color: cardinal; RenderState: Integer; texture: TsvTexture; DrawEnd1,DrawEnd2: Boolean; width: Single = 1);
var
up, right: TVector2f;
dx,dy: Single;
radius: Single;
p0,p1,p2,p3: TVector2f;
p4,p5,p6,p7: TVector2f;
c: TRGBA;
begin
c.Value := color;
if width <= 1 then
begin
sv.RenderDevice.BeginPrimitive(ptLineList,RenderState,nil);
sv.RenderDevice.Color4ub(c.r,c.g,c.b,c.a);
sv.RenderDevice.Vertex2f(x1,y1);
sv.RenderDevice.Vertex2f(x2,y2);
sv.RenderDevice.EndPrimitive;
Exit;
end;
radius := width / 2;
dx := X2 - X1;
dy := Y2 - Y1;
// calculate rotation vectors for line
up := VecNormalize(VecPerp(Vector2f(dx,dy)));
right := VecNormalize(Vector2f(dx,dy));
// calculate triangle strip points
p1 := OffsetCoord(x1,y1,-radius,-radius,up,right);
p7 := OffsetCoord(x2,y2,+radius,-radius,up,right);
p6 := OffsetCoord(x2,y2,+radius,+radius,up,right);
p0 := OffsetCoord(x1,y1,-radius,+radius,up,right);
p5 := OffsetCoord(x2,y2,0,-radius,up,right);
p4 := OffsetCoord(x2,y2,0,+radius,up,right);
p2 := OffsetCoord(x1,y1,0,+radius,up,right);
p3 := OffsetCoord(x1,y1,0,-radius,up,right);
{
U-> 0.0 0.5 0.5 1.0
p1 p3 p5 p7
0.0 +--------*-----------------------*----------+ 0.0
V | up |
| | x1,y1 | x2,y2 |
v | *-----------+-----------* |
| right -> |
| |
0.1 +--------*-----------------------*----------+ 1.0
p0 p2 p4 p6
uv 0.0 0.5 0.5 1.0
}
sv.RenderDevice.BeginPrimitive(ptTriangleStrip,RenderState,texture);
sv.RenderDevice.Color4ub(c.r,c.g,c.b,c.a);
{
triangle strip vertex order
---------------------------
1 3 5 7
+--+--+--+
|\ |\ |\ |
| \| \| \|
+--+--+--+
0 2 4 6
}
if DrawEnd1 then
begin
sv.RenderDevice.Texcoord2f(0.0,1); sv.RenderDevice.Vertex2f(p0.x,p0.y);
sv.RenderDevice.Texcoord2f(0.0,0); sv.RenderDevice.Vertex2f(p1.x,p1.y);
end;
// stretch center of texture along middle section
sv.RenderDevice.Texcoord2f(0.5,1); sv.RenderDevice.Vertex2f(p2.x,p2.y);
sv.RenderDevice.Texcoord2f(0.5,0); sv.RenderDevice.Vertex2f(p3.x,p3.y);
sv.RenderDevice.Texcoord2f(0.5,1); sv.RenderDevice.Vertex2f(p4.x,p4.y);
sv.RenderDevice.Texcoord2f(0.5,0); sv.RenderDevice.Vertex2f(p5.x,p5.y);
if DrawEnd2 then
begin
sv.RenderDevice.Texcoord2f(1.0,1); sv.RenderDevice.Vertex2f(p6.x,p6.y);
sv.RenderDevice.Texcoord2f(1.0,0); sv.RenderDevice.Vertex2f(p7.x,p7.y);
end;
sv.RenderDevice.EndPrimitive;
end;
end.
unit_vectors.pas
Code:
unit unit_vectors;
interface
type
//
// TVector2f
//
PVector2f = ^TVector2f;
TVector2f = record
x, y: Single;
end;
//
// TVector3f
//
PVector3f = ^TVector3f;
TVector3f = record
x, y, z: Single;
end;
//
// TVector4f
//
PVector4f = ^TVector4f;
TVector4f = array[0..3] of Single;
function Vector2f(const aX,aY: Single): TVector2f;
function VecNegative(const v: TVector2f): TVector2f; overload;
function VecAdd(const v1, v2: TVector2f): TVector2f; overload;
function VecSubtract(const v1, v2: TVector2f): TVector2f; overload;
function VecMultiply(const v: TVector2f; const s: Single): TVector2f; overload;
function VecNormalize(const v: TVector2f): TVector2f; overload;
function VecLen(const v: TVector2f): Single; overload;
function VecDot(const v1,v2: TVector2f): Single; overload;
function VecPerp(const v: TVector2f): TVector2f;
function Vector3f(const aX,aY,aZ: Single): TVector3f;
function VecNegative(const v: TVector3f): TVector3f; overload;
function VecAdd(const v1, v2: TVector3f): TVector3f; overload;
function VecSubtract(const v1, v2: TVector3f): TVector3f; overload;
function VecMultiply(const v: TVector3f; const s: Single): TVector3f; overload;
function VecNormalize(const v: TVector3f): TVector3f; overload;
function VecLen(const v: TVector3f): Single; overload;
function VecDot(const v1,v2: TVector3f): Single; overload;
function VecCross(const v1,v2: TVector3f): TVector3f;
function Vector4f(const aX,aY,aZ: Single; const aW: Single = 1): TVector4f;
implementation
//
// TVector2f routines
//
function Vector2f(const aX, aY: Single): TVector2f;
begin
Result.x := aX;
Result.y := aY;
end;
function VecNegative(const v: TVector2f): TVector2f;
begin
Result.x := -v.x;
Result.y := -v.y;
end;
function VecAdd(const v1, v2: TVector2f): TVector2f;
begin
Result.x := v1.x + v2.x;
Result.y := v1.y + v2.y;
end;
function VecSubtract(const v1, v2: TVector2f): TVector2f;
begin
Result.x := v1.x - v2.x;
Result.y := v1.y - v2.y;
end;
function VecMultiply(const v: TVector2f; const s: Single): TVector2f;
begin
Result.x := v.x * s;
Result.y := v.y * s;
end;
function VecNormalize(const v: TVector2f): TVector2f;
var
mag: Single;
begin
mag := VecLen(v);
if mag < 1 then mag := 1;
Result.x := v.x / mag;
Result.y := v.y / mag;
end;
function VecLen(const v: TVector2f): Single;
begin
Result := Sqrt(Sqr(v.x) + Sqr(v.y));
end;
function VecDot(const v1,v2: TVector2f): Single;
begin
Result := v1.x * v2.x + v1.y * v2.y;
end;
function VecPerp(const v: TVector2f): TVector2f;
begin
Result := Vector2f(-v.y, v.x);
end;
//
// TVector3f routines
//
function Vector3f(const aX, aY, aZ: Single): TVector3f;
begin
Result.x := aX;
Result.y := aY;
Result.z := aZ;
end;
function VecNegative(const v: TVector3f): TVector3f;
begin
Result.x := -v.x;
Result.y := -v.y;
Result.z := -v.z;
end;
function VecAdd(const v1, v2: TVector3f): TVector3f;
begin
Result.x := v1.x + v2.x;
Result.y := v1.y + v2.y;
Result.z := v1.z + v2.z;
end;
function VecSubtract(const v1, v2: TVector3f): TVector3f;
begin
Result.x := v1.x - v2.x;
Result.y := v1.y - v2.y;
Result.z := v1.z - v2.z;
end;
function VecMultiply(const v: TVector3f; const s: Single): TVector3f;
begin
Result.x := v.x * s;
Result.y := v.y * s;
Result.z := v.z * s;
end;
function VecNormalize(const v: TVector3f): TVector3f;
var
mag: Single;
begin
mag := VecLen(v);
if mag < 1 then mag := 1;
Result.x := v.x / mag;
Result.y := v.y / mag;
Result.z := v.z / mag;
end;
function VecLen(const v: TVector3f): Single;
begin
Result := Sqrt(Sqr(v.x) + Sqr(v.y) + Sqr(v.z));
end;
function VecDot(const v1,v2: TVector3f): Single;
begin
Result := v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
end;
function VecCross(const v1,v2: TVector3f): TVector3f;
begin
Result.x := v1.y * v2.z - v1.z * v2.y;
Result.y := v1.z * v2.x - v1.x * v2.z;
Result.z := v1.x * v2.y - v1.y * v2.x;
end;
//
// TVector4f routines
//
function Vector4f(const aX, aY, aZ: Single; const aW: Single = 1): TVector4f;
begin
Result[0] := aX;
Result[1] := aY;
Result[2] := aZ;
Result[3] := aW;
end;
end.
cheers,
Bookmarks