Game Engine

Alles, was nicht in die anderen Foren gehört.

Moderator: jNizM

User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Game Engine

02 Sep 2014, 08:21

Ich habe mich mal daran gesetzt eine Game Engine für AHK zu schreiben.
Bissher habe ich tatsächlich einige Ergebnisse zu Tage gefördert.
Ich habe nun ungefähr ein Drittel geschafft und da es tatsächlich eine Menge arbeit ist habe ich mich gefragt ob es überhaupt jemand benutzen würde, oder ob dass ein Zweckloses unterfangen ist und wenn ja was ihr verändern würdet.

Bisher habe ich nur die Zeichen Klasse fertig, möchte aber schonmal meine Ideen teilen:
Eine World Klasse enthält die ganzen Welt Daten, sowie die Möglichkeit mehr von diesen, von der Festplatte, bei Bedarf, nachzuladen. Jedes Element der World Klasse ruft andere Funktionen in der Zeichen, oder Audio Klasse auf. Die Zeichen Klasse Übernimmt für uns das neu Zeichnen bei jedem neuen Bild. Sie enthät 3 Unterklassen DrawSpace (eine seperate Zeichenoberfläche). Der HauptDrawSpace wird bei jedem neuen Bild gezeichnet. In diesen Können dann wieder andere DrawSpaces oder Modelle gezeichnet werden. Modelle sind an sich nur benannte DrawSpaces die unveränderlich sind, und andere komplexere Zeichen Daten enthalten können.
Modelle kann man auch selber erzeugen. Vorgegeben werden ein paar Grundformen (Quadrat...).
Die ganzen Modelle und DrawSpaces werden mit Daten über Textur und Position genauer bestimmt (die beiden anderen Unterklassen).
Die Position und Textur sind im nachhinein noch veränderbar.

Hier ist bis jetzt das Script:
Danke an Bentschi für die MCode funktion.

Code: Select all



Class Draw
{
	
	__New()
	{
		This.OpenGL := New OpenGL()
		This.Model.Rect:=This.OpenGL.CreateList()
		This.OpenGL.TexCoord(0,0),This.OpenGL.Vertex(-0.5,-0.5,0)
		This.OpenGL.TexCoord(1,0),This.OpenGL.Vertex(0.5,-0.5,0)
		This.OpenGL.TexCoord(1,1),This.OpenGL.Vertex(0.5,0.5,0)
		This.OpenGL.TexCoord(0,1),This.OpenGL.Vertex(-0.5,0.5,0)
		This.OpenGL.EndList()
	}
	
	RegisterModel(Name,DrawSpace)
	{
		This.Model[Name]:=This.OpenGL.CreateList()
		DrawFunc:=DrawSpace[1]
		DrawFunc.(This,DrawSpace)
		This.OpenGL.EndList()
	}
	
	UnregisterModel(Name)
	{
		This.OpenGL.DeleteList(This.Model.Remove(Name))
	}
	
	CreatePositionData()
	{
		return New This.PositionData()
	}
	
	CreateDrawSpace()
	{
		return New This.DrawSpace(This)
	}
	
	CreateTextureData()
	{
		static Index:=-1
		return New This.TextureData(Index++,This.OpenGL.Textures)
	}
	
	Class PositionData
	{
		
		
		__New()
		{
			This.pMat := DllCall("GlobalAlloc", "UInt", 0, "Ptr", 128)
		}
		
		__Delete()
		{
			DllCall("GlobalFree", "ptr", This.Pmat)
		}
		
		Translate(X,Y,Z)
		{
		static TranslateFunc:=MCode( "1,x86:8b442404dd4060dd4068dd4070dd442408dd00d8c9dec4dd4008d8c9dec3dd4010dec9dec1dd442410dd4020d8c9dec4dd4028d8c9dec3dd4030dec9dec1dd442418dd4040d8c9dec4dd4048d8c9dec3dd4050dec9dec1dd5870dd5868dd5860c21c00")
			DllCall(TranslateFunc,"Ptr",This.pMat,"Double",X,"Double",Y,"Double",Z)
		}


		RotateX(Deg)
		{
		static RotateXFunc:=MCode("1,x86:8b44240489c183c02083c140dd442408d9ebdec968b4000000da34245ad9fbdd00dd01d9c1d8cbd9c1d8cddee9dd18d9c3decad8cadec1dd1983c00883c108dd00dd01d9c1d8cbd9c1d8cddee9dd18d9c3decad8cadec1dd1983c00883c108dd00dd01d9c1d8cbd9c1d8cddee9dd18decadecadec1dd19c20c")
			DllCall(RotateXFunc,"Ptr",This.pMat,"Double",Deg)
		}

		RotateY(Deg)
		{
		static RotateYFunc:=MCode("1,x86:8b44240489c183c040dd442408d9ebdec968b4000000da34245ad9fbdd00dd01d9c1d8cbd9c1d8cddee9dd18d9c3decad8cadec1dd1983c00883c108dd00dd01d9c1d8cbd9c1d8cddee9dd18d9c3decad8cadec1dd1983c00883c108dd00dd01d9c1d8cbd9c1d8cddee9dd18decadecadec1dd19c20c00")
			DllCall(RotateYFunc,"Ptr",This.pMat,"Double",Deg)
		}

		RotateZ(byref Matrix,Deg)
		{
		static RotateZFunc:=MCode("1,x86:8b44240489c183c120dd442408d9ebdec968b4000000da34245ad9fbdd00dd01d9c1d8cbd9c1d8cddee9dd18d9c3decad8cadec1dd1983c00883c108dd00dd01d9c1d8cbd9c1d8cddee9dd18d9c3decad8cadec1dd1983c00883c108dd00dd01d9c1d8cbd9c1d8cddee9dd18decadecadec1dd19c20c00")
			DllCall(RotateZFunc,"Ptr",This.pMat,"Double",Deg)
		}

		Scale(byref Matrix,X,Y,Z)
		{
		static ScaleFunc:=MCode("1,x86:8b442404dd442408dd00d8c9dd1883c008dd00d8c9dd1883c008dd00dec9dd1883c010dd442410dd00d8c9dd1883c008dd00d8c9dd1883c008dd00dec9dd1883c010dd442418dd00d8c9dd1883c008dd00d8c9dd1883c008dd00dec9dd18c21c00")
			DllCall(ScaleFunc,"Ptr",This.pMat,"Double",X,"Double",Y,"Double",Z)
		}
		
	}
	
	Class DrawSpace
	{
		
		__New(Draw)
		{
			This.Draw:=Draw
		}
		
		DrawDrawSpace(DrawSpace,PositionData)
		{
			This.Insert([This.Draw.DrawSpaceFunc,PositionData])
		}
		
		DrawModel(ModelName,PositionData,TextureData)
		{
			If IsObject(TextureData)
				This.Insert([This.Draw.ModelFuncTex,ModelName,PositionData,TextureData])
			This.Insert([This.Draw.ModelFunc,ModelName,PositionData])
		}
	}
	
	Class TextureData
	{
		
		__New(Index,Textures)
		{
			This.Index:=Index
			This.Textures:=Textures
		}
		
		ChooseTexture(Name)
		{
			This.Texture:=This.Textures[Name]
		}
		
	}
	
	DrawSpaceFunc(Data)
	{
		ApplyPosition(Data[3])
		DrawDrawSpace(Data[2])
		RemovePosition(Data[3])
	}
	
	ModelFuncTex(Data)
	{
		This.ApplyPosition(Data[3])
		This.ApplyTexture(Data[4])
		This.DrawModel(Data[2])
		This.RemovePosition(Data[3])
	}
	
	ModelFunc(Data)
	{
		This.ApplyPosition(Data[3])
		This.DrawModel(Data[2])
		This.RemovePosition(Data[3])
	}
	
	ApplyPosition(PositionData)
	{
		This.OpenGL.PushMatrix()
		This.OpenGL.MultMatrix(PositionData.pMat)
	}
	
	RemovePosition(PositionData)
	{
		This.OpenGL.PopMatrix()
	}
	
	ApplyTexture(TextureData)
	{
		static Index
	    If (TextureData.Index!=Index)
		{
			This.OpenGL.BindTexture(TextureData.Texture)
			Index:=TextureData.Index
		}
	}
	
	DrawModel(Name)
	{
		This.OpenGL.CallList(This.Model[Name])
	}
	
	DrawDrawSpace(DrawSpace)
	{
		For Each,Element in DrawSpace
		{
			DrawFunc:=Element[1]
			DrawFunc.(This,Element)
		}
	}
	
}

Class OpenGL
{
	
	__New(Settings)
	{
		This.Textures := new TextureHandler(This)
		This.Setings  := Settings
		This.hgl  := DllCall("LoadLibrary", "str", "opengl32")
		This.hglu := DllCall("LoadLibrary", "str", "glu32")
		This.SwapBuffersProc  := DllCall("GetProcAddress","ptr",DllCall("GetModuleHandle","str","gdi32"),"astr","SwapBuffers")
		This.BindTextureProc  := DllCall("GetProcAddress","ptr",This.hgl,"astr","glBindTexture")
		This.LoadIdentityProc := DllCall("GetProcAddress","ptr",This.hgl,"astr","glLoadIdentity")
		This.Vertex3dProc     := DllCall("GetProcAddress","ptr",This.hgl,"astr","glVertex3d")
		This.TexCoord2dProc   := DllCall("GetProcAddress","ptr",This.hgl,"astr","glTexCoord2d")
		This.EnableProc       := DllCall("GetProcAddress","ptr",This.hgl,"astr","glEnable")
		This.BeginProc        := DllCall("GetProcAddress","ptr",This.hgl,"astr","glBegin")
		This.EndProc          := DllCall("GetProcAddress","ptr",This.hgl,"astr","glEnd")
		This.GenListsProc     := DllCall("GetProcAddress","ptr",This.hgl,"astr","glGenLists")
		This.NewListProc      := DllCall("GetProcAddress","ptr",This.hgl,"astr","glNewList")
		This.EndListProc      := DllCall("GetProcAddress","ptr",This.hgl,"astr","glEndList")
		This.CallListProc     := DllCall("GetProcAddress","ptr",This.hgl,"astr","glCallList")
		This.DeleteListsProc  := DllCall("GetProcAddress","ptr",This.hgl,"astr","glDeleteLists")
		This.MultMatrixProc   := DllCall("GetProcAddress","ptr",This.hgl,"astr","glMultMatrix")
		This.PushMatrixProc   := DllCall("GetProcAddress","ptr",This.hgl,"astr","glPushMatrix")  
		This.PopMatrixProc    := DllCall("GetProcAddress","ptr",This.hgl,"astr","glPopMatrix")  
	}
	
	LoadMipMap(W,H,Ptr)
	{
		DllCall("opengl32\glGenTextures","Int",1,"UInt*",Texture)
		This.BindTexture(Texture)
		DllCall("opengl32\glTexParameteri","UInt",0xDE1,"UInt",0x2801,"Int",0x2601)
		DllCall("opengl32\glTexParameteri","UInt",0xDE1,"UInt",0x2800,"Int",0x2601)
		DllCall("glu32\gluBuild2DMipmaps","UInt",0xDE1,"uint",4,"Int",W,"Int",H,"Int",0x1908,"UInt",0x1401,"Ptr", Ptr)
		This.BindTexture(0)
		return Texture
	}
	
	UnloadMipMap(Texture)
	{
		If DllCall("opengl32\glIsTexture", "UInt", Texture, "UInt")
			DllCall("opengl32\glDeleteTextures","Int",1,"UInt*",Texture)
	}

	BindTexture(Texture)
	{
		DllCall(This.BindTextureProc,"UInt",0xDE1,"UInt",Texture)
	}
	
	FlushToScreen()
	{
		DllCall(This.SwapBuffersProc,"UInt",This.Gui.hDC)
		DllCall(This.ClearProc,"UInt",0x4100)
		This.LoadIdentity()
	}
	
	LoadIdentity()
	{
		DllCall(This.LoadIdentityProc)
	}
	
	Enable(Cap)
	{
		DllCall(This.EnableProc, "UInt", Cap)
	}
	
	TexCoord(X,Y)
	{
		DllCall(This.TexCoord2dProc,"Double",X,"Double",Y)
	}
	
	Vertex(X,Y,Z)
	{
		DllCall(This.Vertex3dProc,"Double",X,"Double",Y,"Double",Z)
	}
	
	Begin(Cap=0x7)
	{
		DllCall(This.BeginProc,"UInt",Cap)
	}
	
	End()
	{
		DllCall(This.EndProc)
	}
	
	CreateList()
	{
		Index:=DllCall(This.GenListsProc,"Int",1)
		DllCall(This.NewListProc,"UInt",Index,"UInt",0x1300)
		return Index
	}
	
	EndList()
	{
		DllCall(This.EndListProc)
	}
	
	DeleteList(Index)
	{
		DllCall(This.DeleteListsProc,"UInt",Index,"UInt",1)
	}
	
	MultMatrix(pMat)
	{
		DllCall(This.MultMatrixProc,"Ptr",pMat)
	}
	
	PushMatrix()
	{
		DllCall(This.PushMatrixProc)
	}
	
	PopMatrix()
	{
		DllCall(This.PopMatrixProc)
	}
}

Class TextureHandler{
	__new(OpenGL,Settings){
		This.OpenGL   := OpenGL
		This.Settings := Settings
	}
	
	__Delete(){
		If IsObject(this.CurrentlyLoaded)
			This.UnloadTextures()
	}
	
	LoadTextures(File="Tex.tex")
	{
		This.CurrentlyLoaded:=[]
		File  := FileOpen(File,"r")
		If (!IsObject(File))
			Error("Fehler beim laden der Texturdatei`n0400")
		Size  := File.Length
		VarSetCapacity(Texes,Size)
		If (!File.Length)
			Error("Fehler beim laden der Texturdatei`n0401")
		File.RawRead(Texes,Size)
		File.Close()
		Index := 0
		N:=NumGet(Texes,Index,"uint")
		If (!N)
			Error("Fehler beim laden der Texturdatei`n0402")
		Index += 4
		Loop %N%
			This.CurrentlyLoaded.Insert(This.LoadTexture(Texes,Readindex))		
	}
	
	LoadTexture(byref Data,byref Index){
		W     := NumGet(Data,Index,"uint")
		Index += 4
		H     := NumGet(Data,Index,"uint")
		Index += 4
		If !(W&&H)
			Error("Fehler beim Laden einer Textur`n0403")
		Name  := Strget(&Data+Index,"utf-8")
		Index += StrPut(Name,"utf-8")
		If !(Name~="^[\w_]{4,15}$")
			Error("Fehler beim Laden einer Textur`n0404")
		If (IsFunc(This[Name])||This.HasKey(Name))
			Error("Fehler beim Laden einer Textur`n0405")
		This[Name]:=This.OpenGL.LoadMipMap(W,H,&Data+Index)
		Index += W*H*4
		return Name
	}
	
	UnloadTextures()
	{
		For each,Texture in CurrentlyLoaded
			This.OpenGL.UnloadMipMap(Texture)
		This.Remove("CurrentlyLoaded")
	}
}





MCode(mcode)
{
  c := (A_PtrSize=8) ? "x64" : "x86"
  if (!regexmatch(mcode, "^([0-9]+),(" c ":|.*?," c ":)([^,]+)", m))
    return
  if (!DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", t:=[4,1][m1], "ptr", 0, "uint*", s, "ptr", 0, "ptr", 0))
    return
  p := DllCall("GlobalAlloc", "uint", 0, "ptr", s, "ptr")
  if (A_Is64bitOS)
    DllCall("VirtualProtect", "ptr", p, "ptr", s, "uint", 0x40, "uint*", op)
  if (DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", t, "ptr", p, "uint*", s, "ptr", 0, "ptr", 0))
    return p
  DllCall("GlobalFree", "ptr", p)
}
Recommends AHK Studio
Bentschi
Posts: 22
Joined: 02 Oct 2013, 18:45

Re: Game Engine

02 Sep 2014, 11:52

Hab das nachfolgende Projekt mal auf Eis gelegt...
Möglicherweise kannst du ja was davon verwenden.

In TODO hab ich vermerkt was mir noch fehlt.
Was mir noch auf die Schnelle einfällt ist, dass ich die Kameraklasse nicht richtig getestet habe.
Und ein problem mit Licht und Materialien -> die ich in nem Shader berechnen wollte für multiple Lichter (mehr als die 8 die meine Graka berechnen würde).
Alternativ könnte man auch den Lichtshader weg lassen und das Hauptlicht (zB. Sonne) und die dem Model nächsten 7 Lichter verwenden (Jede Graka mit OpenGL unterstützt min. 8 bis max. 32).
Ansonsten sollte alles relativ performant sein, da alle Objekte Displaylisten verwenden.
Geht zwar etwas auf den Grafikspeicher, aber Texturen sind ohnehin schlimmer für den Speicher :D .
Die Idee ist, wenn sich kein Model, Textur, Kamera, ... in der Szene ändert reicht ein einziger Aufruf einer Displayliste die die komplette Szene zeichnet.
Dann noch wglMakeCurrent, SwapBuffers und glClear... sind nur 4 DllCalls.
Btw. diese Engine war auch dafür gedacht, dass mehrere Monitore in Vollbild bzw. mehrere Fenster verwendet werden können.
Daher die umständliche Initialisierung der Renderer-Klasse, die untereinander die Renderkontexte (Texturen, Displaylisten, etc.) teilen.

Code: Select all

; TODO:
;============================
; - Multiple lights
; - Shaders (delete, uniform)
; - Model loading
; - Bumpmaps
; - Fog
; - Blending

#NoEnv
SetWorkingDir, % A_ScriptDir
SetBatchLines, -1

; Init GUI
Gui, +LastFound
Gui, show, w640 h480, AHK 3D Engine

; Init 3D stuff
renderer := new 3D.Renderer(WinExist())
if (!IsObject(renderer))
  MsgBox, % "ERROR: Can't create renderer (" renderer ")"
viewport := new 3D.Viewport(renderer)
camera := new 3D.Camera()
camera.perspective(90, viewport, 0.1, 100)

; Load a texture
tex := new 3D.Texture()
tex.load("test.jpg")

; Create a material
mat := new 3D.Material()
mat.texture(tex)

; Create a cube model
model := new 3D.Model()
a := 0.5
b := -0.5
;pos:    x,y,z
;tex:    | | |  x,y
;normal: | | |  | |  x,y,z
;        | | |  | |  | | |
cube := [a,a,a, 0,0, 0,0,1,   b,a,a, 1,0, 0,0,1,   b,b,a, 1,1, 0,0,1,   a,b,a, 0,1, 0,0,1   ;front
       , a,a,a, 0,0, 1,0,0,   a,b,a, 1,0, 1,0,0,   a,b,b, 1,1, 1,0,0,   a,a,b, 0,1, 1,0,0   ;right
       , a,a,a, 0,0, 0,1,0,   b,a,a, 1,0, 0,1,0,   b,a,b, 1,1, 0,1,0,   a,a,b, 0,1, 0,1,0   ;top
       , a,a,b, 0,0, 0,0,-1,  b,a,b, 1,0, 0,0,-1,  b,b,b, 1,1, 0,0,-1,  a,b,b, 0,1, 0,0,-1  ;back
       , b,a,a, 0,0, -1,0,0,  b,b,a, 1,0, -1,0,0,  b,b,b, 1,1, -1,0,0,  b,a,b, 0,1, -1,0,0  ;left
       , a,b,a, 0,0, 0,-1,0,  b,b,a, 1,0, 0,-1,0,  b,b,b, 1,1, 0,-1,0,  a,b,b, 0,1, 0,-1,0] ;bottom
model.setQuads("3V2T3N", cube, mat)
model.translate(0, 0, -1.2)

light := new 3D.Light()
light.ambient(0.5, 0.5, 0.5, 1.0)
light.diffuse(1.0, 1.0, 1.0, 1.0)
light.specular(0.2, 0.2, 0.2, 1.0)
light.position(0.0, 0.5, 0.0, 1.0)

shader := new 3D.Shader()
shader.vertex("
(Join`n
    void main(void)
    {
      gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
      gl_TexCoord[0] = gl_MultiTexCoord0;
    }
)")
shader.fragment("
(Join`n
    uniform sampler2D Texture0;
    void main(void)
    {
      gl_FragColor = texture2D(Texture0, vec2(gl_TexCoord[0]));
    }
)")

scene := new 3D.Scene()
scene.addChild(light)
scene.addChild(model)
scene.addChild(shader)

stopped := 0
SetTimer, timer, 30
return

timer:
if (!stopped && (GetKeyState("up") || GetKeyState("down") || GetKeyState("left") || GetKeyState("right")))
  stopped := 1
if (!stopped)
  model.rotate(1, 0.94, 1.71, 0.26)
if (stopped && GetKeyState("up"))
  model.rotate(1, 1, 0, 0)
if (stopped && GetKeyState("down"))
  model.rotate(-1, 1, 0, 0)
if (stopped && GetKeyState("left"))
  model.rotate(1, 0, 1, 0)
if (stopped && GetKeyState("right"))
  model.rotate(-1, 0, 1, 0)
renderer.render(scene, viewport, camera)
return

class 3D
{
  static hOpenGL := DllCall("LoadLibrary", "str", "opengl32", "ptr")
  static hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus", "ptr")
  class Renderer
  {
    static shareRenderer := 0
    __new(wnd)
    {
      this.objType := "3D.Renderer"
      if (!isObject(3D.Renderer.shareRenderer) && wnd!="_share")
        3D.Renderer.shareRenderer := new 3D.Renderer("_share")
      if (wnd=="_share")
      {
        lf := WinExist()
        Gui, _3D_Renderer_ShareRenderer: +LastFound
        Gui, _3D_Renderer_ShareRenderer:show, hide
        wnd := WinExist()
        WinExist("ahk_id " lf)
      }
      else if (!isObject(3D.Renderer.shareRenderer))
        return 3D.Renderer.shareRenderer
      this.hWnd := (isObject(wnd) && wnd.hasKey("hWnd")) ? wnd.hWnd : wnd
      if (!(this.hDC := DllCall("GetDC", "ptr", this.hWnd, "ptr")))
        return -3 ; ERROR: Can't get the device context
      VarSetCapacity(pfd, 40, 0)
      NumPut(40, pfd, 0, "ushort")
      NumPut(1, pfd, 2, "ushort")
      NumPut(0x25, pfd, 4, "uint")
      NumPut(32, pfd, 9, "uchar")
      NumPut(16, pfd, 23, "uchar")
      if (!(pf := DllCall("ChoosePixelFormat", "ptr", this.hDC, "ptr", &pfd, "int")))
        return -4 ; ERROR: Can't choose the pixel format
      if (!DllCall("SetPixelFormat", "ptr", this.hDC, "int", pf, "ptr", &pfd))
        return -5 ; ERROR: Can't select the pixel format
      if (!(this.hRC := DllCall("opengl32\wglCreateContext", "ptr", this.hDC, "ptr")))
        return -6 ; ERROR: Can't create the render context
      if (!DllCall("opengl32\wglMakeCurrent", "ptr", this.hDC, "ptr", this.hRC))
        return -7 ; ERROR: Can't activate the render context
      if (IsObject(3D.Renderer.shareRenderer) && !DllCall("opengl32\wglShareLists", "ptr", this.hRC, "ptr", 3D.Renderer.shareRenderer.hRC))
        return -8 ; ERROR: Can't share lists between render context's
      DllCall("opengl32\glShadeModel", "uint", 0x1D01)
      DllCall("opengl32\glHint", "uint", 0x0C50, "uint", 0x1102)
      DllCall("opengl32\glEnable", "uint", 0x0DE1) ;texture
      DllCall("opengl32\glEnable", "uint", 0x4000) ;light
      DllCall("opengl32\glDepthFunc", "uint", 0x0203)
      DllCall("SwapBuffers", "ptr", this.hDC)
    }
    __delete()
    {
      if (this.hRC)
      {
        DllCall("opengl32\wglMakeCurrent", "ptr", 0, "ptr", 0)
        DllCall("opengl32\wglDeleteContext", "ptr", this.hRC)
      }
      if (this.hDC)
        DllCall("ReleaseDC", "ptr", this.hWnd, "ptr", this.hDC)
    }
    render(scene, viewport, camera)
    {
      DllCall("opengl32\wglMakeCurrent", "ptr", this.hDC, "ptr", this.hRC)
      DllCall("opengl32\glViewport", "int", viewport.x, "int", viewport.y, "int", viewport.width, "int", viewport.height)
      DllCall("opengl32\glClear", "uint", 0x00004100)
      DllCall("opengl32\glCallList", "uint", camera.list)
      DllCall("opengl32\glCallList", "uint", scene.list)
      DllCall("SwapBuffers", "ptr", this.hDC)
    }
  }
  class Viewport
  {
    __new(renderer=0)
    {
      this.objType := "3D.Viewport"
      this.x := this.y := 0
      this.width := this.height := 512
      if (renderer.objType="3D.Renderer")
        this.renderer(renderer)
    }
    renderer(renderer)
    {
        VarSetCapacity(rc, 16, 0)
        DllCall("GetClientRect", "ptr", renderer.hWnd, "ptr", &rc)
        this.width := NumGet(rc, 8, "int")
        this.height := NumGet(rc, 12, "int")
    }
    setViewport(x=0, y=0, width=512, height=512)
    {
      this.x := x
      this.y := y
      this.width := width
      this.height := height
    }
  }
  class Scene
  {
    __new()
    {
      this.list := DllCall("opengl32\glGenLists", "uint", 1, "uint")
      this.shaderList := DllCall("opengl32\glGenLists", "uint", 1, "uint")
      this.childs := []
      this.shaders := []
    }
    __delete()
    {
      if (this.list)
        DllCall("opengl32\glFreeLists", "uint", this.list, "uint", 1)
      if (this.shaderList)
        DllCall("opengl32\glFreeLists", "uint", this.list, "uint", 1)
    }
    _update()
    {
      glUseProgram := 3D._glProc("glUseProgramObjectARB", "glUseProgram")
      if (glUseProgram)
      {
        DllCall("opengl32\glNewList", "uint", this.shaderList, "uint", 0x1300)
        for sk,sv in this.shaders
          DllCall(glUseProgram, "uint", sv.program)
        DllCall("opengl32\glEndList")
      }
      DllCall("opengl32\glNewList", "uint", this.list, "uint", 0x1300)
      for k,v in this.childs
      {
        DllCall("opengl32\glCallList", "uint", this.shaderList)
        DllCall("opengl32\glCallList", "uint", v.list)
        if (glUseProgram)
          DllCall(glUseProgram, "uint", 0)
      }
      DllCall("opengl32\glEndList")
    }
    addChild(obj)
    {
      if (obj.objType="3D.Model" || obj.objType="3D.Light")
      {
        this.childs[Object(obj)] := obj
        this._update()
      }
      if (obj.objType="3D.Shader")
      {
        this.shaders[Object(obj)] := obj
        this._update()
      }
    }
  }
  class Transform
  {
    __new()
    {
      this.objType := "3D.Transform"
      this.ptr := DllCall("HeapAlloc", "ptr", DllCall("GetProcessHeap", "ptr"), "uint", 0x8, "ptr", 64, "ptr")
      this.list := DllCall("opengl32\glGenLists", "uint", 1, "uint")
      this.identity()
      this._update()
    }
    _update()
    {
      DllCall("opengl32\glNewList", "uint", this.list, "uint", 0x1300)
      DllCall("opengl32\glMultMatrixf", "ptr", this.ptr)
      DllCall("opengl32\glEndList")
    }
    __delete()
    {
      if (this.ptr)
        DllCall("HeapFree", "ptr", DllCall("GetProcessHeap", "ptr"), "uint", 0, "ptr", this.ptr)
      if (this.list)
        DllCall("opengl32\glFreeLists", "uint", this.list, "uint", 1)
    }
    _glTransform(p*)
    {
      DllCall("opengl32\glMatrixMode", "uint", 0x1700)
      DllCall("opengl32\glLoadMatrixf", "ptr", this.ptr)
      DllCall(p*)
      DllCall("opengl32\glGetFloatv", "uint", 0x0BA6, "ptr", this.ptr)
      this._update()
    }
    identity()
    {
      return this._glTransform("opengl32\glLoadIdentity")
    }
    translate(x, y, z)
    {
      return this._glTransform("opengl32\glTranslatef", "float", x, "float", y, "float", z)
    }
    rotate(angle, x, y, z)
    {
      return this._glTransform("opengl32\glRotatef", "float", angle, "float", x, "float", y, "float", z)
    }
    scale(x, y, z)
    {
      return this._glTransform("opengl32\glScalef", "float", x, "float", y, "float", z)
    }
  }
  class Camera
  {
    __new()
    {
      this.objType := "3D.Camera"
      this.transform := new 3D.Transform()
      this.list := DllCall("opengl32\glGenLists", "uint", 1, "uint")
      this.depthTest := "_?"
    }
    __delete()
    {
      if (this.list)
        DllCall("opengl32\glFreeLists", "uint", this.list, "uint", 1)
    }
    identity()
    {
      return this.transform.identity()
    }
    translate(x, y, z)
    {
      return this.transform.translate(-x, -y, -z)
    }
    rotate(angle, x, y, z)
    {
      return this.transform.rotate(angle, -x, -y, -z)
    }
    scale(x, y, z)
    {
      return this.transform.scale(-x, -y, -z)
    }
    _glCamera(p*)
    {
      DllCall("opengl32\glNewList", "uint", this.list, "uint", 0x1300)
      DllCall("opengl32\glMatrixMode", "uint", 0x1701)
      DllCall("opengl32\glLoadIdentity")
      DllCall(p*)
      DllCall("opengl32\glMatrixMode", "uint", 0x1700)
      DllCall("opengl32\glLoadIdentity")
      DllCall("opengl32\glCallList", "uint", this.transform.list)
      DllCall((this.depthTest) ? "opengl32\glEnable" : "opengl32\glDisable", "uint", 0x0B71)
      DllCall("opengl32\glEndList")
    }
    ortho(left, right, bottom, top, near, far)
    {
      if (this.depthTest=="_?")
        this.depthTest := 0
      this._glCamera("opengl32\glOrtho", "double", left, "double", right, "double", bottom, "double", top, "double", near, "double", far)
    }
    frustum(left, right, bottom, top, near, far)
    {
      if (this.depthTest=="_?")
        this.depthTest := 1
      this._glCamera("opengl32\glFrustum", "double", left, "double", right, "double", bottom, "double", top, "double", near, "double", far)
    }
    perspective(fov, aspect, near, far)
    {
      static pi := 3.1415926535897
      aspect := (aspect.hasKey("objType") && aspect.objType="3D.Viewport") ? aspect.width/aspect.height : aspect
      h := tan(fov/360*pi)*near
      w := h*aspect
      this.frustum(-w, w, -h, h, near, far)
    }
  }
  class Model
  {
    __new()
    {
      this.objType := "3D.Model"
      this.transform := new 3D.Transform()
      this.list := DllCall("opengl32\glGenLists", "uint", 1, "uint")
      this.data := []
    }
    __delete()
    {
      if (this.list)
        DllCall("opengl32\glFreeLists", "uint", this.list, "uint", 1)
    }
    _update()
    {
      static f := {1:0, 2:1, 3:4, 4:7}
      DllCall("opengl32\glNewList", "uint", this.list, "uint", 0x1300)
      DllCall("opengl32\glPushMatrix")
      DllCall("opengl32\glCallList", "uint", this.transform.list)
      for i, d in this.data
      {
        if (d[4].objType!="3D.Material")
          DllCall("opengl32\glDisable", "uint", 0x0B50)
        if (d[4].objType="3D.Material")
        {
          DllCall("opengl32\glEnable", "uint", 0x0B50)
          DllCall("opengl32\glCallList", "uint", d[4])
        }
        else
          DllCall("opengl32\glBindTexture", "uint", 0x0DE1, "uint", 0)
        DllCall("opengl32\glBegin", "uint", f[d[1]])
        RegExMatch(d[2], "iO)^([2-4]V)([1-4]T)?(3N)?$", o)
        p := 1
        while (d[3].hasKey(p))
        {
          x := 1
          if (o[x]="2V")
            DllCall("opengl32\glVertex2f", "float", d[3,p], "float", d[3,p+1])
          else if (o[x]="3V")
            DllCall("opengl32\glVertex3f", "float", d[3,p], "float", d[3,p+1], "float", d[3,p+2])
          else if (o[x]="4V")
            DllCall("opengl32\glVertex3f", "float", d[3,p], "float", d[3,p+1], "float", d[3,p+2], "float", d[3,p+3])
          p += (Substr(o[x], 1, 1)+0)
          x += 1
          if (Substr(o[x], 2, 1)="T")
          {
            if (o[x]="1T")
              DllCall("opengl32\glTexCoord1f", "float", d[3,p])
            if (o[x]="2T")
              DllCall("opengl32\glTexCoord2f", "float", d[3,p], "float", d[3,p+1])
            if (o[x]="3T")
              DllCall("opengl32\glTexCoord3f", "float", d[3,p], "float", d[3,p+1], "float", d[3,p+2])
            if (o[x]="4T")
              DllCall("opengl32\glTexCoord3f", "float", d[3,p], "float", d[3,p+1], "float", d[3,p+2], "float", d[3,p+3])
            p += (Substr(o[x], 1, 1)+0)
            x += 1
          }
          if (Substr(o[x], 2, 1)="N")
          {
            if (o[x]="3N")
              DllCall("opengl32\glNormal3f", "float", d[3,p], "float", d[3,p+1], "float", d[3,p+2])
            p += (Substr(o[x], 1, 1)+0)
            x += 1
          }
        }
        DllCall("opengl32\glEnd")
      }
      DllCall("opengl32\glPopMatrix")
      DllCall("opengl32\glEndList")
    }
    identity()
    {
      return this.transform.identity()
    }
    translate(p*)
    {
      return this.transform.translate(p*)
    }
    rotate(p*)
    {
      return this.transform.rotate(p*)
    }
    scale(p*)
    {
      return this.transform.scale(p*)
    }
    _add(vertcount, format, array, material=0)
    {
      
      if (!RegExMatch(format, "iO)^([2-4]V)([1-4]T)?(3N)?$"))
        return -1
      this.data.insert([vertcount, format, array, material])
      this._update()
    }
    addPoints(format, array, material=0)
    {
      return this._add(1, format, array, material)
    }
    addLines(format, array, material=0)
    {
      return this._add(2, format, array, material)
    }
    addTriangles(format, array, material=0)
    {
      return this._add(3, format, array, material)
    }
    addQuads(format, array, material=0)
    {
      return this._add(4, format, array, material)
    }
    clear()
    {
      this.data := []
      this._update()
    }
    _set(vertcount, format, array, material=0)
    {
      this.clear()
      return this._add(vertcount, format, array, material)
    }
    setPoints(format, array, material=0)
    {
      return this._set(1, format, array, material)
    }
    setLines(format, array, material=0)
    {
      return this._set(2, format, array, material)
    }
    setTriangles(format, array, material=0)
    {
      return this._set(3, format, array, material)
    }
    setQuads(format, array, material=0)
    {
      return this._set(4, format, array, material)
    }
  }
  class Texture
  {
    __new()
    {
      this.objType := "3D.Texture"
      DllCall("opengl32\glGenTextures", "uint", 1, "uint*", tex)
      this.tex := tex
      this.filter(3)
    }
    __delete()
    {
      if (this.tex)
        DllCall("opengl32\glDeleteTextures", "uint", 1, "uint*", this.tex)
    }
    load(filename, format="")
    {
      static t := {RGB:3, RGBA:4, L:0x1909, LA:0x190A, I:0x8049}
      VarSetCapacity(bgpin, 20, 0)
      NumPut(1, bgpin, 0, "int")
      s := -3
      if (DllCall("gdiplus\GdiplusStartup", "ptr*", gptoken, "ptr", &bgpin, "ptr", 0)=0)
      {
        s := -2
        if (DllCall("gdiplus\GdipCreateBitmapFromFile", "wstr", filename, "ptr*", gpbm)=0)
        {
          e := DllCall("gdiplus\GdipGetImageWidth", "ptr", gpbm, "uint*", w)
          e += DllCall("gdiplus\GdipGetImageHeight", "ptr", gpbm, "uint*", h)
          e += DllCall("gdiplus\GdipGetImagePixelFormat", "ptr", gpbm, "uint*", bmformat)
          e += DllCall("gdiplus\GdipImageRotateFlip", "ptr", gpbm, "int", 6)
          if (e=0)
          {
            s := -1
            if (!format)
              format := ((bmformat&0xf=4) ? "L" : "RGB") ((bmformat&0x000C0000) ? "A" : "")
            VarSetCapacity(rc, 16, 0)
            NumPut(w, rc, 8, "int")
            NumPut(h, rc, 12, "int")
            VarSetCapacity(bgpbmdata, 32, 0)
            if (DllCall("gdiplus\GdipBitmapLockBits", "ptr", gpbm, "ptr", &rc, "uint", 0x0001, "int", 0x26200A, "ptr", &bgpbmdata)=0)
            {
              scan := NumGet(bgpbmdata, 16, "ptr")
              DllCall("opengl32\glBindTexture", "int", 0x0DE1, "uint", this.tex)
              DllCall("opengl32\glTexImage2D", "int", 0x0DE1, "int", 0, "int", (t[format]) ? t[format] : 4, "int", w, "int", h, "int", 0, "int", 0x80E1, "int", 0x1401, "ptr", scan)
              DllCall("gdiplus\GdipBitmapUnlockBits", "ptr", gpbm, "ptr", &bgpbmdata)
              s := ""
            }
          }
          DllCall("gdiplus\GdipDisposeImage", "ptr", gpbm)
        }
        DllCall("gdiplus\GdiplusShutdown", "ptr", gptoken)
      }
      return s
    }
    filter(level=3)
    {
      static f := {1:[0,0], 2:[0,1], 3:[1,1]}
      DllCall("opengl32\glBindTexture", "int", 0x0DE1, "uint", this.tex)
      DllCall("opengl32\glTexParameteri", "uint", 0x0DE1, "uint", 0x2801, "uint", 0x2600+(f[level,1]))
      DllCall("opengl32\glTexParameteri", "uint", 0x0DE1, "uint", 0x2800, "uint", 0x2600+(f[level,2]))
    }
  }
  class Material
  {
    __new()
    {
      this.objType := "3D.Material"
      this.list := DllCall("opengl32\glGenLists", "uint", 1, "uint")
      this.data := []
      this.data.ambient := [0.2,0.2,0.2,1.0]
      this.data.diffuse := [0.8,0.8,0.8,1.0]
      this.data.specular := [0.0,0.0,0.0,1.0]
      this.data.emission := [0.0,0.0,0.0,1.0]
      this.data.shininess := 0
      this.data.texture := 0
      this._update()
    }
    __delete()
    {
      if (this.list)
        DllCall("opengl32\glFreeLists", "uint", this.list, "uint", 1)
    }
    _glMaterial(n, clr)
    {
      VarSetCapacity(b, 16, 0)
      NumPut(clr[1], b, 0, "float")
      NumPut(clr[2], b, 4, "float")
      NumPut(clr[3], b, 8, "float")
      NumPut(clr[4], b, 12, "float")
      DllCall("opengl32\glMaterialfv", "uint", 0x0408, "uint", n, "ptr", &b)
    }
    _update()
    {
      DllCall("opengl32\glNewList", "uint", this.list, "uint", 0x1300)
      this._glMaterial(0x1200, this.data.ambient)
      this._glMaterial(0x1201, this.data.diffuse)
      this._glMaterial(0x1202, this.data.specular)
      this._glMaterial(0x1600, this.data.emission)
      DllCall("opengl32\glMaterialf", "uint", 0x0408, "uint", 0x1601, "float", this.data.shininess)
      DllCall("opengl32\glBindTexture", "uint", 0x0DE1, "uint", this.data.texture.tex)
      DllCall("opengl32\glEndList")
    }
    ambient(r=0.2, g=0.2, b=0.2, i=1)
    {
      this.data.ambient := [r,g,b,i]
      this._update()
    }
    diffuse(r=0.8, g=0.8, b=0.8, i=1)
    {
      this.data.diffuse := [r,g,b,i]
      this._update()
    }
    specular(r=0.0, g=0.0, b=0.0, i=1)
    {
      this.data.specular := [r,g,b,i]
      this._update()
    }
    emission(r=0.0, g=0.0, b=0.0, i=1)
    {
      this.data.emission := [r,g,b,i]
      this._update()
    }
    shininess(i=0)
    {
      this.data.shininess := i
      this._update()
    }
    texture(texture)
    {
      this.data.texture := (texture.objType="3D.Texture") ? texture : 0
      this._update()
    }
  }
  class Light
  {
    __new()
    {
      this.objType := "3D.Light"
      this.list := DllCall("opengl32\glGenLists", "uint", 1, "uint")
      this.data := []
      this.data.ambient := [0.0,0.0,0.0,1.0]
      this.data.diffuse := [1.0,1.0,1.0,1.0]
      this.data.specular := [0.0,0.0,0.0,1.0]
      this.data.position := [0.0,0.0,1.0,0.0]
      this.data.direction := [0.0,0.0,-1.0,0.0]
      this._update()
    }
    __delete()
    {
      if (this.list)
        DllCall("opengl32\glFreeLists", "uint", this.list, "uint", 1)
    }
    _glLight(n, clr)
    {
      VarSetCapacity(b, 16, 0)
      NumPut(clr[1], b, 0, "float")
      NumPut(clr[2], b, 4, "float")
      NumPut(clr[3], b, 8, "float")
      NumPut(clr[4], b, 12, "float")
      DllCall("opengl32\glLightfv", "uint", 0x4000, "uint", n, "ptr", &b)
    }
    _update()
    {
      DllCall("opengl32\glNewList", "uint", this.list, "uint", 0x1300)
      this._glLight(0x1200, this.data.ambient)
      this._glLight(0x1201, this.data.diffuse)
      this._glLight(0x1202, this.data.specular)
      this._glLight(0x1203, this.data.position)
      this._glLight(0x1204, this.data.direction)
      DllCall("opengl32\glEndList")
    }
    ambient(r=0.0, g=0.0, b=0.0, i=1)
    {
      this.data.ambient := [r,g,b,i]
      this._update()
    }
    diffuse(r=1.0, g=1.0, b=1.0, i=1)
    {
      this.data.diffuse := [r,g,b,i]
      this._update()
    }
    specular(r=0.0, g=0.0, b=0.0, i=1)
    {
      this.data.specular := [r,g,b,i]
      this._update()
    }
    position(x=0.0, y=0.0, z=1.0, w=0)
    {
      this.data.position := [x,y,z,w]
      this._update()
    }
    direction(x=0.0, y=0.0, z=-1.0)
    {
      this.data.direction := [x,y,z,0.0]
      this._update()
    }
  }
  class Shader
  {
    __new()
    {
      this.objType := "3D.Shader"
      if (!(h := 3D._glProc("glCreateProgramARB", "glCreateProgram")))
        return -1
      this.program := DllCall(h, "uint")
      if (!(h := 3D._glProc("glCreateShaderARB", "glCreateShader")))
        return -1
      this.vertexObject := DllCall(h, "uint", 0x8B31, "uint")
      this.fragmentObject := DllCall(h, "uint", 0x8B30, "uint")
    }
    _setSource(src, obj, outinfo="")
    {
      if (outinfo)
        this[outinfo] := ""
      if (!(h := 3D._glProc("glShaderSourceARB", "glShaderSource")))
        return -1
      DllCall(h, "uint", obj, "int", 1, "astr*", src, "ptr", 0)
      if (!(h := 3D._glProc("glCompileShaderARB", "glCompileShader")))
        return -1
      DllCall(h, "uint", obj)
      if (h := 3D._glProc("glGetShaderiv"))
      {
        DllCall(h, "uint", obj, "uint", 0x8B81, "int*", r)
        if (!r)
        {
          DllCall(h, "uint", obj, "uint", 0x8B84, "int*", s)
          if (!outinfo || !(h := 3D._glProc("glGetShaderInfoLog")))
            return -2
          VarSetCapacity(infob, s+2, 0)
          DllCall(h, "uint", obj, "int", s, "int*", so, "ptr", &infob)
          this[outinfo] := StrGet(&infob, "cp0")
          return -2
        }
      }
      if (!(h := 3D._glProc("glAttachObjectARB", "glAttachShader")))
        return -1
      DllCall(h, "uint", this.program, "uint", this.vertexObject)
      DllCall(h, "uint", this.program, "uint", this.fragmentObject)
      if (!(h := 3D._glProc("glLinkProgramARB", "glLinkProgram")))
        return -1
      DllCall(h, "uint", this.program)
    }
    vertex(src)
    {
      return this._setSource(src, this.vertexObject, "vertexInfo")
    }
    fragment(src)
    {
      return this._setSource(src, this.fragmentObject, "fragmentInfo")
    }
  }
  _glProc(p*)
  {
    for k,v in p
    {
      if (ptr := DllCall("opengl32\wglGetProcAddress", "astr", v, "ptr"))
        return ptr
    }
  }
}
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Game Engine

02 Sep 2014, 12:36

Danke ^^
Recommends AHK Studio
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Game Engine

02 Sep 2014, 13:12

Die Transform Klassen (bei mir Position Data) funktionieren eigentlich exakt gleich.
Recommends AHK Studio
Bentschi
Posts: 22
Joined: 02 Oct 2013, 18:45

Re: Game Engine

02 Sep 2014, 15:12

nnnik wrote:Die Transform Klassen (bei mir Position Data) funktionieren eigentlich exakt gleich.
Das heißt wohl du hast dich nicht verrechnet :lol: ... denn ich hab die OpenGL-Funktionen direkt verwendet und die Matrix neu gelesen. :D
Hatte eigentlich auch an MCode gedacht und obwohl ich ziemlich sicher bin dass MCode performanter ist, wollte ich mir dann aber letztendlich die Arbeit ersparen.

Achja... wenn du den Shader (Zeile 78: scene.addChild(shader)) aus meinem Skript entfernst, funktioniert Licht und Material auch... allerdings die Position des Lichtes passt nicht.
Grund dafür: Hab da etwas rumexperimentiert und der Shader baut lediglich die Standard-Renderpipeline nach. Also auch kein Licht und Material.

Edit:
Nö sorry, die Lichtposition dürfte doch korrekt sein:
http://wiki.delphigl.com/index.php/glLight wrote:Die Position wird durch die Modelansichtsmatrix (zum Zeitpunkt des Aufrufs von glLight) transformiert
Edit2:
... Aber unterstützung für multible Lichtquellen hab ich noch nicht eingebaut
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Game Engine

16 Sep 2014, 11:58

Kannst du mir win Tutorial für Shader empfehlen?
Recommends AHK Studio

Return to “Allgemeines”

Who is online

Users browsing this forum: No registered users and 15 guests