[ Thread Index |
Date Index
| More lists.tuxfamily.org/xmoto-dev Archives
]
- To: xmoto-dev@xxxxxxxxxxxxxxxxxxx, daniel_on_go@xxxxxxxxxxxx
- Subject: [xmoto-dev] SDL_gfx help
- From: "Kees Jongenburger" <kees.jongenburger@xxxxxxxxx>
- Date: Sun, 21 Jan 2007 07:47:28 +0100
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:mime-version:content-type; b=Kk2JTb/SbrBBoXOnuZtkOriaaP5GkiJADq6ZpAp0QNoR92+ZunU5Gr8qo0hn1CZ9Mj6r3VBnMkLf3u+6X81VDMeSImDfsC3H+FbnZQGCxVOOI8IjBxNPQdcWPwbtbHeH78ZoosVFEorD5TJvNxepD87+biCMEoehCxtRJGTIEFI=
Hello
I am searching for somebody who can help me fix the SDL_gfx rendering.
I have the biggest trouble getting is right. I will try to explain my problem.
The problem is related to texture rendering and the way it currently
is implemented
in xmoto. So how is it implemented?
We have a sdl_gfx method that can draw polygons with a given "image/texture"
this method will just draw bits of the image/texture instead of color
like in the normal filledPolygon.
I want to give a preformatted texture to this method so that the game
is rendered correctly.
So given the input texture , the texture coordinates and the vertex
coordinates I want to define a transformation on the base image. we
are in 2d space and do not perform squeaking. The transformations that
are possible are scaling,rotating and flipping .
I don't understand enough about the glTexCoord in VDraw.h so estimate if
there should be a glTexCoordSP.
I think this article covers the theory of what I am explaining only it does
this on a point2point base
http://www.gameprogrammer.com/6-text.html
attached it a "kinda" working version
I have cc'ed Daniel who is working on a 3d engine.
greetings
/*=============================================================================
XMOTO
Copyright (C) 2005-2006 Rasmus Neckelmann (neckelmann@xxxxxxxxx)
This file is part of XMOTO.
XMOTO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
XMOTO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with XMOTO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
=============================================================================*/
#ifndef __VDRAW_H__
#define __VDRAW_H__
#include "VCommon.h"
#include "helpers/VMath.h"
#include "VTexture.h"
#include "Theme.h"
#include "Image.h"
namespace vapp {
/**
* VApp draw modes to be used as argument in startDraw
* DRAW_MODE_POLYGON is a filled polygon drawing mode.
* If a texture was given this texture will be used as filling
* DRAW_MODE_LINE_LOOP is a polygon drawing mode (non filled)
* DRAW_MODE_LINE_STRIP draws lines
**/
enum DrawMode {
DRAW_MODE_NONE,
DRAW_MODE_POLYGON,
DRAW_MODE_LINE_LOOP,
DRAW_MODE_LINE_STRIP
};
/**
* Definition of the blending mode
**/
enum BlendMode {
BLEND_MODE_NONE, //no blending
BLEND_MODE_A, //GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA
BLEND_MODE_B //GL_ONE,GL_ONE
};
/*===========================================================================
Class with various drawing functions
===========================================================================*/
class DrawLib {
public:
DrawLib();
virtual ~ DrawLib();
/* initialize a drawLib from a name */
static DrawLib* DrawLibFromName(std::string i_drawLibName);
/**
* initialize the screen
**/
virtual void init(int nDispWidth, int nDispHeight, int nDispBPP,
bool bWindowed, Theme * ptheme) = 0;
virtual void unInit() = 0;
void setDispWidth(int width) {
m_nDispWidth = width;
};
int getDispWidth(void) {
return m_nDispWidth;
};
void setNoGraphics(bool disable_graphics) {
m_bNoGraphics = disable_graphics;
};
bool isNoGraphics() {
return m_bNoGraphics;
};
void setDispHeight(int height) {
m_nDispHeight = height;
};
int getDispHeight(void) {
return m_nDispHeight;
}
void setDispBPP(int bpp) {
m_nDispBPP = bpp;
}
int getDispBPP(void) {
return m_nDispBPP;
}
void setWindowed(bool windowed) {
m_bWindowed = windowed;
};
bool getWindowed(void) {
return m_bWindowed;
}
/* Methods - low-level */
//add a vertex given screen coordinates
virtual void glVertexSP(float x, float y) = 0;
//add a vertex given opengl coordinates
virtual void glVertex(float x, float y) = 0;
//create a vertex based on a opengl
void glVertex(Vector2f x) {
glVertex(x.x, x.y);
};
//texture coordinate
virtual void glTexCoord(float x, float y) = 0;
virtual void screenProjVertex(float *x, float *y) = 0;
virtual void setColor(Color color) = 0;
/**
* set the texure for drawing
* the value may be NULL to disable texure
* every end draw will reset the texture to NULL
**/
virtual void setTexture(Texture * texture, BlendMode blendMode) = 0;
virtual void setBlendMode(BlendMode blendMode) = 0;
void setColorRGB(int r, int g, int b) {
setColor(MAKE_COLOR(r, g, b, 255));
};
void setColorRGBA(int r, int g, int b, int a) {
setColor(MAKE_COLOR(r, g, b, a));
};
/**
* enables clipping and sets the clipping borders
**/
virtual void setClipRect(int x, int y, int w, int h) = 0;
virtual void setClipRect(SDL_Rect * i_clip_rect) = 0;
virtual void setScale(float x, float y) = 0;
virtual void setTranslate(float x, float y) = 0;
virtual void setLineWidth(float width) = 0;
/**
* returns the current screen clipping
**/
virtual void getClipRect(int *o_px, int *o_py, int *o_pnWidth,
int *o_pnHeight) = 0;
/**
* Start drawing ... used in combination with glVertex
**/
virtual void startDraw(DrawMode mode) = 0;
/**
* End draw
**/
virtual void endDraw() = 0;
/**
* Clears the screen with the configured background
**/
virtual void clearGraphics() = 0;
/**
* resets the state of the zoom and translation
**/
virtual void resetGraphics() {
};
/**
* Flush the graphics. In memory graphics will now be displayed
**/
virtual void flushGraphics() = 0;
/* Methods - primitives */
virtual void drawCircle(const Vector2f & Center, float fRadius,
float fBorder = 1.0f, Color Back =
0, Color Front = -1);
virtual void drawBox(const Vector2f & A, const Vector2f & B,
float fBorder = 1.0f, Color Back =
0, Color Front = -1);
virtual void drawImage(const Vector2f & A, const Vector2f & B,
Texture * pTexture, Color Tint = -1);
/* Methods - text */
virtual void drawText(const Vector2f & Pos, std::string Text,
Color Back = 0, Color Front = -1, bool bEdge =
false) = 0;
virtual int getTextWidth(std::string Text) = 0;
virtual int getTextHeight(std::string Text) = 0;
void setDontUseGLExtensions(bool dont_use) {
m_bDontUseGLExtensions = dont_use;
};
virtual Img *grabScreen(void) = 0;
/*
* set the refecence drawing size
**/
void setDrawDims(int nActualW, int nActualH, int w, int h) {
m_nDrawWidth = w;
m_nDrawHeight = h;
m_nActualWidth = nActualW;
m_nActualHeight = nActualH;
}
//opengl specific to be removed
bool useVBOs() {
return m_bVBOSupported;
};
bool useFBOs() {
return m_bFBOSupported;
};
bool useShaders() {
return m_bShadersSupported;
};
/* Data */
int m_nDrawWidth, m_nDrawHeight;
int m_nActualWidth, m_nActualHeight;
int m_nDispWidth, m_nDispHeight, m_nDispBPP; /* Screen stuff */
int m_nLScissorX, m_nLScissorY, m_nLScissorW, m_nLScissorH;
virtual void _InitTextRendering(Theme * p_theme) = 0;
virtual void _UninitTextRendering(Theme * p_theme) = 0;
bool m_bWindowed; /* Windowed or not */
virtual bool isExtensionSupported(std::string Ext) = 0;
Texture *m_pDefaultFontTex;
Texture *m_texture;
BlendMode m_blendMode;
bool m_bVBOSupported;
bool m_bFBOSupported;
bool m_bShadersSupported;
bool m_bDontUseGLExtensions;
bool m_bNoGraphics; /* No-graphics mode */
private:
};
class DrawLibOpenGL:public DrawLib {
public:
DrawLibOpenGL();
~DrawLibOpenGL();
virtual void init(int nDispWidth, int nDispHeight, int nDispBPP,
bool bWindowed, Theme * ptheme);
virtual void unInit();
/* Methods - low-level */
//add a vertex given screen coordinates
virtual void glVertexSP(float x, float y);
//add a vertex given opengl coordinates
virtual void glVertex(float x, float y);
//texture coordinate
virtual void glTexCoord(float x, float y);
virtual void screenProjVertex(float *x, float *y);
virtual void setColor(Color color);
/**
* set the texure for drawing
* the value may be NULL to disable texure
* every end draw will reset the texture to NULL
**/
virtual void setTexture(Texture * texture, BlendMode blendMode);
virtual void setBlendMode(BlendMode blendMode);
/**
* enables clipping and sets the clipping borders
**/
virtual void setClipRect(int x, int y, int w, int h);
virtual void setClipRect(SDL_Rect * i_clip_rect);
virtual void setScale(float x, float y);
virtual void setTranslate(float x, float y);
virtual void setLineWidth(float width);
/**
* returns the current screen clipping
**/
virtual void getClipRect(int *o_px, int *o_py, int *o_pnWidth,
int *o_pnHeight);
/**
* Start drawing ... used in combination with glVertex
**/
virtual void startDraw(DrawMode mode);
/**
* End draw
**/
virtual void endDraw();
/**
* Clears the screen with the configured background
**/
virtual void clearGraphics();
/**
* Flush the graphics. In memory graphics will now be displayed
**/
virtual void flushGraphics();
/* Methods - text */
virtual void _InitTextRendering(Theme * p_theme);
virtual void _UninitTextRendering(Theme * p_theme);
virtual void drawText(const Vector2f & Pos, std::string Text,
Color Back = 0, Color Front = -1, bool bEdge =
false);
virtual int getTextWidth(std::string Text);
virtual int getTextHeight(std::string Text);
virtual Img *grabScreen(void);
virtual bool isExtensionSupported(std::string Ext);
/**
*keesj:TODO
*I am not happy about all these public members:)
**/
#ifdef ENABLE_OPENGL
/* Extensions */
PFNGLGENBUFFERSARBPROC glGenBuffersARB;
PFNGLBINDBUFFERARBPROC glBindBufferARB;
PFNGLBUFFERDATAARBPROC glBufferDataARB;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
/* Extensions (for render-to-texture) */
PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT;
PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT;
PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT;
PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT;
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC
glGetFramebufferAttachmentParameterivEXT;
PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
/* Extensions (for shaders) */
PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
PFNGLGETHANDLEARBPROC glGetHandleARB;
PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
PFNGLUNIFORM1FARBPROC glUniform1fARB;
PFNGLUNIFORM2FARBPROC glUniform2fARB;
PFNGLUNIFORM3FARBPROC glUniform3fARB;
PFNGLUNIFORM4FARBPROC glUniform4fARB;
PFNGLUNIFORM1IARBPROC glUniform1iARB;
PFNGLUNIFORM2IARBPROC glUniform2iARB;
PFNGLUNIFORM3IARBPROC glUniform3iARB;
PFNGLUNIFORM4IARBPROC glUniform4iARB;
PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
#endif
};
class DrawLibSDLgfx:public DrawLib {
public:
DrawLibSDLgfx();
~DrawLibSDLgfx();
virtual void init(int nDispWidth, int nDispHeight, int nDispBPP,
bool bWindowed, Theme * ptheme);
virtual void unInit();
/* Methods - low-level */
//add a vertex given screen coordinates
virtual void glVertexSP(float x, float y);
//add a vertex given opengl coordinates
virtual void glVertex(float x, float y);
//texture coordinate
virtual void glTexCoord(float x, float y);
virtual void screenProjVertex(float *x, float *y);
virtual void setColor(Color color);
/**
* set the texure for drawing
* the value may be NULL to disable texure
* every end draw will reset the texture to NULL
**/
virtual void setTexture(Texture * texture, BlendMode blendMode);
virtual void setBlendMode(BlendMode blendMode);
/**
* enables clipping and sets the clipping borders
**/
virtual void setClipRect(int x, int y, int w, int h);
virtual void setClipRect(SDL_Rect * i_clip_rect);
virtual void setScale(float x, float y);
virtual void setTranslate(float x, float y);
virtual void setLineWidth(float width);
/**
* returns the current screen clipping
**/
virtual void getClipRect(int *o_px, int *o_py, int *o_pnWidth,
int *o_pnHeight);
/**
* Start drawing ... used in combination with glVertex
**/
virtual void startDraw(DrawMode mode);
/**
* End draw
**/
virtual void endDraw();
/**
* Clears the screen with the configured background
**/
virtual void clearGraphics();
/**
* resets the variables like translation and rotation
**/
virtual void resetGraphics();
/**
* Flush the graphics. In memory graphics will now be displayed
**/
virtual void flushGraphics();
/* Methods - text */
virtual void _InitTextRendering(Theme * p_theme);
virtual void _UninitTextRendering(Theme * p_theme);
virtual void drawText(const Vector2f & Pos, std::string Text,
Color Back = 0, Color Front = -1, bool bEdge =
false);
virtual int getTextWidth(std::string Text);
virtual int getTextHeight(std::string Text);
virtual Img *grabScreen(void);
virtual bool isExtensionSupported(std::string Ext);
private:
int xx_texturedHLine(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y,
SDL_Surface * texture, int texture_dx,
int texture_dy);
int xx_texturedPolygon(SDL_Surface * dst, const Sint16 * vx,
const Sint16 * vy, int n, SDL_Surface * texture,
int texture_dx, int texture_dy);
int xx_texturedHLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2,
Sint16 y, SDL_Surface * texture,
int texture_dx, int texture_dy);
int xx_texturedPolygonAlpha(SDL_Surface * dst, const Sint16 * vx,
const Sint16 * vy, int n,
SDL_Surface * texture, int texture_dx,
int texture_dy);
int xx_filledPolygonColor(SDL_Surface * dst, const Sint16 * vx,
const Sint16 * vy, int n, Uint32 color);
//the mode used when drawing
DrawMode m_drawMode;
//the current scale
Vector2f m_scale;
//the current translate
Vector2f m_translate;
//data buffer for drawing the background
void *m_bg_data;
Vector2f m_min;
Vector2f m_max;
SDL_Surface *m_screen;
//
Vector2f m_textureAnchorPoint;
Texture *m_texture;
/**
* Color used to clear the screen
**/
Color m_backgroundColor;
/**
* color used for the current drawing
**/
Color m_color;
//Vector for creating polygons
std::vector < Vector2f * >m_drawingPoints;
//Vector for keeping track of texture coorinated
std::vector < Vector2f * >m_texturePoints;
//map to hold converted images
std::map < const char *, SDL_Surface *, ltstr > m_image_cache;
//dynamic allocated array for the
//that that is fed to the polygon filling
//algorithms
Sint16 *m_int_drawing_points_x;
Sint16 *m_int_drawing_points_y;
int m_int_drawing_points_allocated;
int *gfxPrimitivesPolyInts;
int gfxPrimitivesPolyAllocated;
bool m_is_screen_point;
};
};
#endif
/*=============================================================================
XMOTO
Copyright (C) 2005-2006 Rasmus Neckelmann (neckelmann@xxxxxxxxx)
This file is part of XMOTO.
XMOTO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
XMOTO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with XMOTO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
=============================================================================*/
/*
* Simple 2D drawing library, built closely on top of OpenGL.
*/
#include "VDraw.h"
#include "VApp.h"
#include "BuiltInFont.h"
#ifdef ENABLE_SDLGFX
#include "SDL_gfxPrimitives.h"
#include "SDL_rotozoom.h"
#include "iqsort.h"
//#define islt(a,b) ((*(const int *)a) - (*(const int *)b))
#define islt(a,b) ((*a)<(*b))
namespace vapp {
int xx_gfxPrimitivesCompareInt(const void *a, const void *b) {
return (*(const int *)a) - (*(const int *)b);
};
DrawLibSDLgfx::DrawLibSDLgfx():DrawLib() {
m_scale.x = 1;
m_scale.y = 1;
m_translate.x = 0;
m_translate.y = 0;
m_bg_data = NULL;
gfxPrimitivesPolyInts = NULL;
gfxPrimitivesPolyAllocated = 0;
m_int_drawing_points_x = NULL;
m_int_drawing_points_y = NULL;
m_int_drawing_points_allocated = 0;
m_min.x = 0;
m_min.y = 0;
m_max.x = 0;
m_max.y = 0;
};
DrawLibSDLgfx::~DrawLibSDLgfx() {
};
/*===========================================================================
Transform an OpenGL vertex to pure 2D
===========================================================================*/
void DrawLibSDLgfx::glVertexSP(float x, float y) {
m_is_screen_point = true;
m_drawingPoints.push_back(new Vector2f(x, y));
if (m_drawingPoints.size() == 0) {
m_min.x = m_max.x = x;
m_min.y = m_max.y = y;
} else {
if (x < m_min.x) {
m_min.x = x;
}
if (x > m_max.x) {
m_max.x = x;
}
if (y < m_min.y) {
m_min.y = y;
}
if (y > m_max.y) {
m_max.y = y;
}
}
}
void DrawLibSDLgfx::glVertex(float x, float y) {
Vector2f *v =
new Vector2f(m_nDrawWidth / 2 + ((x + m_translate.x) * m_scale.x),
m_nDrawHeight / 2 - ((y + m_translate.y) * m_scale.y));
if (m_drawingPoints.size() == 0) {
m_min.x = m_max.x = v->x;
m_min.y = m_max.y = v->y;
} else {
if (v->x < m_min.x) {
m_min.x = v->x;
}
if (v->x > m_max.x) {
m_max.x = v->x;
}
if (v->y < m_min.y) {
m_min.y = v->y;
}
if (v->y > m_max.y) {
m_max.y = v->y;
}
}
m_drawingPoints.push_back(v);
}
void DrawLibSDLgfx::glTexCoord(float x, float y) {
//m_texturePoints.push_back(new Vector2f(x, 1 -y));
m_texturePoints.push_back(new Vector2f(x, y));
}
void DrawLibSDLgfx::screenProjVertex(float *x, float *y) {
*y = m_nActualHeight - (*y);
}
void DrawLibSDLgfx::setClipRect(int x, int y, int w, int h) {
SDL_Rect *rect = new SDL_Rect();
rect->x = x;
rect->y = y;
rect->w = w;
rect->h = h;
setClipRect(rect);
}
void DrawLibSDLgfx::setClipRect(SDL_Rect * clip_rect) {
SDL_SetClipRect(m_screen, clip_rect);
}
void DrawLibSDLgfx::getClipRect(int *px, int *py, int *pnWidth,
int *pnHeight) {
*px = m_nLScissorX;
*py = m_nLScissorY;
*pnWidth = m_nLScissorW;
*pnHeight = m_nLScissorH;
}
void DrawLibSDLgfx::setScale(float x, float y) {
m_scale.x = x * m_nDrawWidth / 2;
m_scale.y = y * m_nDrawHeight / 2;
}
void DrawLibSDLgfx::setTranslate(float x, float y) {
m_translate.x = x;
m_translate.y = y;
}
void DrawLibSDLgfx::setLineWidth(float width) {
}
void DrawLibSDLgfx::init(int nDispWidth, int nDispHeight, int nDispBPP,
bool bWindowed, Theme * ptheme) {
/* Set suggestions */
m_nDispWidth = nDispWidth;
m_nDispHeight = nDispHeight;
m_nDispBPP = nDispBPP;
m_bWindowed = bWindowed;
/* Get some video info */
const SDL_VideoInfo *pVidInfo = SDL_GetVideoInfo();
if (pVidInfo == NULL)
throw Exception("(1) SDL_GetVideoInfo : " +
std::string(SDL_GetError()));
/* Determine target bit depth */
if (m_bWindowed)
/* In windowed mode we can't tinker with the bit-depth */
m_nDispBPP = pVidInfo->vfmt->BitsPerPixel;
int nFlags = SDL_SRCALPHA;
if (!m_bWindowed)
nFlags |= SDL_FULLSCREEN;
/* At last, try to "set the video mode" */
if ((m_screen =
SDL_SetVideoMode(m_nDispWidth, m_nDispHeight, m_nDispBPP,
nFlags)) == NULL) {
Log
("** Warning ** : Tried to set video mode %dx%d @ %d-bit, but SDL responded: %s\n"
" Now SDL will try determining a proper mode itself.",
m_nDispWidth, m_nDispHeight, m_nDispBPP);
/* Hmm, try letting it decide the BPP automatically */
if ((m_screen =
SDL_SetVideoMode(m_nDispWidth, m_nDispHeight, 0,
nFlags)) == NULL) {
/* Still no luck */
Log
("** Warning ** : Still no luck, now we'll try 800x600 in a window.");
m_nDispWidth = 800;
m_nDispHeight = 600;
m_bWindowed = true;
if ((m_screen =
SDL_SetVideoMode(m_nDispWidth, m_nDispHeight, 0,
SDL_SRCALPHA)) == NULL) {
throw Exception("SDL_SetVideoMode : " +
std::string(SDL_GetError()));
}
}
}
/* Retrieve actual configuration */
pVidInfo = SDL_GetVideoInfo();
if (pVidInfo == NULL)
throw Exception("(2) SDL_GetVideoInfo : " +
std::string(SDL_GetError()));
m_nDispBPP = pVidInfo->vfmt->BitsPerPixel;
/* Enable unicode translation and key repeats */
SDL_EnableUNICODE(1);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
SDL_DEFAULT_REPEAT_INTERVAL);
Log("Using SDL_gfx implementation");
//setBackgroundColor(0,0,40,255);
/* Init the Text drawing library */
_InitTextRendering(ptheme);
}
void DrawLibSDLgfx::unInit() {
}
/*===========================================================================
Check for OpenGL extension
===========================================================================*/
bool DrawLibSDLgfx::isExtensionSupported(std::string Ext) {
return false;
}
/*===========================================================================
Grab screen contents
===========================================================================*/
Img *DrawLibSDLgfx::grabScreen(void) {
Img *pImg = new Img;
pImg->createEmpty(m_nDispWidth, m_nDispHeight);
Color *pPixels = pImg->getPixels();
Uint8 red, green, blue, alpha;
SDL_LockSurface(m_screen);
for (int y = 0; y < m_screen->h; y++) {
for (int x = 0; x < m_screen->w; x++) {
void *pixel =
(Uint8 *) m_screen->pixels +
(x * m_screen->format->BytesPerPixel) +
((y) * (m_screen->pitch));
SDL_GetRGB(*(Uint32 *) pixel, m_screen->format, &red, &green,
&blue);
*(Uint32 *) pPixels = MAKE_COLOR(red, green, blue, 255);
pPixels++;
}
}
SDL_UnlockSurface(m_screen);
return pImg;
}
void DrawLibSDLgfx::startDraw(DrawMode mode) {
m_drawMode = mode;
if (m_drawingPoints.size() != 0 || m_texturePoints.size() != 0) {
printf
("error drawingPoints.size(%i) of texturePoints.size(%i) was not 0 =%i\n",
m_drawingPoints.size(), m_texturePoints.size());
}
m_is_screen_point = false;
}
void DrawLibSDLgfx::endDraw() {
int size = m_drawingPoints.size();
int x0, y0, x1, y1;
SDL_Rect *clip = NULL;
//get the current clipping on the screen
//if null we must expect the be drawing
//on the full screen
SDL_GetClipRect(m_screen, clip);
if (clip != NULL) {
x0 = clip->x;
y0 = clip->y;
x1 = x0 + clip->w;
x1 = y0 + clip->h;
} else {
x0 = 0;
y0 = 0;
x1 = m_screen->w;
y1 = m_screen->h;
}
bool draw = true;
//if all the lines are "smaller" or larger then the screen
//we don't need to draw
if (m_max.x < x0 || m_min.x > x1 || m_max.y < y0 || m_min.y > y1) {
draw = false;
}
if (draw == true) {
//keesj:TODO , why not just create one x/y array
//and use that all the time. this is also true
//for texture point and drawing points
//it will also remove the need to clean the m_texturePoints
//and m_drawingPoints collection afterwards
if (size > m_int_drawing_points_allocated) {
if (m_int_drawing_points_allocated == 0) {
m_int_drawing_points_x =
(Sint16 *) malloc(sizeof(Sint16) * size * 2);
m_int_drawing_points_y =
(Sint16 *) malloc(sizeof(Sint16) * size * 2);
m_int_drawing_points_allocated = size * 2;
} else {
m_int_drawing_points_x =
(Sint16 *) realloc(m_int_drawing_points_x,
sizeof(Sint16) *
m_int_drawing_points_allocated * 2);
m_int_drawing_points_y =
(Sint16 *) realloc(m_int_drawing_points_y,
sizeof(Sint16) *
m_int_drawing_points_allocated * 2);
m_int_drawing_points_allocated *= 2;
}
}
//keesj:we are converting floating points int's perhaps
//we need to add 0.5?
for (int i = 0; i < size; i++) {
m_int_drawing_points_x[i] = m_drawingPoints.at(i)->x;
m_int_drawing_points_y[i] = m_drawingPoints.at(i)->y;
}
switch (m_drawMode) {
case DRAW_MODE_POLYGON:
if (m_texture != NULL && m_texturePoints.size() > 2
&& m_drawingPoints.size() > 2) {
//texture points texture point 1 2 and 3
Vector2f t1, t2, t3;
//polygon points 1 2 3
Vector2f p1, p2, p3;
//texture line 1 2 and texture diagonal line 1
Vector2f tl1, tl2, tdl1;
//polygon line 1 2 and diagonal 1
Vector2f pl1, pl2, pdl1;
//the texture vector texture points are expected to be given in
//values that relate to the texture size
Vector2f texture_v = Vector2f(m_texture->surface->w, m_texture->surface->h);
//keesj:if the points there added using non screen points
//we need to convert the texture points to screen points
//I think that this is not the right place for this
if (!m_is_screen_point){
texture_v.y = -texture_v.y;
}
///anchor point for the texture
float x_start_pixel, y_start_pixel;
//we only support scaling , rotation and flipping of textures
//so we only need 3 points to determine the scale and rotation
//convert the texture points to pixel value by
//multiplying the point value with the texture size
t1 = *m_texturePoints.at(0) * texture_v;
t2 = *m_texturePoints.at(1) * texture_v;
t3 = *m_texturePoints.at(2) * texture_v;
//also get the 3 first points of the polygon
p1 = *m_drawingPoints.at(0);
p2 = *m_drawingPoints.at(1);
p3 = *m_drawingPoints.at(2);
//convert the texture points to line vector
//that is the value of the l* describes a line
//because we substract the two points
//for a polygon we at least need 3 points
//I try to think of the polygon as a rectangle
//this is why the two first lines are called tl
//and the third one texture diagonal line
tl1 = t2 - t1;
tl2 = t3 - t2;
tdl1 = t1 - t3;
pl1 = p2 - p1;
pl2 = p3 - p2;
pdl1 = p1 - p3;
float p1Scale = pl1.length() / tl1.length();
float p2Scale = pl2.length() / tl2.length();
float p3Scale = pdl1.length() / tdl1.length();
float x_zoom, y_zoom, angle, angle2;
//know
//the amount of zoom that the lines must perform
angle = tl1.angle() - pl1.angle();
angle2 = tl2.angle() - pl2.angle();
//TODO check???
//we now have two scales and two angles
//and we are going to try to define a scaling that can match both
//for scaling we can say that (acording to pythagoras)
//scale ^2 = dx_scale^2 + dy_scale^2
//and because we have two line and those lines must use the same images
//we can say
//line1_x_scale ^2 + line1_y_scale ^2 = line2_x_scale + ^2 line2_y_scale ^2
//determine the x and y factor of the first angle
//just like the image we are first going to rotate the content ot the texture
//so we rotate tl1
tl1.rotateXY(angle);
tl2.rotateXY(angle);
if (pl1.x != 0 && tl1.x != 0){
x_zoom = pl1.x / tl1.x;
// printf("%f / (sin(%f) * %f) = \n", pl1.x,angle, tl1.length(), x_zoom);
} else if (pl2.x != 0 && tl2.x != 0){
x_zoom = pl2.x / tl2.x;
} else {
x_zoom =2;
}
if (pl1.y != 0 && tl1.y != 0){
y_zoom = pl1.y / tl1.y;
// printf("%f / (sin(%f) * %f) = \n", pl1.x,angle, tl1.length(), x_zoom);
} else if (pl2.y != 0 && tl2.y != 0){
y_zoom = pl2.y / tl2.y;
} else {
y_zoom =2;
}
float fff = ((int)(pl1.angle() - pl2.angle()) + 360) % 360;
float ggg = ((int)(tl1.angle() - tl2.angle()) + 360) % 360;
//keesj:misterious code to determin if the texure
//is following the vertex points.and if not reverse
//this makes the bike look left and right
// if (fff > 180 && ggg < 180) {
// angle += 180;
// x_zoom = -x_zoom;
// }
//
// //SDL does not support very large images this code is located in SDL_surface.c line 48
// //
// // /* Next time I write a library like SDL, I'll use int for size. :) */
// // if ( width >= 16384 || height >= 65536 ) {
// // SDL_SetError("Width or height is too large");
// // return(NULL);
// // }
if (x_zoom * m_texture->surface->w < 16384
&& y_zoom * m_texture->surface->h < 65536) {
char key[255] = "";
// if (m_drawingPoints.size() > 4) {
// angle = 0;
// }
sprintf(key, "rotate-%s_%.0f_%.2f_%.2f",
m_texture->Name.c_str(), angle, x_zoom, y_zoom);
//sprintf(key, "rotate-%s_%i_%i_%i", m_texture->Name.c_str(), (int)angle, (int)60 * x_zoom , (int)60 * y_zoom );
SDL_Surface *s = NULL;
std::map < const char *,
SDL_Surface * >::iterator i = m_image_cache.find(key);
if (i != m_image_cache.end()) {
s = (*i).second;
} else {
char *keyName = (char *)malloc(strlen(key) + 1);
//printf("addding image with key %s\n", key);
SDL_Surface *s1 =
rotozoomSurfaceXY(m_texture->surface, angle, 1, 1, SMOOTHING_OFF);
SDL_Surface *s2 =
rotozoomSurfaceXY(s1, 0, x_zoom,
y_zoom, SMOOTHING_OFF);
if (m_texture->isAlpha) {
s = SDL_DisplayFormatAlpha(s2);
} else {
s =
SDL_ConvertSurface(s2, m_screen->format, SDL_HWSURFACE);
}
SDL_FreeSurface(s1);
SDL_FreeSurface(s2);
strcpy(keyName, key);
m_image_cache.insert(std::make_pair <> (keyName, s));
}
Vector2f middle = (p1 + p3) / 2;
Vector2f middle2 =
(*m_texturePoints.at(0) + *m_texturePoints.at(2)) / 2;
x_start_pixel = middle.x - (s->w * middle2.x);
y_start_pixel = middle.y - (s->h * middle2.y);
//if (m_texture->Name == "cheesy_board_199") {
//if (m_texture->Name == "Loading") {
if (m_texture->Name == "Body1") {
printf("-----------------%s---------------\n",
m_texture->Name.c_str());
printf("texture (%3.2f %.2f)\t(%.2f %.2f)\t(%.2f %.2f)\n", t1.x, t1.y,
t2.x, t2.y, t3.x, t3.y);
printf("drawing points (%3.2f %f)\t(%.2f %.2f)\t(%.2f %.2f)\n", p1.x, p1.y,
p2.x, p2.y, p3.x, p3.y);
printf("lenght\t%f %f\n", t1.length(), t2.length());
printf("lenght points\t%f %f\n", p1.length(), p2.length());
printf("text length\t%f\n", tl1.length());
printf("line lenght\t%f\n", pl1.length());
printf("scale\t%f %f %f \n", p1Scale, p2Scale, p3Scale);
printf("angle\t%f %f %f \n", tl1.angle(),
tl2.angle(), tdl1.angle());
printf("angle point\t%f %f %f \n", pl1.angle(),
pl2.angle(), pdl1.angle());
printf("angle total\t%f %f %f \n",
tl1.angle() - pl1.angle(), tl2.angle() - pl2.angle(),
tdl1.angle() - pdl1.angle());
printf("tr\t%f %f \n", x_start_pixel, y_start_pixel);
printf("zoom\t%f %f \n", x_zoom, y_zoom);
printf("rotate\t%f %f\n", angle, angle2);
printf("starx,starty\t%f %f\n", x_start_pixel,
y_start_pixel);
printf("direction\t%f \n", pl1.angle() - pl2.angle());
printf("direction2\t%f \n", fff);
}
if (m_texture->isAlpha) {
xx_texturedPolygonAlpha(m_screen, m_int_drawing_points_x,
m_int_drawing_points_y, size, s,
x_start_pixel, -y_start_pixel);
} else {
xx_texturedPolygon(m_screen, m_int_drawing_points_x,
m_int_drawing_points_y, size, s,
x_start_pixel, -y_start_pixel);
}
} else {
//zoom to large
printf("Zoom to large x y = %f %f\n",x_zoom,y_zoom);
}
} else {
xx_filledPolygonColor(m_screen, m_int_drawing_points_x,
m_int_drawing_points_y, size, m_color);
}
break;
case DRAW_MODE_LINE_LOOP:
polygonRGBA(m_screen, m_int_drawing_points_x,
m_int_drawing_points_y, size, GET_RED(m_color),
GET_GREEN(m_color), GET_BLUE(m_color),
GET_ALPHA(m_color));
break;
case DRAW_MODE_LINE_STRIP:
for (int f = 0; f < size - 1; f++) {
lineRGBA(m_screen, m_int_drawing_points_x[f],
m_int_drawing_points_y[f],
m_int_drawing_points_x[f + 1],
m_int_drawing_points_y[f + 1], GET_RED(m_color),
GET_GREEN(m_color), GET_BLUE(m_color),
GET_ALPHA(m_color));
}
break;
}
}
for (int i = 0; i < m_drawingPoints.size(); i++) {
delete m_drawingPoints.at(i);
}
for (int i = 0; i < m_texturePoints.size(); i++) {
delete m_texturePoints.at(i);
}
m_drawingPoints.resize(0);
m_texturePoints.resize(0);
m_drawMode = DRAW_MODE_NONE;
m_texture = NULL;
m_min.x = 0;
m_min.y = 0;
m_max.x = 0;
m_max.y = 0;
}
void DrawLibSDLgfx::setColor(Color color) {
m_color = color;
}
void DrawLibSDLgfx::setTexture(Texture * texture, BlendMode blendMode) {
m_texture = texture;
}
void DrawLibSDLgfx::setBlendMode(BlendMode blendMode) {
}
/*===========================================================================
Text dim probing
===========================================================================*/
int DrawLibSDLgfx::getTextHeight(std::string Text) {
int cx = 0, cy = 0, c;
int h = 0;
for (unsigned int i = 0; i < Text.size(); i++) {
c = Text[i];
if (c == ' ') {
cx += 8;
} else if (c == '\r') {
cx = 0;
} else if (c == '\n') {
cx = 0;
cy += 12;
} else {
cx += 8;
}
if (cy > h)
h = cx;
}
return h + 12;
}
int DrawLibSDLgfx::getTextWidth(std::string Text) {
int cx = 0, cy = 0, c;
int w = 0;
for (unsigned int i = 0; i < Text.size(); i++) {
c = Text[i];
if (c == ' ') {
cx += 8;
} else if (c == '\r') {
cx = 0;
} else if (c == '\n') {
cx = 0;
cy += 12;
} else {
cx += 8;
}
if (cx > w)
w = cx;
}
return w;
}
/*===========================================================================
Text drawing
===========================================================================*/
void DrawLibSDLgfx::drawText(const Vector2f & Pos, std::string Text,
Color Back, Color Front, bool bEdge) {
if (bEdge) {
/* SLOOOOW */
drawText(Pos + Vector2f(1, 1), Text, 0, MAKE_COLOR(0, 0, 0, 255),
false);
drawText(Pos + Vector2f(-1, 1), Text, 0, MAKE_COLOR(0, 0, 0, 255),
false);
drawText(Pos + Vector2f(1, -1), Text, 0, MAKE_COLOR(0, 0, 0, 255),
false);
drawText(Pos + Vector2f(-1, -1), Text, 0, MAKE_COLOR(0, 0, 0, 255),
false);
}
int cx = (int)Pos.x, cy = (int)Pos.y, c;
int nCharsPerLine = 256 / 8;
for (unsigned int i = 0; i < Text.size(); i++) {
c = Text[i];
if (c == ' ') {
startDraw(DRAW_MODE_POLYGON);
setColor(Back);
glVertexSP(cx, cy);
glVertexSP(cx + 8, cy);
glVertexSP(cx + 8, cy + 12);
glVertexSP(cx, cy + 12);
endDraw();
cx += 8;
} else if (c == '\r') {
cx = (int)Pos.x;
} else if (c == '\n') {
cx = (int)Pos.x;
cy += 12;
} else {
int y1 = (c / nCharsPerLine) * 12;
int x1 = (c % nCharsPerLine) * 8;
int y2 = y1 + 12;
int x2 = x1 + 8;
startDraw(DRAW_MODE_POLYGON);
setColor(Back);
glVertexSP(cx, cy);
glVertexSP(cx + 8, cy);
glVertexSP(cx + 8, cy + 12);
glVertexSP(cx, cy + 12);
endDraw();
if (m_pDefaultFontTex == NULL) {
printf("Can't draw with empy texture!\n");
}
setTexture(m_pDefaultFontTex, BLEND_MODE_A);
startDraw(DRAW_MODE_POLYGON);
setColor(Front);
glTexCoord((float)x1 / 256.0f, (float)y1 / 256.0f);
glVertexSP(cx, cy);
glTexCoord((float)x2 / 256.0f, (float)y1 / 256.0f);
glVertexSP(cx + 8, cy);
glTexCoord((float)x2 / 256.0f, (float)y2 / 256.0f);
glVertexSP(cx + 8, cy + 12);
glTexCoord((float)x1 / 256.0f, (float)y2 / 256.0f);
glVertexSP(cx, cy + 12);
endDraw();
cx += 8;
}
}
}
/*===========================================================================
Init of text rendering
===========================================================================*/
void DrawLibSDLgfx::_InitTextRendering(Theme * p_theme) {
m_pDefaultFontTex = p_theme->getDefaultFont();
}
/*===========================================================================
Uninit of text rendering
===========================================================================*/
void DrawLibSDLgfx::_UninitTextRendering(Theme * p_theme) {
}
void DrawLibSDLgfx::clearGraphics() {
SDL_LockSurface(m_screen);
if (m_bg_data == NULL) {
m_bg_data =
malloc(m_screen->format->BytesPerPixel * m_screen->w *
m_screen->h);
memset(m_bg_data, 0,
m_screen->format->BytesPerPixel * m_screen->w * m_screen->h);
}
memcpy(m_screen->pixels, m_bg_data,
m_screen->format->BytesPerPixel * m_screen->w * m_screen->h);
SDL_UnlockSurface(m_screen);
//SDL_FillRect(m_screen, NULL, SDL_MapRGB(m_screen->format, 0, 0, 0));
}
void DrawLibSDLgfx::resetGraphics() {
setClipRect(NULL);
m_scale.x = 1;
m_scale.y = 1;
m_translate.x = 0;
m_translate.y = 0;
}
/**
* Flush the graphics. In memory graphics will now be displayed
**/
void DrawLibSDLgfx::flushGraphics() {
SDL_UpdateRect(m_screen, 0, 0, 0, 0);
}
int DrawLibSDLgfx::xx_texturedHLineAlpha(SDL_Surface * dst, Sint16 x1,
Sint16 x2, Sint16 y,
SDL_Surface * texture,
int texture_dx,
int texture_dy) {
Sint16 left, right, top, bottom;
Sint16 w;
Sint16 xtmp;
int result = 0;
int texture_x_walker;
int texture_y_start;
SDL_Rect source_rect, dst_rect;
int pixels_written, write_width;
/*
* Get clipping boundary
*/
left = dst->clip_rect.x;
right = dst->clip_rect.x + dst->clip_rect.w - 1;
top = dst->clip_rect.y;
bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
/*
* Check visibility of hline
*/
if ((x1 < left) && (x2 < left)) {
return (0);
}
if ((x1 > right) && (x2 > right)) {
return (0);
}
if ((y < top) || (y > bottom)) {
return (0);
}
/*
* Swap x1, x2 if required
*/
if (x1 > x2) {
xtmp = x1;
x1 = x2;
x2 = xtmp;
}
/*
* Clip x
*/
if (x1 < left) {
x1 = left;
}
if (x2 > right) {
x2 = right;
}
/*
* Calculate width
*/
w = x2 - x1;
/*
* Sanity check on width
*/
if (w < 0) {
return (0);
}
/*
* Determint where in the texture we start drawing
**/
texture_x_walker = (x1 - texture_dx) % texture->w;
if (texture_x_walker < 0) {
texture_x_walker = texture->w + texture_x_walker;
}
texture_y_start = (y + texture_dy) % texture->h;
if (texture_y_start < 0) {
texture_y_start = texture->h + texture_y_start;
}
//setup the source rectangle we are only drawing one horizontal line
source_rect.y = texture_y_start;
source_rect.x = texture_x_walker;
source_rect.h = 1;
//we will draw to the current y
dst_rect.y = y;
//if there are enough pixels left in the current row of the texture
//draw it all at once
if (w <= texture->w - texture_x_walker) {
source_rect.w = w;
source_rect.x = texture_x_walker;
dst_rect.x = x1;
result != SDL_BlitSurface(texture, &source_rect, dst, &dst_rect);
} else { //we need to draw multiple times
//draw the first segment
pixels_written = texture->w - texture_x_walker;
source_rect.w = pixels_written;
source_rect.x = texture_x_walker;
dst_rect.x = x1;
result != SDL_BlitSurface(texture, &source_rect, dst, &dst_rect);
write_width = texture->w;
//now draw the rest
//set the source x to 0
source_rect.x = 0;
while (pixels_written < w) {
if (write_width >= w - pixels_written) {
write_width = w - pixels_written;
}
source_rect.w = write_width;
dst_rect.x = x1 + pixels_written;
result != SDL_BlitSurface(texture, &source_rect, dst, &dst_rect);
pixels_written += write_width;
}
}
return result;
}
/**
* Draws a polygon filled with the given texture. this operation use SDL_BlitSurface. It supports
* alpha drawing.
* to get the best performance of this operation you need to make sure the texture and the dst surface have the same format
* see http://docs.mandragor.org/files/Common_libs_documentation/SDL/SDL_Documentation_project_en/sdlblitsurface.html
*
* dest the destination surface,
* vx array of x vector components
* vy array of x vector components
* n the amount of vectors in the vx and vy array
* texture the sdl surface to use to fill the polygon
* texture_dx the offset of the texture relative to the screeen. if you move the polygon 10 pixels to the left and want the texture
* to apear the same you need to increase the texture_dx value
* texture_dy see texture_dx
**/
int DrawLibSDLgfx::xx_texturedPolygonAlpha(SDL_Surface * dst,
const Sint16 * vx,
const Sint16 * vy, int n,
SDL_Surface * texture,
int texture_dx,
int texture_dy) {
int result;
int i;
int y, xa, xb;
int minx, maxx, miny, maxy;
int x1, y1;
int x2, y2;
int ind1, ind2;
int ints;
/*
* Sanity check
*/
if (n < 3) {
return -1;
}
/*
* Allocate temp array, only grow array
*/
if (!gfxPrimitivesPolyAllocated) {
gfxPrimitivesPolyInts = (int *)malloc(sizeof(int) * n);
gfxPrimitivesPolyAllocated = n;
} else {
if (gfxPrimitivesPolyAllocated < n) {
gfxPrimitivesPolyInts =
(int *)realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
gfxPrimitivesPolyAllocated = n;
}
}
miny = vy[0];
maxy = vy[0];
minx = vx[0];
maxx = vx[0];
for (i = 1; (i < n); i++) {
if (vy[i] < miny) {
miny = vy[i];
} else if (vy[i] > maxy) {
maxy = vy[i];
}
if (vx[i] < minx) {
minx = vx[i];
} else if (vx[i] > maxx) {
maxx = vx[i];
}
}
if (maxx < 0 || minx > dst->w) {
return 0;
}
if (maxy < 0 || miny > dst->h) {
return 0;
}
/*
* Draw, scanning y
*/
result = 0;
for (y = miny; (y <= maxy); y++) {
ints = 0;
for (i = 0; (i < n); i++) {
if (!i) {
ind1 = n - 1;
ind2 = 0;
} else {
ind1 = i - 1;
ind2 = i;
}
y1 = vy[ind1];
y2 = vy[ind2];
if (y1 < y2) {
x1 = vx[ind1];
x2 = vx[ind2];
} else if (y1 > y2) {
y2 = vy[ind1];
y1 = vy[ind2];
x2 = vx[ind1];
x1 = vx[ind2];
} else {
continue;
}
if (((y >= y1) && (y < y2))
|| ((y == maxy) && (y > y1) && (y <= y2))) {
gfxPrimitivesPolyInts[ints++] =
((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
}
}
QSORT(int, gfxPrimitivesPolyInts, ints, islt);
// qsort(gfxPrimitivesPolyInts, ints, sizeof(int),
// xx_gfxPrimitivesCompareInt);
for (i = 0; (i < ints); i += 2) {
xa = gfxPrimitivesPolyInts[i] + 1;
xa = (xa >> 16) + ((xa & 32768) >> 15);
xb = gfxPrimitivesPolyInts[i + 1] - 1;
xb = (xb >> 16) + ((xb & 32768) >> 15);
result |=
xx_texturedHLineAlpha(dst, xa, xb, y, texture, texture_dx,
texture_dy);
}
}
return (result);
}
int DrawLibSDLgfx::xx_texturedHLine(SDL_Surface * dst, Sint16 x1,
Sint16 x2, Sint16 y,
SDL_Surface * texture,
int texture_dx, int texture_dy) {
Sint16 left, right, top, bottom;
Uint8 *pixel, *pixellast;
int dx;
int pixx, pixy;
Sint16 w;
Sint16 xtmp;
int result = -1;
int texture_start;
int texture_x_walker;
void *texture_start_pixel;
/*
* Get clipping boundary
*/
left = dst->clip_rect.x;
right = dst->clip_rect.x + dst->clip_rect.w - 1;
top = dst->clip_rect.y;
bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
/*
* Check visibility of hline
*/
if ((x1 < left) && (x2 < left)) {
return 0;
}
if ((x1 > right) && (x2 > right)) {
return 0;
}
if ((y < top) || (y > bottom)) {
return 0;
}
/*
* Swap x1, x2 if required
*/
if (x1 > x2) {
xtmp = x1;
x1 = x2;
x2 = xtmp;
}
/*
* Clip x
*/
if (x1 < left) {
x1 = left;
}
if (x2 > right) {
x2 = right;
}
/*
* Calculate width
*/
w = x2 - x1;
/*
* Sanity check on width
*/
if (w < 0) {
return (0);
}
/*
* More variable setup
*/
dx = w;
pixx = dst->format->BytesPerPixel;
pixy = dst->pitch;
pixel = ((Uint8 *) dst->pixels) + pixx * (int)x1 + pixy * (int)y;
//find out a what index the texture starts
//texture_start = (abs(y + texture_dy) % texture->h) * texture->w;
texture_start = (y + texture_dy) % texture->h;
if (texture_start < 0) {
texture_start = texture->h + texture_start;
}
//printf("texture start (h=)%i %i\n",texture_start,texture->h);
//texture_start =texture_start * texture->pitch;
texture_start = texture_start * texture->pitch / pixx;
texture_x_walker = (x1 - texture_dx) % texture->w;
if (texture_x_walker < 0) {
texture_x_walker = texture->w + texture_x_walker;
}
texture_start_pixel =
&((Uint8 *) texture->pixels)[texture_start * pixx];
pixellast = pixel + w * pixx;
//method 2 faster
//option 1 the whole line fits in one draw
if (w <= texture->w - texture_x_walker) {
memcpy(pixel,
&((Uint8 *) texture_start_pixel)[texture_x_walker * pixx],
w * pixx);
} else {
int pixels_written = texture->w - texture_x_walker;
//draw the first segment
memcpy(pixel,
&((Uint8 *) texture_start_pixel)[texture_x_walker * pixx],
pixels_written * pixx);
int write_width = texture->w;
//now draw the rest
while (pixels_written < w) {
if (write_width >= w - pixels_written) {
write_width = w - pixels_written;
}
memcpy(&((Uint8 *) pixel)[pixels_written * pixx],
texture_start_pixel, write_width * pixx);
pixels_written += write_width;
}
}
/*
//methods 1
for (; pixel <= pixellast; pixel += pixx) {
*(Uint16 *) pixel = ((Uint16*)texture_start_pixel)[texture_x_walker] ;
texture_x_walker++;
if (texture_x_walker >= texture->w ){ texture_x_walker=0; }
}
break;
*/
/*
* Set result code
*/
result = 0;
return (result);
}
int DrawLibSDLgfx::xx_texturedPolygon(SDL_Surface * dst,
const Sint16 * vx,
const Sint16 * vy, int n,
SDL_Surface * texture,
int texture_dx, int texture_dy) {
int result;
int i;
int y, xa, xb;
int minx, maxx, miny, maxy;
int x1, y1;
int x2, y2;
int ind1, ind2;
int ints;
/*
* Sanity check
*/
if (n < 3) {
return -1;
}
/*
* Allocate temp array, only grow array
*/
if (!gfxPrimitivesPolyAllocated) {
gfxPrimitivesPolyInts = (int *)malloc(sizeof(int) * n);
gfxPrimitivesPolyAllocated = n;
} else {
if (gfxPrimitivesPolyAllocated < n) {
gfxPrimitivesPolyInts =
(int *)realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
gfxPrimitivesPolyAllocated = n;
}
}
miny = vy[0];
maxy = vy[0];
minx = vx[0];
maxx = vx[0];
for (i = 1; (i < n); i++) {
if (vy[i] < miny) {
miny = vy[i];
} else if (vy[i] > maxy) {
maxy = vy[i];
}
if (vx[i] < minx) {
minx = vx[i];
} else if (vx[i] > maxx) {
maxx = vx[i];
}
}
if (maxx < 0 || minx > dst->w) {
return 0;
}
if (maxy < 0 || miny > dst->h) {
return 0;
}
SDL_LockSurface(dst);
/*
* Draw, scanning y
*/
result = 0;
for (y = miny; (y <= maxy); y++) {
ints = 0;
for (i = 0; (i < n); i++) {
if (!i) {
ind1 = n - 1;
ind2 = 0;
} else {
ind1 = i - 1;
ind2 = i;
}
y1 = vy[ind1];
y2 = vy[ind2];
if (y1 < y2) {
x1 = vx[ind1];
x2 = vx[ind2];
} else if (y1 > y2) {
y2 = vy[ind1];
y1 = vy[ind2];
x2 = vx[ind1];
x1 = vx[ind2];
} else {
continue;
}
if (((y >= y1) && (y < y2))
|| ((y == maxy) && (y > y1) && (y <= y2))) {
gfxPrimitivesPolyInts[ints++] =
((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
}
}
QSORT(int, gfxPrimitivesPolyInts, ints, islt);
//qsort(gfxPrimitivesPolyInts, ints, sizeof(int),
// xx_gfxPrimitivesCompareInt);
for (i = 0; (i < ints); i += 2) {
xa = gfxPrimitivesPolyInts[i] + 1;
xa = (xa >> 16) + ((xa & 32768) >> 15);
xb = gfxPrimitivesPolyInts[i + 1] - 1;
xb = (xb >> 16) + ((xb & 32768) >> 15);
result |=
xx_texturedHLine(dst, xa, xb, y, texture, texture_dx,
texture_dy);
}
}
SDL_UnlockSurface(dst);
return (result);
}
int DrawLibSDLgfx::xx_filledPolygonColor(SDL_Surface * dst,
const Sint16 * vx,
const Sint16 * vy, int n,
Uint32 color) {
int result;
int i;
int y, xa, xb;
int miny, maxy;
int x1, y1;
int x2, y2;
int ind1, ind2;
int ints;
/*
* Sanity check
*/
if (n < 3) {
return -1;
}
/*
* Allocate temp array, only grow array
*/
if (!gfxPrimitivesPolyAllocated) {
gfxPrimitivesPolyInts = (int *)malloc(sizeof(int) * n);
gfxPrimitivesPolyAllocated = n;
} else {
if (gfxPrimitivesPolyAllocated < n) {
gfxPrimitivesPolyInts =
(int *)realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
gfxPrimitivesPolyAllocated = n;
}
}
/*
* Determine Y maxima
*/
miny = vy[0];
maxy = vy[0];
for (i = 1; (i < n); i++) {
if (vy[i] < miny) {
miny = vy[i];
} else if (vy[i] > maxy) {
maxy = vy[i];
}
}
/*
* Draw, scanning y
*/
result = 0;
for (y = miny; (y <= maxy); y++) {
ints = 0;
for (i = 0; (i < n); i++) {
if (!i) {
ind1 = n - 1;
ind2 = 0;
} else {
ind1 = i - 1;
ind2 = i;
}
y1 = vy[ind1];
y2 = vy[ind2];
if (y1 < y2) {
x1 = vx[ind1];
x2 = vx[ind2];
} else if (y1 > y2) {
y2 = vy[ind1];
y1 = vy[ind2];
x2 = vx[ind1];
x1 = vx[ind2];
} else {
continue;
}
if (((y >= y1) && (y < y2))
|| ((y == maxy) && (y > y1) && (y <= y2))) {
gfxPrimitivesPolyInts[ints++] =
((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
}
}
// qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt);
QSORT(int, gfxPrimitivesPolyInts, ints, islt);
for (i = 0; (i < ints); i += 2) {
xa = gfxPrimitivesPolyInts[i] + 1;
xa = (xa >> 16) + ((xa & 32768) >> 15);
xb = gfxPrimitivesPolyInts[i + 1] - 1;
xb = (xb >> 16) + ((xb & 32768) >> 15);
result |= hlineColor(dst, xa, xb, y, color);
}
}
return (result);
}
}
#endif