Architecture
BAD LOOKING CUBE DEMOTOOL PIPELINE | ||
---|---|---|
Blender + Plugin | CSV Screenplay Interpreter | OpenGL Renderer and Time-based Animation |
Python | Delphi 7 Pascal | Delphi 7 Pascal, OpenGL (1.x) |
|
|
|
Useful Code Snippets
As I was writing new engine from scratch I collected a bunch of useful tricks. I'm sharing it for everyone!
Enabling V-SYNC (GL)
type TWglSwapIntervalEXT = procedure(interval: GLInt); stdcall; var wglSwapIntervalEXT: TWglSwapIntervalEXT;
procedure InitVSync; begin if not Assigned(wglSwapIntervalEXT) then begin wglSwapIntervalEXT := wglGetProcAddress('wglSwapIntervalEXT'); if not Assigned(wglSwapIntervalEXT) then Exit; end; wglSwapIntervalEXT(1); end;
Fixing Window Blinking (Redraing)
Rendering OpenGL content in a window is in conflict with internal redrawing of a window. To fix this you need to disable this by overwiting internal procedure.
TFormDemo = class(TForm) private procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; procedure TFormDemo.WMEraseBkgnd(var Message: TWMEraseBkgnd); begin Message.Result := 1; end;
Lerping
function Lerp(A, B, T: glFloat; Linear: Boolean): glFloat; var TD: Double; begin if Linear then begin Result := A + (B - A) * T; end else begin TD := (1-Cos(T*PI))/2; Result := A*(1-TD)+B*TD; end; end;
Accessing Relative Files
At the creation of a window set current path.
SetCurrentDir(ExtractFilePath(Application.ExeName));
Then access file in current (binary) directory.
var CSVFile: TextFile; Line: String; Fields: TStringList; begin AssignFile(CSVFile, 'screenplay.csv'); Reset(CSVFile); Fields := TStringList.Create; Fields.Delimiter := ','; try while not Eof(CSVFile) do begin ReadLn(CSVFile, Line); Fields.DelimitedText := Line; ... end finally Fields.Free; CloseFile(CSVFile); end; end;
Frame Time Calculation
var LastFrameTime, CurrentTime, FrameTime: TDateTime;
// render loop begin CurrentTime := Now; FrameTime := MilliSecondsBetween(CurrentTime, LastFrameTime); LastFrameTime := CurrentTime; ... render frame ... LabelFrameTime.Caption := Format('%.2fms', [FrameTime]); end;
Loading Models from Resourece File
Create resource definition file.
models.rc
Inside write resource name and path to actual file. One file per line.
SM_Skybox RCDATA Models/skybox.obj SM_Terrain RCDATA Models/terrain.obj SM_Model01 RCDATA Models/model_01.obj ...
Compile resource package. This command will create models.RES package file.
brcc32 models.rc
Add resource files (package + definitions).
implementation {$R 'models.RES' 'models.rc'}
Reading data from resource.
function ReadOBJFileFromResource(const ResourceName: string): TModel; var ResStream: TResourceStream; FileLines: TStringList; i,f: Integer; Line: string; Model: TModel; begin ResStream := TResourceStream.Create(HInstance, ResourceName, RT_RCDATA); FileLines := TStringList.Create; try FileLines.LoadFromStream(ResStream); for i := 0 to FileLines.Count - 1 do begin Line := Trim(FileLines[i]); ... read data for model Model ... end; finally FileLines.Free; end; Result := Model; end;
Model := ReadOBJFileFromResource('SM_Model01');
Calculate Position Between Points for Lerp
Based on current demo time calculate value for lerp between two points in timeline. This makes time-based animation easy.
function CalcPos(A,B,T: glFloat): glFloat; begin Result := 0; if A<>B then begin Result := (T-A)/(B-A); end else begin Result := Max(0.0,Min(Result,1.0)); end; end;
Pos := CalcPos(Timeline[Prev].Timestamp, Timeline[Next].Timestamp, DemoTime); Position.X := Lerp(Timeline[Prev].Params[_X], Timeline[Next].Params[_X], Pos);
Gallery
...
Links
...