1 // Computergrafik I
2 // Prof. Dr. Juergen Doellner
3 // Sommersemester 2001
4 //
5 // Programmrahmen fuer Aufgabe 5
6
7 // Stephan Brumme, 702544
8 // last changes: May 01, 2001
9
10 #include "cgairbrush.h"
11 #include <fstream.h>
12
13
14 CGAirbrush::CGAirbrush(unsigned int brushPatternSize)
15 : m_brushPatternSize(brushPatternSize) {
16 assert(brushPatternSize >= 10); // sollte groesser/gleich 10x10 sein!
17
18 // erzeuge brush pattern dynamisch
19 m_brushPattern = new Color[brushPatternSize*brushPatternSize];
20
21 // Initialisiere die RGB- und Alpha-Werte der Schablone
22 // kreisförmiger Pinsel
23 setRadialPattern();
24 // rot
25 setColor(1.0, 0.0, 0.0);
26 }
27
28 CGAirbrush::~CGAirbrush() {
29 // Nicht vergessen: Freigabe des dynamisch erzeugten Objekte
30 delete [] m_brushPattern;
31 }
32
33 void CGAirbrush::onInit() {
34 // Setze die Hintergrundfarbe auf weiss
35 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
36 glClear(GL_COLOR_BUFFER_BIT);
37
38 // Die Schablonen-Reihen sind dicht gepackt
39 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
40
41 // Schalte das Blending ein:
42 glEnable(GL_BLEND);
43 // mische Farbwerte
44 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
45
46 glFlush();
47 }
48
49 void CGAirbrush::onDraw() {
50 // Loesche den Farb-Buffer
51 glClear(GL_COLOR_BUFFER_BIT);
52 glFlush();
53
54 // Wir verwenden Single-Buffering und koennen
55 // die bisher gezeichneten Figuren nicht mehr
56 // restaurieren.
57 }
58
59 void CGAirbrush::onSize(unsigned int newWidth, unsigned int newHeight) {
60 // Nach jeder Groessenaenderung des OpenGL-Fensters
61 // MUSS der Viewport entsprechend angepasst werden:
62 glViewport(0, 0, newWidth - 1, newHeight - 1);
63
64 // Lege das zu verwendende Koordinatensystem fest:
65 // die linke untere Fensterecke hat die Koordinaten (0, 0)
66 // und die rechte obere die Koord. (newWidth, newHeight)
67 glMatrixMode(GL_PROJECTION);
68 glLoadIdentity();
69 gluOrtho2D(0.0, newWidth, 0.0, newHeight);
70 }
71
72 void CGAirbrush::onButton(MouseButton button, int x, int y) {
73
74 if (button == LeftMouseButton)
75 // Mache das selbe wie bei einer Mausbewegung:
76 onMove(x, y);
77 else
78 {
79 // setze Pinsel auf Bildinhalt an der aktuellen Position
80 glReadPixels(x-m_brushPatternSize/2, y-m_brushPatternSize/2,
81 m_brushPatternSize, m_brushPatternSize,
82 GL_RGBA, GL_FLOAT, m_brushPattern);
83 }
84 }
85
86 void CGAirbrush::onMove(int x, int y)
87 {
88 // lege obere linke Ecke fest,
89 // sodass Mauscursor der Mittelpunkt der gezeichneten Fläche ist
90 glRasterPos2i(x-m_brushPatternSize/2, y-m_brushPatternSize/2);
91 // zeichne Pinsel
92 glDrawPixels(m_brushPatternSize, m_brushPatternSize,
93 GL_RGBA, GL_FLOAT, m_brushPattern);
94
95 // Pipeline abarbeiten
96 glFlush();
97 }
98
99 void CGAirbrush::onKey(unsigned char key) {
100 // Keys
101 switch(key) {
102 // beenden
103 case 'q' : exit(0); break;
104
105 // Farbe setzen
106 case '0' : setColor(1.0, 0.0, 0.0); break;
107 case '1' : setColor(0.0, 1.0, 0.0); break;
108 case '2' : setColor(0.0, 0.0, 1.0); break;
109 case '3' : setColor(1.0, 1.0, 0.0); break;
110 case '4' : setColor(1.0, 0.0, 1.0); break;
111 case '5' : setColor(0.0, 1.0, 1.0); break;
112 case '6' : setColor(1.0, 1.0, 1.0); break;
113 case '7' : setColor(0.0, 0.0, 0.0); break;
114
115 // Buffer löschen (weiss)
116 case 'c' : glClear(GL_COLOR_BUFFER_BIT); glFlush(); break;
117
118 // verschiedene Pinsel setzen
119 case 'r' : setRadialPattern(); break;
120 case 'k' : setConstantPattern(0.5); break;
121 case 'e' : setArbitraryPattern(); break;
122
123 default:
124 cerr << "No action defined for key: " << key << endl;
125 }
126 }
127
128 void CGAirbrush::setRadialPattern()
129 {
130 // Mitte des Pinsels bestimmen
131 float nCenterX = m_brushPatternSize/2;
132 float nCenterY = m_brushPatternSize/2;
133
134 // Durchmesser des runden Pinsels
135 float fMaxDistance = m_brushPatternSize/2;
136
137 for (unsigned int nX = 0; nX < m_brushPatternSize; nX++)
138 for (unsigned int nY = 0; nY < m_brushPatternSize; nY++)
139 {
140 // Abstand zur Pinselmitte
141 float fDistance = sqrt((nCenterX-nX) * (nCenterX-nX) +
142 (nCenterY-nY) * (nCenterY-nY));
143
144 // 100% opak in der Pinselmitte, 0% am Rand
145 float fOpacity = 1 - fDistance/fMaxDistance;
146
147 // verhindere Underflow
148 if (fOpacity < 0)
149 fOpacity = 0;
150 fOpacity *= 0.5;
151
152 // setze Opazität
153 m_brushPattern[nX*m_brushPatternSize+nY].alpha = fOpacity;
154 }
155 }
156
157 void CGAirbrush::setConstantPattern(float fOpacity)
158 {
159 // kompletter Pinsel mit einer Opazität
160 for (unsigned int nX = 0; nX < m_brushPatternSize; nX++)
161 for (unsigned int nY = 0; nY < m_brushPatternSize; nY++)
162 m_brushPattern[nX*m_brushPatternSize+nY].alpha = fOpacity;
163 }
164
165 void CGAirbrush::setArbitraryPattern()
166 {
167 // öffne Datei
168 ifstream hPattern("32x32.pat");
169
170 // lies Pinsel ein
171 for (unsigned int nX = 0; nX < m_brushPatternSize; nX++)
172 for (unsigned int nY = 0; nY < m_brushPatternSize; nY++)
173 hPattern >> m_brushPattern[nX*m_brushPatternSize+nY].alpha;
174 }
175
176 void CGAirbrush::setColor(GLfloat red, GLfloat green, GLfloat blue)
177 {
178 // ändere alle Farbwerte im Pinsel
179 for (unsigned int nX = 0; nX < m_brushPatternSize; nX++)
180 for (unsigned int nY = 0; nY < m_brushPatternSize; nY++)
181 {
182 m_brushPattern[nX*m_brushPatternSize+nY].r = red;
183 m_brushPattern[nX*m_brushPatternSize+nY].g = green;
184 m_brushPattern[nX*m_brushPatternSize+nY].b = blue;
185 }
186 }
187
188 int main(int argc, char* argv[]) {
189 CGAirbrush airbrush(32);
190 airbrush.start("CGAirbrush, Stephan Brumme, 702544", false);
191 return(0);
192 }
193
194