From 54087348e33622b91b392fb6641bbbfe43027951 Mon Sep 17 00:00:00 2001 From: notpete Date: Tue, 25 Nov 2003 20:14:34 +0000 Subject: [PATCH] Extended renderer interface, added basic CModel rendering. This was SVN commit r105. --- source/terrain/Renderer.cpp | 381 ++++++++++++++++++++---------------- source/terrain/Renderer.h | 180 ++++++++++++++--- 2 files changed, 368 insertions(+), 193 deletions(-) diff --git a/source/terrain/Renderer.cpp b/source/terrain/Renderer.cpp index 008fc73646..c8dff1a224 100755 --- a/source/terrain/Renderer.cpp +++ b/source/terrain/Renderer.cpp @@ -1,6 +1,23 @@ +//---------------------------------------------------------------- +// +// Name: Renderer.cpp +// Last Update: 25/11/03 +// Author: Rich Cross +// Contact: rich@0ad.wildfiregames.com +// +// Description: OpenGL renderer class; a higher level interface +// on top of OpenGL to handle rendering the basic visual games +// types - terrain, models, sprites, particles etc +//---------------------------------------------------------------- + #include "Renderer.h" +#include "Terrain.h" #include "Matrix3D.h" #include "Camera.h" +#include "Texture.h" + +#include "Model.h" +#include "ModelDef.h" #include "types.h" #include "ogl.h" @@ -9,13 +26,13 @@ #define RENDER_STAGE_BASE (1) #define RENDER_STAGE_TRANS (2) -bool g_WireFrame = false; -unsigned int g_FrameCounter = 0; - CRenderer::CRenderer () { - m_Timer = 0; - m_CurrentSeason = 0; + m_Width=0; + m_Height=0; + m_Depth=0; + m_FrameCounter=0; + m_TerrainMode=FILL; } CRenderer::~CRenderer () @@ -23,31 +40,81 @@ CRenderer::~CRenderer () } -bool CRenderer::Initialize (int width, int height, int depth) +bool CRenderer::Open(int width, int height, int depth) { m_Width = width; m_Height = height; m_Depth = depth; + + // setup default state + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glClearColor(0.0f,0.0f,0.0f,0.0f); + return true; } -void CRenderer::Shutdown () +void CRenderer::Close() { - } -/* -struct Tile -{ - u32 pri_tex : 5; - u32 sec_tex : 5; - u32 alpha_map : 6; -}; - -void render_terrain() +// resize renderer view +void CRenderer::Resize(int width,int height) { - CMatrix3D view = camera->m_Orientation.GetTranspose(); - CMatrix3D proj = camera->GetProjection(); + m_Width = width; + m_Height = height; +} + +// signal frame start +void CRenderer::BeginFrame() +{ + // bump frame counter + m_FrameCounter++; + + // clear buffers + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +// force rendering of any batched objects +void CRenderer::FlushFrame() +{ + // render base terrain + if (m_TerrainMode==WIREFRAME) { + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + } + + for (int i=0;iGetViewPort(); + glMatrixMode (GL_MODELVIEW); + glLoadMatrixf (gl_view); + + const SViewPort& vp = camera.GetViewPort(); glViewport (vp.m_X, vp.m_Y, vp.m_Width, vp.m_Height); +} - if (g_WireFrame) - glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); - else - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); +void CRenderer::Submit(CPatch* patch) +{ + SSubmission sub; + patch->m_LastVisFrame=m_FrameCounter; + sub.m_Object=patch; + m_TerrainPatches.push_back(sub); +} + +void CRenderer::Submit(CModel* model,CMatrix3D* transform) +{ + SSubmission sub; + sub.m_Object=model; + sub.m_Transform=transform; + m_Models.push_back(sub); +} + +void CRenderer::Submit(CSprite* sprite,CMatrix3D* transform) +{ +} + +void CRenderer::Submit(CParticleSys* psys,CMatrix3D* transform) +{ +} + +void CRenderer::Submit(COverlay* overlay) +{ +} - for (int j=0; jGetFustum().IsBoxVisible (CVector3D(0,0,0), terrain->m_Patches[j][i].m_Bounds)) - terrain->m_Patches[j][i].m_LastVisFrame = g_FrameCounter; - } - } - for (j=0; jm_Patches[j][i].m_LastVisFrame == g_FrameCounter) - render_patch(&terrain->m_Patches[j][i]); - } - } +/* +void CRenderer::RenderTileOutline (CMiniPatch *mpatch) +{ + glActiveTexture (GL_TEXTURE0); + glDisable (GL_DEPTH_TEST); + glDisable (GL_TEXTURE_2D); + glLineWidth (4); + + STerrainVertex V[4]; + V[0] = mpatch->m_pVertices[0]; + V[1] = mpatch->m_pVertices[1]; + V[2] = mpatch->m_pVertices[MAP_SIZE*1 + 1]; + V[3] = mpatch->m_pVertices[MAP_SIZE*1]; + + glColor3f (0,1.0f,0); + + glBegin (GL_LINE_LOOP); + + for(int i = 0; i < 4; i++) + glVertex3fv(&V[i].m_Position.X); + + glEnd (); + + glEnable (GL_DEPTH_TEST); + glEnable (GL_TEXTURE_2D); } */ -void CRenderer::RenderTerrain (CTerrain *terrain, CCamera *camera) + +void CRenderer::RenderModel(SSubmission& modelsub) { -// m_Timer += 0.001f; + glPushMatrix(); + glMultMatrixf(modelsub.m_Transform->_data); - if (m_Timer > 1.0f) + SetTexture(0,modelsub.m_Object->GetTexture()); + glColor3f(1.0f,1.0f,1.0f); + + CModel* mdl=(CModel*) modelsub.m_Object; + CModelDef* mdldef=(CModelDef*) mdl->GetModelDef(); + + glBegin(GL_TRIANGLES); + for (int fi=0; fiGetNumFaces(); fi++) { - m_Timer = 0; - - if (m_CurrentSeason == 0) - m_CurrentSeason = 1; - else - m_CurrentSeason = 0; - } + SModelFace *pFace = &mdldef->GetFaces()[fi]; - CMatrix3D view = camera->m_Orientation.GetTranspose(); - CMatrix3D proj = camera->GetProjection(); - - float gl_view[16] = {view._11, view._21, view._31, view._41, - view._12, view._22, view._32, view._42, - view._13, view._23, view._33, view._43, - view._14, view._24, view._34, view._44}; - - float gl_proj[16] = {proj._11, proj._21, proj._31, proj._41, - proj._12, proj._22, proj._32, proj._42, - proj._13, proj._23, proj._33, proj._43, - proj._14, proj._24, proj._34, proj._44}; - - - glMatrixMode (GL_MODELVIEW); - glLoadMatrixf (gl_view); - - glMatrixMode (GL_PROJECTION); - glLoadMatrixf (gl_proj); - - SViewPort vp = camera->GetViewPort(); - //glViewport (vp.m_X, vp.m_Y, vp.m_Width, vp.m_Height); - - if (g_WireFrame) - glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); - else - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - - int j; - - for (j=0; jGetFustum().IsBoxVisible (CVector3D(0,0,0), terrain->m_Patches[j][i].m_Bounds)) - terrain->m_Patches[j][i].m_LastVisFrame = g_FrameCounter; + SModelVertex *pVertex = &mdldef->GetVertices()[pFace->m_Verts[vi]]; + CVector3D Coord = mdl->GetBonePoses()[pVertex->m_Bone].Transform(pVertex->m_Coords); + + glTexCoord2f (pVertex->m_U, pVertex->m_V); + + glVertex3f (Coord.X, Coord.Y, Coord.Z); } } + glEnd(); - for (j=0; jm_Patches[j][i].m_LastVisFrame == g_FrameCounter) - RenderPatchBase (&terrain->m_Patches[j][i]); + glPopMatrix(); +} + +// try and load the given texture +bool CRenderer::LoadTexture(CTexture* texture) +{ + Handle h=texture->GetHandle(); + if (h) { + // already tried to load this texture, nothing to do here - just return accord to whether this + // is a valid handle + return h==0xfffffff ? true : false; + } else { + h=tex_load(texture->GetName()); + if (!h) { + texture->SetHandle(0xffffffff); + return false; + } else { + tex_upload(h); + texture->SetHandle(h); + return true; } } +} +// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit +void CRenderer::SetTexture(int unit,CTexture* texture) +{ + glActiveTexture(GL_TEXTURE0+unit); + if (texture) { + Handle h=texture->GetHandle(); + if (!h) { + LoadTexture(texture); + h=texture->GetHandle(); + } - for (j=0; jm_Patches[j][i].m_LastVisFrame == g_FrameCounter) - RenderPatchTrans (&terrain->m_Patches[j][i]); - + // disable texturing if invalid handle + if (h==0xffffffff) { + glDisable(GL_TEXTURE_2D); + } else { + tex_bind(h); + glEnable(GL_TEXTURE_2D); } + } else { + // switch off texturing on this unit + glDisable(GL_TEXTURE_2D); } } @@ -180,7 +284,7 @@ void CRenderer::RenderPatchBase (CPatch *patch) { MPatch = &(patch->m_MiniPatches[j][i]); - if (MPatch->m_LastRenderedFrame == g_FrameCounter) + if (MPatch->m_LastRenderedFrame == m_FrameCounter) continue; glActiveTexture (GL_TEXTURE0); @@ -225,22 +329,10 @@ tex_bind(MPatch->Tex1); int v1 = MAP_SIZE + x; int v2 = x; - float factor = m_Timer; - if (m_CurrentSeason == 1) - factor = 1.0f - factor; - - float color1[3] = {MPCurrent->m_pVertices[v1].m_Color[0][0]*factor + MPCurrent->m_pVertices[v1].m_Color[1][0]*(1.0f-factor), - MPCurrent->m_pVertices[v1].m_Color[0][1]*factor + MPCurrent->m_pVertices[v1].m_Color[1][1]*(1.0f-factor), - MPCurrent->m_pVertices[v1].m_Color[0][2]*factor + MPCurrent->m_pVertices[v1].m_Color[1][2]*(1.0f-factor)}; - - float color2[3] = {MPCurrent->m_pVertices[v2].m_Color[0][0]*factor + MPCurrent->m_pVertices[v2].m_Color[1][0]*(1.0f-factor), - MPCurrent->m_pVertices[v2].m_Color[0][1]*factor + MPCurrent->m_pVertices[v2].m_Color[1][1]*(1.0f-factor), - MPCurrent->m_pVertices[v2].m_Color[0][2]*factor + MPCurrent->m_pVertices[v2].m_Color[1][2]*(1.0f-factor)}; - glTexCoord2f (tu[0], tv[0]); if (g_HillShading) - glColor3f (color1[0],color1[1],color1[2]); + glColor3fv(&MPCurrent->m_pVertices[v1].m_Color.X); else glColor3f (1,1,1); @@ -251,7 +343,7 @@ tex_bind(MPatch->Tex1); glTexCoord2f (tu[1], tv[1]); if (g_HillShading) - glColor3f (color2[0],color2[1],color2[2]); + glColor3fv(&MPCurrent->m_pVertices[v2].m_Color.X); else glColor3f (1,1,1); @@ -263,7 +355,7 @@ tex_bind(MPatch->Tex1); tu[1]+=0.125f; } - MPCurrent->m_LastRenderedFrame = g_FrameCounter; + MPCurrent->m_LastRenderedFrame = m_FrameCounter; MPCurrent->m_RenderStage = RENDER_STAGE_BASE; if (!MPCurrent->m_pRightNeighbor) @@ -271,7 +363,7 @@ tex_bind(MPatch->Tex1); else { if (MPCurrent->m_pRightNeighbor->Tex1 != MPCurrent->Tex1 || - MPCurrent->m_pRightNeighbor->m_pParrent->m_LastVisFrame != g_FrameCounter) + MPCurrent->m_pRightNeighbor->m_pParrent->m_LastVisFrame != m_FrameCounter) break; } @@ -291,7 +383,6 @@ void CRenderer::RenderPatchTrans (CPatch *patch) float StartU, StartV; glEnable (GL_BLEND); - glDepthFunc (GL_EQUAL); glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); for (int j=0; j<16; j++) @@ -300,7 +391,7 @@ void CRenderer::RenderPatchTrans (CPatch *patch) { MPatch = &(patch->m_MiniPatches[j][i]); - if (MPatch->m_LastRenderedFrame == g_FrameCounter && + if (MPatch->m_LastRenderedFrame == m_FrameCounter && MPatch->m_RenderStage == RENDER_STAGE_TRANS) continue; @@ -370,23 +461,11 @@ tex_bind(MPatch->m_AlphaMap); int v1 = MAP_SIZE + x; int v2 = x; - float factor = m_Timer; - if (m_CurrentSeason == 1) - factor = 1.0f - factor; - - float color1[3] = {MPCurrent->m_pVertices[v1].m_Color[0][0]*factor + MPCurrent->m_pVertices[v1].m_Color[1][0]*(1.0f-factor), - MPCurrent->m_pVertices[v1].m_Color[0][1]*factor + MPCurrent->m_pVertices[v1].m_Color[1][1]*(1.0f-factor), - MPCurrent->m_pVertices[v1].m_Color[0][2]*factor + MPCurrent->m_pVertices[v1].m_Color[1][2]*(1.0f-factor)}; - - float color2[3] = {MPCurrent->m_pVertices[v2].m_Color[0][0]*factor + MPCurrent->m_pVertices[v2].m_Color[1][0]*(1.0f-factor), - MPCurrent->m_pVertices[v2].m_Color[0][1]*factor + MPCurrent->m_pVertices[v2].m_Color[1][1]*(1.0f-factor), - MPCurrent->m_pVertices[v2].m_Color[0][2]*factor + MPCurrent->m_pVertices[v2].m_Color[1][2]*(1.0f-factor)}; - glMultiTexCoord2f (GL_TEXTURE0_ARB, tu[0], tv[0]); glMultiTexCoord2f (GL_TEXTURE1_ARB, tu[0]*2, tv[0]*2); if (g_HillShading) - glColor3f (color1[0],color1[1],color1[2]); + glColor3fv(&MPCurrent->m_pVertices[v1].m_Color.X); else glColor3f (1,1,1); @@ -398,7 +477,7 @@ tex_bind(MPatch->m_AlphaMap); glMultiTexCoord2f (GL_TEXTURE1_ARB, tu[1]*2, tv[1]*2); if (g_HillShading) - glColor3f (color2[0],color2[1],color2[2]); + glColor3fv(&MPCurrent->m_pVertices[v1].m_Color.X); else glColor3f (1,1,1); @@ -410,7 +489,7 @@ tex_bind(MPatch->m_AlphaMap); tu[1]+=0.125f; } - MPCurrent->m_LastRenderedFrame = g_FrameCounter; + MPCurrent->m_LastRenderedFrame = m_FrameCounter; MPCurrent->m_RenderStage = RENDER_STAGE_TRANS; if (!MPCurrent->m_pRightNeighbor) @@ -419,7 +498,7 @@ tex_bind(MPatch->m_AlphaMap); { if (MPCurrent->m_pRightNeighbor->Tex2 != MPCurrent->Tex2 || MPCurrent->m_pRightNeighbor->m_AlphaMap != MPCurrent->m_AlphaMap || - MPCurrent->m_pRightNeighbor->m_pParrent->m_LastVisFrame != g_FrameCounter) + MPCurrent->m_pRightNeighbor->m_pParrent->m_LastVisFrame != m_FrameCounter) break; } @@ -431,38 +510,8 @@ tex_bind(MPatch->m_AlphaMap); } } } - - glDepthFunc (GL_LEQUAL); glDisable (GL_BLEND); glActiveTexture (GL_TEXTURE1); -glDisable(GL_TEXTURE_2D); -} - -void CRenderer::RenderTileOutline (CMiniPatch *mpatch) -{ -if(!mpatch->m_pVertices) -return; - + glDisable(GL_TEXTURE_2D); glActiveTexture (GL_TEXTURE0); - glDisable (GL_DEPTH_TEST); - glDisable (GL_TEXTURE_2D); - glLineWidth (4); - - STerrainVertex V[4]; - V[0] = mpatch->m_pVertices[0]; - V[1] = mpatch->m_pVertices[1]; - V[2] = mpatch->m_pVertices[MAP_SIZE*1 + 1]; - V[3] = mpatch->m_pVertices[MAP_SIZE*1]; - - glColor3f (0,1.0f,0); - - glBegin (GL_LINE_LOOP); - - for(int i = 0; i < 4; i++) - glVertex3fv(&V[i].m_Position.X); - - glEnd (); - - glEnable (GL_DEPTH_TEST); - glEnable (GL_TEXTURE_2D); } diff --git a/source/terrain/Renderer.h b/source/terrain/Renderer.h index e073bb1f6b..239386d0bd 100755 --- a/source/terrain/Renderer.h +++ b/source/terrain/Renderer.h @@ -1,39 +1,165 @@ +//---------------------------------------------------------------- +// +// Name: Renderer.h +// Last Update: 25/11/03 +// Author: Rich Cross +// Contact: rich@0ad.wildfiregames.com +// +// Description: OpenGL renderer class; a higher level interface +// on top of OpenGL to handle rendering the basic visual games +// types - terrain, models, sprites, particles etc +//---------------------------------------------------------------- + + #ifndef RENDERER_H #define RENDERER_H +#include #include "ogl.h" +#include "Frustum.h" -#include "Terrain.h" +// necessary declarations +class CCamera; +class CPatch; +class CModel; +class CSprite; +class CParticleSys; +class COverlay; +class CMaterial; +class CLightEnv; +class SPatchRData; +class CTexture; -extern bool g_WireFrame; -extern unsigned int g_FrameCounter; - -class CRenderer +////////////////////////////////////////////////////////////////////////////////////////// +// SSubmission: generalised class representating a submission of objects to renderer +template +struct SSubmission { - public: - CRenderer(); - ~CRenderer(); + T m_Object; + CMatrix3D* m_Transform; +}; - bool Initialize (int width, int height, int depth); - void Shutdown (); - - void RenderTerrain (CTerrain *terrain, CCamera *camera); - void RenderTileOutline (CMiniPatch *mpatch); - - protected: - void RenderPatchBase (CPatch *patch); - void RenderPatchTrans (CPatch *patch); - - protected: - int m_Width; - int m_Height; - int m_Depth; - -///THERE ARE NOT SUPPOSED TO BE HERE - float m_Timer; - int m_CurrentSeason; +////////////////////////////////////////////////////////////////////////////////////////// +// SVertex3D: simple 3D vertex declaration +struct SVertex3D +{ + float m_Position[3]; + float m_TexCoords[2]; + unsigned int m_Color; +}; +////////////////////////////////////////////////////////////////////////////////////////// +// SVertex2D: simple 2D vertex declaration +struct SVertex2D +{ + float m_Position[2]; + float m_TexCoords[2]; + unsigned int m_Color; }; -#endif \ No newline at end of file +/////////////////////////////////////////////////////////////////////////////////////////// +// CRenderer: base renderer class - primary interface to the rendering engine +class CRenderer +{ +public: + // various enumerations + enum ETerrainMode { WIREFRAME, FILL }; + +public: + // constructor, destructor + CRenderer(); + ~CRenderer(); + + // open up the renderer: performs any necessary initialisation + bool Open(int width,int height,int depth); + // shutdown the renderer: performs any necessary cleanup + void Close(); + + // resize renderer view + void Resize(int width,int height); + + // signal frame start + void BeginFrame(); + // force rendering of any batched objects + void FlushFrame(); + // signal frame end : implicitly flushes batched objects + void EndFrame(); + + // return current frame counter + int GetFrameCounter() const { return m_FrameCounter; } + + // set camera used for subsequent rendering operations; includes viewport, projection and modelview matrices + void SetCamera(CCamera& camera); + + // submission of objects for rendering; the passed matrix indicating the transform must be scoped such that it is valid beyond + // the call to frame end, as must the object itself + void Submit(CPatch* patch); + void Submit(CModel* model,CMatrix3D* transform); + void Submit(CSprite* sprite,CMatrix3D* transform); + void Submit(CParticleSys* psys,CMatrix3D* transform); + void Submit(COverlay* overlay); + +#if 0 + // basic primitive rendering operations in 2 and 3D; handy for debugging stuff, but also useful in + // editor tools (eg for highlighting specific terrain patches) + // note: + // * all 3D vertices specified in world space + // * primitive operations rendered immediatedly, never batched + // * primitives rendered in current material (set via SetMaterial) + void RenderLine(const SVertex2D* vertices); + void RenderLineLoop(int len,const SVertex2D* vertices); + void RenderTri(const SVertex2D* vertices); + void RenderQuad(const SVertex2D* vertices); + void RenderLine(const SVertex3D* vertices); + void RenderLineLoop(int len,const SVertex3D* vertices); + void RenderTri(const SVertex3D* vertices); + void RenderQuad(const SVertex3D* vertices); +#endif + + // set the current lighting environment; (note: the passed pointer is just copied to a variable within the renderer, + // so the lightenv passed must be scoped such that it is not destructed until after the renderer is no longer rendering) + void SetLightEnv(CLightEnv* lightenv); + + // set the mode to render subsequent terrain patches + void SetTerrainMode(ETerrainMode mode) { m_TerrainMode=mode; } + // get the mode to render subsequent terrain patches + ETerrainMode GetTerrainMode() const { return m_TerrainMode; } + + // try and load the given texture + bool LoadTexture(CTexture* texture); + // set the given unit to reference the given texture; pass a null texture to disable texturing on any unit + // note - active texture always set to given unit on exit + void SetTexture(int unit,CTexture* texture); + +protected: + // patch rendering stuff + void RenderPatchBase(CPatch* patch); + void RenderPatchTrans(CPatch* patch); + + // model rendering stuff + void RenderModel(SSubmission& modelsub); + + // RENDERER DATA: + // view width + int m_Width; + // view height + int m_Height; + // view depth (bpp) + int m_Depth; + // frame counter + int m_FrameCounter; + // current terrain rendering mode + ETerrainMode m_TerrainMode; + // submitted object lists for batching + std::vector > m_TerrainPatches; + std::vector > m_Models; + std::vector > m_Sprites; + std::vector > m_ParticleSyses; + std::vector > m_Overlays; + // current lighting setup + CLightEnv* m_LightEnv; +}; + + +#endif