unit Trace;

interface

uses
  JEN_Header,
  JEN_Math;

const
  TracesCount = 128;

type
  TTrace = record
    Start, Finish: TVec3f;
    Time: LongWord;
  end;

  TTraceManager = class
  constructor Create;
  private
    type TVrtxFormat = record
      PosTimeTex : TVec4f;
      Axis : TVec3f;
      GPos : TVec3f;
    end;
    var
    FTex : ITexture;
    FShader : IShaderProgram;
    FPosAttrib : IShaderAttrib;
    FAxisAttrib : IShaderAttrib;
    FGPosAttrib : IShaderAttrib;
    FMatrixUniform : IShaderUniform;
    FTimeUniform : IShaderUniform;
    FVPosUniform : IShaderUniform;
    FVrtBuff : IGeomBuffer;

  //  FNormalTex : ITexture;
    Traces : array[0..TracesCount-1] of TTrace;
  public
    procedure Add(Start, Finish: TVec3f; Time: LongWord; Size: Single);
    procedure OnUpdate(dt: LongInt);
    procedure OnDraw;
  end;

implementation

uses
  Main;

constructor TTraceManager.Create;
var
  VertexBuff : array of TVrtxFormat;
  I : Integer;
begin
  SetLength(VertexBuff, TracesCount*4);
  FillChar(VertexBuff[0], TracesCount*4*sizeof(TVrtxFormat), 0);
  FVrtBuff := Render.CreateGeomBuffer(gbVertex, TracesCount*4, sizeof(TVrtxFormat), @VertexBuff[0]);

  for I := 0 to TracesCount - 1 do
    Traces[I].Time := 0;

  FTex := ResMan.LoadTexture('Media\Trace.dds') ;
  FShader := ResMan.LoadShader('Media\Trace.xml').Compile;
  FMatrixUniform := FShader.Uniform('Jen_ModelViewProjectionMatrix', utMat4);
  FTimeUniform := FShader.Uniform('Jen_Time', utVec1);
  FVPosUniform := FShader.Uniform('Jen_ViewPos', utVec3);
  FPosAttrib := FShader.Attrib('PosTimeTexAttr', atVec4f, False);
  FAxisAttrib := FShader.Attrib('AxisAttr', atVec3f, False);
  FGPosAttrib := FShader.Attrib('GlobalPosAttr', atVec3f, False);

  i:=1;
  FShader.Uniform('DiffMap', utInt).Value(i);
end;

procedure TTraceManager.Add(Start, Finish: TVec3f; Time: LongWord; Size: Single);
var
  I,J : Integer;
  len : Single;
  Vertex : array[1..4] of TVrtxFormat;
begin

  for I := 0 to TracesCount - 1 do
    if Traces[I].Time = 0  then
    begin
      Traces[I].Start := Start;
      Traces[I].Finish := Finish;
      Traces[I].Time := Time;

      Len := (Finish - Start).Length;
      for J := 1 to 4 do
      begin
        Vertex[J].Gpos := Start + (Finish - Start)*0.5;
        Vertex[J].axis := (Finish - Start).Normal;
      end;

      Vertex[1].PosTimeTex := vec4f(-Size/2, -Len/2, (Time+Utils.Time-400)/1000.0, 1/4);
      Vertex[2].PosTimeTex := vec4f(Size/2, -Len/2, (Time+Utils.Time-400)/1000.0, 0);
      Vertex[3].PosTimeTex := vec4f(Size/2, Len/2, (Time+Utils.Time)/1000.0, 0);
      Vertex[4].PosTimeTex := vec4f(-Size/2, Len/2, (Time+Utils.Time)/1000.0, 1/4);

      FVrtBuff.SetData(I*4*sizeof(TVrtxFormat), 4*sizeof(TVrtxFormat), @Vertex[1]);

      Exit;
    end;

end;

procedure TTraceManager.OnUpdate(dt: LongInt);
var
  I : Integer;
  Vertex : array[1..4] of TVrtxFormat;
begin

  FillChar(Vertex, 4*sizeof(TVrtxFormat), 0);

  for I := 0 to TracesCount - 1 do
    if Traces[I].Time > 0 then
    begin
      Traces[I].Time := Max(Traces[I].Time - dt, 0);

      if Traces[I].Time = 0  then
      begin
        FVrtBuff.SetData(I*4*sizeof(TVrtxFormat), 4*sizeof(TVrtxFormat), @Vertex[1]);
        //Exit;
      end;

    end;

end;

procedure TTraceManager.OnDraw;
var
  m : TMat4f;
  p : TVec3f;
  t : Single;
begin

  m := Render.Matrix[mtProj] * Render.Matrix[mtView];
  p := Render.CameraPos;
  t := Utils.Time/1000.0;

  Render.DepthWrite := False;
  Render.DepthTest := True;
  Render.BlendType := btAdd;

  FTex.Bind;
  FShader.Bind;
  FMatrixUniform.Value(m);
  FTimeUniform.Value(t);
  FVPosUniform.Value(p);

  FVrtBuff.Bind;
  FPosAttrib.Value(sizeof(TVrtxFormat),0);
  FPosAttrib.Enable;
  FAxisAttrib.Value(sizeof(TVrtxFormat),16);
  FAxisAttrib.Enable;
  FGPosAttrib.Value(sizeof(TVrtxFormat),28);
  FGPosAttrib.Enable;
  FVrtBuff.Draw(gmQuads, TracesCount*4, false);
end;



end.
