// Computergrafik I // Prof. Dr. Juergen Doellner // Sommersemester 2001 // // Programmrahmen fuer Aufgabe 5 // Stephan Brumme, 702544 // last changes: May 01, 2001 #include "cgairbrush.h" #include CGAirbrush::CGAirbrush(unsigned int brushPatternSize) : m_brushPatternSize(brushPatternSize) { assert(brushPatternSize >= 10); // sollte groesser/gleich 10x10 sein! // erzeuge brush pattern dynamisch m_brushPattern = new Color[brushPatternSize*brushPatternSize]; // Initialisiere die RGB- und Alpha-Werte der Schablone // kreisförmiger Pinsel setRadialPattern(); // rot setColor(1.0, 0.0, 0.0); } CGAirbrush::~CGAirbrush() { // Nicht vergessen: Freigabe des dynamisch erzeugten Objekte delete [] m_brushPattern; } void CGAirbrush::onInit() { // Setze die Hintergrundfarbe auf weiss glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // Die Schablonen-Reihen sind dicht gepackt glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Schalte das Blending ein: glEnable(GL_BLEND); // mische Farbwerte glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glFlush(); } void CGAirbrush::onDraw() { // Loesche den Farb-Buffer glClear(GL_COLOR_BUFFER_BIT); glFlush(); // Wir verwenden Single-Buffering und koennen // die bisher gezeichneten Figuren nicht mehr // restaurieren. } void CGAirbrush::onSize(unsigned int newWidth, unsigned int newHeight) { // Nach jeder Groessenaenderung des OpenGL-Fensters // MUSS der Viewport entsprechend angepasst werden: glViewport(0, 0, newWidth - 1, newHeight - 1); // Lege das zu verwendende Koordinatensystem fest: // die linke untere Fensterecke hat die Koordinaten (0, 0) // und die rechte obere die Koord. (newWidth, newHeight) glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, newWidth, 0.0, newHeight); } void CGAirbrush::onButton(MouseButton button, int x, int y) { if (button == LeftMouseButton) // Mache das selbe wie bei einer Mausbewegung: onMove(x, y); else { // setze Pinsel auf Bildinhalt an der aktuellen Position glReadPixels(x-m_brushPatternSize/2, y-m_brushPatternSize/2, m_brushPatternSize, m_brushPatternSize, GL_RGBA, GL_FLOAT, m_brushPattern); } } void CGAirbrush::onMove(int x, int y) { // lege obere linke Ecke fest, // sodass Mauscursor der Mittelpunkt der gezeichneten Fläche ist glRasterPos2i(x-m_brushPatternSize/2, y-m_brushPatternSize/2); // zeichne Pinsel glDrawPixels(m_brushPatternSize, m_brushPatternSize, GL_RGBA, GL_FLOAT, m_brushPattern); // Pipeline abarbeiten glFlush(); } void CGAirbrush::onKey(unsigned char key) { // Keys switch(key) { // beenden case 'q' : exit(0); break; // Farbe setzen case '0' : setColor(1.0, 0.0, 0.0); break; case '1' : setColor(0.0, 1.0, 0.0); break; case '2' : setColor(0.0, 0.0, 1.0); break; case '3' : setColor(1.0, 1.0, 0.0); break; case '4' : setColor(1.0, 0.0, 1.0); break; case '5' : setColor(0.0, 1.0, 1.0); break; case '6' : setColor(1.0, 1.0, 1.0); break; case '7' : setColor(0.0, 0.0, 0.0); break; // Buffer löschen (weiss) case 'c' : glClear(GL_COLOR_BUFFER_BIT); glFlush(); break; // verschiedene Pinsel setzen case 'r' : setRadialPattern(); break; case 'k' : setConstantPattern(0.5); break; case 'e' : setArbitraryPattern(); break; default: cerr << "No action defined for key: " << key << endl; } } void CGAirbrush::setRadialPattern() { // Mitte des Pinsels bestimmen float nCenterX = m_brushPatternSize/2; float nCenterY = m_brushPatternSize/2; // Durchmesser des runden Pinsels float fMaxDistance = m_brushPatternSize/2; for (unsigned int nX = 0; nX < m_brushPatternSize; nX++) for (unsigned int nY = 0; nY < m_brushPatternSize; nY++) { // Abstand zur Pinselmitte float fDistance = sqrt((nCenterX-nX) * (nCenterX-nX) + (nCenterY-nY) * (nCenterY-nY)); // 100% opak in der Pinselmitte, 0% am Rand float fOpacity = 1 - fDistance/fMaxDistance; // verhindere Underflow if (fOpacity < 0) fOpacity = 0; fOpacity *= 0.5; // setze Opazität m_brushPattern[nX*m_brushPatternSize+nY].alpha = fOpacity; } } void CGAirbrush::setConstantPattern(float fOpacity) { // kompletter Pinsel mit einer Opazität for (unsigned int nX = 0; nX < m_brushPatternSize; nX++) for (unsigned int nY = 0; nY < m_brushPatternSize; nY++) m_brushPattern[nX*m_brushPatternSize+nY].alpha = fOpacity; } void CGAirbrush::setArbitraryPattern() { // öffne Datei ifstream hPattern("32x32.pat"); // lies Pinsel ein for (unsigned int nX = 0; nX < m_brushPatternSize; nX++) for (unsigned int nY = 0; nY < m_brushPatternSize; nY++) hPattern >> m_brushPattern[nX*m_brushPatternSize+nY].alpha; } void CGAirbrush::setColor(GLfloat red, GLfloat green, GLfloat blue) { // ändere alle Farbwerte im Pinsel for (unsigned int nX = 0; nX < m_brushPatternSize; nX++) for (unsigned int nY = 0; nY < m_brushPatternSize; nY++) { m_brushPattern[nX*m_brushPatternSize+nY].r = red; m_brushPattern[nX*m_brushPatternSize+nY].g = green; m_brushPattern[nX*m_brushPatternSize+nY].b = blue; } } int main(int argc, char* argv[]) { CGAirbrush airbrush(32); airbrush.start("CGAirbrush, Stephan Brumme, 702544", false); return(0); }