Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не работает рисование части текстуры (SDL+OpenGL) 
:(
    Опции темы
SadOne
Дата 15.8.2012, 08:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.8.2012

Репутация: нет
Всего: нет



Пишу для себя простенькую игру и столкнулся с проблемой.

Изначально игра писалась на СИ, но потом те крохотные участки кода были перенесены на C++.

В чём, собственно, проблема: не рисуются части текстур - проблема появилась после переноса. Я проверял во всех местах: никаких эксцэсов нет. Помогите, пожалуйста.

файл CRender.h:
Код

#include <SDL/SDL.h>
#include <GL/gl.h>
#include <Base.h>
#ifndef CRENDER_H
#define CRENDER_H

#define GFX_TASK_L0_COUNT 1024
#define GFX_TASK_L1_COUNT 128
#define GFX_TEXLOAD_COUNT 64

struct gfx_texture_t
{
    GLuint width,height;
    GLuint texID;
    SDL_Surface *sys;
};

struct gfx_tex_load_t
{
  gfx_texture_t *dest;
  char          *path;
  bool           free;
};

struct gfx_task_l0_t
{
  uint8_t flag;
#define GFX_FLAG_FILLED (1<<7)
#define GFX_FLAG_WH    1  //назначить свою ш/д
#define GFX_FLAG_ROT   (1<<1)  //угол наклона
#define GFX_FLAG_TEX   (1<<2)  //только часть текстуры
#define GFX_FLAG_DEPTH (1<<3)  //своя глубина ( по дефолту - 0.5)
#define GFX_FLAG_BLEND (1<<4)  //режим бленда
  uint32_t x,y,w,h;
  gfx_texture_t tex;
  float rot;
  float depth;
  uint16_t tex_x,tex_y,tex_w,tex_h;
};

struct gfx_task_l1_t
{
  uint8_t status;
#define GFX_L1_STATUS_FREE   0
#define GFX_L1_STATUS_FILLED 1
  float out_x,out_y;//y уже инвертирован!
  float out_w,out_h;
  float tex_x1,tex_y1;
  float tex_x2,tex_y2;
  float rot,depth;
  unsigned int tex_id;
};


class CRender
{
  public:
    void Init(int,int,bool,bool);
    void Halt();
    int ThreadRFunc(void*);
    int ThreadCFunc(void*);
    int Timer(uint32_t,void*);
    void Stop();
    void Continue();
    void TextureLoadingBegin();
    void TextureLoadingAdd(gfx_texture_t*,char*);
    void TextureLoadingEnd();
    struct
    {
      uint32_t X,Y;
    } Camera;
    //drawing
    void Draw(gfx_texture_t*,uint32_t,uint32_t );
    void Draw(gfx_texture_t*,uint32_t,uint32_t,uint16_t,uint16_t,uint16_t,uint16_t );
    void Draw(gfx_texture_t*,uint32_t,uint32_t,rect_t );
    void Draw(gfx_texture_t*,uint32_t,uint32_t,rect_t,uint32_t,uint32_t);
    //inline
    inline void gfx_l0_add(gfx_task_l0_t);
  private:
    gfx_task_l0_t *task_l0;
    gfx_task_l1_t *task_l1;
    gfx_tex_load_t *tex_load;
    int coord_w, coord_h;
    int fps_tmp,fps;
    int tex_load_i;
    bool stop;
    bool stop_answerR, stop_answerC;
    bool quit;
    bool tex_load_signal;
    SDL_Thread *threadR, *threadC;
    SDL_TimerID timer;
    SDL_Surface *window;
};

#endif // CRENDER_H



Crender.cpp:
Код

#include <CRender.h>
#include <Base.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glu.h>

CRender Render;

int __tmp_render_func(void *ptr);
int __tmp_conventer_func(void *ptr);
unsigned int __tmp_timer_func(unsigned int,void *ptr);

inline void CRender::gfx_l0_add(gfx_task_l0_t newtask)
{
  int a;
  gfx_task_l0_t *task=task_l0;
  for(a=0;a<GFX_TASK_L0_COUNT;a++)
  {
    if(memcmp(&task[a],&newtask,sizeof(gfx_task_l0_t))==0)break;
    if(task[a].flag==0)
    {
      task[a]=newtask;
      break;
    }
  }
}

void CRender::Init(int w,int h,bool fs,bool db)
{
  struct
  {
    int  w;
    int  y;
    bool fs;
    bool db;
  } values = {w,h,fs,db};

  task_l0  = new gfx_task_l0_t[GFX_TASK_L0_COUNT];
  task_l1  = new gfx_task_l1_t[GFX_TASK_L1_COUNT];
  tex_load = new gfx_tex_load_t[GFX_TEXLOAD_COUNT];

  coord_w = w;
  coord_h = h;

  Camera.X = Camera.Y = 0;

  fps_tmp = fps = 0;
  tex_load_i = 0;
  stop = stop_answerR = stop_answerC = false;
  quit = tex_load_signal = false;

  threadR = SDL_CreateThread(__tmp_render_func,&values);
  threadC = SDL_CreateThread(__tmp_conventer_func,NULL);
  timer = SDL_AddTimer(1000,__tmp_timer_func,NULL);
}

void CRender::Stop()
{
  stop = true;
  //waiting R and C threads
  SDL_Delay(20);
}


void CRender::Continue()
{
  stop = false;
  //waiting R and C threads
  SDL_Delay(20);
}

int CRender::ThreadRFunc(void *params)
{
  struct
  {
    int  w;
    int  h;
    bool fs;
    bool db;
  } values = *((typeof(values)*)params);

  window = SDL_SetVideoMode(values.w, values.h, 32, SDL_OPENGL |
                            (values.fs?SDL_FULLSCREEN:0) |
                            (values.db?SDL_DOUBLEBUF:0));

  //hide system cursor
  int tmp[4]={0,0,0,0};
  SDL_SetCursor(SDL_CreateCursor((uint8_t*)&tmp,(uint8_t*)&tmp,2,2,1,1));

  SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,8);
  glClearColor(0.7f, 0.7f, 0.9f, 1.0f);
  glClearDepth(1.0f);
  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);
  glShadeModel(GL_SMOOTH);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(0.0f,(values.w/values.h),
                 0.1f,100.0f);
  glMatrixMode(GL_MODELVIEW);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glEnable(GL_TEXTURE_2D);
  glEnable(GL_BLEND);
  glEnable(GL_ALPHA);
  glEnable(GL_ALPHA_TEST);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glBlendFunc(GL_LEQUAL,0.3f);
  glAlphaFunc(GL_GEQUAL,0.1f);
  //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
  //                GL_LINEAR_MIPMAP_NEAREST);
  //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);


  //start main Render Loop
  while(quit==false)
  {
    gfx_task_l1_t *task;
    int i=0;

    if(stop==true)
    {

      if(tex_load_signal==true)
      {
        for(int i=0;i<tex_load_i;i++)
        {
          //Здесь мы загружаем/освобождаем текстуру
          if(tex_load[i].free==true)
          {
            SDL_FreeSurface(tex_load[i].dest->sys);
            glDeleteTextures(1,&(tex_load[i].dest->texID));
          }
          else
          {
            printf("[Render]loading %s... \n",tex_load[i].path);
            tex_load[i].dest->sys=IMG_Load(tex_load[i].path);
            if(tex_load[i].dest->sys==NULL)puts("IMG_Load() error\n");
            tex_load[i].dest->width=tex_load[i].dest->sys->w;  //Ничего не стоящяя оптимизация
            tex_load[i].dest->height=tex_load[i].dest->sys->h; //Меньше обращений к памяти
            glGenTextures(1, &(tex_load[i].dest->texID));
            glBindTexture(GL_TEXTURE_2D,tex_load[i].dest->texID);
            gluBuild2DMipmaps(GL_TEXTURE_2D, 4, tex_load[i].dest->width, tex_load[i].dest->height,
                              GL_RGBA,GL_UNSIGNED_BYTE,tex_load[i].dest->sys->pixels);
            //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
            //                GL_LINEAR_MIPMAP_NEAREST);
            //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

          }
        }
        tex_load_signal=false;
      }

      if(stop_answerR==false)
        stop_answerR=true;
      else
      {
        //пропускаем ход
        SDL_Delay(20);
        continue;
      }
    }
    else
      if(stop_answerR==true)
        stop_answerR==false;

    //очищаем экран перед прорисовкой
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearDepth(1.0f);

    for(task=task_l1;i++<GFX_TASK_L0_COUNT;task++)
    {
      if(task->status==GFX_L1_STATUS_FILLED)
      {
        glTranslatef(task->out_x,task->out_y,task->depth);

        glBindTexture(GL_TEXTURE_2D, task->tex_id);
        glBegin(GL_QUADS);
          glTexCoord2f(task->tex_x1,task->tex_y2);
          glVertex3f(-task->out_w, -task->out_h, 0);
          glTexCoord2f(task->tex_x2,task->tex_y2);
          glVertex3f(task->out_w, -task->out_h, 0);
          glTexCoord2f(task->tex_x2,task->tex_y1);
          glVertex3f(task->out_w, task->out_h, 0);
          glTexCoord2f(task->tex_x1,task->tex_y1);
          glVertex3f(-task->out_w, task->out_h, 0);
        glEnd();


        glTranslatef(-task->out_x,-task->out_y,-task->depth);
        task->status=GFX_L1_STATUS_FREE;
      }
    }

    glFlush();
    fps_tmp++;
    SDL_GL_SwapBuffers();
    SDL_Delay(30);
  }
  SDL_FreeSurface(window);
  SDL_Delay(50);
  return 0;
}

int CRender::ThreadCFunc(void *params)
{
  register gfx_task_l0_t *task;
  register int i,a;

  while(quit==false)
  {
    task=task_l0;

    if(stop==true)
    {
      if(stop_answerC==false)
        stop_answerC=true;
      else
      {
        //пропускаем ход
        SDL_Delay(30);
        continue;
      }

    }
    else
      if(stop_answerC==true)
        stop_answerC==false;


    for(i=0;i++<GFX_TASK_L1_COUNT;task++)
    {
      if(task->flag !=0)
      {
        gfx_task_l1_t *dst;
        //ищем свободную ячейку
        for(a=0;a<GFX_TASK_L1_COUNT;a++)
          if(task_l1[a].status==GFX_L1_STATUS_FREE)break;

        dst=&(task_l1[a]);

        if(task->flag & GFX_FLAG_DEPTH == GFX_FLAG_DEPTH)
          dst->depth=1.0f-task->depth;//Z тоже инвертирован
        else
          dst->depth=0.5f;

        if(task->flag&GFX_FLAG_ROT==GFX_FLAG_ROT)
          dst->rot=task->rot;
        else
          dst->rot=0.0f;

        if(task->flag&GFX_FLAG_WH==GFX_FLAG_WH)
        {
          dst->out_w=(float)task->w/(float)coord_w;
          dst->out_h=(float)task->h/(float)coord_h;
        }
        else
        {
          dst->out_w=(float)task->tex.width/(float)coord_w;
          dst->out_h=(float)task->tex.height/(float)coord_h;
        }

        if(task->flag&GFX_FLAG_TEX==GFX_FLAG_TEX)
        {
          dst->tex_x1=(float)task->tex_x/(float)task->tex.width;
          dst->tex_x2=dst->tex_x1+((float)task->tex_w/(float)task->tex.width);
          dst->tex_y1=(float)task->tex_y/(float)task->tex.height;
          dst->tex_y2=dst->tex_y1+((float)task->tex_h/(float)task->tex.height);
        }
        else
        {
          dst->tex_x1=0.0f;
          dst->tex_x2=1.0f;
          dst->tex_y1=0.0f;
          dst->tex_y2=1.0f;
        }

        dst->out_x=-1.0f+((float)task->x/(float)coord_w)*2.0f;
        dst->out_y=1.0f-((float)task->y/(float)coord_h)*2.0f;

        dst->tex_id=task->tex.texID;

        dst->status=GFX_L1_STATUS_FILLED;
        task->flag=0;
      }
    }
    SDL_Delay(20);
  }

  SDL_Delay(50);
  return 0;
}

int CRender::Timer(uint32_t time, void *params)
{
  fps=fps_tmp;
  fps_tmp=0;
  return 1000;
}

void CRender::Halt()
{
  if(stop==false) Stop();
  quit = true;
  SDL_RemoveTimer(timer);
  SDL_Delay(800);
}

void CRender::TextureLoadingBegin()
{
  Stop();
  tex_load_i = 0;
}

void CRender::TextureLoadingAdd(gfx_texture_t *tex,char *path)
{
  if(tex_load_i>GFX_TEXLOAD_COUNT)
  {
    //Список переполнен. Выполняем сначала  то, что уже есть.
    TextureLoadingEnd();
    TextureLoadingBegin();
  }

  tex_load[tex_load_i].free=false;
  tex_load[tex_load_i].dest   = tex;
  tex_load[tex_load_i++].path = path;
}

void CRender::TextureLoadingEnd()
{
  tex_load_signal = true;
  while(tex_load_signal == true) SDL_Delay(10);
  Continue();
}

void CRender::Draw(gfx_texture_t *tex, uint32_t x, uint32_t y )
{
  gfx_task_l0_t newtask;

  newtask.flag=GFX_FLAG_FILLED ;
  newtask.x=x-Camera.X;
  newtask.y=y-Camera.Y;
  newtask.tex=*tex;



  gfx_l0_add(newtask);
}

void CRender::Draw(gfx_texture_t *tex,uint32_t x,uint32_t y,uint16_t pX,uint16_t pY,uint16_t pW,uint16_t pH)
{
  gfx_task_l0_t newtask;


  newtask.flag=GFX_FLAG_FILLED | GFX_FLAG_TEX | GFX_FLAG_WH;
  newtask.x=x-Camera.X;
  newtask.y=y-Camera.Y;
  newtask.w=(uint32_t)pW;
  newtask.h=(uint32_t)pH;
  newtask.tex_x=pX;
  newtask.tex_y=pY;
  newtask.tex_w=pW;
  newtask.tex_h=pH;
  newtask.tex=*tex;

  gfx_l0_add(newtask);
}

void CRender::Draw(gfx_texture_t *tex,uint32_t x,uint32_t y,rect_t rect)
{
  gfx_task_l0_t newtask;


  newtask.flag=GFX_FLAG_FILLED + GFX_FLAG_TEX + GFX_FLAG_WH;
  newtask.x=x-Camera.X;
  newtask.y=y-Camera.Y;
  newtask.w=rect.w;
  newtask.h=rect.h;
  newtask.tex_x=rect.x;
  newtask.tex_y=rect.y;
  newtask.tex_w=rect.w;
  newtask.tex_h=rect.h;
  newtask.tex=*tex;

  gfx_l0_add(newtask);
}

void CRender::Draw(gfx_texture_t *tex,uint32_t x,uint32_t y,rect_t rect, uint32_t w, uint32_t h)
{
  gfx_task_l0_t newtask;


  newtask.flag=GFX_FLAG_FILLED + GFX_FLAG_TEX + GFX_FLAG_WH;
  newtask.x=x-Camera.X;
  newtask.y=y-Camera.Y;
  newtask.w=w;
  newtask.h=h;
  newtask.tex_x=rect.x;
  newtask.tex_y=rect.y;
  newtask.tex_w=rect.w;
  newtask.tex_h=rect.h;
  newtask.tex=*tex;

  gfx_l0_add(newtask);
}

////

int __tmp_render_func(void *ptr)
{
  return Render.ThreadRFunc(ptr);
}

int __tmp_conventer_func(void *ptr)
{
  return Render.ThreadCFunc(ptr);
}

unsigned int __tmp_timer_func(unsigned int time, void *ptr)
{
  return (unsigned int)Render.Timer(((uint32_t)time), ptr);
}


PM MAIL ICQ   Вверх
bsa
Дата 15.8.2012, 10:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



SadOne, сравни изменения. а для начала попробуй старый код тупо переименовать в *.cpp и скомпилировать компилятором С++. Если проблем не будет, то постепенно вноси свои изменения, пока проблема не проявится.

Добавлено через 1 минуту и 40 секунд
Кстати, стражи хидера должны быть в начале него, а не после инклюдов. Иначе, компилятор тратит время на поиск подключаемых хидеров. каждый раз, при подключении твоего хидера.
PM   Вверх
SadOne
Дата 15.8.2012, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.8.2012

Репутация: нет
Всего: нет



Собственно, из нововведений только остановка прорисовки и возможность in-time загружать/освобождать текстуры. Я не совсем полно раскрыл суть проблемы. Вот такой код работает:
Код

Render.Draw(&(ui_cursor),Render.Camera.X+Input.mouse_x,Render.Camera.Y+Input.mouse_y);

А такой - нет:
Код

Render.Draw(&(ui_cursor),Render.Camera.X+Input.mouse_x,Render.Camera.Y+Input.mouse_y,0,0,20,20);

PM MAIL ICQ   Вверх
bsa
Дата 16.8.2012, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



SadOne, запусти программу под отладчиком и пройди по шагам контролируя все переменные
PM   Вверх
SadOne
Дата 21.8.2012, 08:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.8.2012

Репутация: нет
Всего: нет



bsa, Проверял - эксцесов не нашёл. Никакой зацепки.
PM MAIL ICQ   Вверх
xvr
Дата 24.8.2012, 09:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



  • Опишите члены класса, которые модифицируются из таймера, как volatile
  • Обнулите (через memset) структуру newtask во всех CRender::Draw перед ее заполнением

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0978 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.