/*************************************************************************** * Copyright (C) 2009 by Stefan Bühler * * stbuehler@web.de * * * * This program 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. * * * * This program 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 this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "piecelibrary.h" #include #include #include #include namespace toruschess { typedef Lib3dsBool (*Lib3dsIoErrorFunc)(void *self); typedef long (*Lib3dsIoSeekFunc)(void *self, long offset, Lib3dsIoSeek origin); typedef long (*Lib3dsIoTellFunc)(void *self); typedef size_t (*Lib3dsIoReadFunc)(void *self, void *buffer, size_t size); typedef size_t (*Lib3dsIoWriteFunc)(void *self, const void *buffer, size_t size); Lib3dsBool io3ds_error(void *self); long io3ds_seek(void *self, long offset, Lib3dsIoSeek origin); long io3ds_tell(void *self); size_t io3ds_read(void *self, void *buffer, size_t size); size_t io3ds_write(void *self, const void *buffer, size_t size); class IO3ds { public: IO3ds(const QByteArray &data) : m_data(data), m_offset(0) { m_io = lib3ds_io_new(this, io3ds_error, io3ds_seek, io3ds_tell, io3ds_read, io3ds_write); } ~IO3ds() { lib3ds_io_free(m_io); } long seek(long offset, Lib3dsIoSeek origin) { switch (origin) { case LIB3DS_SEEK_SET: m_offset = offset; break; case LIB3DS_SEEK_CUR: m_offset += offset; break; case LIB3DS_SEEK_END: m_offset = m_data.length() + offset; break; } return 0; } long tell() { return m_offset; } size_t read(void *buffer, size_t size) { qDebug("read (size %i): data-len = %i, offset = %i", (int) size, m_data.length(), (int) m_offset); if (m_offset >= m_data.length()) return 0; size_t r = qMin(size, (size_t) m_data.length() - m_offset); memcpy(buffer, m_data.constData() + m_offset, r); m_offset += r; qDebug("read: done with %i", (int) r); return r; } size_t write(const void *, size_t ) { return 0; } Lib3dsBool error() { qDebug("3ds error"); return true; } Lib3dsIo* io() { return m_io; } private: Lib3dsIo *m_io; QByteArray m_data; long m_offset; }; Lib3dsBool io3ds_error(void *self) { IO3ds *s = (IO3ds*) self; return s->error(); } long io3ds_seek(void *self, long offset, Lib3dsIoSeek origin) { IO3ds *s = (IO3ds*) self; return s->seek(offset, origin); } long io3ds_tell(void *self) { IO3ds *s = (IO3ds*) self; return s->tell(); } size_t io3ds_read(void *self, void *buffer, size_t size) { IO3ds *s = (IO3ds*) self; return s->read(buffer, size); } size_t io3ds_write(void *self, const void *buffer, size_t size) { IO3ds *s = (IO3ds*) self; return s->write(buffer, size); } Lib3dsFile *read_3ds(const QByteArray &data) { return lib3ds_file_load("media/pawn.3ds"); IO3ds io(data); Lib3dsFile *f = lib3ds_file_new(); if (!lib3ds_file_read(f, io.io())) { // qDebug("data size: %i", (int) data.size()); lib3ds_file_free(f); return NULL; } return f; } QByteArray loadResource(const QString &filename) { QResource res(filename); // qDebug("res size: %i", (int) res.size()); return QByteArray((const char*) res.data(), (int) res.size()); } PieceLibrary::PieceLibrary(QObject *parent) : QObject(parent), m_pieces(0), m_buffers(0), m_pawn_list(0) { m_board = new QImage*[2]; m_board[0] = new QImage(":/media/board2_white.png"); m_board[1] = new QImage(":/media/board2_dark.png"); m_pawn = read_3ds(loadResource(":/media/pawn.3ds")); setSize(45, 45); } PieceLibrary::~PieceLibrary() { if (m_pawn) lib3ds_file_free(m_pawn); if (m_pawn_list) glDeleteLists(m_pawn_list, 1); delete [] m_pieces; delete [] m_buffers; delete [] m_board; } void PieceLibrary::setSize(int width, int height) { m_width = qMax(10, width); m_height = qMax(10, height); if (m_buffers) { for (int i = 0; i < 12; i++) { delete m_buffers[i]; } } else { m_pieces = new QSvgRenderer* [12]; m_buffers = new QImage* [12]; for (int i = 0; i < 12; i++) { m_pieces[i] = new QSvgRenderer(QString(":/media/chess_%1.svg").arg(i+1), this); } } for (int i = 0; i < 12; i++) { m_buffers[i] = new QImage(QSize(m_width, m_height), QImage::Format_ARGB32_Premultiplied); m_buffers[i]->fill(0x0); QPainter p(m_buffers[i]); m_pieces[i]->render(&p); } } void PieceLibrary::paint(QPainter &pt, int place) const { if (place == 0) return; if (place < 0) place = 6 - place; if (place <= 0 || place > 12) return; pt.drawImage(0, 0, *m_buffers[place-1]); } void PieceLibrary::paint(QPainter &pt, int place, const QRect &rect) const { if (place == 0) return; if (place < 0) place = 6 - place; if (place <= 0 || place > 12) return; pt.drawImage(rect, *m_buffers[place-1]); } void PieceLibrary::paint_board(QPainter &pt, bool darkField, const QRect &rect) const { pt.drawImage(rect, *m_board[darkField ? 1 : 0]); } void PieceLibrary::paint_pawn() { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3,GL_FLOAT,0,m_pawn->meshes->pointL); if (m_pawn_list) { glCallList(m_pawn_list); } else { m_pawn_list = glGenLists(1); if (m_pawn_list) glNewList(m_pawn_list, GL_COMPILE_AND_EXECUTE); for (unsigned int i = 0; i < m_pawn->meshes->faces; i++) { glNormal3fv(m_pawn->meshes->faceL[i].normal); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, m_pawn->meshes->faceL[i].points); } if (m_pawn_list) glEndList(); } glDisableClientState(GL_VERTEX_ARRAY); } }