torpor
hack hack hack, the little machines fight back
I'm personally very interested in your progress here Whynodd, so I hope you'll continue to share details - and maybe sources - in your quest to nail the HelloGLES(1,2)World ..
				
			torpor said:I'm personally very interested in your progress here Whynodd, so I hope you'll continue to share details - and maybe sources - in your quest to nail the HelloGLES(1,2)World ..
const char* pszFragShader = "\
  precision mediump float;\
  varying vec4 coordinates;\
  void main (void)\
    {\
      float dis;\
      dis = distance(coordinates,vec4(0.0,0.0,0.0,1.0));\
      dis = (sin(20.0*dis)+1.0)/2.0;\
      gl_FragColor = vec4(1.0-dis,1.0-dis, 1.0-dis, 1.0);\
    }";
const char* pszVertShader = "\
  attribute   vec4    vPosition;\
  varying vec4 coordinates;\
  void main(void)\
  {\
    coordinates = vPosition;\
    gl_Position = vPosition;\
  }";int Game::start()
{
  //initialisation stuff//
  ...
  KeyInput keyInput; // instance of a class that cares about input
  pthread_t keyInputThread;
  pthread_create( &keyInputThread, NULL, processInputThread, &keyInput); // after this, the key handler is infinitely running
  while (gamestate.getrunning())
  {
    // do a timestep here 
    scene.draw(); // and now draw the scene
    if (keyInput.getkeyQuit())
    {
      gamestate.setrunning(false);
    }
  }
  return 1;
}void* Game::processInputThread(void* obj)
{
	KeyInput* myObj = reinterpret_cast<KeyInput*>(obj);
	myObj->processInput(); // processInput is finally the infinite loop that handles input
	return 0;
}int KeyInput::findGPIOkeys()
{
	char name[100];
	GPIOkeyHandle=0; // its an int
	for (int i = 0; i<10; i++)
	{
		sprintf(name, "/dev/input/event%i", i);
		GPIOkeyHandle = open(name, O_RDONLY);
		if (GPIOkeyHandle < 0) break; /* no more devices */
		ioctl(GPIOkeyHandle, EVIOCGNAME(sizeof(name)), name);
		if (strcmp(name, "gpio-keys") == 0)
		{
			return 1; // found the buttons!
		}
		close(GPIOkeyHandle); /* we don't need this device */
	}
	GPIOkeyHandle=0;
	return 0; // did not find the buttons
}void KeyInput::processInput()
{
	#ifdef PANDORA
	while(1) // immer weiter schön die Tasten einlesen
	{
		struct input_event ev[64];
		int rd, ret;
		int fd = -1;
		fd_set fdset;
		// Der kommende Block sucht sich das input device aus, das etwas zu sagen hat
		FD_ZERO(&fdset);
		if (GPIOkeyHandle!= -1)
		{
			FD_SET(GPIOkeyHandle, &fdset);
		}
		ret = select(GPIOkeyHandle+1, &fdset, NULL, NULL, NULL);
		if (ret == -1)
		{
			printf("Error at select\n");
			return; // hier vielleicht mit fehler returnen und im aufrufenden Game behandeln
		}
		if (GPIOkeyHandle!= -1 && FD_ISSET(GPIOkeyHandle, &fdset))
		{
			fd = GPIOkeyHandle;
		}
		rd = read(fd, ev, sizeof(ev)); // blocks here if no buttons are pressed
		if (rd < (int) sizeof(ev[0]))
		{
			printf("Error reading GPIO-keys event\n");
			return;
		}
		// Jetzt die gelesenen Events verarbeiten
		for (int i = 0; i < rd / sizeof(ev[0]); i++)
		{
			switch (ev[i].type)
			{
				case EV_SYN: //Wird wohl bei jedem Tastendruck ausgelöst. K.a. was das ist.
				break;
				case EV_KEY:
					//set_key(ev[i].code, ev[i].value); // Überbleibsel aus op_test_inputs.c, http://pandorawiki.org/Kernel_interface
					switch (ev[i].code)
					{
						case KEY_RIGHTSHIFT: // L
						break;
						case KEY_RIGHTCTRL:  // R
						break;
						case KEY_LEFTALT:    // Start
						  this->keyPause=ev[i].value;
						break;
						case KEY_LEFTCTRL:   // Select
							this->keyQuit=ev[i].value;
						break;
						case KEY_MENU:       // Menu
						break;
						case KEY_LEFT:       // Steuerkreuz
							this->keyLeft=ev[i].value;
						break;
						case KEY_RIGHT:
							this->keyRight=ev[i].value;
						break;
						case KEY_UP:
							this->keyUp=ev[i].value;
						break;
						case KEY_DOWN:
							this->keyDown=ev[i].value;
						break;
						case KEY_PAGEUP:     // Y
						break;
						case KEY_PAGEDOWN:   // X
						break;
						case KEY_HOME:       // A
						break;
						case KEY_END:        // B
						break;
						default:
						break;
					}
				break;
					/* fallthrough */
				default:
					printf("unexpected event: type %i, code %d\n", ev[i].type, ev[i].code);
				break;
			}
		}
	}
	#endif
}class Matrix4x4
{
    public:
    Matrix4x4();
    //belegt die Matrix mit der Identity
    void identity();
    //Setzt projectionMatrix auf eine Projektionsmatrix mit den angegebenen Parametern
    void perspective(float fov, float aspect, float near, float far);
    float matrix[16];
};class MatrixStacks
{
  public:
    int pushProjection();
    int pushModelview();
    int pushTexture();
    int popProjection();
    int popModelview();
    int popTexture();
    //Löscht den Matrixstack und behält die aktuelle Matrix bei
    void clearProjection();
    //Löscht den Matrixstack und behält die aktuelle Matrix bei
    void clearModelview();
    //Löscht den Matrixstack und behält die aktuelle Matrix bei
    void clearTexture();
    static Matrix4x4 projectionMatrix;
    static Matrix4x4 textureMatrix;
    static Matrix4x4 modelviewMatrix;
  private:
    static vector<Matrix4x4> textureStack;
    static vector<Matrix4x4> modelviewStack;
    static vector<Matrix4x4> projectionStack;
};Done.Whynodd said:Btw: Can a mod change the thread title to something similar to "OpenGLES2 (racing)game development, progress and useful code"?
Hmm, code bloat: Hundreds of header files and I only need a small fraction of it. It would take a week for me to understand and integrate such a library but only 3 days to code it by myself. Also I want to compile as fast as possible. This is also the reason why I decide against a physics engine like Bullet. Hard to integrate (at least for me), hard to understand and bloaty. Found a good tutorial that explains physics integration in a nutshell (Physics integration)Laurent said:Why don't you use an already implemented and hopefully well-tested library for your transformations?
For instance: http://glm.g-truc.net/
Here it is. If you want to use it, you shurely figure out how it works. This is work in progress but it already loads obj-files (made with blender) and puts the data into memory.I'm interested in your obj-loader code!
...
vector<Vector3> vertices;
vector<Vector3> normals;
vector<Vector2> texcoords;
vector<UintVector3> vertexAssociations;
vector<UintVector3> texcoordAssociations;
vector<UintVector3> normalAssociations;
vector<string> materialAssociations;
...
bool GraphicObject::loadOBJ(string filename)
{
  ifstream file;
  file.open(filename.c_str(), ios_base::in);
  if (file.is_open())
  {
    vertices.clear(); // alles erstmal löschen
    normals.clear();
    texcoords.clear();
    vertexAssociations.clear();
    normalAssociations.clear();
    texcoordAssociations.clear();
	string element;
	string currentMaterial="none";
	while (!file.eof())
	{
		file >> element;
		if (element=="v") //Vertexkoordinaten
		{
			double x,y,z;
			file >> x;
			file >> y;
			file >> z;
			//std::cout << "Vertices: " << x << " " << y << " " << z << std::endl;
			vertices.push_back(Vector3(x,y,z));
		}
		if (element=="vn") //Normalen
		{
			double x,y,z;
			file >> x;
			file >> y;
			file >> z;
			//std::cout << "Normalen: " << x << " " << y << " " << z << std::endl;
			normals.push_back(Vector3(x,y,z));
		}
		if (element=="vt") //Texturkoordinaten
		{
			double x,y;
			file >> x;
			file >> y;
			//std::cout << "Texturkoordinaten: " << x << " " << y << std::endl;
			texcoords.push_back(Vector2(x,y));
		}
		if (element=="usemtl")
		{
                        file >> currentMaterial;
                        tracer.systemInfo("GraphicObject","loadOBJ","Material jetzt: "+ currentMaterial);
                }
		if (element=="f") //Zuordunugen zu den Koordinaten und Normalen
		{
			unsigned int vertexIndex[3];
			unsigned int texcoordIndex[3];
			unsigned int normalIndex[3];
			for (int i=0; i<3; i++) // alle 3 Parts ablaufen (TRIangle)
			{
				file >> element;
				vector<string> parts;
				stringSplit(element,"/",parts);
				vertexIndex[i]=atoi(parts[0].c_str());
				texcoordIndex[i]=atoi(parts[1].c_str());
				normalIndex[i]=atoi(parts[2].c_str());
			}
			vertexAssociations.push_back(UintVector3(vertexIndex[0]-1,vertexIndex[1]-1,vertexIndex[2]-1));
			texcoordAssociations.push_back(UintVector3(texcoordIndex[0]-1,texcoordIndex[1]-1,texcoordIndex[2]-1));
			normalAssociations.push_back(UintVector3(normalIndex[0]-1,normalIndex[1]-1,normalIndex[2]-1));
			materialAssociations.push_back(currentMaterial);
		}
        }
    file.close();
    return 1;
  }
  else
  {
  	tracer.error("GraphicObject","loadOBJ","OBJ " + filename + " konnte nicht geladen werden");
	return 0;
  }
}
void GraphicObject::stringSplit(string str, string delim, vector<string> & results)
{
	int cutAt;
	while( (cutAt = str.find_first_of(delim)) != str.npos )
	{
		if(cutAt > 0)
		{
			results.push_back(str.substr(0,cutAt));
		}
		else
		{
			results.push_back("0");
		}
		str = str.substr(cutAt+1);
	}
	if(str.length() > 0)
	{
		results.push_back(str);
	}
}for (int i=0; i<vertexAssociations.size(); i++)
{
        materials[materialAssociations[i]]->applyMaterial();
          
        glBegin(GL_TRIANGLES);  
        glNormal3f( normals[normalAssociations[i].first].x, normals[normalAssociations[i].first].y, normals[normalAssociations[i].first].z);             
        glVertex3f( vertices[vertexAssociations[i].first].x, vertices[vertexAssociations[i].first].y, vertices[vertexAssociations[i].first].z);
          	
    	glNormal3f( normals[normalAssociations[i].second].x, normals[normalAssociations[i].second].y, normals[normalAssociations[i].second].z);
        glVertex3f( vertices[vertexAssociations[i].second].x, vertices[vertexAssociations[i].second].y, vertices[vertexAssociations[i].second].z);
      			
        glNormal3f( normals[normalAssociations[i].third].x, normals[normalAssociations[i].third].y, normals[normalAssociations[i].third].z); 
      	glVertex3f( vertices[vertexAssociations[i].third].x, vertices[vertexAssociations[i].third].y, vertices[vertexAssociations[i].third].z);  	
    	glEnd();
}void Matrix4x4::frustum(float left, float right, float bottom, float top, float near, float far)
{
  // Vergleiche mit http://wiki.delphigl.com/index.php/glFrustum
	matrix[ 0] = 2.0f*near/(right-left);
	matrix[ 4] = 0.0f;
	matrix[ 8] = 0.0f;
	matrix[12] = 0.0f;
	matrix[ 1] = 0.0f;
	matrix[ 5] = 2.0f*near/(top-bottom);
	matrix[ 9] = 0.0f;
	matrix[13] = 0.0f;
	matrix[ 2] = (right+left)/(right-left);
	matrix[ 6] = (top+bottom)/(top-bottom);
	matrix[10] = -(far+near)/(far-near);
	matrix[14] = -1.0f;
	matrix[3] = 0.0f;
	matrix[7] = 0.0f;
	matrix[11] = -(2.0f*far*near)/(far-near);
	matrix[15] = 0.0f;
}float ratio = (float)preferences.resolutionX / (float)preferences.resolutionY;
float leftRight = 2* tan(preferences.viewingAngle/2) * preferences.zNear;
float topBottom = leftRight/ratio;
matrixStacks.projectionMatrix.identity();
matrixStacks.projectionMatrix.frustum(-leftRight, leftRight, -topBottom, topBottom, (float)preferences.zNear, (float)preferences.zFar);gl_Position = projectionMatrix * modelviewMatrix * vPosition;\void Matrix4x4::frustum(float left, float right, float bottom, float top, float near, float far)
{
  // Vergleiche mit http://wiki.delphigl.com/index.php/glFrustum
	matrix[ 0] = 2.0f*near/(right-left);
	matrix[ 4] = 0.0f;
	matrix[ 8] = (right+left)/(right-left);
	matrix[12] = 0.0f;
	matrix[ 1] = 0.0f;
	matrix[ 5] = 2.0f*near/(top-bottom);
	matrix[ 9] = (top+bottom)/(top-bottom);
	matrix[13] = 0.0f;
	matrix[ 2] = 0.0;
	matrix[ 6] = 0.0;
	matrix[10] = -(far+near)/(far-near);
	matrix[14] = -(2.0f*far*near)/(far-near);
	matrix[3] = 0.0f;
	matrix[7] = 0.0f;
	matrix[11] = -1.0;
	matrix[15] = 0.0f;
} 
	