unit renderobject; {$mode objfpc}{$H+} {$modeswitch advancedrecords} interface uses Classes, SysUtils,GL, GLext, glu, types; type TRenderObject=class(TObject) private children: array of TRenderObject; fTextureCoords: record x: single; y: single; x2: single; y2: single; end; protected fChildrenOnly: boolean; procedure renderRelative; virtual; function getWidth:single; virtual; abstract; procedure setWidth(w: single); virtual; function getHeight:single; virtual; abstract; procedure setHeight(h: single); virtual; function getTexture: integer; virtual; abstract; function getLeft: single; virtual; function getRight: single; virtual; function getTop: single; virtual; function getBottom: single; virtual; public valid: boolean; x,y: single; rotationpoint: TPointF; rotation: single; procedure render; virtual; procedure addChild(child: TRenderObject); procedure removeChild(child: TRenderObject); procedure setTextureCoords(_x: single; _y: single; _x2: single; _y2: single); constructor create; property width: single read getWidth write setWidth; property height: single read getHeight write setHeight; property left: single read getLeft; property right: single read getRight; property top: single read getTop; property bottom: single read getBottom; property texture: integer read getTexture; property childrenonly: boolean read fChildrenOnly write fChildrenOnly; end; implementation function TRenderObject.getLeft: single; begin //todo: deal with rotation (or just let the caller deal with that) result:=x-width*((rotationpoint.x+1)/2); end; function TRenderObject.getRight: single; begin //rx=-1 : x+0 | x+w*0 //rx=0 : x+w/2 | x+w*0.5 //rx=1 : x+w/1 | x+w*1 //(rx+1)/2: //-1 -> (-1+1)/2=0/2=0 //0 -> (0+1)/2=1/2=0.5 //1 -> (1+1)/2=2/2=1 result:=x+width*((rotationpoint.x+1)/2); end; function TRenderObject.getTop: single; begin result:=y-height*((rotationpoint.y+1)/2); end; function TRenderObject.getBottom: single; begin result:=y+height*((rotationpoint.y+1)/2); end; procedure TRenderObject.setWidth(w: single); begin // end; procedure TRenderObject.setHeight(h: single); begin // end; procedure TRenderObject.addChild(child: TRenderObject); begin setlength(children, length(children)+1); children[length(children)-1]:=child; end; procedure TRenderObject.removeChild(child: TRenderObject); var i,j: integer; begin for i:=0 to length(children)-1 do if children[i]=child then begin for j:=i to length(children)-2 do children[j]:=children[j+1]; setlength(children, length(children)-1); end; end; procedure TRenderObject.setTextureCoords(_x: single; _y: single; _x2: single; _y2: single); begin fTextureCoords.x:=_x; fTextureCoords.y:=_y; fTextureCoords.x2:=_x2; fTextureCoords.y2:=_y2; end; procedure TRenderObject.renderRelative; var w, h: single; dw,dh: single; rx,ry: single; i: integer; begin //set the texture glBindTexture(GL_TEXTURE_2D, getTexture); glActiveTexture(GL_TEXTURE0); w:=width; // / 2; h:=height;// / 2; dw:=width / 2; dh:=height / 2; glTranslatef(x,-y,0); glRotatef(-rotation,0,0,0.5); rx:=-rotationpoint.x; ry:=-rotationpoint.y; if rx<>0 then rx:=dw*rx; if ry<>0 then ry:=-1*dh*ry; if fChildrenOnly=false then begin glBegin(GL_QUADS); // Each set of 4 vertices form a quad glTexCoord2f(fTextureCoords.x,fTextureCoords.y2); glVertex2f(rx+dw*-1, ry+dh*-1); glTexCoord2f(fTextureCoords.x2,fTextureCoords.y2); glVertex2f(rx+dw, ry+dh*-1); glTexCoord2f(fTextureCoords.x2,fTextureCoords.y); glVertex2f(rx+dw, ry+dh); glTexCoord2f(fTextureCoords.x,fTextureCoords.y); glVertex2f(rx+dw*-1, ry+dh); glEnd(); end; //render children for i:=0 to length(children)-1 do begin glPushMatrix(); children[i].renderRelative; glPopMatrix(); end; end; procedure TRenderObject.render; begin glLoadIdentity(); glPushMatrix(); renderRelative(); glPopMatrix(); end; constructor TRenderObject.create; begin fTextureCoords.x:=0; fTextureCoords.y:=0; fTextureCoords.x2:=1; fTextureCoords.y2:=1; end; end.