OpenGL gui working. Added sketch of the pheromone map. Added shaders.
This commit is contained in:
224
GLSLProgram.cpp
Normal file
224
GLSLProgram.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "GLSLProgram.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
CGLSLProgram::CGLSLProgram(void)
|
||||
{
|
||||
m_vIdShader[VERTEX] = 0;
|
||||
m_vIdShader[FRAGMENT] = 0;
|
||||
m_vIdShader[GEOMETRY] = 0;
|
||||
m_vIdShader[TESSELATION] = 0;
|
||||
m_mapVarShader.clear();
|
||||
m_mapSubroutines.clear();
|
||||
}
|
||||
|
||||
CGLSLProgram::~CGLSLProgram(void)
|
||||
{
|
||||
m_mapVarShader.clear();
|
||||
m_mapSubroutines.clear();
|
||||
if(m_uIdProgram > 0)
|
||||
{
|
||||
glDeleteProgram(m_uIdProgram);
|
||||
cout << "Program deleted! " << endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool CGLSLProgram::loadShaderFile(std::string strFilename, GLuint iHandle)
|
||||
{
|
||||
std::ifstream shaderSource(strFilename.c_str());
|
||||
if (!shaderSource.is_open())
|
||||
{
|
||||
std::cerr<< " File not found "<< strFilename.c_str()<< endl;
|
||||
return false;
|
||||
}
|
||||
// now read in the data
|
||||
string strSource = std::string((std::istreambuf_iterator<char>(shaderSource)), std::istreambuf_iterator<char>());
|
||||
shaderSource.close();
|
||||
strSource+="\0";
|
||||
//pass the code to OGL
|
||||
const char* data=strSource.c_str();
|
||||
glShaderSource(iHandle, 1, &data, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLSLProgram::recompileShader(std::string strFileName, SHADERTYPE typeShader)
|
||||
{
|
||||
glDetachShader(m_uIdProgram, m_vIdShader[typeShader]);
|
||||
loadShader(strFileName, typeShader);
|
||||
glAttachShader(m_uIdProgram, m_vIdShader[typeShader]);
|
||||
//link the program
|
||||
glLinkProgram(m_uIdProgram);
|
||||
checkLinkingErrors();
|
||||
glDeleteShader(m_vIdShader[typeShader]);
|
||||
std::cout << "de pinga" << std::endl;
|
||||
}
|
||||
|
||||
void CGLSLProgram::loadShader(std::string strFileName, SHADERTYPE typeShader)
|
||||
{
|
||||
GLuint hShader = 0;
|
||||
GLint status;
|
||||
|
||||
//Create shader object
|
||||
switch (typeShader)
|
||||
{
|
||||
case VERTEX : { hShader = glCreateShader(GL_VERTEX_SHADER); break; }
|
||||
case FRAGMENT : { hShader = glCreateShader(GL_FRAGMENT_SHADER); break; }
|
||||
case GEOMETRY : { hShader = glCreateShader(GL_GEOMETRY_SHADER); break; }
|
||||
case TESSELATION : { hShader = 0; std::cerr<<"not implemented.... yet :-)" << std::endl; }
|
||||
}
|
||||
|
||||
if(loadShaderFile(strFileName, hShader))
|
||||
{
|
||||
//now compile the shader
|
||||
glCompileShader(hShader);
|
||||
glGetShaderiv(hShader, GL_COMPILE_STATUS, &status);
|
||||
if(status == GL_FALSE)
|
||||
{
|
||||
char infoLog[1024];
|
||||
glGetShaderInfoLog(hShader, 1024, NULL, infoLog);
|
||||
cout << "The shader at " << strFileName.c_str() << " failed to compile with the following errors:" << endl
|
||||
<< infoLog << endl;
|
||||
glDeleteShader(hShader);
|
||||
}
|
||||
else //here, everything is OK
|
||||
{
|
||||
cout << "The shader at " << strFileName.c_str() << " was compiled without errors." << endl;
|
||||
m_vIdShader[typeShader] = hShader;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr<< "something wrong loading the shader located in " << strFileName.c_str() << "." << std::endl;
|
||||
glDeleteShader(hShader);
|
||||
}
|
||||
}
|
||||
|
||||
void CGLSLProgram::checkLinkingErrors()
|
||||
{
|
||||
GLint infologLength = 0;
|
||||
glGetProgramiv(m_uIdProgram, GL_INFO_LOG_LENGTH, &infologLength);
|
||||
//std::cerr<<"Link Log Length "<<infologLength<<"\n";
|
||||
|
||||
if(infologLength > 1)
|
||||
{
|
||||
char *infoLog = new char[infologLength];
|
||||
GLint charsWritten = 0;
|
||||
|
||||
glGetProgramInfoLog(m_uIdProgram, infologLength, &charsWritten, infoLog);
|
||||
|
||||
std::cerr<<infoLog<<std::endl;
|
||||
delete [] infoLog;
|
||||
glGetProgramiv(m_uIdProgram, GL_LINK_STATUS, &infologLength);
|
||||
if(infologLength == GL_FALSE)
|
||||
{
|
||||
std::cerr<<"Program link failed exiting \n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CGLSLProgram::create()
|
||||
{
|
||||
m_uIdProgram = glCreateProgram();
|
||||
//attach the shaders
|
||||
if(m_vIdShader[VERTEX] > 0)
|
||||
glAttachShader(m_uIdProgram, m_vIdShader[VERTEX]);
|
||||
if(m_vIdShader[FRAGMENT] > 0)
|
||||
glAttachShader(m_uIdProgram, m_vIdShader[FRAGMENT]);
|
||||
if(m_vIdShader[GEOMETRY] > 0)
|
||||
glAttachShader(m_uIdProgram, m_vIdShader[GEOMETRY]);
|
||||
//delete the shaders
|
||||
glDeleteShader(m_vIdShader[VERTEX]);
|
||||
glDeleteShader(m_vIdShader[FRAGMENT]);
|
||||
glDeleteShader(m_vIdShader[GEOMETRY]);
|
||||
checkLinkingErrors();
|
||||
}
|
||||
|
||||
void CGLSLProgram::create_link()
|
||||
{
|
||||
m_uIdProgram = glCreateProgram();
|
||||
//attach the shaders
|
||||
if(m_vIdShader[VERTEX] > 0)
|
||||
glAttachShader(m_uIdProgram, m_vIdShader[VERTEX]);
|
||||
if(m_vIdShader[FRAGMENT] > 0)
|
||||
glAttachShader(m_uIdProgram, m_vIdShader[FRAGMENT]);
|
||||
if(m_vIdShader[GEOMETRY] > 0)
|
||||
glAttachShader(m_uIdProgram, m_vIdShader[GEOMETRY]);
|
||||
//link the program
|
||||
glLinkProgram(m_uIdProgram);
|
||||
//check errors on linking
|
||||
checkLinkingErrors();
|
||||
//delete the shaders
|
||||
glDeleteShader(m_vIdShader[VERTEX]);
|
||||
glDeleteShader(m_vIdShader[FRAGMENT]);
|
||||
glDeleteShader(m_vIdShader[GEOMETRY]);
|
||||
}
|
||||
|
||||
void CGLSLProgram::link()
|
||||
{
|
||||
//link the program
|
||||
glLinkProgram(m_uIdProgram);
|
||||
//check errors on linking
|
||||
checkLinkingErrors();
|
||||
}
|
||||
|
||||
void CGLSLProgram::enable()
|
||||
{
|
||||
glUseProgram(m_uIdProgram);
|
||||
}
|
||||
|
||||
void CGLSLProgram::disable()
|
||||
{
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
GLuint CGLSLProgram::getId()
|
||||
{
|
||||
return m_uIdProgram;
|
||||
}
|
||||
|
||||
void CGLSLProgram::addAttribute(std::string strParName)
|
||||
{
|
||||
m_mapVarShader[strParName] = glGetAttribLocation(m_uIdProgram, strParName.c_str());
|
||||
}
|
||||
|
||||
GLint CGLSLProgram::getLocation(std::string strParName)
|
||||
{
|
||||
std::map<string, GLint>::iterator it = m_mapVarShader.find(strParName);
|
||||
if(it == m_mapVarShader.end())
|
||||
return -1;
|
||||
else
|
||||
return m_mapVarShader[strParName];
|
||||
}
|
||||
|
||||
void CGLSLProgram::addUniform(std::string strParName)
|
||||
{
|
||||
m_mapVarShader[strParName] = glGetUniformLocation(m_uIdProgram, strParName.c_str());
|
||||
}
|
||||
|
||||
void CGLSLProgram::addUniformSubroutine(std::string strParName, int iShaderType)
|
||||
{
|
||||
//m_vRoutinesIds.front()
|
||||
m_mapVarShader[strParName] = glGetSubroutineUniformLocation(m_uIdProgram, iShaderType, strParName.c_str());
|
||||
}
|
||||
|
||||
void CGLSLProgram::addSubroutine(std::string strFunctionName, unsigned int iShaderType)
|
||||
{
|
||||
//m_vRoutinesIds.push_back(glGetSubroutineIndex(m_uIdProgram, iShaderType, strFunctionName.c_str()));
|
||||
m_mapSubroutines[strFunctionName] = glGetSubroutineUniformLocation(m_uIdProgram, iShaderType, strFunctionName.c_str());
|
||||
}
|
||||
|
||||
//only for 1 subroutine at time
|
||||
void CGLSLProgram::setSubroutine(std::string strUniformName, std::string strSubRoutine, int iShaderType)
|
||||
{
|
||||
int index = getLocation(strUniformName);
|
||||
if(index > -1)
|
||||
{
|
||||
GLuint routine_index = glGetSubroutineIndex(m_uIdProgram, iShaderType, strSubRoutine.c_str());
|
||||
glUniformSubroutinesuiv(iShaderType, 1, &routine_index);
|
||||
}
|
||||
}
|
42
GLSLProgram.hpp
Normal file
42
GLSLProgram.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
/// For now, just 1 vertex's type can be attach to the program
|
||||
/// In order add more than 1 vertex's type to the program, the shaders should be named (eg. "shader1", "shader2" & so on)
|
||||
class CGLSLProgram
|
||||
{
|
||||
public:
|
||||
enum SHADERTYPE {VERTEX = 0, FRAGMENT, GEOMETRY, TESSELATION};
|
||||
|
||||
GLuint m_uIdProgram; //id of the program
|
||||
GLuint m_vIdShader[4]; //ids of the loaded shaders; the 4th is empty always
|
||||
CGLSLProgram(void);
|
||||
~CGLSLProgram(void);
|
||||
|
||||
void loadShader(std::string strFileName, SHADERTYPE typeShader);
|
||||
void create();
|
||||
void create_link();
|
||||
void link();
|
||||
void enable();
|
||||
void disable();
|
||||
void addAttribute(std::string strParName);
|
||||
void addSubroutine(std::string strFunctionName, unsigned int iShaderType);
|
||||
void addUniform(std::string strParName);
|
||||
void addUniformSubroutine(std::string strParName, int iShaderType);
|
||||
GLint getLocation(std::string strParName);
|
||||
GLuint getId();
|
||||
void setSubroutine(std::string strUniformName, std::string strSubRoutine, int iShaderType);
|
||||
std::map<std::string, GLint> m_mapSubroutines;
|
||||
void recompileShader(std::string strFileName, SHADERTYPE typeShader);
|
||||
private:
|
||||
std::map<std::string, GLint> m_mapVarShader;
|
||||
std::vector<GLuint> m_vRoutinesIds;
|
||||
bool loadShaderFile(std::string strFilename, GLuint iHandle);
|
||||
void checkLinkingErrors();
|
||||
};
|
||||
|
11
Makefile
11
Makefile
@@ -21,12 +21,14 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
TARGET = ias-ss
|
||||
OBJECTS = ias_ss.o robot.o ias_robot.o gui.o
|
||||
OBJECTS = ias_ss.o robot.o ias_robot.o gui.o ogl.o GLSLProgram.o pnglite.o pheromone.o
|
||||
DEPENDS = $(OBJECTS:.o=.d)
|
||||
CXXFLAGS = -ansi -pedantic -Wall `pkg-config --cflags playerc++`
|
||||
LDLIBS = `pkg-config --libs playerc++` -lboost_system -lpthread -lGLU -lGL -lfltk -lfltk_gl
|
||||
CFLAGS = -ansi -pedantic -Wall -I./include
|
||||
CXXFLAGS = -ansi -pedantic -Wall `pkg-config --cflags playerc++` -I./include
|
||||
LDLIBS = `pkg-config --libs playerc++` -lboost_system -lpthread -lz -lGLEW -lGLU -lGL -lfltk -lfltk_gl
|
||||
|
||||
all: CXXFLAGS += -O2 -D_NDEBUG
|
||||
all: $(TARGET)
|
||||
@@ -39,6 +41,9 @@ $(TARGET): $(OBJECTS)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
pnglite.o: pnglite.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $*.cpp -o $*.o
|
||||
$(CXX) -MM $(CXXFLAGS) $*.cpp > $*.d
|
||||
|
58
gui.cpp
58
gui.cpp
@@ -1,37 +1,71 @@
|
||||
/*************************************************************************************
|
||||
* Copyright (c) 2016, Miguel Angel Astor Romero *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this *
|
||||
* list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer in the documentation *
|
||||
* and/or other materials provided with the distribution. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND *
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*************************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "gui.hpp"
|
||||
#include "ogl.hpp"
|
||||
|
||||
static const int REFRESH_MS = 0.016; // for 60 fps.
|
||||
|
||||
static void redraw_callback(void * arg) {
|
||||
Fl_Gl_Window * window = static_cast<Fl_Gl_Window *>(arg);
|
||||
GlGui * window = static_cast<GlGui *>(arg);
|
||||
window->redraw();
|
||||
Fl::repeat_timeout(0.016, redraw_callback, window);
|
||||
if(!window->isFinished())
|
||||
Fl::repeat_timeout(REFRESH_MS, redraw_callback, window);
|
||||
}
|
||||
|
||||
GlGui::GlGui(Fl_Window * parent, int x, int y, int w, int h, const char * l) : Fl_Gl_Window(x, y, w, h, l) {
|
||||
GlGui::GlGui(Fl_Window * parent, int x, int y, int w, int h, const char * l, PheromoneMap * phero_map) : Fl_Gl_Window(x, y, w, h, l) {
|
||||
this->parent = parent;
|
||||
this->phero_map = phero_map;
|
||||
title += l;
|
||||
initialized = false;
|
||||
Fl::add_timeout(0.016, redraw_callback, this);
|
||||
resizable(this);
|
||||
done = false;
|
||||
}
|
||||
|
||||
void GlGui::draw() {
|
||||
if(!valid()) {
|
||||
if(!initialized) {
|
||||
//opengl::initialize();
|
||||
|
||||
std::cout << "OpenGL Version: " << (char*)glGetString(GL_VERSION) << std::endl;
|
||||
std::cout << "OpenGL Vendor: " << (char*)glGetString(GL_VENDOR) << std::endl;
|
||||
|
||||
ogl::initialize(phero_map);
|
||||
Fl::add_timeout(REFRESH_MS, redraw_callback, this);
|
||||
initialized = true;
|
||||
}
|
||||
//opengl::reshape(w(), h());
|
||||
ogl::reshape(w(), h());
|
||||
}
|
||||
|
||||
//opengl::display();
|
||||
ogl::display();
|
||||
}
|
||||
|
||||
int GlGui::handle(int event) {
|
||||
return Fl_Gl_Window::handle(event);
|
||||
}
|
||||
|
||||
void GlGui::finish() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
bool GlGui::isFinished() {
|
||||
return done;
|
||||
}
|
||||
|
34
gui.hpp
34
gui.hpp
@@ -1,18 +1,44 @@
|
||||
#pragma once
|
||||
/*************************************************************************************
|
||||
* Copyright (c) 2016, Miguel Angel Astor Romero *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this *
|
||||
* list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer in the documentation *
|
||||
* and/or other materials provided with the distribution. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND *
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*************************************************************************************/
|
||||
|
||||
#ifndef GUI_HPP
|
||||
#define GUI_HPP
|
||||
|
||||
#include <string>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Gl_Window.H>
|
||||
#include <FL/gl.h>
|
||||
|
||||
#include <string>
|
||||
#include "pheromone.hpp"
|
||||
|
||||
class GlGui : public Fl_Gl_Window {
|
||||
public:
|
||||
GlGui(Fl_Window * parent, int x, int y, int w, int h, const char * l);
|
||||
GlGui(Fl_Window * parent, int x, int y, int w, int h, const char * l, PheromoneMap * phero_map);
|
||||
void finish();
|
||||
bool isFinished();
|
||||
|
||||
protected:
|
||||
virtual void draw();
|
||||
@@ -22,6 +48,8 @@ private:
|
||||
Fl_Window * parent;
|
||||
std::string title;
|
||||
bool initialized;
|
||||
bool done;
|
||||
PheromoneMap * phero_map;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -34,12 +34,13 @@ static const long HALF_SECOND_USEC = 500000;
|
||||
static const double MIN_DIST_M = 1.5;
|
||||
static const double CRIT_DIST_M = 1.0;
|
||||
|
||||
IASSS_Robot::IASSS_Robot(std::string hostname, uint32_t port) : Robot(hostname, port) {
|
||||
std::cout << "Creating IAS-SS robot on host \"" << hostname << "\" and port " << port << "." << std::endl;
|
||||
IASSS_Robot::IASSS_Robot(std::string hostname, uint32_t port, PheromoneMap * phero_map) : Robot(hostname, port) {
|
||||
_phero_map = phero_map;
|
||||
log("Creating IAS-SS robot");
|
||||
}
|
||||
|
||||
IASSS_Robot::~IASSS_Robot() {
|
||||
std::cout << "Destroying IAS-SS robot on " << _host_name << ":" << _port << std::endl;
|
||||
log("Destroying IAS-SS robot");
|
||||
}
|
||||
|
||||
void IASSS_Robot::run() {
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#define IAS_ROBOT_HPP
|
||||
|
||||
#include "robot.hpp"
|
||||
#include "pheromone.hpp"
|
||||
|
||||
/**
|
||||
* Concrete robot that implements the IAS-SS architecture as defined in:
|
||||
@@ -41,12 +42,13 @@
|
||||
*/
|
||||
class IASSS_Robot : Robot {
|
||||
public:
|
||||
IASSS_Robot(std::string hostname, uint32_t port);
|
||||
IASSS_Robot(std::string hostname, uint32_t port, PheromoneMap * phero_map);
|
||||
virtual ~IASSS_Robot();
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
PheromoneMap * _phero_map;
|
||||
|
||||
void avoid_wall(float front_speed, float turn_speed);
|
||||
};
|
||||
|
||||
|
17
ias_ss.cpp
17
ias_ss.cpp
@@ -38,10 +38,17 @@ const uint32_t PORT = PlayerCc::PLAYER_PORTNUM + 1;
|
||||
const uint32_t NUM_ROBOTS = 4;
|
||||
|
||||
static bool done = false;
|
||||
static Fl_Window * window;
|
||||
static Fl_Window * window = NULL;
|
||||
static GlGui * glWindow = NULL;
|
||||
static PheromoneMap * phero_map = NULL;
|
||||
|
||||
extern "C" void handler(int signal) {
|
||||
done = true;
|
||||
|
||||
if(window != NULL) {
|
||||
glWindow->finish();
|
||||
window->hide();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void * robot_thread(void * arg) {
|
||||
@@ -57,7 +64,7 @@ extern "C" void * robot_thread(void * arg) {
|
||||
|
||||
void create_gui(int argc, char **argv) {
|
||||
window = new Fl_Window(20, 40, W, H, TITLE);
|
||||
new GlGui(window, 0, 0, W, H, TITLE);
|
||||
glWindow = new GlGui(window, 0, 0, W, H, TITLE, phero_map);
|
||||
window->end();
|
||||
window->show(argc, argv);
|
||||
window->make_current();
|
||||
@@ -70,9 +77,11 @@ int main(int argc, char **argv) {
|
||||
signal(SIGINT, handler);
|
||||
|
||||
try {
|
||||
phero_map = new PheromoneMap("maps/cave_mask.png");
|
||||
|
||||
// Initialize the robot objects and threads.
|
||||
for(uint32_t i = 0; i < NUM_ROBOTS; ++i) {
|
||||
robots.push_back(new IASSS_Robot(PlayerCc::PLAYER_HOSTNAME, PORT + i));
|
||||
robots.push_back(new IASSS_Robot(PlayerCc::PLAYER_HOSTNAME, PORT + i, phero_map));
|
||||
|
||||
if(pthread_create(&robot_threads[i], NULL, robot_thread, static_cast<void *>(robots[i])) != 0) {
|
||||
perror("Could not create robot thread");
|
||||
@@ -93,6 +102,8 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
robots.clear();
|
||||
|
||||
delete phero_map;
|
||||
|
||||
} catch (PlayerCc::PlayerError & e) {
|
||||
std::cerr << e << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
|
227
include/pnglite.h
Normal file
227
include/pnglite.h
Normal file
@@ -0,0 +1,227 @@
|
||||
/* pnglite.h - Interface for pnglite library
|
||||
Copyright (c) 2007 Daniel Karling
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
Daniel Karling
|
||||
daniel.karling@gmail.com
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _PNGLITE_H_
|
||||
#define _PNGLITE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
/*
|
||||
Enumerations for pnglite.
|
||||
Negative numbers are error codes and 0 and up are okay responses.
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PNG_DONE = 1,
|
||||
PNG_NO_ERROR = 0,
|
||||
PNG_FILE_ERROR = -1,
|
||||
PNG_HEADER_ERROR = -2,
|
||||
PNG_IO_ERROR = -3,
|
||||
PNG_EOF_ERROR = -4,
|
||||
PNG_CRC_ERROR = -5,
|
||||
PNG_MEMORY_ERROR = -6,
|
||||
PNG_ZLIB_ERROR = -7,
|
||||
PNG_UNKNOWN_FILTER = -8,
|
||||
PNG_NOT_SUPPORTED = -9,
|
||||
PNG_WRONG_ARGUMENTS = -10
|
||||
};
|
||||
|
||||
/*
|
||||
The five different kinds of color storage in PNG files.
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PNG_GREYSCALE = 0,
|
||||
PNG_TRUECOLOR = 2,
|
||||
PNG_INDEXED = 3,
|
||||
PNG_GREYSCALE_ALPHA = 4,
|
||||
PNG_TRUECOLOR_ALPHA = 6
|
||||
};
|
||||
|
||||
/*
|
||||
Typedefs for callbacks.
|
||||
*/
|
||||
|
||||
typedef unsigned (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer);
|
||||
typedef unsigned (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer);
|
||||
typedef void (*png_free_t)(void* p);
|
||||
typedef void * (*png_alloc_t)(size_t s);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* zs; /* pointer to z_stream */
|
||||
png_read_callback_t read_fun;
|
||||
png_write_callback_t write_fun;
|
||||
void* user_pointer;
|
||||
|
||||
unsigned char* png_data;
|
||||
unsigned png_datalen;
|
||||
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned char depth;
|
||||
unsigned char color_type;
|
||||
unsigned char compression_method;
|
||||
unsigned char filter_method;
|
||||
unsigned char interlace_method;
|
||||
unsigned char bpp;
|
||||
}png_t;
|
||||
|
||||
/*
|
||||
Function: png_init
|
||||
|
||||
This function initializes pnglite. The parameters can be used to set your own memory allocation routines following these formats:
|
||||
|
||||
> void* (*custom_alloc)(size_t s)
|
||||
> void (*custom_free)(void* p)
|
||||
Parameters:
|
||||
pngalloc - Pointer to custom allocation routine. If 0 is passed, malloc from libc will be used.
|
||||
pngfree - Pointer to custom free routine. If 0 is passed, free from libc will be used.
|
||||
|
||||
Returns:
|
||||
Always returns PNG_NO_ERROR.
|
||||
*/
|
||||
|
||||
int png_init(png_alloc_t pngalloc, png_free_t pngfree);
|
||||
|
||||
/*
|
||||
Function: png_open_file
|
||||
|
||||
This function is used to open a png file with the internal file IO system. This function should be used instead of
|
||||
png_open if no custom read function is used.
|
||||
|
||||
Parameters:
|
||||
png - Empty png_t struct.
|
||||
filename - Filename of the file to be opened.
|
||||
|
||||
Returns:
|
||||
PNG_NO_ERROR on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
int png_open_file(png_t *png, const char* filename);
|
||||
|
||||
int png_open_file_read(png_t *png, const char* filename);
|
||||
int png_open_file_write(png_t *png, const char* filename);
|
||||
|
||||
/*
|
||||
Function: png_open
|
||||
|
||||
This function reads or writes a png from/to the specified callback. The callbacks should be of the format:
|
||||
|
||||
> size_t (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer);
|
||||
> size_t (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer).
|
||||
|
||||
Only one callback has to be specified. The read callback in case of PNG reading, otherwise the write callback.
|
||||
|
||||
Writing:
|
||||
The callback will be called like fwrite.
|
||||
|
||||
Reading:
|
||||
The callback will be called each time pnglite needs more data. The callback should read as much data as requested,
|
||||
or return 0. This should always be possible if the PNG is sane. If the output-buffer is a null-pointer the callback
|
||||
should only skip ahead the specified number of elements. If the callback is a null-pointer the user_pointer will be
|
||||
treated as a file pointer (use png_open_file instead).
|
||||
|
||||
Parameters:
|
||||
png - png_t struct
|
||||
read_fun - Callback function for reading.
|
||||
user_pointer - User pointer to be passed to read_fun.
|
||||
|
||||
Returns:
|
||||
PNG_NO_ERROR on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer);
|
||||
|
||||
int png_open_read(png_t* png, png_read_callback_t read_fun, void* user_pointer);
|
||||
int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer);
|
||||
|
||||
/*
|
||||
Function: png_print_info
|
||||
|
||||
This function prints some info about the opened png file to stdout.
|
||||
|
||||
Parameters:
|
||||
png - png struct to get info from.
|
||||
*/
|
||||
|
||||
void png_print_info(png_t* png);
|
||||
|
||||
/*
|
||||
Function: png_error_string
|
||||
|
||||
This function translates an error code to a human readable string.
|
||||
|
||||
Parameters:
|
||||
error - Error code.
|
||||
|
||||
Returns:
|
||||
Pointer to string.
|
||||
*/
|
||||
|
||||
char* png_error_string(int error);
|
||||
|
||||
/*
|
||||
Function: png_get_data
|
||||
|
||||
This function decodes the opened png file and stores the result in data. data should be big enough to hold the decoded png. Required size will be:
|
||||
|
||||
> width*height*(bytes per pixel)
|
||||
|
||||
Parameters:
|
||||
data - Where to store result.
|
||||
|
||||
Returns:
|
||||
PNG_NO_ERROR on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
int png_get_data(png_t* png, unsigned char* data);
|
||||
|
||||
int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data);
|
||||
|
||||
/*
|
||||
Function: png_close_file
|
||||
|
||||
Closes an open png file pointer. Should only be used when the png has been opened with png_open_file.
|
||||
|
||||
Parameters:
|
||||
png - png to close.
|
||||
|
||||
Returns:
|
||||
PNG_NO_ERROR
|
||||
*/
|
||||
|
||||
int png_close_file(png_t* png);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Binary file not shown.
Before Width: | Height: | Size: 897 B After Width: | Height: | Size: 1.1 KiB |
107
ogl.cpp
Normal file
107
ogl.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*************************************************************************************
|
||||
* Copyright (c) 2016, Miguel Angel Astor Romero *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this *
|
||||
* list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer in the documentation *
|
||||
* and/or other materials provided with the distribution. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND *
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*************************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <GL/glew.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <pnglite.h>
|
||||
|
||||
#include "ogl.hpp"
|
||||
#include "GLSLProgram.hpp"
|
||||
|
||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||
|
||||
namespace ogl
|
||||
{
|
||||
// Variables
|
||||
static CGLSLProgram m_program;
|
||||
static PheromoneMap * m_phero_map = NULL;
|
||||
static GLuint m_textureHandle;
|
||||
|
||||
// Quad definition
|
||||
static glm::vec4 vec_points[6];
|
||||
static glm::vec2 vec_tex_coords[6];
|
||||
|
||||
static void quad() {
|
||||
vec_tex_coords[0] = glm::vec2( 0.0f, 0.0f); vec_points[0] = glm::vec4( -0.5f, -0.5f, 0.0f, 1.0f );
|
||||
vec_tex_coords[1] = glm::vec2( 0.0f, 1.0f); vec_points[1] = glm::vec4( -0.5f, 0.5f, 0.0f, 1.0f );
|
||||
vec_tex_coords[2] = glm::vec2( 1.0f, 0.0f); vec_points[2] = glm::vec4( 0.5f, -0.5f, 0.0f, 1.0f );
|
||||
vec_tex_coords[3] = glm::vec2( 1.0f, 0.0f); vec_points[3] = glm::vec4( 0.5f, -0.5f, 0.0f, 1.0f );
|
||||
vec_tex_coords[4] = glm::vec2( 0.0f, 1.0f); vec_points[4] = glm::vec4( -0.5f, 0.5f, 0.0f, 1.0f );
|
||||
vec_tex_coords[5] = glm::vec2( 1.0f, 1.0f); vec_points[5] = glm::vec4( 0.5f, 0.5f, 0.0f, 1.0f );
|
||||
}
|
||||
|
||||
void initialize(PheromoneMap * phero_map) {
|
||||
glewInit();
|
||||
|
||||
quad();
|
||||
m_phero_map = phero_map;
|
||||
|
||||
m_program.loadShader("shaders/basic.vert", CGLSLProgram::VERTEX);
|
||||
m_program.loadShader("shaders/basic.frag", CGLSLProgram::FRAGMENT);
|
||||
m_program.create_link();
|
||||
m_program.enable();
|
||||
m_program.addUniform("sTexture");
|
||||
m_program.disable();
|
||||
|
||||
std::cout << "OpenGL Version: " << (char*)glGetString(GL_VERSION) << std::endl;
|
||||
std::cout << "OpenGL Vendor: " << (char*)glGetString(GL_VENDOR) << std::endl;
|
||||
}
|
||||
|
||||
void display() {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
|
||||
|
||||
if(m_phero_map != NULL)
|
||||
m_textureHandle = m_phero_map->s_build_texture(); // Good grief!
|
||||
|
||||
m_program.enable();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_textureHandle);
|
||||
glUniform1i(m_program.getLocation("sTexture"), 0);
|
||||
|
||||
glBegin(GL_TRIANGLES); {
|
||||
for(int i = 0; i < 6; i++) {
|
||||
glTexCoord2f(vec_tex_coords[i].s, vec_tex_coords[i].t);
|
||||
glVertex4f(vec_points[i].x, vec_points[i].y, vec_points[i].z, vec_points[i].w);
|
||||
}
|
||||
} glEnd();
|
||||
|
||||
m_program.disable();
|
||||
}
|
||||
|
||||
void reshape(int w, int h) {
|
||||
if(h == 0)
|
||||
h = 1;
|
||||
glViewport(0, 0, w, h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(-0.5, 0.5, -0.5, 0.5);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
}
|
37
ogl.hpp
Normal file
37
ogl.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*************************************************************************************
|
||||
* Copyright (c) 2016, Miguel Angel Astor Romero *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this *
|
||||
* list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer in the documentation *
|
||||
* and/or other materials provided with the distribution. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND *
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*************************************************************************************/
|
||||
|
||||
#ifndef OGL_HPP
|
||||
#define OGL_HPP
|
||||
|
||||
#include "pheromone.hpp"
|
||||
|
||||
namespace ogl {
|
||||
void initialize(PheromoneMap * phero_map);
|
||||
void display();
|
||||
void reshape(int w, int h);
|
||||
}
|
||||
|
||||
#endif
|
59
pheromone.cpp
Normal file
59
pheromone.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <pnglite.h>
|
||||
|
||||
#include "pheromone.hpp"
|
||||
|
||||
PheromoneMap::PheromoneMap(const char * file_name) {
|
||||
load_map(file_name);
|
||||
sem_init(&map_semaphore, 0, 1);
|
||||
tex_created = false;
|
||||
}
|
||||
|
||||
PheromoneMap::~PheromoneMap() {
|
||||
free(data);
|
||||
sem_destroy(&map_semaphore);
|
||||
|
||||
if(tex_created) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, handle);
|
||||
glDeleteTextures(1, &handle);
|
||||
}
|
||||
}
|
||||
|
||||
void PheromoneMap::load_map(const char * file_name) {
|
||||
png_t tex;
|
||||
|
||||
png_init(0, 0);
|
||||
png_open_file_read(&tex, file_name);
|
||||
data = (unsigned char*) malloc(tex.width * tex.height * tex.bpp);
|
||||
png_get_data(&tex, data);
|
||||
|
||||
std::cout << "Loaded map \"" << file_name << "\" :: " << tex.width << "x" << tex.height << "x" << (int)tex.bpp << std::endl;
|
||||
m_width = tex.width;
|
||||
m_height = tex.height;
|
||||
m_bpp = tex.bpp;
|
||||
|
||||
png_close_file(&tex);
|
||||
}
|
||||
|
||||
GLuint PheromoneMap::s_build_texture() {
|
||||
sem_wait(&map_semaphore); {
|
||||
if(tex_created) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, handle);
|
||||
glDeleteTextures(1, &handle);
|
||||
}
|
||||
|
||||
glGenTextures(1, &handle);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, handle);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
tex_created = true;
|
||||
} sem_post(&map_semaphore);
|
||||
|
||||
return handle;
|
||||
}
|
26
pheromone.hpp
Normal file
26
pheromone.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef PHEROMONE_HPP
|
||||
#define PHEROMONE_HPP
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
class PheromoneMap {
|
||||
public:
|
||||
PheromoneMap(const char * file_name);
|
||||
~PheromoneMap();
|
||||
|
||||
GLuint s_build_texture();
|
||||
|
||||
private:
|
||||
unsigned char * data;
|
||||
unsigned m_width;
|
||||
unsigned m_height;
|
||||
unsigned char m_bpp;
|
||||
sem_t map_semaphore;
|
||||
bool tex_created;
|
||||
GLuint handle;
|
||||
|
||||
void load_map(const char * file_name);
|
||||
};
|
||||
|
||||
#endif
|
877
pnglite.c
Normal file
877
pnglite.c
Normal file
@@ -0,0 +1,877 @@
|
||||
/* pnglite.c - pnglite library
|
||||
For conditions of distribution and use, see copyright notice in pnglite.h
|
||||
*/
|
||||
#define DO_CRC_CHECKS 1
|
||||
#define USE_ZLIB 1
|
||||
|
||||
#if USE_ZLIB
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "zlite.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pnglite.h>
|
||||
|
||||
|
||||
|
||||
static png_alloc_t png_alloc;
|
||||
static png_free_t png_free;
|
||||
|
||||
static size_t file_read(png_t* png, void* out, size_t size, size_t numel)
|
||||
{
|
||||
size_t result;
|
||||
if(png->read_fun)
|
||||
{
|
||||
result = png->read_fun(out, size, numel, png->user_pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!out)
|
||||
{
|
||||
result = fseek(png->user_pointer, (long)(size*numel), SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = fread(out, size, numel, png->user_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static size_t file_write(png_t* png, void* p, size_t size, size_t numel)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
if(png->write_fun)
|
||||
{
|
||||
result = png->write_fun(p, size, numel, png->user_pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = fwrite(p, size, numel, png->user_pointer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int file_read_ul(png_t* png, unsigned *out)
|
||||
{
|
||||
unsigned char buf[4];
|
||||
|
||||
if(file_read(png, buf, 1, 4) != 4)
|
||||
return PNG_FILE_ERROR;
|
||||
|
||||
*out = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int file_write_ul(png_t* png, unsigned in)
|
||||
{
|
||||
unsigned char buf[4];
|
||||
|
||||
buf[0] = (in>>24) & 0xff;
|
||||
buf[1] = (in>>16) & 0xff;
|
||||
buf[2] = (in>>8) & 0xff;
|
||||
buf[3] = (in) & 0xff;
|
||||
|
||||
if(file_write(png, buf, 1, 4) != 4)
|
||||
return PNG_FILE_ERROR;
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static unsigned get_ul(unsigned char* buf)
|
||||
{
|
||||
unsigned result;
|
||||
unsigned char foo[4];
|
||||
|
||||
memcpy(foo, buf, 4);
|
||||
|
||||
result = (foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static unsigned set_ul(unsigned char* buf, unsigned in)
|
||||
{
|
||||
buf[0] = (in>>24) & 0xff;
|
||||
buf[1] = (in>>16) & 0xff;
|
||||
buf[2] = (in>>8) & 0xff;
|
||||
buf[3] = (in) & 0xff;
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
int png_init(png_alloc_t pngalloc, png_free_t pngfree)
|
||||
{
|
||||
if(pngalloc)
|
||||
png_alloc = pngalloc;
|
||||
else
|
||||
png_alloc = &malloc;
|
||||
|
||||
if(pngfree)
|
||||
png_free = pngfree;
|
||||
else
|
||||
png_free = &free;
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_get_bpp(png_t* png)
|
||||
{
|
||||
int bpp;
|
||||
|
||||
switch(png->color_type)
|
||||
{
|
||||
case PNG_GREYSCALE:
|
||||
bpp = 1; break;
|
||||
case PNG_TRUECOLOR:
|
||||
bpp = 3; break;
|
||||
case PNG_INDEXED:
|
||||
bpp = 1; break;
|
||||
case PNG_GREYSCALE_ALPHA:
|
||||
bpp = 2; break;
|
||||
case PNG_TRUECOLOR_ALPHA:
|
||||
bpp = 4; break;
|
||||
default:
|
||||
return PNG_FILE_ERROR;
|
||||
}
|
||||
|
||||
bpp *= png->depth/8;
|
||||
|
||||
return bpp;
|
||||
}
|
||||
|
||||
static int png_read_ihdr(png_t* png)
|
||||
{
|
||||
unsigned length;
|
||||
#if DO_CRC_CHECKS
|
||||
unsigned orig_crc;
|
||||
unsigned calc_crc;
|
||||
#endif
|
||||
unsigned char ihdr[13+4]; /* length should be 13, make room for type (IHDR) */
|
||||
|
||||
file_read_ul(png, &length);
|
||||
|
||||
if(length != 13)
|
||||
{
|
||||
printf("%d\n", length);
|
||||
return PNG_CRC_ERROR;
|
||||
}
|
||||
|
||||
if(file_read(png, ihdr, 1, 13+4) != 13+4)
|
||||
return PNG_EOF_ERROR;
|
||||
#if DO_CRC_CHECKS
|
||||
file_read_ul(png, &orig_crc);
|
||||
|
||||
calc_crc = crc32(0L, 0, 0);
|
||||
calc_crc = crc32(calc_crc, ihdr, 13+4);
|
||||
|
||||
if(orig_crc != calc_crc)
|
||||
return PNG_CRC_ERROR;
|
||||
#else
|
||||
file_read_ul(png);
|
||||
#endif
|
||||
|
||||
png->width = get_ul(ihdr+4);
|
||||
png->height = get_ul(ihdr+8);
|
||||
png->depth = ihdr[12];
|
||||
png->color_type = ihdr[13];
|
||||
png->compression_method = ihdr[14];
|
||||
png->filter_method = ihdr[15];
|
||||
png->interlace_method = ihdr[16];
|
||||
|
||||
if(png->color_type == PNG_INDEXED)
|
||||
return PNG_NOT_SUPPORTED;
|
||||
|
||||
if(png->depth != 8 && png->depth != 16)
|
||||
return PNG_NOT_SUPPORTED;
|
||||
|
||||
if(png->interlace_method)
|
||||
return PNG_NOT_SUPPORTED;
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_write_ihdr(png_t* png)
|
||||
{
|
||||
unsigned char ihdr[13+4];
|
||||
unsigned char *p = ihdr;
|
||||
unsigned crc;
|
||||
|
||||
file_write(png, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 1, 8);
|
||||
|
||||
file_write_ul(png, 13);
|
||||
|
||||
*p = 'I'; p++;
|
||||
*p = 'H'; p++;
|
||||
*p = 'D'; p++;
|
||||
*p = 'R'; p++;
|
||||
set_ul(p, png->width); p+=4;
|
||||
set_ul(p, png->height); p+=4;
|
||||
*p = png->depth; p++;
|
||||
*p = png->color_type; p++;
|
||||
*p = 0; p++;
|
||||
*p = 0; p++;
|
||||
*p = 0; p++;
|
||||
|
||||
file_write(png, ihdr, 1, 13+4);
|
||||
|
||||
crc = crc32(0L, 0, 0);
|
||||
crc = crc32(crc, ihdr, 13+4);
|
||||
|
||||
file_write_ul(png, crc);
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
void png_print_info(png_t* png)
|
||||
{
|
||||
printf("PNG INFO:\n");
|
||||
printf("\twidth:\t\t%d\n", png->width);
|
||||
printf("\theight:\t\t%d\n", png->height);
|
||||
printf("\tdepth:\t\t%d\n", png->depth);
|
||||
printf("\tcolor:\t\t");
|
||||
|
||||
switch(png->color_type)
|
||||
{
|
||||
case PNG_GREYSCALE: printf("greyscale\n"); break;
|
||||
case PNG_TRUECOLOR: printf("truecolor\n"); break;
|
||||
case PNG_INDEXED: printf("palette\n"); break;
|
||||
case PNG_GREYSCALE_ALPHA: printf("greyscale with alpha\n"); break;
|
||||
case PNG_TRUECOLOR_ALPHA: printf("truecolor with alpha\n"); break;
|
||||
default: printf("unknown, this is not good\n"); break;
|
||||
}
|
||||
|
||||
printf("\tcompression:\t%s\n", png->compression_method?"unknown, this is not good":"inflate/deflate");
|
||||
printf("\tfilter:\t\t%s\n", png->filter_method?"unknown, this is not good":"adaptive");
|
||||
printf("\tinterlace:\t%s\n", png->interlace_method?"interlace":"no interlace");
|
||||
}
|
||||
|
||||
int png_open_read(png_t* png, png_read_callback_t read_fun, void* user_pointer)
|
||||
{
|
||||
char header[8];
|
||||
int result;
|
||||
|
||||
png->read_fun = read_fun;
|
||||
png->write_fun = 0;
|
||||
png->user_pointer = user_pointer;
|
||||
|
||||
if(!read_fun && !user_pointer)
|
||||
return PNG_WRONG_ARGUMENTS;
|
||||
|
||||
if(file_read(png, header, 1, 8) != 8)
|
||||
return PNG_EOF_ERROR;
|
||||
|
||||
if(memcmp(header, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) != 0)
|
||||
return PNG_HEADER_ERROR;
|
||||
|
||||
result = png_read_ihdr(png);
|
||||
|
||||
png->bpp = (unsigned char)png_get_bpp(png);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer)
|
||||
{
|
||||
png->write_fun = write_fun;
|
||||
png->read_fun = 0;
|
||||
png->user_pointer = user_pointer;
|
||||
|
||||
if(!write_fun && !user_pointer)
|
||||
return PNG_WRONG_ARGUMENTS;
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer)
|
||||
{
|
||||
return png_open_read(png, read_fun, user_pointer);
|
||||
}
|
||||
|
||||
int png_open_file_read(png_t *png, const char* filename)
|
||||
{
|
||||
FILE* fp = fopen(filename, "rb");
|
||||
|
||||
if(!fp)
|
||||
return PNG_FILE_ERROR;
|
||||
|
||||
return png_open_read(png, 0, fp);
|
||||
}
|
||||
|
||||
int png_open_file_write(png_t *png, const char* filename)
|
||||
{
|
||||
FILE* fp = fopen(filename, "wb");
|
||||
|
||||
if(!fp)
|
||||
return PNG_FILE_ERROR;
|
||||
|
||||
return png_open_write(png, 0, fp);
|
||||
}
|
||||
|
||||
int png_open_file(png_t *png, const char* filename)
|
||||
{
|
||||
return png_open_file_read(png, filename);
|
||||
}
|
||||
|
||||
int png_close_file(png_t* png)
|
||||
{
|
||||
fclose(png->user_pointer);
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_init_deflate(png_t* png, unsigned char* data, int datalen)
|
||||
{
|
||||
z_stream *stream;
|
||||
png->zs = png_alloc(sizeof(z_stream));
|
||||
|
||||
stream = png->zs;
|
||||
|
||||
if(!stream)
|
||||
return PNG_MEMORY_ERROR;
|
||||
|
||||
memset(stream, 0, sizeof(z_stream));
|
||||
|
||||
if(deflateInit(stream, Z_DEFAULT_COMPRESSION) != Z_OK)
|
||||
return PNG_ZLIB_ERROR;
|
||||
|
||||
stream->next_in = data;
|
||||
stream->avail_in = datalen;
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_init_inflate(png_t* png)
|
||||
{
|
||||
#if USE_ZLIB
|
||||
z_stream *stream;
|
||||
png->zs = png_alloc(sizeof(z_stream));
|
||||
#else
|
||||
zl_stream *stream;
|
||||
png->zs = png_alloc(sizeof(zl_stream));
|
||||
#endif
|
||||
|
||||
stream = png->zs;
|
||||
|
||||
if(!stream)
|
||||
return PNG_MEMORY_ERROR;
|
||||
|
||||
|
||||
|
||||
#if USE_ZLIB
|
||||
memset(stream, 0, sizeof(z_stream));
|
||||
if(inflateInit(stream) != Z_OK)
|
||||
return PNG_ZLIB_ERROR;
|
||||
#else
|
||||
memset(stream, 0, sizeof(zl_stream));
|
||||
if(z_inflateInit(stream) != Z_OK)
|
||||
return PNG_ZLIB_ERROR;
|
||||
#endif
|
||||
|
||||
stream->next_out = png->png_data;
|
||||
stream->avail_out = png->png_datalen;
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_end_deflate(png_t* png)
|
||||
{
|
||||
z_stream *stream = png->zs;
|
||||
|
||||
if(!stream)
|
||||
return PNG_MEMORY_ERROR;
|
||||
|
||||
deflateEnd(stream);
|
||||
|
||||
png_free(png->zs);
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_end_inflate(png_t* png)
|
||||
{
|
||||
#if USE_ZLIB
|
||||
z_stream *stream = png->zs;
|
||||
#else
|
||||
zl_stream *stream = png->zs;
|
||||
#endif
|
||||
|
||||
if(!stream)
|
||||
return PNG_MEMORY_ERROR;
|
||||
|
||||
#if USE_ZLIB
|
||||
if(inflateEnd(stream) != Z_OK)
|
||||
#else
|
||||
if(z_inflateEnd(stream) != Z_OK)
|
||||
#endif
|
||||
{
|
||||
printf("ZLIB says: %s\n", stream->msg);
|
||||
return PNG_ZLIB_ERROR;
|
||||
}
|
||||
|
||||
png_free(png->zs);
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_inflate(png_t* png, char* data, int len)
|
||||
{
|
||||
int result;
|
||||
#if USE_ZLIB
|
||||
z_stream *stream = png->zs;
|
||||
#else
|
||||
zl_stream *stream = png->zs;
|
||||
#endif
|
||||
|
||||
if(!stream)
|
||||
return PNG_MEMORY_ERROR;
|
||||
|
||||
stream->next_in = (unsigned char*)data;
|
||||
stream->avail_in = len;
|
||||
|
||||
#if USE_ZLIB
|
||||
result = inflate(stream, Z_SYNC_FLUSH);
|
||||
#else
|
||||
result = z_inflate(stream);
|
||||
#endif
|
||||
|
||||
if(result != Z_STREAM_END && result != Z_OK)
|
||||
{
|
||||
printf("%s\n", stream->msg);
|
||||
return PNG_ZLIB_ERROR;
|
||||
}
|
||||
|
||||
if(stream->avail_in != 0)
|
||||
return PNG_ZLIB_ERROR;
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_deflate(png_t* png, char* outdata, int outlen, int *outwritten)
|
||||
{
|
||||
int result;
|
||||
|
||||
z_stream *stream = png->zs;
|
||||
|
||||
|
||||
if(!stream)
|
||||
return PNG_MEMORY_ERROR;
|
||||
|
||||
stream->next_out = (unsigned char*)outdata;
|
||||
stream->avail_out = outlen;
|
||||
|
||||
result = deflate(stream, Z_SYNC_FLUSH);
|
||||
|
||||
*outwritten = outlen - stream->avail_out;
|
||||
|
||||
if(result != Z_STREAM_END && result != Z_OK)
|
||||
{
|
||||
printf("%s\n", stream->msg);
|
||||
return PNG_ZLIB_ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int png_write_idats(png_t* png, unsigned char* data)
|
||||
{
|
||||
unsigned char *chunk;
|
||||
unsigned long written;
|
||||
unsigned long crc;
|
||||
unsigned size = png->width * png->height * png->bpp + png->height;
|
||||
|
||||
(void)png_init_deflate;
|
||||
(void)png_end_deflate;
|
||||
(void)png_deflate;
|
||||
|
||||
chunk = png_alloc(size);
|
||||
memcpy(chunk, "IDAT", 4);
|
||||
|
||||
written = size;
|
||||
compress(chunk+4, &written, data, size);
|
||||
|
||||
crc = crc32(0L, Z_NULL, 0);
|
||||
crc = crc32(crc, chunk, written+4);
|
||||
set_ul(chunk+written+4, crc);
|
||||
file_write_ul(png, written);
|
||||
file_write(png, chunk, 1, written+8);
|
||||
png_free(chunk);
|
||||
|
||||
file_write_ul(png, 0);
|
||||
file_write(png, "IEND", 1, 4);
|
||||
crc = crc32(0L, (const unsigned char *)"IEND", 4);
|
||||
file_write_ul(png, crc);
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_read_idat(png_t* png, unsigned firstlen)
|
||||
{
|
||||
unsigned type = 0;
|
||||
char *chunk;
|
||||
int result;
|
||||
unsigned length = firstlen;
|
||||
unsigned old_len = length;
|
||||
|
||||
#if DO_CRC_CHECKS
|
||||
unsigned orig_crc;
|
||||
unsigned calc_crc;
|
||||
#endif
|
||||
|
||||
chunk = png_alloc(firstlen);
|
||||
|
||||
result = png_init_inflate(png);
|
||||
|
||||
if(result != PNG_NO_ERROR)
|
||||
{
|
||||
png_end_inflate(png);
|
||||
png_free(chunk);
|
||||
return result;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if(file_read(png, chunk, 1, length) != length)
|
||||
{
|
||||
png_end_inflate(png);
|
||||
png_free(chunk);
|
||||
return PNG_FILE_ERROR;
|
||||
}
|
||||
|
||||
#if DO_CRC_CHECKS
|
||||
calc_crc = crc32(0L, Z_NULL, 0);
|
||||
calc_crc = crc32(calc_crc, (unsigned char*)"IDAT", 4);
|
||||
calc_crc = crc32(calc_crc, (unsigned char*)chunk, length);
|
||||
|
||||
file_read_ul(png, &orig_crc);
|
||||
|
||||
if(orig_crc != calc_crc)
|
||||
{
|
||||
result = PNG_CRC_ERROR;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
file_read_ul(png);
|
||||
#endif
|
||||
|
||||
result = png_inflate(png, chunk, length);
|
||||
|
||||
if(result != PNG_NO_ERROR) break;
|
||||
|
||||
file_read_ul(png, &length);
|
||||
|
||||
if(length > old_len)
|
||||
{
|
||||
png_free(chunk);
|
||||
chunk = png_alloc(length);
|
||||
old_len = length;
|
||||
}
|
||||
|
||||
if(file_read(png, &type, 1, 4) != 4)
|
||||
{
|
||||
result = PNG_FILE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
}while(type == *(unsigned int*)"IDAT");
|
||||
|
||||
if(type == *(unsigned int*)"IEND")
|
||||
result = PNG_DONE;
|
||||
|
||||
png_free(chunk);
|
||||
png_end_inflate(png);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int png_process_chunk(png_t* png)
|
||||
{
|
||||
int result = PNG_NO_ERROR;
|
||||
unsigned type;
|
||||
unsigned length;
|
||||
|
||||
file_read_ul(png, &length);
|
||||
|
||||
if(file_read(png, &type, 1, 4) != 4)
|
||||
return PNG_FILE_ERROR;
|
||||
|
||||
if(type == *(unsigned int*)"IDAT") /* if we found an idat, all other idats should be followed with no other chunks in between */
|
||||
{
|
||||
png->png_datalen = png->width * png->height * png->bpp + png->height;
|
||||
png->png_data = png_alloc(png->png_datalen);
|
||||
|
||||
if(!png->png_data)
|
||||
return PNG_MEMORY_ERROR;
|
||||
|
||||
return png_read_idat(png, length);
|
||||
}
|
||||
else if(type == *(unsigned int*)"IEND")
|
||||
{
|
||||
return PNG_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
file_read(png, 0, 1, length + 4); /* unknown chunk */
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void png_filter_sub(int stride, unsigned char* in, unsigned char* out, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned char a = 0;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
if(i >= stride)
|
||||
a = out[i - stride];
|
||||
|
||||
out[i] = in[i] + a;
|
||||
}
|
||||
}
|
||||
|
||||
static void png_filter_up(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(prev_line)
|
||||
{
|
||||
for(i = 0; i < len; i++)
|
||||
out[i] = in[i] + prev_line[i];
|
||||
}
|
||||
else
|
||||
memcpy(out, in, len);
|
||||
}
|
||||
|
||||
static void png_filter_average(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned char a = 0;
|
||||
unsigned char b = 0;
|
||||
unsigned int sum = 0;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
if(prev_line)
|
||||
b = prev_line[i];
|
||||
|
||||
if(i >= stride)
|
||||
a = out[i - stride];
|
||||
|
||||
sum = a;
|
||||
sum += b;
|
||||
|
||||
out[i] = (char)(in[i] + sum/2);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char png_paeth(unsigned char a, unsigned char b, unsigned char c)
|
||||
{
|
||||
int p = (int)a + b - c;
|
||||
int pa = abs(p - a);
|
||||
int pb = abs(p - b);
|
||||
int pc = abs(p - c);
|
||||
|
||||
int pr;
|
||||
|
||||
if(pa <= pb && pa <= pc)
|
||||
pr = a;
|
||||
else if(pb <= pc)
|
||||
pr = b;
|
||||
else
|
||||
pr = c;
|
||||
|
||||
return (char)pr;
|
||||
}
|
||||
|
||||
static void png_filter_paeth(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
unsigned char c;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
if(prev_line && i >= stride)
|
||||
{
|
||||
a = out[i - stride];
|
||||
b = prev_line[i];
|
||||
c = prev_line[i - stride];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(prev_line)
|
||||
b = prev_line[i];
|
||||
else
|
||||
b = 0;
|
||||
|
||||
if(i >= stride)
|
||||
a = out[i - stride];
|
||||
else
|
||||
a = 0;
|
||||
|
||||
c = 0;
|
||||
}
|
||||
|
||||
out[i] = in[i] + png_paeth(a, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
static int png_filter(png_t* png, unsigned char* data)
|
||||
{
|
||||
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int png_unfilter(png_t* png, unsigned char* data)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned pos = 0;
|
||||
unsigned outpos = 0;
|
||||
unsigned char *filtered = png->png_data;
|
||||
|
||||
int stride = png->bpp;
|
||||
|
||||
while(pos < png->png_datalen)
|
||||
{
|
||||
unsigned char filter = filtered[pos];
|
||||
|
||||
pos++;
|
||||
|
||||
if(png->depth == 16)
|
||||
{
|
||||
for(i = 0; i < png->width * stride; i+=2)
|
||||
{
|
||||
*(short*)(filtered+pos+i) = (filtered[pos+i] << 8) | filtered[pos+i+1];
|
||||
}
|
||||
}
|
||||
|
||||
switch(filter)
|
||||
{
|
||||
case 0: /* none */
|
||||
memcpy(data+outpos, filtered+pos, png->width * stride);
|
||||
break;
|
||||
case 1: /* sub */
|
||||
png_filter_sub(stride, filtered+pos, data+outpos, png->width * stride);
|
||||
break;
|
||||
case 2: /* up */
|
||||
if(outpos)
|
||||
png_filter_up(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
|
||||
else
|
||||
png_filter_up(stride, filtered+pos, data+outpos, 0, png->width*stride);
|
||||
break;
|
||||
case 3: /* average */
|
||||
if(outpos)
|
||||
png_filter_average(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
|
||||
else
|
||||
png_filter_average(stride, filtered+pos, data+outpos, 0, png->width*stride);
|
||||
break;
|
||||
case 4: /* paeth */
|
||||
if(outpos)
|
||||
png_filter_paeth(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
|
||||
else
|
||||
png_filter_paeth(stride, filtered+pos, data+outpos, 0, png->width*stride);
|
||||
break;
|
||||
default:
|
||||
return PNG_UNKNOWN_FILTER;
|
||||
}
|
||||
|
||||
outpos += png->width * stride;
|
||||
pos += png->width * stride;
|
||||
}
|
||||
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
int png_get_data(png_t* png, unsigned char* data)
|
||||
{
|
||||
int result = PNG_NO_ERROR;
|
||||
|
||||
while(result == PNG_NO_ERROR)
|
||||
{
|
||||
result = png_process_chunk(png);
|
||||
}
|
||||
|
||||
if(result != PNG_DONE)
|
||||
{
|
||||
png_free(png->png_data);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = png_unfilter(png, data);
|
||||
|
||||
png_free(png->png_data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned char *filtered;
|
||||
png->width = width;
|
||||
png->height = height;
|
||||
png->depth = depth;
|
||||
png->color_type = color;
|
||||
png->bpp = png_get_bpp(png);
|
||||
|
||||
filtered = png_alloc(width * height * png->bpp + height);
|
||||
|
||||
for(i = 0; i < png->height; i++)
|
||||
{
|
||||
filtered[i*png->width*png->bpp+i] = 0;
|
||||
memcpy(&filtered[i*png->width*png->bpp+i+1], data + i * png->width*png->bpp, png->width*png->bpp);
|
||||
}
|
||||
|
||||
png_filter(png, filtered);
|
||||
png_write_ihdr(png);
|
||||
png_write_idats(png, filtered);
|
||||
|
||||
png_free(filtered);
|
||||
return PNG_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
char* png_error_string(int error)
|
||||
{
|
||||
switch(error)
|
||||
{
|
||||
case PNG_NO_ERROR:
|
||||
return "No error";
|
||||
case PNG_FILE_ERROR:
|
||||
return "Unknown file error.";
|
||||
case PNG_HEADER_ERROR:
|
||||
return "No PNG header found. Are you sure this is a PNG?";
|
||||
case PNG_IO_ERROR:
|
||||
return "Failure while reading file.";
|
||||
case PNG_EOF_ERROR:
|
||||
return "Reached end of file.";
|
||||
case PNG_CRC_ERROR:
|
||||
return "CRC or chunk length error.";
|
||||
case PNG_MEMORY_ERROR:
|
||||
return "Could not allocate memory.";
|
||||
case PNG_ZLIB_ERROR:
|
||||
return "zlib reported an error.";
|
||||
case PNG_UNKNOWN_FILTER:
|
||||
return "Unknown filter method used in scanline.";
|
||||
case PNG_DONE:
|
||||
return "PNG done";
|
||||
case PNG_NOT_SUPPORTED:
|
||||
return "The PNG is unsupported by pnglite, too bad for you!";
|
||||
case PNG_WRONG_ARGUMENTS:
|
||||
return "Wrong combination of arguments passed to png_open. You must use either a read_function or supply a file pointer to use.";
|
||||
default:
|
||||
return "Unknown error.";
|
||||
};
|
||||
}
|
9
shaders/basic.frag
Normal file
9
shaders/basic.frag
Normal file
@@ -0,0 +1,9 @@
|
||||
#version 120
|
||||
|
||||
uniform sampler2D sTexture;
|
||||
|
||||
void main(void) {
|
||||
vec4 tex = texture2D(sTexture, gl_TexCoord[0].st);
|
||||
gl_FragColor = clamp(tex, 0.0, 1.0);
|
||||
//gl_FragColor = vec4(gl_TexCoord[0].s, gl_TexCoord[0].t, 0.0, 1.0);
|
||||
}
|
6
shaders/basic.vert
Normal file
6
shaders/basic.vert
Normal file
@@ -0,0 +1,6 @@
|
||||
#version 120
|
||||
|
||||
void main() {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = ftransform();
|
||||
}
|
Reference in New Issue
Block a user