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 // setze Pinsel auf Bildinhalt an der aktuellen Position
79 glReadPixels(x-m_brushPatternSize/2, y-m_brushPatternSize/2,
80 m_brushPatternSize, m_brushPatternSize,
81 GL_RGBA, GL_FLOAT, m_brushPattern);
82 }
83 }
84
85 void CGAirbrush::onMove(int x, int y)
86 {
87 // lege obere linke Ecke fest,
88 // sodass Mauscursor der Mittelpunkt der gezeichneten Fläche ist
89 glRasterPos2i(x-m_brushPatternSize/2, y-m_brushPatternSize/2);
90 // zeichne Pinsel
91 glDrawPixels(m_brushPatternSize, m_brushPatternSize,
92 GL_RGBA, GL_FLOAT, m_brushPattern);
93
94 // Pipeline abarbeiten
95 glFlush();
96 }
97
98 void CGAirbrush::onKey(unsigned char key) {
99 // Keys
100 switch(key) {
101 // beenden
102 case 'q' : exit(0); break;
103
104 // Farbe setzen
105 case '0' : setColor(1.0, 0.0, 0.0); break;
106 case '1' : setColor(0.0, 1.0, 0.0); break;
107 case '2' : setColor(0.0, 0.0, 1.0); break;
108 case '3' : setColor(1.0, 1.0, 0.0); break;
109 case '4' : setColor(1.0, 0.0, 1.0); break;
110 case '5' : setColor(0.0, 1.0, 1.0); break;
111 case '6' : setColor(1.0, 1.0, 1.0); break;
112 case '7' : setColor(0.0, 0.0, 0.0); break;
113
114 // Buffer löschen (weiss)
115 case 'c' : glClear(GL_COLOR_BUFFER_BIT); glFlush(); break;
116
117 // verschiedene Pinsel setzen
118 case 'r' : setRadialPattern(); break;
119 case 'k' : setConstantPattern(0.5); break;
120 case 'e' : setArbitraryPattern(); break;
121
122 default:
123 cerr << "No action defined for key: " << key << endl;
124 }
125 }
126
127 void CGAirbrush::setRadialPattern()
128 {
129 // Mitte des Pinsels bestimmen
130 float nCenterX = m_brushPatternSize/2;
131 float nCenterY = m_brushPatternSize/2;
132
133 // Durchmesser des runden Pinsels
134 float fMaxDistance = m_brushPatternSize/2;
135
136 for (unsigned int nX = 0; nX < m_brushPatternSize; nX++)
137 for (unsigned int nY = 0; nY < m_brushPatternSize; nY++)
138 {
139 // Abstand zur Pinselmitte
140 float fDistance = sqrt((nCenterX-nX) * (nCenterX-nX) +
141 (nCenterY-nY) * (nCenterY-nY));
142
143 // 100% opak in der Pinselmitte, 0% am Rand
144 float fOpacity = 1 - fDistance/fMaxDistance;
145
146 // verhindere Underflow
147 if (fOpacity < 0)
148 fOpacity = 0;
149 fOpacity *= 0.5;
150
151 // setze Opazität
152 m_brushPattern[nX*m_brushPatternSize+nY].alpha = fOpacity;
153 }
154 }
155
156 void CGAirbrush::setConstantPattern(float fOpacity)
157 {
158 // kompletter Pinsel mit einer Opazität
159 for (unsigned int nX = 0; nX < m_brushPatternSize; nX++)
160 for (unsigned int nY = 0; nY < m_brushPatternSize; nY++)
161 m_brushPattern[nX*m_brushPatternSize+nY].alpha = fOpacity;
162 }
163
164 void CGAirbrush::setArbitraryPattern()
165 {
166 // öffne Datei
167 ifstream hPattern("32x32.pat");
168
169 // lies Pinsel ein
170 for (unsigned int nX = 0; nX < m_brushPatternSize; nX++)
171 for (unsigned int nY = 0; nY < m_brushPatternSize; nY++)
172 hPattern >> m_brushPattern[nX*m_brushPatternSize+nY].alpha;
173 }
174
175 void CGAirbrush::setColor(GLfloat red, GLfloat green, GLfloat blue)
176 {
177 // ändere alle Farbwerte im Pinsel
178 for (unsigned int nX = 0; nX < m_brushPatternSize; nX++)
179 for (unsigned int nY = 0; nY < m_brushPatternSize; nY++)
180 {
181 m_brushPattern[nX*m_brushPatternSize+nY].r = red;
182 m_brushPattern[nX*m_brushPatternSize+nY].g = green;
183 m_brushPattern[nX*m_brushPatternSize+nY].b = blue;
184 }
185 }
186
187 int main(int argc, char* argv[]) {
188 CGAirbrush airbrush(32);
189 airbrush.start("CGAirbrush, Stephan Brumme, 702544", false);
190 return(0);
191 }
192
193
194