Showing
46 changed files
with
6401 additions
and
0 deletions
Makefile
0 → 100755
1 | +CC=gcc | |
2 | +CPP=g++ | |
3 | +MAKE=make | |
4 | +LD=ld | |
5 | + | |
6 | +# CFLAGS=-ggdb | |
7 | +CXXFLAGS= | |
8 | + | |
9 | +LDFLAGS_X11=-L/usr/X11R6/lib -lX11 -lXext | |
10 | +INC_X11=-I/usr/X11R6/include | |
11 | + | |
12 | +# LDFLAGS=$(LDFLAGS_X11) -lefence | |
13 | +LDFLAGS=$(LDFLAGS_X11) | |
14 | +INC=$(INC_X11) | |
15 | + | |
16 | +OBJECTS=gra_app.o dispatcher.o event_source.o rasterize.o | |
17 | +XWIN_OBJ=xwin/canvas_x11.o xwin/canvas_x11_shm.o xwin/disp_x11.o xwin/xclass.o | |
18 | +GEOM_OBJ=geometry/vertex.o geometry/polygon.o geometry/polyeder.o | |
19 | +HELPER_OBJ= | |
20 | +MATH_OBJ=math/sin_cos.o | |
21 | +CANVAS_IMP_OBJ=canvas_imps/canvas_imp_rgb.o | |
22 | + | |
23 | +OBJ=$(OBJECTS) $(GEOM_OBJ) $(HELPER_OBJ) $(MATH_OBJ) $(XWIN_OBJ) | |
24 | +OBJ+=$(CANVAS_IMP_OBJ) | |
25 | + | |
26 | +%.o: %.cpp | |
27 | + $(CPP) $(CFLAGS) $(CXXFLAGS) $(INC) -c $*.cpp | |
28 | + | |
29 | +.PHONY : all geometry helper math xwin canvas_imps geometry_clean helper_clean math_clean xwin_clean canvas_imps_clean clean | |
30 | + | |
31 | +all: engage | |
32 | + | |
33 | +engage: geometry helper math xwin canvas_imps $(OBJECTS) | |
34 | + $(CPP) $(CFLAGS) $(CXXFLAGS) $(INC) $(LDFLAGS) -o $@ $(OBJ) | |
35 | + | |
36 | +geometry: | |
37 | + @cd geometry && $(MAKE) | |
38 | + | |
39 | +helper: | |
40 | + @cd helper && $(MAKE) | |
41 | + | |
42 | +math: | |
43 | + @cd math && $(MAKE) | |
44 | + | |
45 | +xwin: | |
46 | + @cd xwin && $(MAKE) | |
47 | + | |
48 | +canvas_imps: | |
49 | + @cd canvas_imps && $(MAKE) | |
50 | + | |
51 | +geometry_clean: | |
52 | + @cd geometry && $(MAKE) clean | |
53 | + | |
54 | +helper_clean: | |
55 | + @cd helper && $(MAKE) clean | |
56 | + | |
57 | +math_clean:: | |
58 | + @cd math && $(MAKE) clean | |
59 | + | |
60 | +xwin_clean:: | |
61 | + @cd xwin && $(MAKE) clean | |
62 | + | |
63 | +canvas_imps_clean:: | |
64 | + @cd canvas_imps && $(MAKE) clean | |
65 | + | |
66 | +clean: geometry_clean helper_clean math_clean xwin_clean canvas_imps_clean | |
67 | + @rm -f gra_app | |
68 | + @rm -f *.o | ... | ... |
callback.h
0 → 100755
1 | +/** | |
2 | + * \file callback.h | |
3 | + * | |
4 | + * \brief Implementiert callbacks aus Membern und Funktionen. | |
5 | + * | |
6 | + * Enthält alle nötigen Klassen, um sowohl aus Klassenmembern | |
7 | + * als auch aus normalen Funktionen Callbacks zu machen. Das heißt | |
8 | + * das sowohl die Adresse des Objekts als auch die der Methode/Funktion | |
9 | + * gespeichert wird und bei bedarf richtig aufgerufen wird. Es lassen sich | |
10 | + * also Methoden in Arrays oder Listen vorhalten. | |
11 | + * | |
12 | + * \author Georg Steffers <georg@steffers.org> | |
13 | + * | |
14 | + * \date 04.12.2003 | |
15 | + * | |
16 | + * \version ..2001 (Georg Steffers): erste implementation | |
17 | + * \version 2001-2003 (Georg Steffers): diverse Modifikationen | |
18 | + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen | |
19 | + */ | |
20 | + | |
21 | +/* | |
22 | + * Copyright (C)2003 Georg Steffers | |
23 | + * | |
24 | + * This program is free software; you can redistribute it and/or modify | |
25 | + * it under the terms of the GNU General Public License as published by | |
26 | + * the Free Software Foundation; either version 2 of the License, or | |
27 | + * (at your option) any later version. | |
28 | + * | |
29 | + * This program is distributed in the hope that it will be useful, | |
30 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
31 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
32 | + * GNU General Public License for more details. | |
33 | + * | |
34 | + * You should have received a copy of the GNU General Public License | |
35 | + * along with this program; if not, write to the Free Software | |
36 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
37 | + */ | |
38 | + | |
39 | +using namespace std; | |
40 | + | |
41 | +#include <cstring> | |
42 | + | |
43 | +// enthaelt die adressen unserer callbackfunktion bzw. der Klasse und des | |
44 | +// Members die wir aufrufen moechten....(dies hier ist die Basisklasse | |
45 | +// diese wird gleich spezifiziert | |
46 | +class FunctorBase { | |
47 | + public: | |
48 | + // dient wohl nur dazu die groesse eines Member-Pointers zu bestimmen. | |
49 | + typedef void (FunctorBase::*t_MemberFunc)(); | |
50 | + | |
51 | + // hierdrin wird der Quatsch gespeichert.... | |
52 | + union { | |
53 | + const void* Callback; | |
54 | + char CallbackMember[sizeof(t_MemberFunc)]; | |
55 | + }; | |
56 | + void* Class; | |
57 | + | |
58 | + // Konstruktoren | |
59 | + | |
60 | + // wichtig, wenn ein Object der Klasse FunctorBase oder einer | |
61 | + // abgeleiteten Klasse kopiert werden soll. | |
62 | + FunctorBase() : Class(0), Callback(0) {} | |
63 | + | |
64 | + // Hiermit wird eine FunctorBase angelegt. | |
65 | + FunctorBase(const void* _Class, const void* _Callback, size_t Size) { | |
66 | + if(_Class) { //Mit nem Member initialisiert | |
67 | + Class=(void*)_Class; | |
68 | + memcpy(CallbackMember, _Callback, Size); | |
69 | + } | |
70 | + else { // Mit ner normalen Funktion initialisiert | |
71 | + Class=NULL; | |
72 | + Callback=_Callback; | |
73 | + } | |
74 | + } | |
75 | +}; | |
76 | + | |
77 | +// dies wird nu ein Functor, der einen Callback aufnehmen kann, der einen | |
78 | +// beliebiegen Parameter hat und void zurueckgibt. | |
79 | +template <class P1, class P2> | |
80 | +class callback : protected FunctorBase { | |
81 | + // wir machen einen protected Konstruktor fuer die Klasse, damit nur | |
82 | + // abgeleitete Klassen einen callback erzeugen koennen. Diese mussen dann | |
83 | + // sicherstellen, das Funktor1 nur mit Methoden oder Funktionen erzeugt | |
84 | + // wird, die genau einen Parameter akzeptieren und void zurueckliefern. | |
85 | + // Der Teil RestoreTypeAndCall(_RTAC) initialisiert RestoreTypeAndCall | |
86 | + // auf _RTAC. | |
87 | + protected: | |
88 | + typedef void (*t_RestoreTypeAndCall)(const FunctorBase&, P1, P2); | |
89 | + callback(t_RestoreTypeAndCall _RTAC, const void *_Class, | |
90 | + const void *_Callback, size_t _Size) : | |
91 | + FunctorBase (_Class, _Callback, _Size), RestoreTypeAndCall(_RTAC) {} | |
92 | + | |
93 | + private: | |
94 | + t_RestoreTypeAndCall RestoreTypeAndCall; | |
95 | + | |
96 | + public: | |
97 | + callback() {} | |
98 | + void operator() (P1 p1, P2 p2) const { // ueber den koennen wir nachher | |
99 | + // den Callback aufrufen. | |
100 | + if(Class) // Wir haben nen Member... | |
101 | + RestoreTypeAndCall(*this, p1, p2); | |
102 | + else // normale Funktion, koennen wir direkt aufrufen... | |
103 | + ((void (*)(P1,P2))Callback)(p1, p2); | |
104 | + } | |
105 | + const void* getcb(void) { return Callback; } | |
106 | + | |
107 | + int is_null(void) { | |
108 | + if(Class != 0 || Callback != 0) | |
109 | + return false; | |
110 | + return true; | |
111 | + } | |
112 | +}; | |
113 | + | |
114 | +// beim speichern der Klasse als void* ist uns der Typ der Klasse und | |
115 | +// auch das eigentliche Object verloren gegangen. | |
116 | +// Deshalb kommt hier jetzt ne Klasse, die den Typ kennt und | |
117 | +// bei bedarf (jedesmal wenn eine Memberfunktion als Callback aufgerufen | |
118 | +// werden soll) zurueckwandelt. | |
119 | +// Ein template: Callee ist jede beliebige Klasse und Func jeder Member | |
120 | +template <class Callee, class Func, class P1, class P2> | |
121 | +class MemberTranslator : public callback<P1,P2> { | |
122 | + public: | |
123 | + MemberTranslator(Callee &Class, const Func &MemberFunction) : | |
124 | + callback<P1,P2>(RestoreTypeAndCall, &Class, &MemberFunction, | |
125 | + sizeof(Func)) {} | |
126 | + | |
127 | + static void RestoreTypeAndCall(const FunctorBase &ftor, P1 p1, P2 p2) { | |
128 | + Callee* Who = (Callee*)(ftor.Class); | |
129 | + Func TheMemberFunction=*(Func*)(void*)(ftor.CallbackMember); | |
130 | + (Who->*TheMemberFunction)(p1, p2); | |
131 | + } | |
132 | +}; | |
133 | + | |
134 | +// Da der Konstruktor von callback protected ist brauchen wir noch einen | |
135 | +// Translator um aus normalen Funktionen Callbacks zu machen. | |
136 | +template <class P1, class P2> | |
137 | +class FunctionTranslator : public callback<P1,P2> { | |
138 | + public: | |
139 | + FunctionTranslator(void *regularFunc) : | |
140 | + callback<P1,P2>(NULL,NULL,regularFunc,0) {} | |
141 | +}; | |
142 | + | |
143 | +// und jetzt noch 2 makeCallback Templates um das erstellen von Callbacks zu | |
144 | +// erleichtern. | |
145 | +template <class Callee, class P1, class P2> | |
146 | +callback<P1, P2> mk_callback(Callee &Class, void (Callee::*Member)(P1, P2)) { | |
147 | + return MemberTranslator<Callee,void (Callee::*)(P1,P2),P1,P2>(Class, | |
148 | + Member); | |
149 | +} | |
150 | + | |
151 | +template <class P1, class P2> | |
152 | +callback<P1, P2> mk_callback(void (*theFunc)(P1, P2)) { | |
153 | + return FunctionTranslator<P1, P2>((void*)theFunc); | |
154 | +} | ... | ... |
canvas.h
0 → 100755
1 | +/** | |
2 | + * \file canvas.h | |
3 | + * | |
4 | + * \brief Ein canvas ist etwas worauf gezeichnet werden kann. | |
5 | + * | |
6 | + * <p>Diese beschreibt einen Speicherbereich in dem gezeichnet werden kann | |
7 | + * und Methoden zum "blitten" also dem darstellen dieses Speicherbereichs | |
8 | + * auf dem Bildschirm. Außerdem werden Funktionen zur Farbverwaltung zur | |
9 | + * verfügung gestellt.</p> | |
10 | + * <p>canvas ist von event-source abgeleitet, da es events erzeugen kann | |
11 | + * wie z.B. ein redraw-request u.ä.</p> | |
12 | + * | |
13 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
14 | + * | |
15 | + * \date 04.12.2003 | |
16 | + * | |
17 | + * \version ..2002 [gs]: erste funktionierende Implementation | |
18 | + * \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen | |
19 | + * \version 19.12.2003 [gs]: draw_text hinzugefügt, das ist hier eigentlich | |
20 | + * nicht ganz richtig, aber damit ich nicht meinen | |
21 | + * eigenen Font-Renderer schreiben muss um debug | |
22 | + * Ausgaben zu machen und dafüe die | |
23 | + * X11-Funktionen nutzen kann, ist der hier. | |
24 | + */ | |
25 | + | |
26 | +/* | |
27 | + * Copyright (C)2003 Georg Steffers | |
28 | + * | |
29 | + * This program is free software; you can redistribute it and/or modify | |
30 | + * it under the terms of the GNU General Public License as published by | |
31 | + * the Free Software Foundation; either version 2 of the License, or | |
32 | + * (at your option) any later version. | |
33 | + * | |
34 | + * This program is distributed in the hope that it will be useful, | |
35 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
36 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
37 | + * GNU General Public License for more details. | |
38 | + * | |
39 | + * You should have received a copy of the GNU General Public License | |
40 | + * along with this program; if not, write to the Free Software | |
41 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
42 | + */ | |
43 | + | |
44 | +#ifndef __canvas_h__ | |
45 | +#define __canvas_h__ | |
46 | + | |
47 | +#include "canvas_imps/canvas_imp.h" | |
48 | +#include "event_source.h" | |
49 | +#include "rasterize.h" | |
50 | +#include <cstdio> | |
51 | + | |
52 | +typedef enum blit_status {NO_BLIT, BLIT, DRAW}; | |
53 | + | |
54 | +class canvas : public event_source { | |
55 | + protected: | |
56 | + unsigned x_size, y_size; | |
57 | + canvas_imp* sinfo; | |
58 | + | |
59 | + blit_status blit; | |
60 | + unsigned long draw_color; | |
61 | + | |
62 | + public: | |
63 | + virtual void draw_text(int x, int y, char* text, int length) = 0; | |
64 | + canvas(unsigned xs, unsigned ys) : event_source() { | |
65 | + x_size=xs; | |
66 | + y_size=ys; | |
67 | + | |
68 | + sinfo=NULL; | |
69 | + blit=NO_BLIT; | |
70 | + } | |
71 | + virtual ~canvas() { | |
72 | + close_screen(); | |
73 | + } | |
74 | + | |
75 | + virtual rasterizer* create_rasterizer(void) = 0; | |
76 | + virtual void refresh_palette(void) {}; | |
77 | + virtual void open_screen(void)=0; | |
78 | + virtual void close_screen(void) {}; | |
79 | + virtual void blit_screen(void)=0; | |
80 | + blit_status& blitting(void) { return blit; } | |
81 | + unsigned long get_color(unsigned red, unsigned green, unsigned blue) { | |
82 | + return sinfo->ext_to_native(red, green, blue); | |
83 | + } | |
84 | + void set_color(unsigned long col) { draw_color=col; } | |
85 | + void set_color(unsigned red, unsigned green, unsigned blue) { | |
86 | + draw_color=sinfo->ext_to_native(red, green, blue); | |
87 | + } | |
88 | + void light_native(unsigned long* col, unsigned intens) { | |
89 | + sinfo->light_native(col, intens); | |
90 | + } | |
91 | + | |
92 | + char bpp(void) { return sinfo->bytes_per_pixel; } | |
93 | + | |
94 | + virtual unsigned get_x_size(void) const { return x_size; } | |
95 | + virtual unsigned get_y_size(void) const { return y_size; } | |
96 | +}; | |
97 | + | |
98 | +class canvas_factory { | |
99 | + public: | |
100 | + virtual canvas* create(unsigned xs, unsigned ys) const=0; | |
101 | +}; | |
102 | + | |
103 | +#endif // __canvas_h__ | ... | ... |
canvas_imps/Makefile
0 → 100755
canvas_imps/canvas_imp.h
0 → 100755
1 | +/** | |
2 | + * \file canvas_imp.h | |
3 | + * | |
4 | + * \brief ein Prototyp einer Canvas Implementation | |
5 | + * | |
6 | + * Die Canvas Implementation dient Hauptsächlich dazu color, | |
7 | + * light und fogtables passend zum canvas zur verfügung zu stellen. | |
8 | + * Es werden auch Methoden bereit gestellt, über die man externe | |
9 | + * Farbdefinitionen (z.B. für jeweils rot, grün und blau | |
10 | + * Werte zwischen 0 und 255) in das von dem canvas benutzte Farbschema | |
11 | + * zu convertieren. | |
12 | + * | |
13 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
14 | + * | |
15 | + * \date 04.12.2003 | |
16 | + * | |
17 | + * \version ..2002 [gs]: erste funktionierende Implementation | |
18 | + * \version 22.12.2003 [gs]: <ul><li> | |
19 | + * beginn der Dokumentation via doxygen | |
20 | + * </li><li> | |
21 | + * Light und Fogtables hinzugefügt | |
22 | + * </li></ul> | |
23 | + */ | |
24 | + | |
25 | +/* | |
26 | + * Copyright (C)2003 Georg Steffers | |
27 | + * | |
28 | + * This program is free software; you can redistribute it and/or modify | |
29 | + * it under the terms of the GNU General Public License as published by | |
30 | + * the Free Software Foundation; either version 2 of the License, or | |
31 | + * (at your option) any later version. | |
32 | + * | |
33 | + * This program is distributed in the hope that it will be useful, | |
34 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
35 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
36 | + * GNU General Public License for more details. | |
37 | + * | |
38 | + * You should have received a copy of the GNU General Public License | |
39 | + * along with this program; if not, write to the Free Software | |
40 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
41 | + */ | |
42 | + | |
43 | +#ifndef __canvas_imp_h__ | |
44 | +#define __canvas_imp_h__ | |
45 | + | |
46 | +#define MAX_LIGHT_LEVELS 255 | |
47 | +#define NUM_LIGHT_LEVELS (MAX_LIGHT_LEVELS+1) | |
48 | + | |
49 | +#define MAX_FOG_LEVELS 255 | |
50 | +#define NUM_FOG_LEVELS (MAX_FOG_LEVELS + 1) | |
51 | + | |
52 | +class canvas; | |
53 | +class rasterizer; | |
54 | + | |
55 | +class canvas_imp { | |
56 | + friend class canvas; | |
57 | + friend class rasterizer; | |
58 | + | |
59 | + protected: | |
60 | + unsigned ext_max_red; | |
61 | + unsigned ext_max_green; | |
62 | + unsigned ext_max_blue; | |
63 | + | |
64 | + virtual void compute_light_table(void)=0; | |
65 | + virtual void compute_fog_table(void)=0; | |
66 | + | |
67 | + public: | |
68 | + virtual unsigned long ext_to_native(unsigned red, | |
69 | + unsigned green, | |
70 | + unsigned blue)=0; | |
71 | + virtual ~canvas_imp() {}; | |
72 | + | |
73 | + // virtual void light_to_native(unsigned char* pcolor, | |
74 | + // int intensity)=0; | |
75 | + // virtual void fog_to_native(unsigned char* pcolor, | |
76 | + // int intensity)=0; | |
77 | + | |
78 | + virtual void set_color(unsigned long col) {}; | |
79 | + | |
80 | + virtual void light_native(unsigned long* col, unsigned intense) = 0; | |
81 | + | |
82 | + unsigned char* p_screenbuf; | |
83 | + char bytes_per_pixel; | |
84 | +}; | |
85 | + | |
86 | +#endif // __canvas_imp_h__ | ... | ... |
canvas_imps/canvas_imp_rgb.cpp
0 → 100755
1 | +#include "canvas_imp_rgb.h" | |
2 | +#include <cstdio> | |
3 | + | |
4 | +void canvas_imp_rgb::compute_color_resolution(void) { | |
5 | + for(unsigned rgb=red; rgb<=blue; rgb++) { | |
6 | + unsigned mask_tmp=col_mask[rgb]; | |
7 | + | |
8 | + for(col_shift[rgb]=0; (mask_tmp & 0x01) == 0; col_shift[rgb]++) | |
9 | + mask_tmp>>=1; | |
10 | + for(col_max[rgb]=1; mask_tmp & 0x01 == 1; col_max[rgb]*=2) | |
11 | + mask_tmp>>=1; | |
12 | + col_max[rgb]--; | |
13 | + } | |
14 | +} | |
15 | + | |
16 | +void canvas_imp_rgb::compute_light_table(void) { | |
17 | + for(unsigned rgb=red; rgb<=blue; rgb++) | |
18 | + for(unsigned c=0; c<=col_max[rgb]; c++) | |
19 | + for(unsigned i=0; i<NUM_LIGHT_LEVELS; i++) | |
20 | + light_table[rgb][c*NUM_LIGHT_LEVELS+i]=c*i/MAX_LIGHT_LEVELS; | |
21 | +} | |
22 | + | |
23 | +void canvas_imp_rgb::compute_fog_table(void) { | |
24 | + for(unsigned rgb=red; rgb<=blue; rgb++) | |
25 | + for(unsigned c=0; c<=col_max[rgb]; c++) | |
26 | + for(unsigned i=0; i<NUM_FOG_LEVELS; i++) | |
27 | + fog_table[rgb][c*NUM_FOG_LEVELS+i]= | |
28 | + c+(unsigned)(((float)i/MAX_FOG_LEVELS)*(col_max[rgb]-c)); | |
29 | +} | |
30 | + | |
31 | +canvas_imp_rgb::canvas_imp_rgb(unsigned long red_mask, | |
32 | + unsigned long green_mask, | |
33 | + unsigned long blue_mask, | |
34 | + char bytes_per_pixel, | |
35 | + char bytes_per_rgb) { | |
36 | + this->col_mask[red]=red_mask; | |
37 | + this->col_mask[green]=green_mask; | |
38 | + this->col_mask[blue]=blue_mask; | |
39 | + | |
40 | + this->bytes_per_pixel=bytes_per_pixel; | |
41 | + this->bytes_per_rgb=bytes_per_rgb; | |
42 | + | |
43 | + ext_max_red=255; | |
44 | + ext_max_green=255; | |
45 | + ext_max_blue=255; | |
46 | + | |
47 | + compute_color_resolution(); | |
48 | + | |
49 | + light_table[red]=new unsigned[(col_max[red]+1)*NUM_LIGHT_LEVELS]; | |
50 | + light_table[green]=new unsigned[(col_max[green]+1)*NUM_LIGHT_LEVELS]; | |
51 | + light_table[blue]=new unsigned[(col_max[blue]+1)*NUM_LIGHT_LEVELS]; | |
52 | + fog_table[red]=new unsigned[(col_max[red]+1)*NUM_FOG_LEVELS]; | |
53 | + fog_table[green]=new unsigned[(col_max[green]+1)*NUM_FOG_LEVELS]; | |
54 | + fog_table[blue]=new unsigned[(col_max[blue]+1)*NUM_FOG_LEVELS]; | |
55 | + | |
56 | + compute_light_table(); | |
57 | + compute_fog_table(); | |
58 | +} | |
59 | + | |
60 | +unsigned long canvas_imp_rgb::ext_to_native(unsigned red, | |
61 | + unsigned green, | |
62 | + unsigned blue) { | |
63 | + unsigned long red_rescaled=red * col_max[this->red] / ext_max_red; | |
64 | + unsigned long green_rescaled=green * col_max[this->green] / ext_max_green; | |
65 | + unsigned long blue_rescaled=blue * col_max[this->blue] / ext_max_blue; | |
66 | + | |
67 | + return (red_rescaled << col_shift[this->red]) | | |
68 | + (green_rescaled << col_shift[this->green]) | | |
69 | + (blue_rescaled << col_shift[this->blue]); | |
70 | +} | |
71 | + | |
72 | +void canvas_imp_rgb::light_native(unsigned long* col, unsigned intense) { | |
73 | + unsigned char* c2=(unsigned char*)col; | |
74 | + | |
75 | + unsigned long color=0; | |
76 | + unsigned long color_shift=0; | |
77 | + | |
78 | + for(register int p=0; p<bytes_per_rgb; p++) { | |
79 | + color += (*c2++) << color_shift; | |
80 | + color_shift += 8; // 8=BITS_PER_BYTE | |
81 | + } | |
82 | + | |
83 | + // mögliche restliche bytes zwischen bytes_per_rgb und | |
84 | + // bytes_per_pixel überspringen (warum muss ich nochmal | |
85 | + // rausfinden. | |
86 | + for(register int p=bytes_per_rgb; p<bytes_per_pixel; p++) | |
87 | + c2++; | |
88 | + | |
89 | + unsigned long r=(color&col_mask[red]) >> col_shift[red]; | |
90 | + unsigned long g=(color&col_mask[green]) >> col_shift[green]; | |
91 | + unsigned long b=(color&col_mask[blue]) >> col_shift[blue]; | |
92 | + | |
93 | + color=(light_table[red][r*NUM_LIGHT_LEVELS+intense] << | |
94 | + col_shift[red]) | | |
95 | + (light_table[green][g*NUM_LIGHT_LEVELS+intense] << | |
96 | + col_shift[green]) | | |
97 | + (light_table[blue][b*NUM_LIGHT_LEVELS+intense] << | |
98 | + col_shift[blue]); | |
99 | + | |
100 | + { | |
101 | + register int i; | |
102 | + unsigned long mask = 255; | |
103 | + char shift = 0; | |
104 | + | |
105 | + for(c2-=bytes_per_pixel, i=0; i<bytes_per_pixel; i++) { | |
106 | + *c2 = (color & mask) >> shift; | |
107 | + c2++; | |
108 | + mask <<= 8; | |
109 | + shift += 8; | |
110 | + } | |
111 | + } | |
112 | +} | ... | ... |
canvas_imps/canvas_imp_rgb.h
0 → 100755
1 | +/** | |
2 | + * \file canvas_imp_rgb.h | |
3 | + * | |
4 | + * \brief eine Canvas Implementation für ein rgb Canvas. | |
5 | + * | |
6 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
7 | + * | |
8 | + * \date 04.12.2003 | |
9 | + * | |
10 | + * \version ..2002 [gs]: erste funktionierende Implementation | |
11 | + * \version 22.12.2003 [gs]: <ul><li> | |
12 | + * beginn der Dokumentation via doxygen | |
13 | + * </li><li> | |
14 | + * Light und Fogtables hinzugefügt | |
15 | + * eine Methode für perPixel Shading | |
16 | + * eingebaut, (soll heissen ein gesetztes | |
17 | + * Pixel kann nachtr&aum;glich noch | |
18 | + * geshaded werden. | |
19 | + * </li></ul> | |
20 | + */ | |
21 | + | |
22 | +/* | |
23 | + * Copyright (C)2003 Georg Steffers | |
24 | + * | |
25 | + * This program is free software; you can redistribute it and/or modify | |
26 | + * it under the terms of the GNU General Public License as published by | |
27 | + * the Free Software Foundation; either version 2 of the License, or | |
28 | + * (at your option) any later version. | |
29 | + * | |
30 | + * This program is distributed in the hope that it will be useful, | |
31 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
32 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
33 | + * GNU General Public License for more details. | |
34 | + * | |
35 | + * You should have received a copy of the GNU General Public License | |
36 | + * along with this program; if not, write to the Free Software | |
37 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
38 | + */ | |
39 | + | |
40 | +#ifndef __canvas_imp_rgb_h__ | |
41 | +#define __canvas_imp_rgb_h__ | |
42 | + | |
43 | +#include "canvas_imp.h" | |
44 | + | |
45 | +class canvas_imp_rgb : public canvas_imp { | |
46 | + private: | |
47 | + enum rgb_e_t { red=0, green, blue }; | |
48 | + | |
49 | + unsigned* light_table[3]; | |
50 | + unsigned* fog_table[3]; | |
51 | + | |
52 | + char bytes_per_rgb; | |
53 | + | |
54 | + unsigned long col_mask[3]; | |
55 | + unsigned col_shift[3]; | |
56 | + unsigned col_max[3]; | |
57 | + | |
58 | + void compute_color_resolution(void); | |
59 | + void compute_light_table(void); | |
60 | + void compute_fog_table(void); | |
61 | + | |
62 | + public: | |
63 | + canvas_imp_rgb(unsigned long, unsigned long, unsigned long, | |
64 | + char, char); | |
65 | + virtual ~canvas_imp_rgb() {} | |
66 | + | |
67 | + unsigned long ext_to_native(unsigned, unsigned, unsigned); | |
68 | + | |
69 | + void light_native(unsigned long* col, unsigned intense); | |
70 | + | |
71 | + // und wieder fehlt alles für light und fog. | |
72 | +}; | |
73 | + | |
74 | +#endif // __canvas_imp_rgb_h__ | ... | ... |
debug.20040104
0 → 100755
This diff could not be displayed because it is too large.
dispatcher.cpp
0 → 100755
1 | +/** | |
2 | + * \file dispatcher.cpp | |
3 | + * | |
4 | + * \brief Stadardimplementation der virtuellen Member des Dispatcher-Managers. | |
5 | + * | |
6 | + * Für eine detailierte Beschreibung von Dispatcher und | |
7 | + * Dispatcher-Manager schauen Sie bitte unter \ref dispatcher.h | |
8 | + * | |
9 | + * \author Georg Steffers <georg@steffers.org> | |
10 | + * | |
11 | + * \date 04.12.2003 | |
12 | + * | |
13 | + * \version ..2002 (Georg Steffers): erste funktionierende Implementation | |
14 | + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen | |
15 | + */ | |
16 | + | |
17 | +/* | |
18 | + * Copyright (C)2003 Georg Steffers | |
19 | + * | |
20 | + * This program is free software; you can redistribute it and/or modify | |
21 | + * it under the terms of the GNU General Public License as published by | |
22 | + * the Free Software Foundation; either version 2 of the License, or | |
23 | + * (at your option) any later version. | |
24 | + * | |
25 | + * This program is distributed in the hope that it will be useful, | |
26 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | + * GNU General Public License for more details. | |
29 | + * | |
30 | + * You should have received a copy of the GNU General Public License | |
31 | + * along with this program; if not, write to the Free Software | |
32 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
33 | + */ | |
34 | + | |
35 | +using namespace std; | |
36 | + | |
37 | +#include <cstring> | |
38 | + | |
39 | +#include "dispatcher.h" | |
40 | + | |
41 | +disp_manager::disp_manager(dispatcher* d) { | |
42 | + disp_count=0; | |
43 | + disp=NULL; | |
44 | + | |
45 | + if(d!=NULL) { | |
46 | + disp=new dispatcher*[1]; | |
47 | + disp[0]=d; | |
48 | + disp_count++; | |
49 | + } | |
50 | +} | |
51 | + | |
52 | +dispatcher*& disp_manager::operator[](unsigned index) { | |
53 | + if(index+1>disp_count) { | |
54 | + dispatcher** disp_tmp=new dispatcher*[index+1]; | |
55 | + memcpy(disp_tmp, disp, sizeof(dispatcher*)*disp_count); | |
56 | + | |
57 | + delete [] disp; | |
58 | + disp=disp_tmp; | |
59 | + disp_count=index+1; | |
60 | + } | |
61 | + | |
62 | + return disp[index]; | |
63 | +} | |
64 | + | |
65 | +void disp_manager::start(void) { | |
66 | + run=true; | |
67 | + | |
68 | + while(run) | |
69 | + do_once(); | |
70 | +} | |
71 | + | |
72 | +void disp_manager::do_once(void) { | |
73 | + for(int i=0; i<disp_count; i++) | |
74 | + if(disp[i]->e_src) | |
75 | + disp[i]->go(); | |
76 | +} | ... | ... |
dispatcher.h
0 → 100755
1 | +/** | |
2 | + * \file dispatcher.h | |
3 | + * | |
4 | + * \brief Deklaration eines abstrakten Event-Dispatchers und des | |
5 | + * Dispatcher-Managers. | |
6 | + * | |
7 | + * <p>In einem Dispatcher werden callbacks eingetragen, die bei bestimmten | |
8 | + * Events aufgerufen werden sollen, Der Dispatcher kümmert sich dann | |
9 | + * darum das diese zum richtigen Zeitpunk und für das richtige Event | |
10 | + * aufgerufen werden. Der Dispatcher wird mit der Event-Quelle initialisiert, | |
11 | + * die die Events erzeugt. Die hier definierte Dispatcher Klasse ist abstrakt | |
12 | + * und muß noch in einer abgeleiteten Klasse konkretisiert werden. So | |
13 | + * kann ich diverse Dispatcher erzeugen, die intern unterschiedlich arbeiten, | |
14 | + * im Moment existiert die X11 implementation eines Dispatches.</p> | |
15 | + * <p>Im Dispatcher Manager werden die einzelnen Dispatcher registriert. Er | |
16 | + * sorgt dann dann standartmäßig dafür, das die einzelnen | |
17 | + * Dispatcher immer wieder nacheinenader in der Reihenfolge in der sie dem | |
18 | + * Manager hinzugefügt wurden ausgeführt werden und so alle Events immer | |
19 | + * wieder gecheckt werden. Dieses verhalten kann man aber ändern indem | |
20 | + * man einen neuen Manager von diesem ableitet und die virtuellen Methoden | |
21 | + * entsprechend überschreibt.</p> | |
22 | + * | |
23 | + * \author Georg Steffers <georg@steffers.org> | |
24 | + * | |
25 | + * \date 04.12.2003 | |
26 | + * | |
27 | + * \version ..2002 (Georg Steffers): erste funktionierende Implementation | |
28 | + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen | |
29 | + */ | |
30 | + | |
31 | +/* | |
32 | + * Copyright (C)2003 Georg Steffers | |
33 | + * | |
34 | + * This program is free software; you can redistribute it and/or modify | |
35 | + * it under the terms of the GNU General Public License as published by | |
36 | + * the Free Software Foundation; either version 2 of the License, or | |
37 | + * (at your option) any later version. | |
38 | + * | |
39 | + * This program is distributed in the hope that it will be useful, | |
40 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
41 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
42 | + * GNU General Public License for more details. | |
43 | + * | |
44 | + * You should have received a copy of the GNU General Public License | |
45 | + * along with this program; if not, write to the Free Software | |
46 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
47 | + */ | |
48 | + | |
49 | +#ifndef __dispatcher_h__ | |
50 | +#define __dispatcher_h__ | |
51 | + | |
52 | +#include "callback.h" | |
53 | +#include "event_source.h" | |
54 | + | |
55 | +class disp_manager; | |
56 | +class dispatcher { | |
57 | + friend class disp_manager; | |
58 | + | |
59 | + protected: | |
60 | + callback<event_source*,void*> cb[MaxEvent]; | |
61 | + event_source* e_src; | |
62 | + int halt_f; | |
63 | + | |
64 | + public: | |
65 | + dispatcher(event_source* es=NULL) { | |
66 | + e_src=es; | |
67 | + halt_f=false; | |
68 | + } | |
69 | + virtual ~dispatcher() {} | |
70 | + | |
71 | + void register_callback(event e, callback<event_source*, void*> _cb) { | |
72 | + if(e_src) | |
73 | + cb[e]=_cb; | |
74 | + } | |
75 | + | |
76 | + virtual void go(void)=0; | |
77 | + virtual void trigger_event(event)=0; | |
78 | + void halt(void) { halt_f=true; } | |
79 | + void cont(void) { halt_f=false; } | |
80 | +}; | |
81 | + | |
82 | +// Da ich u.U. mehrere Eventquellen in einem Programm habe brauche | |
83 | +// ich eine Klasse die die verschiedenen Dispatcher-Klassen kontrolliert | |
84 | +// nacheinander aufruft. | |
85 | +class disp_manager { | |
86 | + private: | |
87 | + dispatcher** disp; | |
88 | + unsigned disp_count; | |
89 | + unsigned run; | |
90 | + | |
91 | + public: | |
92 | + disp_manager(dispatcher* = NULL); | |
93 | + ~disp_manager() { | |
94 | + delete [] disp; | |
95 | + } | |
96 | + | |
97 | + dispatcher*& operator[](unsigned index); | |
98 | + | |
99 | + unsigned count(void) { return disp_count; } | |
100 | + virtual void start(void); | |
101 | + virtual void stop(event_source*, void*) { | |
102 | + run=false; | |
103 | + } | |
104 | + virtual void do_once(void); | |
105 | +}; | |
106 | + | |
107 | +class dispatcher_factory { | |
108 | + public: | |
109 | + virtual dispatcher* create(event_source* es) const=0; | |
110 | +}; | |
111 | + | |
112 | +#endif // __dispatcher_h__ | ... | ... |
event_source.cpp
0 → 100755
1 | +/** | |
2 | + * \file event_source.cpp | |
3 | + * | |
4 | + * \brief definition und initialisierung von max_id | |
5 | + * | |
6 | + * Für eine detailierte Beschreibung von event_source | |
7 | + * schauen Sie bitte unter \ref event_source.h | |
8 | + * | |
9 | + * \author Georg Steffers <georg@steffers.org> | |
10 | + * | |
11 | + * \date 04.12.2003 | |
12 | + * | |
13 | + * \version ..2002 (Georg Steffers): erste funktionierende Implementation | |
14 | + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen | |
15 | + */ | |
16 | + | |
17 | +/* | |
18 | + * Copyright (C)2003 Georg Steffers | |
19 | + * | |
20 | + * This program is free software; you can redistribute it and/or modify | |
21 | + * it under the terms of the GNU General Public License as published by | |
22 | + * the Free Software Foundation; either version 2 of the License, or | |
23 | + * (at your option) any later version. | |
24 | + * | |
25 | + * This program is distributed in the hope that it will be useful, | |
26 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | + * GNU General Public License for more details. | |
29 | + * | |
30 | + * You should have received a copy of the GNU General Public License | |
31 | + * along with this program; if not, write to the Free Software | |
32 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
33 | + */ | |
34 | + | |
35 | +#include "event_source.h" | |
36 | + | |
37 | +unsigned event_source::max_id=0; | ... | ... |
event_source.h
0 → 100755
1 | +/** | |
2 | + * \file event_source.h | |
3 | + * | |
4 | + * \brief Interface für Events generierende Klassen | |
5 | + * | |
6 | + * Alle Klassen die Events erzeugen wollen müssen von diesem | |
7 | + * Interface abgeleitet werden, damit man einen Dispatcher fü:r Sie | |
8 | + * erzeugen kann. | |
9 | + * | |
10 | + * \author Georg Steffers <georg@steffers.org> | |
11 | + * | |
12 | + * \date 04.12.2003 | |
13 | + * | |
14 | + * \version ..2002 (Georg Steffers): erste funktionierende Implementation | |
15 | + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen | |
16 | + */ | |
17 | + | |
18 | +/* | |
19 | + * Copyright (C)2003 Georg Steffers | |
20 | + * | |
21 | + * This program is free software; you can redistribute it and/or modify | |
22 | + * it under the terms of the GNU General Public License as published by | |
23 | + * the Free Software Foundation; either version 2 of the License, or | |
24 | + * (at your option) any later version. | |
25 | + * | |
26 | + * This program is distributed in the hope that it will be useful, | |
27 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
28 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
29 | + * GNU General Public License for more details. | |
30 | + * | |
31 | + * You should have received a copy of the GNU General Public License | |
32 | + * along with this program; if not, write to the Free Software | |
33 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
34 | + */ | |
35 | + | |
36 | +#ifndef __event_source_h__ | |
37 | +#define __event_source_h__ | |
38 | + | |
39 | +class event_source { | |
40 | + private: | |
41 | + static unsigned max_id; | |
42 | + unsigned id; | |
43 | + | |
44 | + public: | |
45 | + event_source() { | |
46 | + id=max_id++; | |
47 | + } | |
48 | +}; | |
49 | + | |
50 | +typedef enum event {Key, Update, Draw, Idle, Stop, MaxEvent}; | |
51 | + | |
52 | +#endif // __event_source_h__ | ... | ... |
factory.h
0 → 100755
1 | +/** | |
2 | + * \file factory.h | |
3 | + * | |
4 | + * \brief erzeugt auf Anfrage passende Objekte. | |
5 | + * | |
6 | + * \author Georg Steffers <georg@steffers.org> | |
7 | + * | |
8 | + * \date 04.12.2003 | |
9 | + * | |
10 | + * \version ..2002 (Georg Steffers): erste funktionierende Implementation | |
11 | + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen | |
12 | + */ | |
13 | + | |
14 | +/* | |
15 | + * Copyright (C)2003 Georg Steffers | |
16 | + * | |
17 | + * This program is free software; you can redistribute it and/or modify | |
18 | + * it under the terms of the GNU General Public License as published by | |
19 | + * the Free Software Foundation; either version 2 of the License, or | |
20 | + * (at your option) any later version. | |
21 | + * | |
22 | + * This program is distributed in the hope that it will be useful, | |
23 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | + * GNU General Public License for more details. | |
26 | + * | |
27 | + * You should have received a copy of the GNU General Public License | |
28 | + * along with this program; if not, write to the Free Software | |
29 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
30 | + */ | |
31 | + | |
32 | +#ifndef __factory_h__ | |
33 | +#define __factory_h__ | |
34 | + | |
35 | +#include "xwin/disp_x11.h" | |
36 | +#include "xwin/canvas_x11_shm.h" | |
37 | +#include "xwin/canvas_x11.h" | |
38 | +#include "canvas_imps/canvas_imp_rgb.h" | |
39 | +#include "rasterize.h" | |
40 | + | |
41 | +class factory_manager { | |
42 | + public: | |
43 | + canvas_factory* canvas_f; | |
44 | + dispatcher_factory* dispatcher_f; | |
45 | + //rasterizer_factory* rasterizer_f; | |
46 | + | |
47 | + factory_manager() : canvas_f(new canvas_x11_shm_factory), | |
48 | + dispatcher_f(new disp_x11_factory) {} | |
49 | + virtual ~factory_manager() { | |
50 | + delete canvas_f; | |
51 | + delete dispatcher_f; | |
52 | + }; | |
53 | +}; | |
54 | + | |
55 | +#endif // __factory_h__ | ... | ... |
geometry/.Makefile.swp
0 → 100755
No preview for this file type
geometry/.text.c.swp
0 → 100755
No preview for this file type
geometry/Makefile
0 → 100755
1 | +CC=gcc | |
2 | +CPP=g++ | |
3 | +#CFLAGS=-ggdb | |
4 | +CXXFLAGS= | |
5 | +MAKE=make | |
6 | + | |
7 | +OBJECTS=vertex.o polygon.o polyeder.o | |
8 | +TEMPLATES=../helper/container.h ../helper/container_tpl.h | |
9 | +TEMPLATES+=../math/Mmn.h ../math/Mmn_tpl.h ../math/V_K4.h ../math/V_K4_tpl.h | |
10 | + | |
11 | +%.o: %.c++ $(TEMPLATES) | |
12 | + $(CPP) $(CFLAGS) $(CXXFLAGS) -c $*.c++ | |
13 | + | |
14 | +.PHONY : all clean | |
15 | + | |
16 | +all: $(OBJECTS) | |
17 | + | |
18 | +clean: | |
19 | + @rm -f *.o | ... | ... |
geometry/movable.h
0 → 100755
1 | +/** | |
2 | + * \file movable.h | |
3 | + * | |
4 | + * \brief Definition eines Templates für bewegte Objekte | |
5 | + * | |
6 | + * Organisiert, verwaltet und steuert die Bewegung bewegter Objekte. | |
7 | + * | |
8 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
9 | + * | |
10 | + * \date 19.12.2003 | |
11 | + * | |
12 | + * \version 19.12.2003 [gs]: erste Implementation aus gra_app gezogen. | |
13 | + * \version 21.12.2003 [gs]: Bug in rotate_im_axis(double, vertex, vertex) | |
14 | + * gefixt. Dort wurden immer die Objektkoordinaten | |
15 | + * auf den Weltursprung verschoben und nicht die | |
16 | + * Vektorbasis wie es eigentlich sein sollte. | |
17 | + */ | |
18 | + | |
19 | +/* | |
20 | + * Copyright (C)2003 Georg Steffers | |
21 | + * | |
22 | + * This program is free software; you can redistribute it and/or modify | |
23 | + * it under the terms of the GNU General Public License as published by | |
24 | + * the Free Software Foundation; either version 2 of the License, or | |
25 | + * (at your option) any later version. | |
26 | + * | |
27 | + * This program is distributed in the hope that it will be useful, | |
28 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
29 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
30 | + * GNU General Public License for more details. | |
31 | + * | |
32 | + * You should have received a copy of the GNU General Public License | |
33 | + * along with this program; if not, write to the Free Software | |
34 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
35 | + */ | |
36 | + | |
37 | +#ifndef __movable_h__ | |
38 | +#define __movable_h__ | |
39 | + | |
40 | +#include "vertex.h" | |
41 | +#include "../math/Mmn.h" | |
42 | + | |
43 | +/** | |
44 | + * \brief Ein Interface für bewegte Objekte | |
45 | + * | |
46 | + * alle Objektklassen, die auch Kind dieses komplett öffentlichen | |
47 | + * Interfaces sind lassen sich dadurch rotieren und bewegen, das man die | |
48 | + * Rotations- und Bewegungsgeschwindigkeit bezüglich der lokalen, | |
49 | + * bzw. der Weltkoordinaten angibt. | |
50 | + * jeder Aufruf der Methode update aktualisiert dann die Positionen der | |
51 | + * Vektoren dieses Objekts. | |
52 | + */ | |
53 | +class movable { | |
54 | + protected: | |
55 | + vertex vrp; //!< \brief \<Punkt\> (view reference point) | |
56 | + //! das Zentrum des Objekts | |
57 | + vertex vfw_t; //!< \<Punkt\> Spitze von \ref vfw | |
58 | + vertex vup_t; //!< \<Punkt\> Spitze von \ref vup | |
59 | + vertex vri_t; //!< \<Punkt\> Spitze von \ref vri | |
60 | + vertex vfw; //!< \brief \<Vektor\> (vektor forward) | |
61 | + //! Objektkoordinatensystem z | |
62 | + vertex vup; //!< \brief \<Vektor\> (vektor up) | |
63 | + //! Objektkoordinatensystem y | |
64 | + vertex vri; //!< \brief \<Vektor\> (vektor right) | |
65 | + //! Objektkoordinatensystem x | |
66 | + | |
67 | + Mmn<double> t_mat; //!< Die aktuelle Transformationsmatrize | |
68 | + | |
69 | + //! \brief Geschwinidigkeiten | |
70 | + //! relativ zu Weltkoordinaten | |
71 | + double speed_x, speed_y, speed_z, rot_speed_x, rot_speed_y, rot_speed_z; | |
72 | + //! \brief Geschwinidigkeiten | |
73 | + //! relativ zu Objekt | |
74 | + double speed_vfw, speed_vri, speed_vup, | |
75 | + rot_speed_vfw, rot_speed_vri, rot_speed_vup; | |
76 | + | |
77 | + | |
78 | + time_t last_transform; //!<\brief Zeitpunkt der letzten Transformation | |
79 | + //! | |
80 | + //! Damit läßt sich der genaue | |
81 | + //! Zeitraum seit der letzten Transformation | |
82 | + //! berechnen und in alle Transformations | |
83 | + //! Berechnungen mit einfügen, so das | |
84 | + //! wir wirkliche Echtzeit bekommen. | |
85 | + | |
86 | + //! Speed-Falloffs pro Sekunde | |
87 | + double speed_x_falloff, | |
88 | + speed_y_falloff, | |
89 | + speed_z_falloff, | |
90 | + rot_speed_x_falloff, | |
91 | + rot_speed_y_falloff, | |
92 | + rot_speed_z_falloff; | |
93 | + double speed_vfw_falloff, | |
94 | + speed_vri_falloff, | |
95 | + speed_vup_falloff, | |
96 | + rot_speed_vfw_falloff, | |
97 | + rot_speed_vri_falloff, | |
98 | + rot_speed_vup_falloff; | |
99 | + | |
100 | + //! \brief Konstruktor | |
101 | + //! | |
102 | + //! privater Kontruktor, da man von dem Interface | |
103 | + //! keinen Eigenen Instanzen bilden können soll. | |
104 | + movable() { | |
105 | + vrp=vertex(0,0,0,1); | |
106 | + vfw_t=vertex(0,0,1,1); | |
107 | + vup_t=vertex(0,1,0,1); | |
108 | + vri_t=vertex(1,0,0,1); | |
109 | + vfw=vfw_t-vrp; | |
110 | + vup=vup_t-vrp; | |
111 | + vri=vri_t-vrp; | |
112 | + t_mat=Mmn<double>(4); | |
113 | + } | |
114 | + | |
115 | + public: | |
116 | + virtual const Mmn<double>& get_t_mat(void) { return t_mat; } | |
117 | + | |
118 | + virtual void reset(void) { | |
119 | + vrp.reset(); | |
120 | + vfw_t.reset(); | |
121 | + vup_t.reset(); | |
122 | + vri_t.reset(); | |
123 | + vfw=vfw_t-vrp; | |
124 | + vup=vup_t-vrp; | |
125 | + vri=vri_t-vrp; | |
126 | + | |
127 | + t_mat=Mmn<double>(4); | |
128 | + } | |
129 | + | |
130 | + /** | |
131 | + * \param t_st Transformationsstufe | |
132 | + */ | |
133 | + virtual void transform(unsigned t_st) { | |
134 | + vrp.transform(t_mat, t_st); | |
135 | + vfw_t.transform(t_mat, t_st); | |
136 | + vup_t.transform(t_mat, t_st); | |
137 | + vri_t.transform(t_mat, t_st); | |
138 | + vfw=vfw_t-vrp; | |
139 | + vup=vup_t-vrp; | |
140 | + vri=vri_t-vrp; | |
141 | + } | |
142 | + | |
143 | + void print(void) { | |
144 | + t_mat.print(); | |
145 | + } | |
146 | + | |
147 | + const vertex& get_vrp(void) { | |
148 | + return vrp; | |
149 | + } | |
150 | + | |
151 | + const vertex& get_vfw_t(void) { | |
152 | + return vfw_t; | |
153 | + } | |
154 | + | |
155 | + const vertex& get_vup_t(void) { | |
156 | + return vup_t; | |
157 | + } | |
158 | + | |
159 | + const vertex& get_vri_t(void) { | |
160 | + return vri_t; | |
161 | + } | |
162 | + | |
163 | + const vertex& get_vfw(void) { | |
164 | + return vfw; | |
165 | + } | |
166 | + | |
167 | + const vertex& get_vup(void) { | |
168 | + return vup; | |
169 | + } | |
170 | + | |
171 | + const vertex& get_vri(void) { | |
172 | + return vri; | |
173 | + } | |
174 | + | |
175 | + /** | |
176 | + * \brief direkte Veränderung der Position über eine | |
177 | + * vorberechnete Matrize. | |
178 | + * \param trans_mat Eine komplette vorberechnete Transformationsmatrix | |
179 | + */ | |
180 | + void move_im(const Mmn<double>& trans_mat) { | |
181 | + t_mat=trans_mat%t_mat; | |
182 | + } | |
183 | + /** | |
184 | + * \brief Verschiebung über (lokale) Objekkoordinaten | |
185 | + * \param axe Achse entlang der verschoben wird | |
186 | + * \param step wie weit verschoben wird | |
187 | + */ | |
188 | + void translate_im_axe(vertex axe, double step) { | |
189 | + axe=axe.norm()*step; | |
190 | + t_mat=mat_translate(axe[X], axe[Y], axe[Z])%t_mat; | |
191 | + } | |
192 | + /** | |
193 | + * \brief Verschiebung über (globale) Weltkoordinaten | |
194 | + * \param x Verschiebung in VRI | |
195 | + * \param y Verschiebung in VUP | |
196 | + * \param z Verschiebung in VFW | |
197 | + */ | |
198 | + void translate_im_global(double x, double y, double z) { | |
199 | + t_mat=mat_translate(x, y, z)%t_mat; | |
200 | + } | |
201 | + /** | |
202 | + * \brief Drehung über (lokale) Objekkoordinaten vfw | |
203 | + * \param angle Wieviel Grad soll gedreht werden | |
204 | + */ | |
205 | + void rotate_im_vfw(double angle) { | |
206 | + vfw_t.transform(t_mat, 1); | |
207 | + vrp.transform(t_mat, 1); | |
208 | + | |
209 | + rotate_im_axis(angle, vfw_t, vrp); | |
210 | + | |
211 | + vfw_t.reset(); | |
212 | + vrp.reset(); | |
213 | + } | |
214 | + /** | |
215 | + * \brief Drehung über (lokale) Objekkoordinaten vup | |
216 | + * \param angle Wieviel Grad soll gedreht werden | |
217 | + */ | |
218 | + void rotate_im_vup(double angle) { | |
219 | + vup_t.transform(t_mat, 1); | |
220 | + vrp.transform(t_mat, 1); | |
221 | + | |
222 | + rotate_im_axis(angle, vup_t, vrp); | |
223 | + | |
224 | + vup_t.reset(); | |
225 | + vrp.reset(); | |
226 | + } | |
227 | + /** | |
228 | + * \brief Drehung über (lokale) Objekkoordinaten vri | |
229 | + * \param angle Wieviel Grad soll gedreht werden | |
230 | + */ | |
231 | + void rotate_im_vri(double angle) { | |
232 | + vri_t.transform(t_mat, 1); | |
233 | + vrp.transform(t_mat, 1); | |
234 | + | |
235 | + rotate_im_axis(angle, vri_t, vrp); | |
236 | + | |
237 | + vri_t.reset(); | |
238 | + vrp.reset(); | |
239 | + } | |
240 | + /** | |
241 | + * \brief Drehung um X-Achse im Weltkoordinaten-Zentrum | |
242 | + * \param angle Wieviel Grad soll gedreht werden | |
243 | + */ | |
244 | + void rotate_im_g_x(double angle) { | |
245 | + t_mat=mat_rot_x(angle)%t_mat; | |
246 | + } | |
247 | + /** | |
248 | + * \brief Drehung um Y-Achse im Weltkoordinaten-Zentrum | |
249 | + * \param angle Wieviel Grad soll gedreht werden | |
250 | + */ | |
251 | + void rotate_im_g_y(double angle) { | |
252 | + t_mat=mat_rot_y(angle)%t_mat; | |
253 | + } | |
254 | + /** | |
255 | + * \brief Drehung um Z-Achse im Weltkoordinaten-Zentrum | |
256 | + * \param angle Wieviel Grad soll gedreht werden | |
257 | + */ | |
258 | + void rotate_im_g_z(double angle) { | |
259 | + t_mat=mat_rot_z(angle)%t_mat; | |
260 | + } | |
261 | + /** | |
262 | + * \brief Drehung um X-Achse im Objektkoordinaten-Zentrum | |
263 | + * \param angle Wieviel Grad soll gedreht werden | |
264 | + */ | |
265 | + void rotate_im_l_x(double angle) { | |
266 | + Mmn<double> mat_center(4); | |
267 | + Mmn<double> mat_reset(4); | |
268 | + | |
269 | + mat_center.a(0,3)=-t_mat.a(0,3); | |
270 | + mat_center.a(1,3)=-t_mat.a(1,3); | |
271 | + mat_center.a(2,3)=-t_mat.a(2,3); | |
272 | + | |
273 | + mat_reset.a(0,3)=t_mat.a(0,3); | |
274 | + mat_reset.a(1,3)=t_mat.a(1,3); | |
275 | + mat_reset.a(2,3)=t_mat.a(2,3); | |
276 | + | |
277 | + t_mat=mat_reset%mat_rot_x(angle)%mat_center%t_mat; | |
278 | + } | |
279 | + /** | |
280 | + * \brief Drehung um Y-Achse im Objektkoordinaten-Zentrum | |
281 | + * \param angle Wieviel Grad soll gedreht werden | |
282 | + */ | |
283 | + void rotate_im_l_y(double angle) { | |
284 | + Mmn<double> mat_center(4); | |
285 | + Mmn<double> mat_reset(4); | |
286 | + | |
287 | + mat_center.a(0,3)=-t_mat.a(0,3); | |
288 | + mat_center.a(1,3)=-t_mat.a(1,3); | |
289 | + mat_center.a(2,3)=-t_mat.a(2,3); | |
290 | + | |
291 | + mat_reset.a(0,3)=t_mat.a(0,3); | |
292 | + mat_reset.a(1,3)=t_mat.a(1,3); | |
293 | + mat_reset.a(2,3)=t_mat.a(2,3); | |
294 | + | |
295 | + t_mat=mat_reset%mat_rot_y(angle)%mat_center%t_mat; | |
296 | + } | |
297 | + /** | |
298 | + * \brief Drehung um Z-Achse im Objektkoordinaten-Zentrum | |
299 | + * \param angle Wieviel Grad soll gedreht werden | |
300 | + */ | |
301 | + void rotate_im_l_z(double angle) { | |
302 | + Mmn<double> mat_center(4); | |
303 | + Mmn<double> mat_reset(4); | |
304 | + | |
305 | + mat_center.a(0,3)=-t_mat.a(0,3); | |
306 | + mat_center.a(1,3)=-t_mat.a(1,3); | |
307 | + mat_center.a(2,3)=-t_mat.a(2,3); | |
308 | + | |
309 | + mat_reset.a(0,3)=t_mat.a(0,3); | |
310 | + mat_reset.a(1,3)=t_mat.a(1,3); | |
311 | + mat_reset.a(2,3)=t_mat.a(2,3); | |
312 | + | |
313 | + t_mat=mat_reset%mat_rot_z(angle)%mat_center%t_mat; | |
314 | + } | |
315 | + /** | |
316 | + * \brief Drehung um eine beliebige Achse | |
317 | + * \param angle Wieviel Grad soll gedreht werden | |
318 | + * \param axe Die Achse um die gedreht werden soll als | |
319 | + * Ursprungsvektor (also einer der in WC(0,0,0) beginnt) | |
320 | + */ | |
321 | + void rotate_im_axis(double angle, const vertex& axe) { | |
322 | + t_mat=mat_rot_axe(angle, axe.get_t())%t_mat; | |
323 | + } | |
324 | + | |
325 | + /** | |
326 | + * \brief Drehung um Z-Achse im Objektkoordinaten-Zentrum | |
327 | + * \param angle Wieviel Grad soll gedreht werden | |
328 | + * \param tip Vertexspitze der Rotationsachse | |
329 | + * \param base Vertexbasis der Rotationsachse | |
330 | + */ | |
331 | + void rotate_im_axis(double angle, vertex tip, vertex base) { | |
332 | + Mmn<double> mat_center(4); | |
333 | + Mmn<double> mat_reset(4); | |
334 | + | |
335 | + mat_center.a(0,3)=-base[X]; | |
336 | + mat_center.a(1,3)=-base[Y]; | |
337 | + mat_center.a(2,3)=-base[Z]; | |
338 | + | |
339 | + mat_reset.a(0,3)=base[X]; | |
340 | + mat_reset.a(1,3)=base[Y]; | |
341 | + mat_reset.a(2,3)=base[Z]; | |
342 | + | |
343 | +// if(angle==0 || angle==180) { | |
344 | +// cout << "------------------------------\n"; | |
345 | +// cout << "Winkel: " << angle << "Grad\n"; | |
346 | +// t_mat.print(); | |
347 | +// } | |
348 | + t_mat=mat_reset%mat_rot_axe(angle, (tip-base).get_t())%mat_center%t_mat; | |
349 | +// if(angle==0 || angle==180) { | |
350 | +// t_mat.print(); | |
351 | +// cout << "------------------------------\n"; | |
352 | +// } | |
353 | + } | |
354 | + // sowohl für translatio, als auch für Rotation sollte ich denke | |
355 | + // ich eigene Methoden für jede Richtung schreiben.!!! | |
356 | +}; | |
357 | + | |
358 | +#endif // __movable_h__ | ... | ... |
geometry/polyeder.c++
0 → 100755
1 | +#include "polyeder.h" | |
2 | + | |
3 | +polyeder::polyeder(const polygon& p, const vertex_list& vl) : | |
4 | + container<polygon>(p), vl(vl) { | |
5 | + for(unsigned i=0; i<count; i++) { | |
6 | + content[i].set_vertex_list(&this->vl); | |
7 | + content[i]._init_normal_(); | |
8 | + content[i].set_polyeder(this); | |
9 | + } | |
10 | +} | |
11 | + | |
12 | +polyeder::polyeder(const polygon* p, unsigned c, const vertex_list& vl) : | |
13 | + container<polygon>(p, c), vl(vl) { | |
14 | + for(unsigned i=0; i<count; i++) { | |
15 | + content[i].set_vertex_list(&this->vl); | |
16 | + content[i]._init_normal_(); | |
17 | + content[i].set_polyeder(this); | |
18 | + } | |
19 | +} | |
20 | + | |
21 | +polyeder::polyeder(const polyeder& p) : | |
22 | + container<polygon>(p), vl(p.vl) { | |
23 | + for(unsigned i=0; i<count; i++) { | |
24 | + content[i].set_vertex_list(&this->vl); | |
25 | + content[i].set_polyeder(this); | |
26 | + } | |
27 | +} | |
28 | + | |
29 | +const polyeder& polyeder::operator=(const polyeder& p) { | |
30 | + if(this==&p) | |
31 | + return *this; | |
32 | + | |
33 | + container<polygon>::operator=(p); | |
34 | + vl=p.vl; | |
35 | + | |
36 | + for(unsigned i=0; i<count; i++) { | |
37 | + content[i].set_vertex_list(&vl); | |
38 | + content[i].set_polyeder(this); | |
39 | + } | |
40 | + | |
41 | + return *this; | |
42 | +} | |
43 | + | |
44 | +void polyeder::transform(const Mmn<double>& tm, int p) { | |
45 | + for(unsigned i=0; i<count; i++) { | |
46 | + content[i].transform(tm, p); | |
47 | + } | |
48 | +} | |
49 | + | |
50 | +void polyeder::transform_normals(const Mmn<double>& tm, int p) { | |
51 | + for(unsigned i=0; i<count; i++) { | |
52 | + content[i].transform_normal(tm, p); | |
53 | + } | |
54 | +} | |
55 | + | |
56 | +void polyeder::reset(void) { | |
57 | + vl.reset(); | |
58 | + | |
59 | + for(unsigned i=0; i<count; i++) { | |
60 | + content[i].reset(); | |
61 | + } | |
62 | +} | |
63 | + | |
64 | +void polyeder::trans_poly(unsigned i, const Mmn<double>& tm, int p) { | |
65 | + content[i].transform(tm, p); | |
66 | +} | |
67 | + | |
68 | +void polyeder::project_2d(double lcx, double sw, double sh, | |
69 | + double ph_ar, double sy, int p) { | |
70 | + for(unsigned i=0; i<count; i++) { | |
71 | + content[i].project_2d(lcx, sw, sh, ph_ar, sy, p+1); | |
72 | + } | |
73 | + for(unsigned i=0; i<vl.card(); i++) { | |
74 | + vl[i].set_trans_stage(p); | |
75 | + } | |
76 | +} | ... | ... |
geometry/polyeder.h
0 → 100755
1 | +/** | |
2 | + * \file polyeder.h | |
3 | + * | |
4 | + * \brief Ein Polyeder (eine gruppe von Polygonen) | |
5 | + * | |
6 | + * Ein Polyeder organisier die Vertexliste und Anordnung von Polygonen | |
7 | + * die zu einem Körper gehören. | |
8 | + * | |
9 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
10 | + * | |
11 | + * \date 19.12.2003 | |
12 | + * | |
13 | + * \version ..2002 [gs]: erste Implementation | |
14 | + * \version 19.12.2003 [gs]: <ul><li> | |
15 | + * Vergleichsoperator hinzugefügt | |
16 | + * </li><li> | |
17 | + * polyeder_movable von gra_app nach hier hin | |
18 | + * übertragen | |
19 | + * </li><li> | |
20 | + * Member world_coordinate rausgesmissen, vielleicht | |
21 | + * bau ich den noch mal wieder ein, aber er darf nie | |
22 | + * implizit benutzt werden, ich denke es ist besser | |
23 | + * Alle Positionen und Ausrichtungen von Objekten in | |
24 | + * einer Weltklasse zu speichern. | |
25 | + * </li></ul> | |
26 | + */ | |
27 | + | |
28 | +/* | |
29 | + * Copyright (C)2003 Georg Steffers | |
30 | + * | |
31 | + * This program is free software; you can redistribute it and/or modify | |
32 | + * it under the terms of the GNU General Public License as published by | |
33 | + * the Free Software Foundation; either version 2 of the License, or | |
34 | + * (at your option) any later version. | |
35 | + * | |
36 | + * This program is distributed in the hope that it will be useful, | |
37 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
38 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
39 | + * GNU General Public License for more details. | |
40 | + * | |
41 | + * You should have received a copy of the GNU General Public License | |
42 | + * along with this program; if not, write to the Free Software | |
43 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
44 | + */ | |
45 | + | |
46 | +#ifndef __polyeder_h__ | |
47 | +#define __polyeder_h__ | |
48 | + | |
49 | +#include "../helper/container.h" | |
50 | +#include "../math/Mmn.h" | |
51 | +#include "polygon.h" | |
52 | +#include "vertex.h" | |
53 | +#include "movable.h" | |
54 | + | |
55 | +class polyeder : public container<polygon> { | |
56 | + public: | |
57 | + vertex_list vl; | |
58 | + | |
59 | + public: | |
60 | + polyeder() : container<polygon>() {} | |
61 | + polyeder(const polygon&, const vertex_list&); | |
62 | + polyeder(const polygon*, unsigned, const vertex_list&); | |
63 | + polyeder(const polyeder&); | |
64 | + ~polyeder() {} | |
65 | + | |
66 | + const polyeder& operator=(const polyeder&); | |
67 | + const polygon& operator[](unsigned index) const { | |
68 | + return content[index]; | |
69 | + } | |
70 | + polygon& operator[](unsigned index) { | |
71 | + return content[index]; | |
72 | + } | |
73 | + | |
74 | + virtual void transform(const Mmn<double>&, int=0); | |
75 | + virtual void transform_normals(const Mmn<double>&, int=0); | |
76 | + void trans_poly(unsigned, const Mmn<double>&, int=0); | |
77 | + virtual void reset(void); | |
78 | + /** | |
79 | + * \param lcx (lens coverage(x)) = Sichtfeld(x) | |
80 | + * \param sw (screen width) = Breite des Projektionsfensters | |
81 | + * \param sh (screen height) = Hoehe des Projektionsfensters | |
82 | + * \param ph_ar (physical aspect ratio) = Seitenverhaeltnis des | |
83 | + * Anzeigegeraets | |
84 | + * \param sy (scale y) = Wenn Anzeigegeraet und Projektionfenster die | |
85 | + * selbe Groesse haben 1, ansonsten der Wert um y proportional | |
86 | + * zu x zu projezieren. | |
87 | + * \param p Transformationsstufe | |
88 | + */ | |
89 | + void project_2d(double lcx, double sw, double sh, | |
90 | + double ph_ar, double sy=1, int p=0); | |
91 | +}; | |
92 | + | |
93 | +class polyeder_movable : public polyeder, public movable { | |
94 | + public: | |
95 | + polyeder_movable() : polyeder(), movable() {} | |
96 | + polyeder_movable(const polygon& p, const vertex_list& vl) : | |
97 | + polyeder(p, vl) {} | |
98 | + polyeder_movable(const polygon* p, unsigned c, const vertex_list& vl) : | |
99 | + polyeder(p, c, vl) {} | |
100 | + polyeder_movable(const polyeder& p) : | |
101 | + polyeder(p) {} | |
102 | + | |
103 | + void transform(int transstage) { | |
104 | + polyeder::transform(t_mat, transstage); | |
105 | + movable::transform(transstage); | |
106 | + } | |
107 | + | |
108 | + void transform_normals(int p) { | |
109 | + polyeder::transform_normals(t_mat, p); | |
110 | + } | |
111 | + | |
112 | + void reset(void) { | |
113 | + polyeder::reset(); | |
114 | + movable::reset(); | |
115 | + } | |
116 | +}; | |
117 | + | |
118 | +#endif | ... | ... |
geometry/polygon.c++
0 → 100755
1 | +#include "polygon.h" | |
2 | + | |
3 | +void polygon::_init_normal_(void) { | |
4 | + if(vl && count>0) { | |
5 | + for(unsigned i=0; i<count; i++) { | |
6 | + center[O_X]+=(*vl)[content[i]][O_X]; | |
7 | + center[O_Y]+=(*vl)[content[i]][O_Y]; | |
8 | + center[O_Z]+=(*vl)[content[i]][O_Z]; | |
9 | + } | |
10 | + | |
11 | + center[X]=center[O_X]/=count; | |
12 | + center[Y]=center[O_Y]/=count; | |
13 | + center[Z]=center[O_Z]/=count; | |
14 | + center[W]=center[O_W]=1; | |
15 | + | |
16 | + normal=center+ | |
17 | + (((*vl)[content[1]]-(*vl)[content[0]])| | |
18 | + ((*vl)[content[count-1]]-(*vl)[content[0]])).norm(); | |
19 | + } | |
20 | + else { | |
21 | + center=vertex(); | |
22 | + normal=vertex(); | |
23 | + } | |
24 | +} | |
25 | + | |
26 | +void polygon::transform(const Mmn<double>& tm, int p) { | |
27 | + for(unsigned i=0; i<count; i++) { | |
28 | + (*vl)[content[i]].transform(tm, p); | |
29 | + } | |
30 | + | |
31 | + transform_normal(tm, p); | |
32 | +} | |
33 | + | |
34 | +void polygon::transform_normal(const Mmn<double>& tm, int p) { | |
35 | + center.transform(tm, p); | |
36 | + normal.transform(tm, p); | |
37 | +} | |
38 | + | |
39 | +void polygon::reset(void) { | |
40 | +/* for(unsigned i=0; i<count; i++) { | |
41 | + (*vl)[content[i]].reset(); | |
42 | + }*/ | |
43 | + | |
44 | + center.reset(); | |
45 | + normal.reset(); | |
46 | +} | |
47 | + | |
48 | +/** | |
49 | + * \brief Clipping gegen eine vordere Z-Ebene | |
50 | + * | |
51 | + * Dieser Algorithmus clippt das polygon gegen eine vordere Z-Ebene | |
52 | + * | |
53 | + * \param this Das ungeclippte unprojezierte Polygon. | |
54 | + * \return ein geclipptes Polygon. | |
55 | + */ | |
56 | +polygon polygon::clip_front_z(double min_Z) const { | |
57 | + container<unsigned> clip; | |
58 | + polygon ret; | |
59 | + | |
60 | + for(unsigned j=0; j<(*this).card(); j++) { | |
61 | + double x0=(*vl)[container<unsigned>::operator[](j)][X], | |
62 | + y0=(*vl)[container<unsigned>::operator[](j)][Y], | |
63 | + z0=(*vl)[container<unsigned>::operator[](j)][Z], | |
64 | + x1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][X], | |
65 | + y1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][Y], | |
66 | + z1=(*vl)[container<unsigned>::operator[]((j+1)%(*this).card())][Z]; | |
67 | + | |
68 | + // Wenn beide drin sind den zweiten übernehmen. | |
69 | + if(z0>min_Z && z1>min_Z) | |
70 | + // Nur P2 nach clip übernehmen | |
71 | + clip[clip.card()]= | |
72 | + container<unsigned>::operator[]((j+1)%(*this).card()); | |
73 | + | |
74 | + // Wenn nur P2 drin ist | |
75 | + if(z0<=min_Z && z1>min_Z) { | |
76 | + // Schnittpunkt berechnen und nach temp übernehmen | |
77 | + unsigned idx=(*vl).card(); | |
78 | + double t=(min_Z-z0)/(z1-z0); | |
79 | + double x=x0+t*(x1-x0); | |
80 | + double y=y0+t*(y1-y0); | |
81 | + | |
82 | + // neuen Vertex zur Vertexliste. | |
83 | + (*vl)[idx]=vertex(x, y, min_Z, COORD); | |
84 | + | |
85 | + // und ins geclippte polygon | |
86 | + clip[clip.card()]=idx; | |
87 | + // und P2 ins geclippte polygon | |
88 | + clip[clip.card()]= | |
89 | + container<unsigned>::operator[]((j+1)%(*this).card()); | |
90 | + } | |
91 | + | |
92 | + // Wenn nur P1 drin ist | |
93 | + if(z0>min_Z && z1<=min_Z) { | |
94 | + // Schnittpunkt berechnen und nach temp übernehmen | |
95 | + unsigned idx=(*vl).card(); | |
96 | + double t=(min_Z-z1)/(z0-z1); | |
97 | + double x=x1+t*(x0-x1); | |
98 | + double y=y1+t*(y0-y1); | |
99 | + | |
100 | + // neuen Vertex zur Vertexliste. | |
101 | + (*vl)[idx]=vertex(x, y, min_Z, COORD); | |
102 | + | |
103 | + // und ins geclippte polygon | |
104 | + clip[clip.card()]=idx; | |
105 | + } | |
106 | + } | |
107 | + | |
108 | + // Das geclippte Polygon zurückliefern. | |
109 | + ret=polygon(clip, vl); | |
110 | + ret.set_id(id); | |
111 | + return ret; | |
112 | +} | |
113 | + | |
114 | +/** | |
115 | +* \brief Clippings nach Sutherland-Hodgman | |
116 | +* | |
117 | +* Cliped das Polygon an dem Polygon p. Es wird ein neues Polygon | |
118 | +* erzeugt, das diesem Polygon innerhalb des Polygons p entspricht. | |
119 | +* Dieses neue Polygon nutzt die selbe Vertexliste. | |
120 | +* | |
121 | +* \param p Das Polygon an dem geclipped werden soll. | |
122 | +* \returns Ein in p passendes Polygon. | |
123 | +*/ | |
124 | +polygon polygon::clip_2d(const polygon& p) const { | |
125 | + //! enthält während des clippings die aktuellen | |
126 | + //! Vertex_listen indizies. | |
127 | + container<unsigned> clip; | |
128 | + | |
129 | + // Zuerst Origialdaten sichern. | |
130 | + clip=(container<unsigned>)*this; | |
131 | + | |
132 | + // Solange unbearbeitete Kanten im Clippolygon sind... | |
133 | + for(unsigned i=0; i<p.card(); i++) { | |
134 | + //! enthält immer die neuen geclippten VL-Indizies | |
135 | + container<unsigned> temp; | |
136 | + | |
137 | + //! Hole nächste Kante des Clippolygons und sichere sie als | |
138 | + //! Vektor. Diese ist definiert über die beiden Punkte | |
139 | + //! p[i] und p[(i+1)%p.card()] | |
140 | + double x0=p[i][X], | |
141 | + y0=p[i][Y], | |
142 | + x1=p[(i+1)%p.card()][X], | |
143 | + y1=p[(i+1)%p.card()][Y]; | |
144 | + | |
145 | + // Jetzt muss zunaechst ein Vektor erzeugt werden der senkrecht | |
146 | + // von der Kante ins Poligon zeigt | |
147 | + // chk=(X=P1.Y-P2.Y, Y=P2.X-P1.X, 0) | |
148 | + vertex chk(y0-y1, x1-x0, 0, VEKTOR); | |
149 | + | |
150 | + // Solange Kanten nicht bearbeitet wurden | |
151 | + for(unsigned j=0; j<clip.card(); j++) { | |
152 | + //! hole nächste Kante aus clipped Prüfe ob Punkt1 und/oder | |
153 | + //! Punkt2 immerhalb des Clippolygons sind. | |
154 | + //! Kante ist (*vl)[clip[j]] und (*vl)[clip[(j+1)%clip.count]] | |
155 | + double x0s=(*vl)[clip[j]][X], | |
156 | + y0s=(*vl)[clip[j]][Y], | |
157 | + x1s=(*vl)[clip[(j+1)%clip.card()]][X], | |
158 | + y1s=(*vl)[clip[(j+1)%clip.card()]][Y]; | |
159 | + | |
160 | + //! Liegt der erste Punkt innerhalb des Clippolygons | |
161 | + //! chk%(P1 - clipP1) > 0.05 und/oder | |
162 | + double chk_p1=chk%((*vl)[clip[j]] - (*p.vl)[i]); | |
163 | + //! liegt der zweite Punkt innerhalb des Clippolygons | |
164 | + //! chk%(P2 - clipP1) > 0.05 | |
165 | + double chk_p2=chk%((*vl)[clip[(j+1)%clip.card()]] - | |
166 | + (*p.vl)[i]); | |
167 | + | |
168 | + // 0.05 ist ein Epsilon um Ungenauigkeiten auszugleichen und | |
169 | + // ganz sicher zu gehen das der Punkt wirklich innerhalb liegt. | |
170 | + | |
171 | + // Wenn beide drin sind | |
172 | + if(chk_p1>0.05 && chk_p2>0.05) | |
173 | + // Nur P2 nach temp übernehmen | |
174 | + temp[temp.card()]=clip[(j+1)%clip.card()]; | |
175 | + | |
176 | + // Wenn nur P1 drin ist | |
177 | + if(chk_p1>0.05 && chk_p2<=0.05) { | |
178 | + // Schnittpunkt berechnen und nach temp übernehmen | |
179 | + unsigned idx=(*vl).card(); | |
180 | + double x,y; | |
181 | + | |
182 | + x=x0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/ | |
183 | + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(x1-x0); | |
184 | + | |
185 | + y=y0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/ | |
186 | + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(y1-y0); | |
187 | + | |
188 | + // neuen Vertex zur Vertexliste. | |
189 | + (*vl)[idx]=vertex(x, y, 0, COORD); | |
190 | + | |
191 | + temp[temp.card()]=idx; | |
192 | + } | |
193 | + | |
194 | + // Wenn nur P2 drin ist | |
195 | + if(chk_p1<=0.05 && chk_p2>0.05) { | |
196 | + // Schnittpunkt berechnen und nach temp übernehmen | |
197 | + unsigned idx=(*vl).card(); | |
198 | + double x,y; | |
199 | + | |
200 | + x=x0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/ | |
201 | + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(x1-x0); | |
202 | + | |
203 | + y=y0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/ | |
204 | + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(y1-y0); | |
205 | + | |
206 | + // neuen Vertex zur Vertexliste. | |
207 | + (*vl)[idx]=vertex(x, y, 0, COORD); | |
208 | + | |
209 | + temp[temp.card()]=idx; | |
210 | + | |
211 | + // P2 nach temp übernehmen | |
212 | + temp[temp.card()]=clip[(j+1)%clip.card()]; | |
213 | + } | |
214 | + | |
215 | + // Wenn keiner drin ist | |
216 | + // Nichts nach temp | |
217 | + } | |
218 | + | |
219 | + // temp enthält jetzt die aktuellen Vertexindizies, | |
220 | + // für den nächsten durchlauf muß clip | |
221 | + // darauf gesetzt werden. | |
222 | + clip=temp; | |
223 | + } | |
224 | + | |
225 | + // Das geclippte Polygon zurückliefern. | |
226 | + return polygon(clip, vl); | |
227 | +} | |
228 | + | |
229 | +void polygon::project_2d(double lcx, double sw, double sh, | |
230 | + double ph_ar, double sy, int p) { | |
231 | + for(unsigned i=0; i<count; i++) { | |
232 | + (*vl)[content[i]].project_2d(lcx, sw, sh, ph_ar, sy, p); | |
233 | + } | |
234 | +} | ... | ... |
geometry/polygon.h
0 → 100755
1 | +/** | |
2 | + * \file polygon.h | |
3 | + * | |
4 | + * \brief definiert alle Klassen zu Polygonen (Gruppen mehrerer Vertexe die | |
5 | + * eine Fläche bilden. | |
6 | + * | |
7 | + * Hier ist die Klasse polygon definiert, die die zentrale Klasse der | |
8 | + * 3D-Application ist. Es werden immer Polygone dargestellt. | |
9 | + * | |
10 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
11 | + * | |
12 | + * \date 16.12.2003 | |
13 | + * | |
14 | + * \version ..2002 [gs]: erste Implementation | |
15 | + * \version 16.12.2003 [gs]: <ul><li> | |
16 | + * Beginn der Dokumentation mir Doxygen | |
17 | + * </li><li> | |
18 | + * Den Sutherland-Hodgman Clipping Algorithmus | |
19 | + * eingebaut. Er scheint zu funktionieren, muss | |
20 | + * aber noch ausgiebig getestet werden. | |
21 | + * </li></ul> | |
22 | + * \version 19.12.2003 [gs]: <ul><li> | |
23 | + * Vergleichsoprator hinzugefügt | |
24 | + * </li><li> | |
25 | + * polygon_movable von gra_app übertragen | |
26 | + * </li></ul> | |
27 | + * \version 21.12.2003 [gs]: vorderes z-clipping eingebaut. | |
28 | + */ | |
29 | + | |
30 | +/* | |
31 | + * Copyright (C)2003 Georg Steffers | |
32 | + * | |
33 | + * This program is free software; you can redistribute it and/or modify | |
34 | + * it under the terms of the GNU General Public License as published by | |
35 | + * the Free Software Foundation; either version 2 of the License, or | |
36 | + * (at your option) any later version. | |
37 | + * | |
38 | + * This program is distributed in the hope that it will be useful, | |
39 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
40 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
41 | + * GNU General Public License for more details. | |
42 | + * | |
43 | + * You should have received a copy of the GNU General Public License | |
44 | + * along with this program; if not, write to the Free Software | |
45 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
46 | + */ | |
47 | + | |
48 | +#ifndef __polygon_h__ | |
49 | +#define __polygon_h__ | |
50 | + | |
51 | +#include "../helper/container.h" | |
52 | +#include "../math/Mmn.h" | |
53 | +#include "vertex.h" | |
54 | +#include "movable.h" | |
55 | + | |
56 | + | |
57 | +class polyeder; | |
58 | + | |
59 | +class polygon : public container<unsigned> { | |
60 | + private: | |
61 | + vertex_list* vl; | |
62 | + vertex center; | |
63 | + vertex normal; | |
64 | + | |
65 | + polyeder* pe; | |
66 | + char id[30]; | |
67 | + | |
68 | + public: | |
69 | + polygon() | |
70 | + : container<unsigned>(), vl(NULL), center(vertex()), | |
71 | + normal(vertex()), pe(NULL) {} | |
72 | + polygon(vertex_list *const vl) | |
73 | + : container<unsigned>(), vl(vl), center(vertex()), | |
74 | + normal(vertex()), pe(NULL) {} | |
75 | + polygon(const unsigned& p, vertex_list *const vl) | |
76 | + : container<unsigned>(p), vl(vl), pe(NULL) { _init_normal_(); } | |
77 | + polygon(const container<unsigned>& p, vertex_list *const vl) | |
78 | + : container<unsigned>(p), vl(vl), pe(NULL) { _init_normal_(); } | |
79 | + polygon(const unsigned* idxs, unsigned count, vertex_list *const vl) | |
80 | + : container<unsigned>(idxs, count), vl(vl), | |
81 | + pe(NULL) { _init_normal_(); } | |
82 | + polygon(const polygon& p) | |
83 | + : container<unsigned>(p), vl(p.vl), | |
84 | + center(p.center), normal(p.normal), pe(p.pe) { strncpy(id, p.id, 29); } | |
85 | + ~polygon() {} | |
86 | + | |
87 | + virtual void _init_normal_(); | |
88 | + | |
89 | + virtual bool operator==(const polygon& p) const { | |
90 | + if(this->container<unsigned>::operator==((container<unsigned>)p)&& | |
91 | + center==p.center && | |
92 | + normal==p.normal) | |
93 | + return true; | |
94 | + | |
95 | + return false; | |
96 | + } | |
97 | + | |
98 | + void set_id(const char* i) { strncpy(id, i, 29); } | |
99 | + const char* get_id(void) const { return id; } | |
100 | + | |
101 | + virtual polygon clip_2d(const polygon& p) const; | |
102 | + virtual polygon clip_front_z(double min_Z) const; | |
103 | + | |
104 | + virtual const polygon& operator=(const polygon& p) { | |
105 | + if(this==&p) | |
106 | + return *this; | |
107 | + | |
108 | + container<unsigned>::operator=(p); | |
109 | + vl=p.vl; | |
110 | + center=p.center; | |
111 | + normal=p.normal; | |
112 | + pe=p.pe; | |
113 | + strncpy(id, p.id, 29); | |
114 | + | |
115 | + return *this; | |
116 | + } | |
117 | + virtual void set_vertex_list(vertex_list *const vl) { | |
118 | + this->vl=vl; | |
119 | + // dachte ich zuerst, aber eigentlich sollte alles richtig | |
120 | + // gesetzt sein, da sich ja die indizies in der neuen Vertexliste | |
121 | + // nicht aender sondern nur die Adressen! | |
122 | + //if(normal==0 || center==0) | |
123 | + // _init_normal_(); | |
124 | + } | |
125 | + virtual void set_polyeder(polyeder *const pe) { | |
126 | + this->pe=pe; | |
127 | + } | |
128 | + virtual const polyeder& get_polyeder(void) { | |
129 | + return *pe; | |
130 | + } | |
131 | + virtual const vertex& operator[](unsigned index) const { | |
132 | + return (*vl)[content[index]]; | |
133 | + } | |
134 | + virtual vertex& operator[](unsigned index) { | |
135 | + return (*vl)[content[index]]; | |
136 | + } | |
137 | + | |
138 | + virtual unsigned vl_idx(unsigned index) { | |
139 | + return content[index]; | |
140 | + } | |
141 | + | |
142 | + /* | |
143 | + * Ich sollte den Normalenvektor aus der Vertexliste nehmen und | |
144 | + * bei bedarf neu berechnen oder aber die transformation für | |
145 | + * normalenvektoren benutzen wenn ich ihn transformiere. | |
146 | + */ | |
147 | + virtual vertex const& center_p(void) { | |
148 | + return center; | |
149 | + } | |
150 | + | |
151 | + virtual vertex const& normal_p(void) const { | |
152 | + return normal; | |
153 | + } | |
154 | + | |
155 | + virtual void transform(const Mmn<double>&, int=0); | |
156 | + virtual void transform_normal(const Mmn<double>&, int=0); | |
157 | + virtual void reset(void); | |
158 | + virtual void project_2d(double lcx, double sw, double sh, | |
159 | + double ph_ar, double sy=1, int p=0); | |
160 | +}; | |
161 | + | |
162 | +class polygon_movable : public polygon, public movable { | |
163 | + public: | |
164 | + polygon_movable() : polygon(), movable() {} | |
165 | + polygon_movable(vertex_list *const vl) : | |
166 | + polygon(vl) {} | |
167 | + polygon_movable(const unsigned& p, vertex_list *const vl) : | |
168 | + polygon(p, vl) {} | |
169 | + polygon_movable(const unsigned* idxs, unsigned count, | |
170 | + vertex_list *const vl) : | |
171 | + polygon(idxs, count, vl) {} | |
172 | + polygon_movable(const polygon& p) : | |
173 | + polygon(p) {} | |
174 | + | |
175 | + void transform(int transstage) { | |
176 | + polygon::transform(t_mat, transstage); | |
177 | + movable::transform(transstage); | |
178 | + } | |
179 | + | |
180 | + void transform_normal(int p) { | |
181 | + polygon::transform_normal(t_mat, p); | |
182 | + } | |
183 | + | |
184 | + void reset(void) { | |
185 | + polygon::reset(); | |
186 | + movable::reset(); | |
187 | + } | |
188 | +}; | |
189 | + | |
190 | + | |
191 | +#endif // __polygon_h__ | ... | ... |
geometry/vertex.c++
0 → 100755
1 | +#include "vertex.h" | |
2 | + | |
3 | +const vertex& vertex::operator=(const vertex& v) { | |
4 | + if(this==&v) | |
5 | + return *this; | |
6 | + | |
7 | + original=v.original; | |
8 | + transformed=v.transformed; | |
9 | + trans_stage=v.trans_stage; | |
10 | + | |
11 | + return *this; | |
12 | +} | |
13 | + | |
14 | +vertex operator*(const double& a, const vertex& v) { | |
15 | + return v * a; | |
16 | +} | |
17 | + | |
18 | +vertex vertex::operator*(const double& a) const { | |
19 | + vertex v=*this; | |
20 | + v.original=v.original*a; | |
21 | + v.transformed=v.transformed*a; | |
22 | + return v; | |
23 | +} | |
24 | + | |
25 | +double vertex::operator% (const vertex& v) const { | |
26 | + return transformed%v.transformed; | |
27 | +} | |
28 | + | |
29 | +vertex vertex::operator| (const vertex& v) const { | |
30 | + vertex w=*this; | |
31 | + w.original=w.original|v.original; | |
32 | + w.transformed=w.transformed|v.transformed; | |
33 | + return w; | |
34 | +} | |
35 | + | |
36 | +vertex vertex::operator+ (const vertex& v) const { | |
37 | + vertex w=*this; | |
38 | + w.original=w.original+v.original; | |
39 | + w.transformed=w.transformed+v.transformed; | |
40 | + return w; | |
41 | +} | |
42 | + | |
43 | +vertex vertex::operator- (const vertex& v) const { | |
44 | + vertex w=*this; | |
45 | + w.original=w.original-v.original; | |
46 | + w.transformed=w.transformed-v.transformed; | |
47 | + return w; | |
48 | +} | |
49 | + | |
50 | +vertex vertex::norm(void) const { | |
51 | + vertex w; | |
52 | + w.original=original*(1/original.v_betr()); | |
53 | + w.transformed=transformed*(1/transformed.v_betr()); | |
54 | + return w; | |
55 | +} | |
56 | + | |
57 | +double vertex::betr(void) const { | |
58 | + return transformed.v_betr(); | |
59 | +} | |
60 | + | |
61 | +void vertex::reset(void) { | |
62 | + if(trans_stage!=0) { | |
63 | + trans_stage=0; | |
64 | + transformed=original; | |
65 | + } | |
66 | +} | |
67 | + | |
68 | +void vertex::transform(const Mmn<double>& t_mat, int p) { | |
69 | + if(trans_stage < p) { | |
70 | + transformed=t_mat % transformed; | |
71 | + trans_stage=p; | |
72 | + } | |
73 | +} | |
74 | + | |
75 | +void vertex::project_2d(double lcx, double sw, double sh, | |
76 | + double ph_ar, double sy, int p) { | |
77 | + if(trans_stage < p) { | |
78 | + transformed[X]=transformed[X]/transformed[Z] * | |
79 | + (lcx * sw) + 0.5*sw; | |
80 | + transformed[Y]=-transformed[Y]/transformed[Z] * | |
81 | + (lcx * ph_ar * sh) + 0.5*sy*sh; | |
82 | + transformed[Z]=1/transformed[Z]; // 1/Z ist linear im projezierten | |
83 | + // Polygon kann ich also über die | |
84 | + // Polygonkanten interpolieren | |
85 | + // brauche ich fuer z-Buffer, | |
86 | + // Texturemapping und evtl. noch mehr. | |
87 | + | |
88 | + trans_stage=p; | |
89 | + } | |
90 | +} | |
91 | + | |
92 | +inline double vertex::unproject_X(double tx, double tz, | |
93 | + double lcx, double sw) { | |
94 | + return (tx - 0.5*sw) / (lcx * sw) / tz; | |
95 | +} | |
96 | + | |
97 | +inline double vertex::unproject_Y(double ty, double tz, | |
98 | + double lcx, double sh, | |
99 | + double ph_ar, double sy) { | |
100 | + return (ty - 0.5*sy*sh) / (lcx * ph_ar * sh) / tz; | |
101 | +} | |
102 | + | |
103 | +inline double vertex::unproject_Z(double tz) { | |
104 | + return 1/tz; | |
105 | +} | |
106 | + | |
107 | +inline double vertex::unproject_U(double tu, double tz, | |
108 | + double lcx, double sw) { | |
109 | + return (tu - 0.5*sw) / (lcx * sw) / tz; | |
110 | +} | |
111 | + | |
112 | +inline double vertex::unproject_V(double tv, double tz, | |
113 | + double lcx, double sh, | |
114 | + double ph_ar, double sy) { | |
115 | + return (tv - 0.5*sy*sh) / (lcx * ph_ar * sh) / tz; | |
116 | +} | |
117 | + | |
118 | +void vertex_list::reset(void) { | |
119 | + for(unsigned i=0; i<count; i++) | |
120 | + content[i].reset(); | |
121 | + | |
122 | + if(variable) { | |
123 | + delete [] variable; | |
124 | + variable=NULL; | |
125 | + var_count=0; | |
126 | + } | |
127 | +} | ... | ... |
geometry/vertex.h
0 → 100755
1 | +/** | |
2 | + * \file vertex.h | |
3 | + * | |
4 | + * \brief Definiert eine Klasse für einen Vertex und eine Klasse fü | |
5 | + * einen Vertexliste | |
6 | + * | |
7 | + * Ein Vertex ist bei mir ein transformbares 4-Tupel, das sowohl einen Vektor | |
8 | + * als auch eine Coordinate darstellen kann. Ich bezeichne beides als Vertex, | |
9 | + * weil auch der Vektor einen Coordinate darstellen kann (falls man ihn als | |
10 | + * Ursprungsvektor betrachtet) | |
11 | + * Eine Vertexliste ist ein Container der Vertexe aufnehmen kann und | |
12 | + * insbesondere zwei getrennte Sepicherbereiche zur aufnahme von Vertexen hat, | |
13 | + * über die aber mit dem gleichen Zugriffsmechanismus zugegriffen wird. | |
14 | + * Die wird gebraucht um leicht Vertexe für das clipping hinzufügen | |
15 | + * zu können. | |
16 | + * | |
17 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
18 | + * | |
19 | + * \date 16.12.2003 | |
20 | + * | |
21 | + * \version ..2002 [gs]: erste Implementation | |
22 | + * \version 16.12.2003 [gs]: <ul><li> | |
23 | + * Beginn der Dokumentation mir Doxygen | |
24 | + * </li><li> | |
25 | + * Vertexlist zu einer zweiteiligen Liste gemacht, | |
26 | + * damit Sie für clipping geeignet ist. | |
27 | + * </li></ul> | |
28 | + * \version 19.12.2003 [gs]: Vergleichsoperator hinzugefügt und | |
29 | + * clip_2d_mask rausgeshmissen. | |
30 | + */ | |
31 | + | |
32 | +/* | |
33 | + * Copyright (C)2003 Georg Steffers | |
34 | + * | |
35 | + * This program is free software; you can redistribute it and/or modify | |
36 | + * it under the terms of the GNU General Public License as published by | |
37 | + * the Free Software Foundation; either version 2 of the License, or | |
38 | + * (at your option) any later version. | |
39 | + * | |
40 | + * This program is distributed in the hope that it will be useful, | |
41 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
42 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
43 | + * GNU General Public License for more details. | |
44 | + * | |
45 | + * You should have received a copy of the GNU General Public License | |
46 | + * along with this program; if not, write to the Free Software | |
47 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
48 | + */ | |
49 | + | |
50 | +#ifndef __vertex_h__ | |
51 | +#define __vertex_h__ | |
52 | + | |
53 | +#include "../math/Mmn.h" | |
54 | +#include "../math/V_K4.h" | |
55 | +#include "../helper/container.h" | |
56 | + | |
57 | +#define X 0 | |
58 | +#define Y 1 | |
59 | +#define Z 2 | |
60 | +#define W 3 | |
61 | +#define O_X 4 | |
62 | +#define O_Y 5 | |
63 | +#define O_Z 6 | |
64 | +#define O_W 7 | |
65 | + | |
66 | +//! W=0 heißt der Vertex stellt einen Vektor dar. | |
67 | +#define VEKTOR 0 | |
68 | +//! W=0 heißt der Vertex stellt einen Coordinate dar. | |
69 | +#define COORD 1 | |
70 | + | |
71 | +class vertex { | |
72 | + private: | |
73 | + V_K4<double> original; | |
74 | + V_K4<double> transformed; | |
75 | + int trans_stage; | |
76 | +// char clip_mask_2d; | |
77 | + | |
78 | + public: | |
79 | + vertex() : trans_stage(0) {} | |
80 | + vertex(double x, double y, double z, double w=VEKTOR) | |
81 | + : original(x,y,z,w), transformed(x,y,z,w), | |
82 | + trans_stage(0) {} | |
83 | + vertex(const vertex& v) : original(v.original), | |
84 | + transformed(v.transformed), | |
85 | + trans_stage(v.trans_stage) {} | |
86 | + | |
87 | + const vertex& operator=(const vertex& v); | |
88 | + const double& operator[](unsigned xyzw) const { | |
89 | + if(xyzw < X) { xyzw=X; } | |
90 | + if(xyzw > O_W) { xyzw=O_W; } | |
91 | + | |
92 | + if(xyzw <= W) | |
93 | + return transformed.a(xyzw, 0); | |
94 | + else | |
95 | + return original.a(xyzw-O_X, 0); | |
96 | + } | |
97 | + double& operator[](unsigned xyzw) { | |
98 | + if(xyzw < X) { xyzw=X; } | |
99 | + if(xyzw > O_W) { xyzw=O_W; } | |
100 | + | |
101 | + if(xyzw <= W) | |
102 | + return transformed.a(xyzw, 0); | |
103 | + else | |
104 | + return original.a(xyzw-O_X, 0); | |
105 | + } | |
106 | + vertex operator*(const double&) const; | |
107 | + friend vertex operator*(const double&, const vertex&); | |
108 | + | |
109 | + double operator% (const vertex&) const; | |
110 | + vertex operator| (const vertex&) const; | |
111 | + vertex operator+ (const vertex&) const; | |
112 | + vertex operator- (const vertex&) const; | |
113 | + bool operator== (const vertex& v) const { | |
114 | + if(this->original == v.original && | |
115 | + this->transformed == v.transformed && | |
116 | + this->trans_stage == v.trans_stage) | |
117 | + return true; | |
118 | + | |
119 | + return false; | |
120 | + } | |
121 | + | |
122 | + vertex norm(void) const; | |
123 | + double betr(void) const; | |
124 | + | |
125 | + void reset(void); | |
126 | + void set_trans_stage(int p=0) { trans_stage=p; } | |
127 | + unsigned get_trans_stage(void) const { return trans_stage; } | |
128 | + V_K4<double> const& get_o(void) const {return original;} | |
129 | + V_K4<double> const& get_t(void) const {return transformed;} | |
130 | + | |
131 | + void transform(const Mmn<double>&, int=0); | |
132 | + void project_2d(double lcx, double sw, double sh, | |
133 | + double ph_ar, double sy, int p); | |
134 | + | |
135 | + double unproject_X(double, double, double, double); | |
136 | + double unproject_Y(double, double, double, double, double, double); | |
137 | + double unproject_Z(double); | |
138 | + double unproject_U(double, double, double, double); | |
139 | + double unproject_V(double, double, double, double, double, double); | |
140 | + | |
141 | + void print() { | |
142 | + original.print(); | |
143 | + transformed.print(); | |
144 | + cout << "---\n"; | |
145 | + } | |
146 | +}; | |
147 | + | |
148 | +vertex operator*(const double& a, const vertex& v); | |
149 | + | |
150 | +class vertex_list : public container<vertex> { | |
151 | + protected: | |
152 | + vertex* variable; | |
153 | + unsigned var_count; | |
154 | + | |
155 | + public: | |
156 | + vertex_list() | |
157 | + : container<vertex>(), variable(NULL), var_count(0) {} | |
158 | + vertex_list(const vertex& v) | |
159 | + : container<vertex>(v), variable(NULL), var_count(0) {} | |
160 | + vertex_list(const vertex* idxs, unsigned count) | |
161 | + : container<vertex>(idxs, count), variable(NULL), var_count(0) {} | |
162 | + vertex_list(const vertex_list& v) | |
163 | + : container<vertex>(v), var_count(v.var_count) { | |
164 | + if(var_count > 0) | |
165 | + variable=new vertex[var_count]; | |
166 | + else | |
167 | + variable=NULL; | |
168 | + | |
169 | + for(unsigned i=0; i<var_count; i++) | |
170 | + variable[i]=v.variable[i]; | |
171 | + } | |
172 | + ~vertex_list() { | |
173 | + if(variable) { | |
174 | + delete [] variable; | |
175 | + variable=NULL; | |
176 | + var_count=0; | |
177 | + } | |
178 | + } | |
179 | + | |
180 | + vertex& operator[](unsigned index) { | |
181 | + if(index+1 <= count) | |
182 | + return content[index]; | |
183 | + else | |
184 | + index-=count-1; | |
185 | + | |
186 | + if(index+1 > var_count) { | |
187 | + vertex* content_tmp=new vertex[index+1]; | |
188 | + | |
189 | + for(unsigned i=0; i<var_count; i++) | |
190 | + content_tmp[i]=variable[i]; | |
191 | + | |
192 | + delete [] variable; | |
193 | + variable=content_tmp; | |
194 | + var_count=index+1; | |
195 | + } | |
196 | + | |
197 | + return variable[index]; | |
198 | + } | |
199 | + | |
200 | + void resize(unsigned size) { | |
201 | + if(size < count) { | |
202 | + if(variable) { | |
203 | + delete [] variable; | |
204 | + variable=NULL; | |
205 | + var_count=0; | |
206 | + } | |
207 | + return; | |
208 | + } | |
209 | + else | |
210 | + size-=count; | |
211 | + | |
212 | + vertex* content_tmp; | |
213 | + if(size>0) { | |
214 | + content_tmp=new vertex[size]; | |
215 | + | |
216 | + for(unsigned i=0; i<size<var_count?size:var_count; i++) | |
217 | + content_tmp[i]=variable[i]; | |
218 | + } | |
219 | + else | |
220 | + content_tmp=NULL; | |
221 | + | |
222 | + delete [] variable; | |
223 | + variable=content_tmp; | |
224 | + var_count=size; | |
225 | + } | |
226 | + | |
227 | + unsigned fix_card(void) { return container<vertex>::card(); } | |
228 | + unsigned var_card(void) { return var_count; } | |
229 | + unsigned card(void) { return fix_card()+var_card(); } | |
230 | + void reset(void); | |
231 | +}; | |
232 | + | |
233 | +#endif // __vertex_h__ | ... | ... |
gra_app.cpp
0 → 100755
1 | +/** | |
2 | + * \file gra_app.cpp | |
3 | + * | |
4 | + * \brief Testapplication zu engage | |
5 | + * | |
6 | + * Dieses kleine Prog testet die bestehenden Funktionen von engage und | |
7 | + * dient dazu neue Funktionen testweise einzubauen, bevor sie endgültig | |
8 | + * in die lib kommen. | |
9 | + * | |
10 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
11 | + * | |
12 | + * \date 16.12.2003 | |
13 | + * | |
14 | + * \version ..2002 [gs]: erste Implementation | |
15 | + * \version 13.12.2003 [gs]: movable eingefügt mit Funktionen für die | |
16 | + * wichtigsten Bewegungen (muss aber noch eine | |
17 | + * großes cleanup und fixing her) schient aber | |
18 | + * für die momentanen bedürfnisse zu | |
19 | + * reichen. | |
20 | + * \version 16.12.2003 [gs]: <ul><li> | |
21 | + * Beginn der Dokumentation mit Doxygen | |
22 | + * </li><li> | |
23 | + * einige kleinere Fixes an movable | |
24 | + * </li></ul> | |
25 | + * \version 19.12.2003 [gs]: <ul><li> | |
26 | + * Eine Polygonliste eingebaut und diese sortiert, | |
27 | + * so das die am Weitesten vom Betrachter entfernten | |
28 | + * Polygone zuerst gezeichnet werden. | |
29 | + * Dazu musste auch eine Methode geschaffen werden | |
30 | + * mit der man feststellen konnte zu welchem Polyeder | |
31 | + * welches Polygon gehört. Dies habe ich mit | |
32 | + * der Methode contains in der Klasse container | |
33 | + * eingebaut. | |
34 | + * </li><li> | |
35 | + * Die Klasse movable in eine eigenen Datei verschoben | |
36 | + * geometry/movable.h. Außerdem die Klassen | |
37 | + * polygon_movable nach geometry/polygon.h und | |
38 | + * polyeder_movable nach geometry/polyeder.h | |
39 | + * verschoben. | |
40 | + * </li><li> | |
41 | + * Ein viertes Polygon hinzugefügt, das erst | |
42 | + * verschoben und dann um die Weltachsen gedreht wird. | |
43 | + * Nur um zu demonstrieren was diese Reihenfolge | |
44 | + * der transformation für eine Wirkung hat. | |
45 | + * </li><li> | |
46 | + * kleinere Änderungen im Darstellungsteil. | |
47 | + * </li><li> | |
48 | + * über die in canvas neu geschaffene Methode | |
49 | + * draw_text die Zeit ss:ms die für einen | |
50 | + * kompletten Transformations/Zeichenvorgang | |
51 | + * benötigt wird angezeigt. | |
52 | + * </li></ul> | |
53 | + * \version 21.12.2003 [gs]: <ul><li> | |
54 | + * Herausgefunden warum die Würfel so gross sind | |
55 | + * obwohl sie nur eine Kantenlänge von 10 haben. | |
56 | + * Es ligt daran das sie mathematisch vor dem | |
57 | + * screen liegen, dadurch werden sie bei der | |
58 | + * projection größer skaliert. | |
59 | + * </li><li> | |
60 | + * Die Klasse Camera eingefügt und das | |
61 | + * Hauptprogramm so umgeschrieben das es eine | |
62 | + * Camera-Instanz nutzt um | |
63 | + * <ol><li> | |
64 | + * eine Kameratransformation zu machen | |
65 | + * </li><li> | |
66 | + * die 2D-Projektion durchzuführen. | |
67 | + * </li></ol> | |
68 | + * </li><li> | |
69 | + * so modifiziert das erst nur die Vertices von | |
70 | + * movable und die Normalenvektoren der Polygone | |
71 | + * berechnet werden, nur wenn das Polygon auch | |
72 | + * wirklich gezeichnet wird werden die weiteren | |
73 | + * Vertices transformiert und projeziert. | |
74 | + * </li><li> | |
75 | + * So umgebaut das das vordere z-clipping der | |
76 | + * Polygone genutzt wird. | |
77 | + * </li></ul> | |
78 | + * \version 22.12.2003 [gs]: Beleuchtung über die in canvas_imp neu | |
79 | + * eingebauten light_table eingebaut. | |
80 | + */ | |
81 | + | |
82 | +/** | |
83 | + * \mainpage Referenzmanual zu ENGAGE | |
84 | + * | |
85 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
86 | + * \date 22.12.2003 | |
87 | + * \version 0.0.0: Erster Aufbau, jede Menge immer noch zu tun. | |
88 | + * | |
89 | + * Dies Projekt war zu anfang eine kleine app um ein wenig x-lib zu | |
90 | + * Programmieren. Als das ein wenig langweilig wurde und zumindest | |
91 | + * rudimentär funktionierte habe ich angefangen eine kleine 3D-Engine | |
92 | + * dazuzuschreiben.<br> | |
93 | + * Heute habe ich das Ziel dies ganze in irgendeinem Spiel zu verwenden. | |
94 | + * Bis dahin ist allerdings noch jede Menge zu tun. | |
95 | + * Was bislang fertig ist: | |
96 | + * <ul> | |
97 | + * <li>Klassen um die X-Lib auf einfacher Ebene anzusprechen, allerdings | |
98 | + * noch komplett ohne kommunikation mit dem Windowmanager. | |
99 | + * </li><li> | |
100 | + * Klasse um Manipulationen und Berechnungen verschiedenster Art an | |
101 | + * Matrizen und Vektoren mit 4 Tupeln zu machen, wie gauss, verschiedene | |
102 | + * Wege die Determinante zu berechnen, Inverse über Adjunkte oder | |
103 | + * über Gauss, Transponieren, Skalarprodukt, Matritzenprodunkt, Addition | |
104 | + * Subtraktion, etc. | |
105 | + * </li><li> | |
106 | + * Das Muster eines Event-Dispatchers sowie ein template von dem dich | |
107 | + * Klassen ableiten müssen, die Events für diesen erzeugen. | |
108 | + * </li><li> | |
109 | + * einen abstrakten canvas der events erzeugt, Möglihkeiten zur | |
110 | + * Farbverwaltung bietet und einen passenden rasterer erzeugt. Davon | |
111 | + * abgeleitet ein canvas für X11 und wiederum davon abgeleitete ein | |
112 | + * canvas für X11-SHM. | |
113 | + * rasterizer ist wiederum eine abstrakte Klasse die eine Schnittstelle bietet | |
114 | + * um auf einen canvas zu schreiben. davon abgeleitet existiert eine Klasse | |
115 | + * rasterizer_rgb, der speziell auf ein RGB Canvas schreibt, wie das z.B. | |
116 | + * in einem Truecolor Grafikmodus unter X11 nötig ist. | |
117 | + * </li><li> | |
118 | + * Eine Helferklasse container, die verschiedene Daten speichen und | |
119 | + * organisieren kann. Diese sollte in zukunft abstrakt werden und | |
120 | + * Implementierungen versiedener Datenstrukturierungsmethoden verdecken, | |
121 | + * wie z.B. diverse Listenformen, Bäme oder einfache Arrays. | |
122 | + * Im Moment organisiert sie die Daten in einem Array. Einige wichtige Klassen | |
123 | + * (eigentlich alle die mehrere Elemente nicht bekannter Anzahl verwalten | |
124 | + * müssen) leiten sich von dieser Klasse ab. Das ist insbesondere | |
125 | + * vertex_list, polygon und polyeder. | |
126 | + * </li><li> | |
127 | + * Die grundlegenden Geometrieklassen (unterliegen nach wie vor starken | |
128 | + * Veränderungen. Das sind im einzelnen: | |
129 | + * <ol><li> | |
130 | + * <b>vertex:</b> Diese Struktur nimmt einen 4-Tupel Vektor auf, der | |
131 | + * entweder eine 3D-Coordinate oder aber einen Vektor im 3D-Raum beschreibt. | |
132 | + * es werden sowohl die Originaldaten sowie transformierte Daten gespeichert. | |
133 | + * Außerdem wird der transformationsstatus zwischengespeicher. (Das | |
134 | + * verhindert das, wenn sich z.B. ein Polygon einen Vertex mit einem anderen | |
135 | + * teilt, transformationen nur einmal an dem Vertex vorgenommen werden. | |
136 | + * </li><li> | |
137 | + * <b>vertex_list:</b> Eine Struktur um mehrere Vertexe zu verwalten. | |
138 | + * Sie besteht aus einem fixen und einem Variablen Teil, daher modifiziert | |
139 | + * sie einige Operatoren, die sie von container erbt. Die zweigeteiltheit | |
140 | + * ist wichtig, da bei einigen Operationen (insb. Clipping) zusätzliche | |
141 | + * Vertexe entstehen können, die aber nur temporär wichtig sind. | |
142 | + * Durch die Zweigeteiltheit läßt sich immer genau unterscheiden | |
143 | + * was erzeugte und was originale Vertexe waren. Weiterhin ist wichtig, | |
144 | + * das auf beide Teile mit derselben Zugriffsfunktion zugegriffen werden kann. | |
145 | + * </li><li> | |
146 | + * <b>polygon:</b> ist eine Liste von Indexen in eine Vertexliste, die | |
147 | + * ein Polygon beschreibt. Leitet sich von container ab und verwaltet ihren | |
148 | + * container teil die indexe. Weiterhin enthält polygon einen pointer auf | |
149 | + * eine vertex_list, auf die sich die Indexwerte bezieht und die Informationen | |
150 | + * zu einem Normalenvektor (als Basispunkt und Spitze Paar). | |
151 | + * Seit neustem enthält ein Polygon auch noch einen pointer auf den | |
152 | + * polyeder zu dem es gehört (wenn es zu einem gehört, ansonsten null) | |
153 | + * und es sollte auch noch den index in diesem Polyeder enthäten. | |
154 | + * Damit wäre es dann einfach von einem polygon wieder auf seinen | |
155 | + * Polyeder zu schließen (es kann aber auch sein das ich dieses Konzept | |
156 | + * wieder verwerfe und versuche irgendwie über den container eine | |
157 | + * Möglichkeit der zuordnung zu schaffen.<br> | |
158 | + * Da dies eine polygonale Engine ist enthält polygon einige wichtige | |
159 | + * Methoden, wie das clipping zur vorderen z-ebene und das clipping ein einem | |
160 | + * weiteren polygon (nach der 2D-Projektion, um das Polygon gegen die | |
161 | + * Canvas (Rasterer)-Grenzen zu clippen. | |
162 | + * </li><li> | |
163 | + * <b>polyeder:</b> ist eine von container abgeleitete Klasse die eine | |
164 | + * Gruppe zusammengehöriger polygone verwaltet. Zusammengehörend | |
165 | + * bedeutet in diesem Fall vor allem, das sie die gleiche Vertexliste nutzen. | |
166 | + * </li></ol></li></ul> | |
167 | + * | |
168 | + * Was die Engine bislang (mehr oder weniger sauber implementiert) macht: | |
169 | + * <ul><li> | |
170 | + * beliebige transformtion beliebiger polygone im 3D-Raum. | |
171 | + * </li><li> | |
172 | + * Perspektivische Projektion | |
173 | + * </li><li> | |
174 | + * clipping der projezierten Vertexe gegen die canvas-Grenzen | |
175 | + * </li><li> | |
176 | + * clipping der 3D-Coordinaten gegen eine vordere Z-Ebene | |
177 | + * </li><li> | |
178 | + * falls gewünscht Backface-Culling | |
179 | + * </li><li> | |
180 | + * definieren einer Kamera und positionieren dieser. | |
181 | + * </li><li> | |
182 | + * Darstellung flatshaded, wireframe oder kombiniert. | |
183 | + * </li><li> | |
184 | + * Sortiert die polygone nach z, damit die hintersten zuerst gezeichnet werden. | |
185 | + * </li></ul> | |
186 | + * | |
187 | + * \bug [gs] Mein Backfaceculling funktioniert nicht, das scheint daran zu | |
188 | + * liegen, das eine projezierte Seite die 90 Grad zu mir aber stark am | |
189 | + * Rand des sichtbaren Bereichs ist sehr wohl von mir gesehen werden kann. | |
190 | + * In die berechnung des cullings muss also irgendwie das Scihtfeld | |
191 | + * bzw der Blickwinkel mit einbezogen werden. | |
192 | + * -- Gefixed: man muss als Blickwinkel nur den vrp nehmen, dann klappts. | |
193 | + * \bug [gs] Das Programm darf nicht mehr mit -ffast-math compiliert werden, | |
194 | + * da dann anscheinend irgendwas bei der berechnung der inversen | |
195 | + * Camera-Matrix kaputtoptimiert wird. | |
196 | + * | |
197 | + * \todo [gs] Evtl. sollte ich für den Rasterizer imlib2 oder evas | |
198 | + * verwenden (bzw ich baue einen rasterizer der diese Libs nutzt). | |
199 | + * Evtl. kann evas auch einen kompletten canvas für mich bilden, incl. | |
200 | + * Rasterizer. (Auch ein GL Rasterizer sollte noch geschrieben werden. | |
201 | + * \todo [gs] Eine menge cleanups. | |
202 | + * \todo [gs] Java Version schreiben und hoffen das sie schnell genug ist. | |
203 | + * \todo [gs] Natürlich noch jede Menge, Lightmapping, Texturemapping, | |
204 | + * Schadowmapping, vorne und hinten z-clipping usw. | |
205 | + * \todo [gs] gutes Konzept finden um z-clipping, transformieren und | |
206 | + * projezieren zu machen (es darf z.B. nich projeziert werden, solange | |
207 | + * das z-clipping läuft. | |
208 | + * \todo [gs] ein gutes konzept finden ein polygon einem polyeder zuzuweisen, | |
209 | + * und den index innerhalb des Polyeders zu bestimmen, auch wenn | |
210 | + * das polygon bereits transformiert wurde...in diesem zusammenhang | |
211 | + * glaube ich immer mehr, das es doch besser währe, das polygon | |
212 | + * wuerde beim clipping doch nicht einfach ein neues Polygon erzeugen | |
213 | + * und stattdessen sich selbst modifizieren und eine referenz auf | |
214 | + * sich zurückgeben. (Bei den == Operatoren würde ich dann immer | |
215 | + * checken ob es sich wirklich um eine Referenz auf die selbe Instanz | |
216 | + * (sprich Adressen gleich) ist. | |
217 | + * | |
218 | + * Copyright ©2003 Georg Steffers | |
219 | + * | |
220 | + * This program is free software; you can redistribute it and/or modify | |
221 | + * it under the terms of the GNU General Public License as published by | |
222 | + * the Free Software Foundation; either version 2 of the License, or | |
223 | + * (at your option) any later version. | |
224 | + * | |
225 | + * This program is distributed in the hope that it will be useful, | |
226 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
227 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
228 | + * GNU General Public License for more details. | |
229 | + * | |
230 | + * You should have received a copy of the GNU General Public License | |
231 | + * along with this program; if not, write to the Free Software | |
232 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
233 | + * <br><br><br> | |
234 | + */ | |
235 | + | |
236 | +#ifndef __XProto_h__ | |
237 | +#define __XProto_h__ | |
238 | + | |
239 | +using namespace std; | |
240 | + | |
241 | +#include <cmath> | |
242 | +#include <time.h> | |
243 | +#include <unistd.h> | |
244 | + | |
245 | +#include "factory.h" | |
246 | +#include "dispatcher.h" | |
247 | +#include "canvas.h" | |
248 | +#include "rasterize.h" | |
249 | +#include "math/Mmn.h" | |
250 | +#include "math/V_K4.h" | |
251 | +#include "math/sin_cos.h" | |
252 | +#include "geometry/vertex.h" | |
253 | +#include "geometry/polygon.h" | |
254 | +#include "geometry/polyeder.h" | |
255 | + | |
256 | +#include <time.h> | |
257 | +#include <sys/timeb.h> | |
258 | + | |
259 | +int compf(const void* a, const void* b) { | |
260 | + polygon* _a=(polygon*)a; | |
261 | + polygon* _b=(polygon*)b; | |
262 | + | |
263 | + return (int)(_a->center_p()[Z] - _b->center_p()[Z])*-1; | |
264 | +} | |
265 | + | |
266 | +class light { | |
267 | + protected: | |
268 | + unsigned intensity; | |
269 | + double dist_falloff; | |
270 | + | |
271 | + public: | |
272 | + light(unsigned intense=255) : intensity(intense) {} | |
273 | + | |
274 | + virtual unsigned get_intensity(void) { return intensity; } | |
275 | + virtual void set_intensity(unsigned in) { intensity=in; } | |
276 | +}; | |
277 | + | |
278 | +class ambient_light : public light { | |
279 | + public: | |
280 | + ambient_light(unsigned intense=255) : light(intense) {} | |
281 | +}; | |
282 | + | |
283 | +// Diese Lampe ist ähnlich wie die Sonne, sie beleuchtet die | |
284 | +// gesamte Scenen aus einer Richtung. Diese definiere ich einfach | |
285 | +// als fvw des movable. | |
286 | +class direct_light : public light, public movable { | |
287 | + public: | |
288 | + direct_light(unsigned intense=255) : light(intense), movable() {} | |
289 | + | |
290 | + const vertex& get_direction(void) { | |
291 | + return vfw; | |
292 | + } | |
293 | +}; | |
294 | + | |
295 | +class camera : public movable { | |
296 | + private: | |
297 | + double lcxa; //!< (lens coverage(x) angle = Sichtfeld(x)-Winkle | |
298 | + double lcx; //!< (lens coverage(x)) = Sichtfeld(x) | |
299 | + double sw; //!< (screen width) = Breite des Projektionsfensters | |
300 | + double sh; //!< (screen height) = Hoehe des Projektionsfensters | |
301 | + double ph_ar; /**< \brief (physical aspect ratio) = Seitenverhaeltnis | |
302 | + * des Anzeigegeraets | |
303 | + */ | |
304 | + double sy; //!< (scale y) = Wert um y proportional zu projezieren. | |
305 | + double dz; //!< (delta z) = Abstand des Auges zum screen | |
306 | + | |
307 | + Mmn<double> cam_trans; | |
308 | + | |
309 | + public: | |
310 | + camera(double lcxa=60) : movable() { | |
311 | + this->set_lens_coverage(lcxa); | |
312 | + } | |
313 | + | |
314 | + camera(const rasterizer& scr, double lcxa=60) : movable() { | |
315 | + this->set_lens_coverage(lcxa); | |
316 | + this->sw=scr.get_x_size(); | |
317 | + this->sh=scr.get_y_size(); | |
318 | + this->ph_ar=this->sw/this->sh; | |
319 | + this->sy=this->sh/this->sw*this->ph_ar; | |
320 | + this->dz=(this->sh/2)/tan(RAD(this->lcxa/2)); | |
321 | + } | |
322 | + | |
323 | + camera(const rasterizer& scr, double ph_ar, | |
324 | + double lcxa) : movable() { | |
325 | + this->set_lens_coverage(lcxa); | |
326 | + this->sw=scr.get_x_size(); | |
327 | + this->sh=scr.get_y_size(); | |
328 | + this->ph_ar=ph_ar; | |
329 | + this->sy=this->sh/this->sw*this->ph_ar; | |
330 | + this->dz=(this->sh/2)/tan(RAD(this->lcxa/2)); | |
331 | + } | |
332 | + | |
333 | + camera(double sw, double sh, double lcxa=60) : movable() { | |
334 | + this->set_lens_coverage(lcxa); | |
335 | + this->sw=sw; | |
336 | + this->sh=sh; | |
337 | + this->ph_ar=this->sw/this->sh; | |
338 | + this->sy=this->sh/this->sw*this->ph_ar; | |
339 | + this->dz=(this->sh/2)/tan(RAD(this->lcxa/2)); | |
340 | + } | |
341 | + | |
342 | + camera(double sw, double sh, | |
343 | + double ph_ar, double lcxa=60) : movable() { | |
344 | + this->set_lens_coverage(lcxa); | |
345 | + this->sw=sw; | |
346 | + this->sh=sh; | |
347 | + this->ph_ar=ph_ar; | |
348 | + this->sy=this->sh/this->sw*this->ph_ar; | |
349 | + this->dz=(this->sh/2)/tan(RAD(this->lcxa/2)); | |
350 | + } | |
351 | + | |
352 | + /** | |
353 | + * \brief Setze Sichtfeld. (zwischen 10 und 170) | |
354 | + * | |
355 | + * lcx ist eine Konstante die die größe der Sichtfeldes | |
356 | + * beschreibt. Diese Funktion ermittelt diese Konstante anhand von | |
357 | + * Werten zwischen 10 und 170 wobei das volle menschliche Sichtfeld | |
358 | + * einem Wert von 100 entspricht. 10 ist extrem Tele und 170 extrem | |
359 | + * Weitwinkel. | |
360 | + * | |
361 | + * \param angle Winkel fürs Sichtfeld (zwischen 10 und 170) | |
362 | + * | |
363 | + * \pre 10 < angel < 170 | |
364 | + */ | |
365 | + void set_lens_coverage(double angle) { | |
366 | + lcxa=angle; | |
367 | + | |
368 | + if(lcxa>170) lcxa=170; | |
369 | + if(lcxa<10) lcxa=10; | |
370 | + | |
371 | + lcx=0.5*(1/tan(lcxa*M_PI/(180.0*2.0))); | |
372 | + } | |
373 | + | |
374 | + const Mmn<double>& cam_trans_mat(void) { | |
375 | + cam_trans=t_mat.inv_Ad(); | |
376 | + | |
377 | + if(cam_trans.is_null()) | |
378 | + cam_trans=t_mat.gauss(INVERSE); | |
379 | + | |
380 | + return cam_trans; | |
381 | + } | |
382 | + | |
383 | + double get_lcx(void) const { | |
384 | + return lcx; | |
385 | + } | |
386 | + | |
387 | + double get_sw(void) const { | |
388 | + return sw; | |
389 | + } | |
390 | + | |
391 | + double get_sh(void) const { | |
392 | + return sh; | |
393 | + } | |
394 | + | |
395 | + double get_ph_ar(void) const { | |
396 | + return ph_ar; | |
397 | + } | |
398 | + | |
399 | + double get_sy(void) const { | |
400 | + return sy; | |
401 | + } | |
402 | + | |
403 | + double get_dz(void) const { | |
404 | + return dz; | |
405 | + } | |
406 | +}; | |
407 | + | |
408 | +/** | |
409 | + * \brief Das eigentliche Programm | |
410 | + * | |
411 | + * Hier werden alle Teile zu einem kleinen Testprogramm zusammengefügt. | |
412 | + */ | |
413 | +class app { | |
414 | + private: | |
415 | + canvas* scr; //!< Der Canvas auf dem gezeichnet wird | |
416 | + rasterizer* ras; //!< Der Rasterizer zu dem \ref scr | |
417 | + dispatcher* d; //!< Der X11-Dispatcher | |
418 | + disp_manager manager; //!< Der Dispatcher-Manager | |
419 | + | |
420 | + polyeder_movable p; //!< erster Polyeder | |
421 | + polyeder_movable p2; //!< zweiter Polyeder | |
422 | + polyeder_movable p3; //!< dritter Polyeder | |
423 | + polyeder_movable p4; //!< und weils so lustig ist noch einer | |
424 | + | |
425 | + camera cam; | |
426 | + direct_light li; | |
427 | + direct_light li2; | |
428 | + ambient_light li3; | |
429 | + | |
430 | + double winkel; | |
431 | + int stepping; | |
432 | + double cam_winkel; | |
433 | + int cam_stepping; | |
434 | + double li_winkel; | |
435 | + int li_stepping; | |
436 | + double li2_winkel; | |
437 | + int li2_stepping; | |
438 | + | |
439 | + double clip_front; | |
440 | + | |
441 | + unsigned secs, secs_tmp; | |
442 | + unsigned short ms; | |
443 | + | |
444 | + /** | |
445 | + * \brief Bringt den Canvas auf den Bildschirm | |
446 | + * | |
447 | + * Dies ist eine Callback-Methode die zu jedem expose-event u.ä. | |
448 | + * aufgerufen wird um den Inhalt des Canvas auf das Fenster zu | |
449 | + * übertragen. Diese Methode wird ausschließlich vom | |
450 | + * Dispatcher \ref d aufgerufen. | |
451 | + * | |
452 | + * \param es Die Quelle des Events, in diesem Fall also der canvas | |
453 | + * \param key Wird nicht benutzt | |
454 | + * | |
455 | + * \pre redraw muß als callback in \ref d registriert sein. | |
456 | + * \pre \ref scr muß ein gültiger canvas sein. | |
457 | + */ | |
458 | + void redraw(event_source* es, void* key) { | |
459 | + char buffer[10]="\0"; | |
460 | + | |
461 | + sprintf(buffer, "%02d:%03d", secs, ms); | |
462 | + | |
463 | + scr->blit_screen(); | |
464 | + scr->draw_text(5,15,buffer,strlen(buffer)); | |
465 | + //usleep(10); | |
466 | + } | |
467 | + | |
468 | + /** | |
469 | + * \brief verarbeitet Tastendrücke im Canvas | |
470 | + * | |
471 | + * Dies ist eine Callback-Methode die zu jedem keypress-event | |
472 | + * im Canvas aufgerufen wird. Hierüber ist es möglich | |
473 | + * das Programm zu steuern. Diese Methode wird ausschließlich | |
474 | + * vom Dispatcher \ref d aufgerufen. | |
475 | + * | |
476 | + * \param es Die Quelle des Events, in diesem Fall also der Canvas | |
477 | + * \param key Der Ascii-Code der gedrückten Taste. | |
478 | + * | |
479 | + * \pre exitOnEsc muß als callback in \ref d registriert sein. | |
480 | + * \pre \ref scr muß ein gültiger canvas sein. | |
481 | + * | |
482 | + * \post Falls ESC gedrückt wurde -> Programmende | |
483 | + * \post Falls s oder S gedrückt wurde Dispatcher anhalten | |
484 | + * \post Falls c oder C gedr%uuml;ckt wurde Dispatcher starten | |
485 | + */ | |
486 | + void exitOnEsc(event_source* es, void* key) { | |
487 | + switch (*(char*)key) { | |
488 | + case 27: | |
489 | + d->trigger_event(Stop); | |
490 | + case 'x': | |
491 | + case 'X': | |
492 | + d->halt(); | |
493 | + break; | |
494 | + case 'c': | |
495 | + case 'C': | |
496 | + d->cont(); | |
497 | + break; | |
498 | + case '+': | |
499 | + cam_stepping=(cam_stepping+1)%11; | |
500 | + break; | |
501 | + case '-': | |
502 | + cam_stepping=cam_stepping>0?(cam_stepping-1)%11:10; | |
503 | + break; | |
504 | + case 'q': | |
505 | + case 'Q': | |
506 | + clip_front=clip_front>0?clip_front-10:0; | |
507 | + break; | |
508 | + case 'w': | |
509 | + case 'W': | |
510 | + clip_front=clip_front<100?clip_front+10:100; | |
511 | + break; | |
512 | + case 'r': | |
513 | + case 'R': | |
514 | + li_stepping=(li_stepping+1)%11; | |
515 | + break; | |
516 | + case 'e': | |
517 | + case 'E': | |
518 | + li_stepping=li_stepping>0?(li_stepping-1)%11:10; | |
519 | + break; | |
520 | + case 'z': | |
521 | + case 'Z': | |
522 | + li2_stepping=(li2_stepping+1)%11; | |
523 | + break; | |
524 | + case 't': | |
525 | + case 'T': | |
526 | + li2_stepping=li2_stepping>0?(li2_stepping-1)%11:10; | |
527 | + break; | |
528 | + case 'd': | |
529 | + case 'D': | |
530 | + stepping=(stepping+1)%11; | |
531 | + break; | |
532 | + case 's': | |
533 | + case 'S': | |
534 | + stepping=0; | |
535 | + break; | |
536 | + case 'a': | |
537 | + case 'A': | |
538 | + stepping=stepping>0?(stepping-1)%11:10; | |
539 | + default: | |
540 | + break; | |
541 | + } | |
542 | + } | |
543 | + | |
544 | + /** | |
545 | + * \brief Rotiert, projeziert und zeichnet die drei Polyeder | |
546 | + * \ref p, \ref p2 und \ref p3 | |
547 | + * | |
548 | + * Hier werden mit Hilfe der Klassen aus \ref Mmn.h, \ref sin_cos.h und | |
549 | + * \ref V_K4.h die Polyeder gedreht, skaliert, projeziert und | |
550 | + * schließlich mit Hilfe der Methoden des Rasterizers \ref ras | |
551 | + * auch noch gezeichnet. Am ende wird dann ein Expose-Event | |
552 | + * ausgelöst, damit die Änderungen auch am Bildschirm | |
553 | + * sichtbar werden. | |
554 | + * | |
555 | + * \note Im Moment wir rotate auch über disp_x11 aufgerufen, das ist | |
556 | + * nicht notwendig, und eigentlich sogar falsch, denn es wird überhaupt | |
557 | + * nicht auf ein X-Event reagiert. Was ich brauche ist ein weiteren | |
558 | + * Dispatcher (disp_app) der Application-Events aufführt, | |
559 | + * Die Rotation müsste dann quasi im idle-Fall ausgeführt werden. | |
560 | + * Es würde sicherlich Sinn machen diesen dispatcher dann irgendwie | |
561 | + * als thread zu implementieren. Immerhin ist X ja auch ein eigener | |
562 | + * Prozess. (OK, der Vergleich hinkt, da ich die XEvents auch im | |
563 | + * Hauptprozess abarbeite. | |
564 | + * | |
565 | + * \param es Die Quelle des Events, in diesem Fall also der canvas | |
566 | + * \param dummy Wird nicht benutzt | |
567 | + * | |
568 | + * \pre redraw muß als callback in \ref d registriert sein. | |
569 | + * \pre \ref scr muß ein gültiger canvas sein. | |
570 | + * | |
571 | + * \post Die Polyeder sind transformiert und auf dem Canvas | |
572 | + * gezeichnet. Ein Expose-Event wurde ausgelöst. | |
573 | + */ | |
574 | + void rotate(event_source* es, void* dummy) { | |
575 | + struct timeb tb1; | |
576 | + struct timeb tb2; | |
577 | + | |
578 | + ftime(&tb1); | |
579 | + | |
580 | + winkel=WINKEL(winkel+stepping); | |
581 | + | |
582 | + cam_winkel=WINKEL(cam_winkel+cam_stepping); | |
583 | + li_winkel=WINKEL(li_winkel-li_stepping); | |
584 | + li2_winkel=WINKEL(li2_winkel+li2_stepping); | |
585 | + | |
586 | + container<polygon> po_list, po_list_zclipped; | |
587 | + | |
588 | + //if(winkel==3) | |
589 | + // sleep(10); | |
590 | + | |
591 | + p.rotate_im_g_x(45); | |
592 | + p.translate_im_global(-30.0*sin(RAD(winkel)), | |
593 | + 5.0*cos(RAD(winkel)), | |
594 | + 10.0*cos(RAD(winkel))); | |
595 | + p.rotate_im_vfw(WINKEL(2*winkel)); | |
596 | + | |
597 | + p2.translate_im_global(5.0*cos(RAD(winkel)), | |
598 | + 20.0*sin(RAD(winkel)), | |
599 | + 20.0*cos(RAD(winkel))); | |
600 | + p2.rotate_im_l_z(WINKEL(winkel)); | |
601 | + p2.rotate_im_l_y(WINKEL(360-winkel)); | |
602 | + p2.translate_im_global(0,0,-5); | |
603 | + | |
604 | + //p3.translate_im_global(0,0,5); | |
605 | + | |
606 | + p4.translate_im_global(0,0,15); | |
607 | + p4.rotate_im_g_x(WINKEL(winkel)); | |
608 | + p4.rotate_im_g_y(WINKEL(winkel)); | |
609 | + p4.translate_im_global(0,0,5); | |
610 | + | |
611 | + cam.translate_im_global(0,0,-60); | |
612 | + cam.rotate_im_g_y(WINKEL(-cam_winkel)); | |
613 | + cam.rotate_im_axis(WINKEL(cam_winkel), | |
614 | + vertex(1,0,1,COORD), vertex(0,0,0,COORD)); | |
615 | + | |
616 | + li.translate_im_global(0,0,-10); | |
617 | + li.rotate_im_g_y(WINKEL(45.0)); | |
618 | + li.rotate_im_axis(WINKEL(li_winkel), | |
619 | + vertex(1,0,-1,COORD), vertex(0,0,0,COORD)); | |
620 | + | |
621 | + li2.translate_im_global(0,0,-10); | |
622 | + li2.rotate_im_g_x(WINKEL(li2_winkel)); | |
623 | + | |
624 | + Mmn<double> ctm(cam.cam_trans_mat()); | |
625 | + | |
626 | + p.move_im(ctm); | |
627 | + p2.move_im(ctm); | |
628 | + p3.move_im(ctm); | |
629 | + p4.move_im(ctm); | |
630 | + li.move_im(ctm); | |
631 | + li2.move_im(ctm); | |
632 | + | |
633 | + /* p.transform(1); | |
634 | + p2.transform(1); | |
635 | + p3.transform(1); | |
636 | + p4.transform(1); | |
637 | + | |
638 | + cam.transform(1); */ | |
639 | + | |
640 | + // Zu Anfang reicht es die Vertexe für die Objektposition und | |
641 | + // die Normalenvertexe zu transformieren, dann kommt das | |
642 | + // backface culling und nur wenn ein polygon wirklich gezeichnet | |
643 | + // wird mache ich die letzten transformationen und die | |
644 | + // projektion. | |
645 | + p.transform_normals(1); | |
646 | + p2.transform_normals(1); | |
647 | + p3.transform_normals(1); | |
648 | + p4.transform_normals(1); | |
649 | + | |
650 | + p.movable::transform(1); | |
651 | + p2.movable::transform(1); | |
652 | + p3.movable::transform(1); | |
653 | + p4.movable::transform(1); | |
654 | + | |
655 | + li.transform(1); | |
656 | + li2.transform(1); | |
657 | + | |
658 | + /* p.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(), | |
659 | + cam.get_ph_ar(), cam.get_sy(), 2); | |
660 | + p2.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(), | |
661 | + cam.get_ph_ar(), cam.get_sy(), 2); | |
662 | + p3.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(), | |
663 | + cam.get_ph_ar(), cam.get_sy(), 2); | |
664 | + p4.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(), | |
665 | + cam.get_ph_ar(), cam.get_sy(), 2); */ | |
666 | + | |
667 | + // Ich muss nach einem verdammt guten Weg suchen herauszufinden | |
668 | + // zu welchem polyeder ein polygon gehoert, ich denke das beste ist | |
669 | + // einen pointer auf den polyeder im polygon zu speichern wenn | |
670 | + // es einem polyeder zugeordnet wird. | |
671 | + vertex view, normal, center, norm_v; | |
672 | + | |
673 | + for(unsigned i=0; i<p.card(); i++) { | |
674 | + view=p.get_vrp(); | |
675 | + | |
676 | + center=p[i].center_p(); | |
677 | + normal=p[i].normal_p(); | |
678 | + norm_v=normal-center; | |
679 | + | |
680 | + if(((norm_v%view)/(norm_v.betr()*view.betr())) < 0.0) { | |
681 | + po_list[po_list.card()]=p[i]; | |
682 | + po_list[po_list.card()-1].transform(p.get_t_mat(), 1); | |
683 | + } | |
684 | + } | |
685 | + | |
686 | + for(unsigned i=0; i<p2.card(); i++) { | |
687 | + view=p2.get_vrp(); | |
688 | + | |
689 | + center=p2[i].center_p(); | |
690 | + normal=p2[i].normal_p(); | |
691 | + norm_v=normal-center; | |
692 | + | |
693 | + if(((norm_v%view)/(norm_v.betr()*view.betr())) < 0.0) { | |
694 | + po_list[po_list.card()]=p2[i]; | |
695 | + po_list[po_list.card()-1].transform(p2.get_t_mat(), 1); | |
696 | + } | |
697 | + } | |
698 | + | |
699 | + for(unsigned i=0; i<p3.card(); i++) { | |
700 | + //hier kein backface-culling... | |
701 | + | |
702 | + //view=p3.get_vrp(); | |
703 | + | |
704 | + //center=p3[i].center_p(); | |
705 | + //normal=p3[i].normal_p(); | |
706 | + //norm_v=normal-center; | |
707 | + | |
708 | + //if(((norm_v%view)/(norm_v.betr()*view.betr())) < 0.0) { | |
709 | + po_list[po_list.card()]=p3[i]; | |
710 | + po_list[po_list.card()-1].transform(p3.get_t_mat(), 1); | |
711 | + //} | |
712 | + } | |
713 | + | |
714 | + for(unsigned i=0; i<p4.card(); i++) { | |
715 | + view=p4.get_vrp(); | |
716 | + | |
717 | + center=p4[i].center_p(); | |
718 | + normal=p4[i].normal_p(); | |
719 | + norm_v=normal-center; | |
720 | + | |
721 | + if(((norm_v%view)/(norm_v.betr()*view.betr())) < 0.0) { | |
722 | + po_list[po_list.card()]=p4[i]; | |
723 | + po_list[po_list.card()-1].transform(p4.get_t_mat(), 1); | |
724 | + } | |
725 | + } | |
726 | + | |
727 | + po_list.sort(compf); | |
728 | + | |
729 | + for(unsigned i=0; i<po_list.card(); i++) { | |
730 | + po_list_zclipped[i]=po_list[i].clip_front_z(clip_front); | |
731 | + } | |
732 | + | |
733 | + ras->clear_buffer(); | |
734 | + | |
735 | + double normal_X[6]; | |
736 | + double normal_Y[6]; | |
737 | + | |
738 | + for(unsigned i=0; i<po_list.card(); i++) { | |
739 | + int idx; | |
740 | + | |
741 | + if((idx=p3.contains(po_list[i])) >= 0) { | |
742 | + unsigned long col; | |
743 | + | |
744 | + vertex center=po_list[i].center_p(); | |
745 | + vertex normal=po_list[i].normal_p(); | |
746 | + vertex norm_v=normal-center; | |
747 | + | |
748 | + | |
749 | + if(idx==1) | |
750 | + col=scr->get_color(0,0,255); | |
751 | + else | |
752 | + col=scr->get_color(0,255,255); | |
753 | + | |
754 | + vertex light(li.get_direction()); | |
755 | + | |
756 | + unsigned in=0, in_tmp; | |
757 | + double intense=(norm_v.norm()%light.norm())*-1; | |
758 | + intense=intense<0.02?0.02:intense; | |
759 | + intense=intense>1.0?1.0:intense; | |
760 | + | |
761 | + in_tmp=(unsigned)(intense*li.get_intensity()); | |
762 | + in=in_tmp>in?in_tmp:in; | |
763 | + | |
764 | + light=li2.get_direction(); | |
765 | + | |
766 | + intense=(norm_v.norm()%light.norm())*-1; | |
767 | + intense=intense<0.02?0.02:intense; | |
768 | + intense=intense>1.0?1.0:intense; | |
769 | + | |
770 | + in_tmp=(unsigned)(intense*li2.get_intensity()); | |
771 | + in=in_tmp>in?in_tmp:in; | |
772 | + in_tmp=(unsigned)(li3.get_intensity()); | |
773 | + in=in_tmp>in?in_tmp:in; | |
774 | + | |
775 | + scr->light_native(&col, in); | |
776 | + | |
777 | + if(po_list_zclipped[i].card() >= 3) { | |
778 | + po_list_zclipped[i].project_2d(cam.get_lcx(), cam.get_sw(), | |
779 | + cam.get_sh(), cam.get_ph_ar(), | |
780 | + cam.get_sy(), 2); | |
781 | + ras->draw_polygon_flat(po_list_zclipped[i], col); | |
782 | + } | |
783 | + } | |
784 | + | |
785 | + if((idx=p4.contains(po_list[i])) >= 0) { | |
786 | + unsigned long col=scr->get_color(0,0,255); | |
787 | + | |
788 | + vertex center=po_list[i].center_p(); | |
789 | + vertex normal=po_list[i].normal_p(); | |
790 | + vertex norm_v=normal-center; | |
791 | + | |
792 | + vertex light(li.get_direction()); | |
793 | + | |
794 | + unsigned in=0, in_tmp; | |
795 | + double intense=(norm_v.norm()%light.norm())*-1; | |
796 | + intense=intense<0.02?0.02:intense; | |
797 | + intense=intense>1.0?1.0:intense; | |
798 | + | |
799 | + in_tmp=(unsigned)(intense*li.get_intensity()); | |
800 | + in=in_tmp>in?in_tmp:in; | |
801 | + | |
802 | + light=li2.get_direction(); | |
803 | + | |
804 | + intense=(norm_v.norm()%light.norm())*-1; | |
805 | + intense=intense<0.02?0.02:intense; | |
806 | + intense=intense>1.0?1.0:intense; | |
807 | + | |
808 | + in_tmp=(unsigned)(intense*li2.get_intensity()); | |
809 | + in=in_tmp>in?in_tmp:in; | |
810 | + in_tmp=(unsigned)(li3.get_intensity()); | |
811 | + in=in_tmp>in?in_tmp:in; | |
812 | + | |
813 | + scr->light_native(&col, in); | |
814 | + | |
815 | + if(po_list_zclipped[i].card() >= 3) { | |
816 | + po_list_zclipped[i].project_2d(cam.get_lcx(), cam.get_sw(), | |
817 | + cam.get_sh(), cam.get_ph_ar(), | |
818 | + cam.get_sy(), 2); | |
819 | + ras->draw_polygon_flat(po_list_zclipped[i], col); | |
820 | + //ras->draw_polygon_wire(po_list_zclipped[i], | |
821 | + // scr->get_color(255, 255, 255)); | |
822 | + } | |
823 | + } | |
824 | + | |
825 | + if((idx=p.contains(po_list[i])) >= 0) { | |
826 | + unsigned long col=scr->get_color(255,0,0); | |
827 | + | |
828 | + vertex center=po_list[i].center_p(); | |
829 | + vertex normal=po_list[i].normal_p(); | |
830 | + vertex norm_v=normal-center; | |
831 | + | |
832 | + vertex light(li.get_direction()); | |
833 | + | |
834 | + unsigned in=0, in_tmp; | |
835 | + double intense=(norm_v.norm()%light.norm())*-1; | |
836 | + intense=intense<0.02?0.02:intense; | |
837 | + intense=intense>1.0?1.0:intense; | |
838 | + | |
839 | + in_tmp=(unsigned)(intense*li.get_intensity()); | |
840 | + in=in_tmp>in?in_tmp:in; | |
841 | + | |
842 | + light=li2.get_direction(); | |
843 | + | |
844 | + intense=(norm_v.norm()%light.norm())*-1; | |
845 | + intense=intense<0.02?0.02:intense; | |
846 | + intense=intense>1.0?1.0:intense; | |
847 | + | |
848 | + in_tmp=(unsigned)(intense*li2.get_intensity()); | |
849 | + in=in_tmp>in?in_tmp:in; | |
850 | + in_tmp=(unsigned)(li3.get_intensity()); | |
851 | + in=in_tmp>in?in_tmp:in; | |
852 | + | |
853 | + scr->light_native(&col, in); | |
854 | + | |
855 | + center.project_2d(cam.get_lcx(), cam.get_sw(), | |
856 | + cam.get_sh(), cam.get_ph_ar(), | |
857 | + cam.get_sy(), | |
858 | + center.get_trans_stage()+1); | |
859 | + normal.project_2d(cam.get_lcx(), cam.get_sw(), | |
860 | + cam.get_sh(), cam.get_ph_ar(), | |
861 | + cam.get_sy(), | |
862 | + center.get_trans_stage()+1); | |
863 | + | |
864 | + if(po_list_zclipped.card() >= 3) { | |
865 | + po_list_zclipped[i].project_2d(cam.get_lcx(), cam.get_sw(), | |
866 | + cam.get_sh(), cam.get_ph_ar(), | |
867 | + cam.get_sy(), 2); | |
868 | + ras->draw_polygon_flat(po_list_zclipped[i], col); | |
869 | + //ras->draw_polygon_wire(po_list_zclipped[i], | |
870 | + // scr->get_color(255, 255, 255)); | |
871 | + ras->line(center[X], center[Y], normal[X], normal[Y], | |
872 | + scr->get_color(0, 0, 0)); | |
873 | + } | |
874 | + } | |
875 | + | |
876 | + if((idx=p2.contains(po_list[i])) >= 0) { | |
877 | + unsigned long col=scr->get_color(0,255,0); | |
878 | + | |
879 | + vertex center=po_list[i].center_p(); | |
880 | + vertex normal=po_list[i].normal_p(); | |
881 | + vertex norm_v=normal-center; | |
882 | + | |
883 | + vertex light(li.get_direction()); | |
884 | + | |
885 | + unsigned in=0, in_tmp; | |
886 | + double intense=(norm_v.norm()%light.norm())*-1; | |
887 | + intense=intense<0.02?0.02:intense; | |
888 | + intense=intense>1.0?1.0:intense; | |
889 | + | |
890 | + in_tmp=(unsigned)(intense*li.get_intensity()); | |
891 | + in=in_tmp>in?in_tmp:in; | |
892 | + | |
893 | + light=li2.get_direction(); | |
894 | + | |
895 | + intense=(norm_v.norm()%light.norm())*-1; | |
896 | + intense=intense<0.02?0.02:intense; | |
897 | + intense=intense>1.0?1.0:intense; | |
898 | + | |
899 | + in_tmp=(unsigned)(intense*li2.get_intensity()); | |
900 | + in=in_tmp>in?in_tmp:in; | |
901 | + in_tmp=(unsigned)(li3.get_intensity()); | |
902 | + in=in_tmp>in?in_tmp:in; | |
903 | + | |
904 | + scr->light_native(&col, in); | |
905 | + | |
906 | + center.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(), | |
907 | + cam.get_ph_ar(), cam.get_sy(), | |
908 | + center.get_trans_stage()+1); | |
909 | + normal.project_2d(cam.get_lcx(), cam.get_sw(), cam.get_sh(), | |
910 | + cam.get_ph_ar(), cam.get_sy(), | |
911 | + center.get_trans_stage()+1); | |
912 | + | |
913 | + if(po_list_zclipped[i].card() >= 3) { | |
914 | + po_list_zclipped[i].project_2d(cam.get_lcx(), cam.get_sw(), | |
915 | + cam.get_sh(), cam.get_ph_ar(), | |
916 | + cam.get_sy(), 2); | |
917 | + ras->draw_polygon_flat(po_list_zclipped[i], col); | |
918 | + //ras->draw_polygon_wire(po_list_zclipped[i], | |
919 | + // scr->get_color(255, 255, 255)); | |
920 | + ras->line(center[X], center[Y], normal[X], normal[Y], | |
921 | + scr->get_color(0, 0, 0)); | |
922 | + } | |
923 | + } | |
924 | + } | |
925 | + | |
926 | + //ras->draw_polyeder_wire(p, scr->get_color(255,255,255)); | |
927 | + //ras->draw_polyeder_wire(p2, scr->get_color(255,255,255)); | |
928 | + | |
929 | + p.reset(); | |
930 | + p2.reset(); | |
931 | + p3.reset(); | |
932 | + p4.reset(); | |
933 | + cam.reset(); | |
934 | + li.reset(); | |
935 | + li2.reset(); | |
936 | + | |
937 | + ftime(&tb2); | |
938 | + | |
939 | + secs_tmp=tb2.time-tb1.time; | |
940 | + ms=(secs_tmp*1000+tb2.millitm)-tb1.millitm; | |
941 | + secs=(secs_tmp>0)?ms/(secs_tmp*1000):0; | |
942 | + ms=(secs_tmp>0)?ms%(secs_tmp*1000):ms; | |
943 | + | |
944 | + d->trigger_event(Draw); | |
945 | + } | |
946 | + | |
947 | + public: | |
948 | + /** | |
949 | + * \brief Konstruktor | |
950 | + * | |
951 | + * Alle Grundlegenden Initialisierungen. Canvas, Dispatcher und | |
952 | + * Rasterizer erzeugen. Callbacks registrieren und | |
953 | + * Polyeder erzeugen. Eckwerte für die 2D-Projektion festlegen. | |
954 | + */ | |
955 | + app() { | |
956 | + // Der factory_manager erzeugt mir den gewünschten | |
957 | + // Canvas und Dispatcher. | |
958 | + factory_manager f; | |
959 | + | |
960 | + // Erzeuge den Canvas, Dispatcher und Rasterizer | |
961 | + scr=f.canvas_f->create(400, 300); | |
962 | + d=f.dispatcher_f->create(scr); | |
963 | + ras=scr->create_rasterizer(); | |
964 | + | |
965 | + // Registriere die Callbacks und trage Dispatcher in Manager ein | |
966 | + d->register_callback(Key, mk_callback(*this, &app::exitOnEsc)); | |
967 | + d->register_callback(Idle, mk_callback(*this, &app::rotate)); | |
968 | + d->register_callback(Draw, mk_callback(*this, &app::redraw)); | |
969 | + | |
970 | + manager[0]=d; | |
971 | + d->register_callback(Stop, | |
972 | + mk_callback(manager, &disp_manager::stop)); | |
973 | + | |
974 | + // Dann wolln wir die cam mal initilisieren. | |
975 | + cam=camera(*ras, 50.0); | |
976 | + li2.set_intensity(127); | |
977 | + li3.set_intensity(40); | |
978 | + | |
979 | + // zuerst werden alle nötigen Vertexe erzeugt | |
980 | + vertex v[]={vertex(5,5,5,1), | |
981 | + vertex(5,-5,5,1), | |
982 | + vertex(-5,-5,5,1), | |
983 | + vertex(-5,5,5,1), | |
984 | + vertex(5,5,-5,1), | |
985 | + vertex(5,-5,-5,1), | |
986 | + vertex(-5,-5,-5,1), | |
987 | + vertex(-5,5,-5,1)}; | |
988 | + | |
989 | + // und in einer Vertexliste gespeicher. | |
990 | + vertex_list vl(v, 8); | |
991 | + | |
992 | + // ein Hilfsarray erzeugt um damit | |
993 | + unsigned v_idx[][4]={{3,2,1,0}, // hinten | |
994 | + {0,1,5,4}, // rechts | |
995 | + {4,5,6,7}, // vorne | |
996 | + {7,6,2,3}, // links | |
997 | + {4,0,3,7}, // oben | |
998 | + {1,5,6,2}}; // unten | |
999 | + | |
1000 | + // die Polygone zu definieren. | |
1001 | + // (Der letzte Parameter ist die Vertexliste die das Polygon | |
1002 | + // nutzen soll. Hier kann ich NULL nehmen, da sie beim erzeugen | |
1003 | + // der Polyeders auf dessen Vertexliste gesetzt werden. | |
1004 | + // (siehe unten)) | |
1005 | + /*polygon_movable pa[]={ | |
1006 | + polygon_movable((unsigned*)v_idx[0], 4, NULL), | |
1007 | + polygon_movable((unsigned*)v_idx[1], 4, NULL), | |
1008 | + polygon_movable((unsigned*)v_idx[2], 4, NULL), | |
1009 | + polygon_movable((unsigned*)v_idx[3], 4, NULL), | |
1010 | + polygon_movable((unsigned*)v_idx[4], 4, NULL), | |
1011 | + polygon_movable((unsigned*)v_idx[5], 4, NULL)};*/ | |
1012 | + polygon pa[]={ | |
1013 | + polygon((unsigned*)v_idx[0], 4, NULL), | |
1014 | + polygon((unsigned*)v_idx[1], 4, NULL), | |
1015 | + polygon((unsigned*)v_idx[2], 4, NULL), | |
1016 | + polygon((unsigned*)v_idx[3], 4, NULL), | |
1017 | + polygon((unsigned*)v_idx[4], 4, NULL), | |
1018 | + polygon((unsigned*)v_idx[5], 4, NULL)}; | |
1019 | + | |
1020 | + | |
1021 | + // Jetzt definieren wir mit der oben erzeugten Vertexlist und | |
1022 | + // dem Array aus Polygonen 2 Polyeder, die wir beide vom | |
1023 | + // Ursprung auf der Z-Achse weg bewegen. | |
1024 | + p=polyeder(pa, 6, vl); | |
1025 | + p2=polyeder(pa, 6, vl); | |
1026 | + p4=polyeder(pa, 6, vl); | |
1027 | + | |
1028 | + p[2].set_id("DEBUG"); | |
1029 | + cout << "BLA: " << p[2].get_id() << "\n"; | |
1030 | + | |
1031 | + polygon pa3[]={polygon((unsigned*)v_idx[0], 4, NULL), | |
1032 | + polygon((unsigned*)v_idx[2], 4, NULL)}; | |
1033 | + p3=polyeder(pa3, 2, vl); | |
1034 | + | |
1035 | + winkel=0; | |
1036 | + stepping=0; | |
1037 | + cam_winkel=0; | |
1038 | + cam_stepping=0; | |
1039 | + li_winkel=WINKEL(-45.0); | |
1040 | + li_stepping=0; | |
1041 | + li2_winkel=WINKEL(90.0); | |
1042 | + li2_stepping=0; | |
1043 | + clip_front=0; | |
1044 | + //halt=false; | |
1045 | + } | |
1046 | + | |
1047 | + /** | |
1048 | + * \brief Destruktor | |
1049 | + * | |
1050 | + * freigeben und entfernen alles dynamisch erzeugten Elemente. | |
1051 | + */ | |
1052 | + ~app() { | |
1053 | + delete ras; | |
1054 | + delete d; | |
1055 | + delete scr; | |
1056 | + } | |
1057 | + | |
1058 | + /** | |
1059 | + * \brief startet den Manager und damit das Programm. | |
1060 | + */ | |
1061 | + void go(void) { | |
1062 | + manager.start(); | |
1063 | + } | |
1064 | +}; | |
1065 | + | |
1066 | +int main(int argc, char* argv[]) { | |
1067 | + app a; | |
1068 | + | |
1069 | + a.go(); | |
1070 | + | |
1071 | + // cout << "jokus\n"; | |
1072 | + | |
1073 | + return 0; | |
1074 | +} | |
1075 | + | |
1076 | +#endif | ... | ... |
helper/Makefile
0 → 100755
helper/container.h
0 → 100755
1 | +/** | |
2 | + * \file container.h | |
3 | + * | |
4 | + * \brief Definition eines Container-Templates | |
5 | + * | |
6 | + * Hiermit können alle möglichen Daten organisiert werden. | |
7 | + | |
8 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
9 | + * | |
10 | + * \date 04.12.2003 | |
11 | + * | |
12 | + * \version ..2002 [gs]: erste funktionierende Implementation | |
13 | + * \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen | |
14 | + * \version 19.12.2003 [gs]: <ul><li> | |
15 | + * Vergleichsoperator hinzugefügt. | |
16 | + * </li><li> | |
17 | + * die Methode contains hinzugefügt, die | |
18 | + * über den Vergleichsoperator eines | |
19 | + * Elements prüft ob es in diesem Container | |
20 | + * existiert. | |
21 | + * </li></ul> | |
22 | + */ | |
23 | + | |
24 | +/* | |
25 | + * Copyright (C)2003 Georg Steffers | |
26 | + * | |
27 | + * This program is free software; you can redistribute it and/or modify | |
28 | + * it under the terms of the GNU General Public License as published by | |
29 | + * the Free Software Foundation; either version 2 of the License, or | |
30 | + * (at your option) any later version. | |
31 | + * | |
32 | + * This program is distributed in the hope that it will be useful, | |
33 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
34 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
35 | + * GNU General Public License for more details. | |
36 | + * | |
37 | + * You should have received a copy of the GNU General Public License | |
38 | + * along with this program; if not, write to the Free Software | |
39 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
40 | + */ | |
41 | + | |
42 | +#ifndef __container_h__ | |
43 | +#define __container_h__ | |
44 | + | |
45 | +#include <stdlib.h> | |
46 | + | |
47 | +template <class C> | |
48 | +class container { | |
49 | + protected: | |
50 | + C* content; | |
51 | + unsigned count; | |
52 | + | |
53 | + public: | |
54 | + container(); | |
55 | + container(const C& c); | |
56 | + container(const C* c, unsigned co); | |
57 | + container(const container<C>& c); | |
58 | + virtual ~container(); | |
59 | + | |
60 | + virtual const container<C>& operator=(const container<C>& c); | |
61 | + virtual bool operator==(const container<C>& c) const { | |
62 | + if(count==c.count) { | |
63 | + for(unsigned i=0; i<count; i++) | |
64 | + if(!(content[i]==c[i])) | |
65 | + return false; | |
66 | + } | |
67 | + else | |
68 | + return false; | |
69 | + | |
70 | + return true; | |
71 | + } | |
72 | + | |
73 | + const C& operator[](unsigned index) const; | |
74 | + C& operator[](unsigned index); | |
75 | + | |
76 | + //! Prüft ob ein Element in dem Container ist. | |
77 | + //! Gibt -1 zurück falls nicht, ansonsten den index an dem | |
78 | + //! sich das Element vefindet | |
79 | + int contains(const C& c) { | |
80 | + for(unsigned i=0; i<count; i++) | |
81 | + if(content[i]==c) | |
82 | + return i; | |
83 | + | |
84 | + return -1; | |
85 | + } | |
86 | + | |
87 | + void sort(int (*comp)(const void*, const void*)) { | |
88 | + qsort(content, count, sizeof(C), comp); | |
89 | + } | |
90 | + | |
91 | + void resize(unsigned size); | |
92 | + unsigned card(void) const { return count; } | |
93 | + virtual void insert(unsigned idx, const C& value); | |
94 | +}; | |
95 | + | |
96 | +#include "container_tpl.h" | |
97 | + | |
98 | +#endif // __container_h__ | ... | ... |
helper/container_tpl.h
0 → 100755
1 | +/** | |
2 | + * \file container_tpl.h | |
3 | + * | |
4 | + * \brief ein Template das als Behälter für alles mögliche dient. | |
5 | + * | |
6 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
7 | + * | |
8 | + * \date 16.12.2003 | |
9 | + * | |
10 | + * \version ..2002 [gs]: erste Implementation | |
11 | + * \version 16.12.2003 [gs]: <ul><li> | |
12 | + * Beginn der Dokumentaion mit Doxygen | |
13 | + * </li><li> | |
14 | + * Einige Änderungen, so das | |
15 | + * content in einem leeren container | |
16 | + * NULL ist und dann entsprechen auch | |
17 | + * nicht alle Aktionen mit diesem | |
18 | + * container möglich sind. | |
19 | + * </li></ul> | |
20 | + */ | |
21 | + | |
22 | +/* | |
23 | + * Copyright (C)2003 Georg Steffers | |
24 | + * | |
25 | + * This program is free software; you can redistribute it and/or modify | |
26 | + * it under the terms of the GNU General Public License as published by | |
27 | + * the Free Software Foundation; either version 2 of the License, or | |
28 | + * (at your option) any later version. | |
29 | + * | |
30 | + * This program is distributed in the hope that it will be useful, | |
31 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
32 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
33 | + * GNU General Public License for more details. | |
34 | + * | |
35 | + * You should have received a copy of the GNU General Public License | |
36 | + * along with this program; if not, write to the Free Software | |
37 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
38 | + */ | |
39 | + | |
40 | +using namespace std; | |
41 | + | |
42 | +#include <cstring> | |
43 | +#include "container.h" | |
44 | + | |
45 | +template <class C> | |
46 | +container<C>::container() : content(NULL), count(0) { | |
47 | + //content=new C[1]; | |
48 | +} | |
49 | + | |
50 | +template <class C> | |
51 | +container<C>::container(const C& c) : count(1) { | |
52 | + content=new C[1]; | |
53 | + content[0]=c; | |
54 | +} | |
55 | + | |
56 | +template <class C> | |
57 | +container<C>::container(const C* c, unsigned co) : count(co) { | |
58 | + if(count > 0) | |
59 | + content=new C[count]; | |
60 | + else | |
61 | + content=NULL; | |
62 | + | |
63 | + for(unsigned i=0; i<count; i++) | |
64 | + content[i]=c[i]; | |
65 | +} | |
66 | + | |
67 | +template <class C> | |
68 | +container<C>::container(const container<C>& c) : count(c.count) { | |
69 | + if(count > 0) | |
70 | + content=new C[count]; | |
71 | + else | |
72 | + content=NULL; | |
73 | + | |
74 | + for(unsigned i=0; i<count; i++) | |
75 | + content[i]=c.content[i]; | |
76 | +} | |
77 | + | |
78 | +template <class C> | |
79 | +container<C>::~container() { | |
80 | + if(content) { | |
81 | + delete [] content; | |
82 | + content=NULL; | |
83 | + } | |
84 | + count=0; | |
85 | +} | |
86 | + | |
87 | +template <class C> | |
88 | +const container<C>& container<C>::operator=(const container<C>& c) { | |
89 | + if(this==&c) | |
90 | + return *this; | |
91 | + | |
92 | + if(count != c.count) { | |
93 | + delete [] content; | |
94 | + if(c.count > 0) | |
95 | + content=new C[c.count]; | |
96 | + else | |
97 | + content=NULL; | |
98 | + } | |
99 | + | |
100 | + count=c.count; | |
101 | + | |
102 | + for(unsigned i=0; i<count; i++) | |
103 | + content[i]=c.content[i]; | |
104 | + | |
105 | + return *this; | |
106 | +} | |
107 | + | |
108 | +template <class C> | |
109 | +const C& container<C>::operator[](unsigned index) const { | |
110 | + if(index+1 > count) | |
111 | + return content[0]; | |
112 | + | |
113 | + return content[index]; | |
114 | +} | |
115 | + | |
116 | +template <class C> | |
117 | +C& container<C>::operator[](unsigned index) { | |
118 | + if(index+1 > count) { | |
119 | + C* content_tmp=new C[index+1]; | |
120 | + | |
121 | + for(unsigned i=0; i<count; i++) | |
122 | + content_tmp[i]=content[i]; | |
123 | +// memcpy(content_tmp, content, count*sizeof(C)); | |
124 | + | |
125 | + delete [] content; | |
126 | + content=content_tmp; | |
127 | + count=index+1; | |
128 | + } | |
129 | + | |
130 | + return content[index]; | |
131 | +} | |
132 | + | |
133 | +// WARNUNG!!! Diese funktion verkleiner auch ohne weitern check. d.h. ist | |
134 | +// size < count, dann verliert man alle Einträge >size. | |
135 | +template <class C> | |
136 | +void container<C>::resize(unsigned size) { | |
137 | + C* content_tmp; | |
138 | + | |
139 | + if(size>0) { | |
140 | + content_tmp=new C[size]; | |
141 | + | |
142 | + for(unsigned i=0; i<size<count?size:count; i++) | |
143 | + content_tmp[i]=content[i]; | |
144 | + } | |
145 | + else | |
146 | + content_tmp=NULL; | |
147 | + | |
148 | + delete [] content; | |
149 | + content=content_tmp; | |
150 | + count=size; | |
151 | +} | |
152 | + | |
153 | +template <class C> | |
154 | +void container<C>::insert(unsigned idx, const C& value) { | |
155 | + C* content_tmp=new C[count+1]; | |
156 | + | |
157 | + memcpy(content_tmp, content, idx*sizeof(C)); | |
158 | + content_tmp[idx]=value; | |
159 | + | |
160 | + for(unsigned i=0; i<count; i++) | |
161 | + content_tmp[i]=content[i]; | |
162 | +// memcpy(&content_tmp[idx+1], &content[idx], (count-idx)*sizeof(C)); | |
163 | + | |
164 | + delete [] content; | |
165 | + content=content_tmp; | |
166 | + count++; | |
167 | +} | ... | ... |
math/Makefile
0 → 100755
math/Mmn.h
0 → 100755
1 | +/** | |
2 | + * \file Mmn.h | |
3 | + * | |
4 | + * \brief Matrizenmanipulation beliebiger Matrizen | |
5 | + * | |
6 | + * Stellt eine Klasse zur verfügung, mit der sich alle denkbaren | |
7 | + * algebraischen Manipulationen an Matrizen beliebiger größe | |
8 | + * ausführen lassen, incl. lösen eines Gleichungssystems dessen | |
9 | + * erweiterte Koeffizientenmatrix diese Matrix ist. | |
10 | + * | |
11 | + * \author Georg Steffers <georg@steffers.org> [GS] | |
12 | + * | |
13 | + * \date 06.12.2003 | |
14 | + * | |
15 | + * \version ..2002 erste funktionierende Version [GS] | |
16 | + * \version 06.12.2003 beginn der Dokumentation via doxygen [GS] | |
17 | + */ | |
18 | + | |
19 | +/* | |
20 | + * Copyright (C)2003 Georg Steffers | |
21 | + * | |
22 | + * This program is free software; you can redistribute it and/or modify | |
23 | + * it under the terms of the GNU General Public License as published by | |
24 | + * the Free Software Foundation; either version 2 of the License, or | |
25 | + * (at your option) any later version. | |
26 | + * | |
27 | + * This program is distributed in the hope that it will be useful, | |
28 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
29 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
30 | + * GNU General Public License for more details. | |
31 | + * | |
32 | + * You should have received a copy of the GNU General Public License | |
33 | + * along with this program; if not, write to the Free Software | |
34 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
35 | + */ | |
36 | + | |
37 | +#ifndef __MMN_H__ | |
38 | +#define __MMN_H__ | |
39 | + | |
40 | +using namespace std; | |
41 | + | |
42 | +#include <cmath> | |
43 | +#include <iostream> | |
44 | + | |
45 | +#include "sin_cos.h" | |
46 | + | |
47 | +typedef enum gauss_typ {TREPPENNORMALE, INVERSE}; //!< \brief Was soll mit dem | |
48 | + //! Gauss-Algorithmus | |
49 | + //! ermittelt werden? | |
50 | + | |
51 | +template <class K> | |
52 | +class Mmn; | |
53 | + | |
54 | +//! Skalarmultiplikation Skalar * Matrize | |
55 | +template <class K> | |
56 | +Mmn<K> operator*(const K&, const Mmn<K>&); | |
57 | + | |
58 | +/** | |
59 | + * \brief Darstellung einer Matrize und der auf ihr möglichen | |
60 | + * algebraischen Operationen | |
61 | + * | |
62 | + * Diese Klasse stellt meinen Lernerfolg in Lineare Algebra I dar. | |
63 | + */ | |
64 | +template <class K> | |
65 | +class Mmn { | |
66 | + protected: | |
67 | + K** _a; //!< \brief Die Matrize als doppelter Pointer auf | |
68 | + //! den skalaren Typ K | |
69 | + unsigned m, n; //!< Zeilen, Spalten der Matrize | |
70 | + unsigned Rg; //!< \brief Der Rang der Matrize | |
71 | + //! | |
72 | + //! wird nur gefüllt wenn die Matrize über | |
73 | + //! Gauss in Treppennormalform gebracht wurde. | |
74 | + bool Det_F; //!< enthält Det einen gültigen Wert? | |
75 | + K Det; //!< \brief Die Determinante der Matrize | |
76 | + //! | |
77 | + //! Sobald sie errechnet wurde wird sie hier | |
78 | + //! gespeichert, bis die Matrize verändert | |
79 | + //! wird, damit sie nicht immer wieder neu berechnet | |
80 | + //! werden muß | |
81 | + | |
82 | + void freeall(void); //!< die matrize wieder freigeben | |
83 | + K sarrus(void) const; //!< \brief Sarrusregel | |
84 | + //! | |
85 | + //! zum ermitteln | |
86 | + //! der Determinante einer 3x3 Matrize | |
87 | + K laplace(void) const; //!< \brief Laplace'scher Entwicklungssatz | |
88 | + //! | |
89 | + //! zum ermitteln der Determinante bei | |
90 | + //! größeren Matrizen als 3x3 | |
91 | + | |
92 | + public: | |
93 | + // Konstruktoren | |
94 | + //! Defaultkontruktor | |
95 | + Mmn() : _a(NULL), m(0), n(0), Rg(0), Det_F(false) {} | |
96 | + Mmn(unsigned); //!< EinheitsMatrix | |
97 | + Mmn(unsigned, unsigned); //!< NullMatrix | |
98 | + Mmn(K*, unsigned, unsigned); //!< \brief Konstruktor für eine | |
99 | + //! beliebige Matrix | |
100 | + Mmn(const Mmn<K>&); //!< Copykonstruktor | |
101 | + virtual ~Mmn(); //!< Destruktor | |
102 | + | |
103 | + //! Zuweisungsoperator | |
104 | + const Mmn<K>& operator=(const Mmn<K>&); | |
105 | + | |
106 | + //! Skalarmultiplikation (Matrix * Skalar) | |
107 | + Mmn<K> operator*(const K&) const; | |
108 | + //! Als friend damit auch Parameter 1 ein Skalar sein kann | |
109 | + friend Mmn<K> operator*<>(const K&, const Mmn<K>&); | |
110 | + | |
111 | + // Hier können eh nur Matrizen verwendet werden. Daher sind | |
112 | + // keine weiteren friends nötig | |
113 | + Mmn<K> operator%(const Mmn<K>&) const; //!< Matrizenprodukt | |
114 | + Mmn<K> operator+(const Mmn<K>&) const; //!< Matrizensumme | |
115 | + Mmn<K> operator-(void) const; //!< Negation | |
116 | + Mmn<K> operator-(const Mmn<K>&) const; //!< Subtraktion | |
117 | + | |
118 | + //! eine NullMatrix derselben Groesse | |
119 | + Mmn<K> null(void) const { return Mmn<K>(m,n); } | |
120 | + | |
121 | + bool is_null(void) const { | |
122 | + for(unsigned i=0; i<m; i++) | |
123 | + for(unsigned j=0; j<n; j++) | |
124 | + if(_a[i][j]!=(K)0) | |
125 | + return false; | |
126 | + | |
127 | + return true; | |
128 | + } | |
129 | + | |
130 | + // Einheitsmatrizen, entweder zu Anzahl Spalten, oder Zeilen | |
131 | + //! Einheitsmatrizen zu Anzahl Spalten | |
132 | + Mmn<K> In(void) const { return Mmn<K>(n); } | |
133 | + //! Einheitsmatrizen zu Anzahl Zeilen | |
134 | + Mmn<K> Im(void) const { return Mmn<K>(m); } | |
135 | + | |
136 | + //! Ein Element aij der Matrize | |
137 | + K& a(unsigned i, unsigned j) { Det_F=false; return _a[i][j]; } | |
138 | + const K& a(unsigned i, unsigned j) const { return _a[i][j]; } | |
139 | + | |
140 | + //! Determinante | |
141 | + K det(void); | |
142 | + K det(void) const; | |
143 | + | |
144 | + //! Transponierte | |
145 | + Mmn<K> T(void) const; | |
146 | + | |
147 | + // Zeile und/oder Spalte aus matrize enftfernen | |
148 | + //! Zeile aus matrize enftfernen | |
149 | + Mmn<K> Ai(unsigned) const; | |
150 | + //! Spalte aus matrize enftfernen | |
151 | + Mmn<K> Aj(unsigned) const; | |
152 | + //! Zeile und Spalte aus matrize enftfernen | |
153 | + Mmn<K> Aij(unsigned, unsigned) const; | |
154 | + | |
155 | + // Adjunkten ermitteln (2 verschiedene Verfahren) | |
156 | + Mmn<K> Ad_det(void) const; //!< Adjunkte ueber Determinanten entwickelt | |
157 | + Mmn<K> Ad_inv(void) const; //!< Inverse=>Adjunkte / gauss=>Adj.-Satz | |
158 | + | |
159 | + // Inverse ermitteln (2 verschiedene Verfahren) | |
160 | + Mmn<K> gauss(gauss_typ) const; //!< \brief inverse Matrix ueber | |
161 | + //! Gauss-Algorithmus | |
162 | + Mmn<K> inv_Ad(void) const; //!< \brief Adjunkte=>Inverse / | |
163 | + //! Ad_det=>Adj.-Satz | |
164 | + | |
165 | + // lineare Gleichungssysteme | |
166 | + Mmn<K> solve(void) const; //!< Gleichungssystem loesen | |
167 | + Mmn<K> special_solve(void) const; //!< \brief eine Spezielle Loesung des | |
168 | + //! mit an=1, damit alle xi!=0 | |
169 | + | |
170 | + // formatierte Ausgabe | |
171 | + void print(ostream& = cout) const; //!< Daten der Matrize ausgeben | |
172 | +}; | |
173 | + | |
174 | +template <class K> | |
175 | +Mmn<K> operator*(const K& a, const Mmn<K>& A) { | |
176 | + return A * a; | |
177 | +} | |
178 | + | |
179 | +template <class K> | |
180 | +inline ostream& operator<<(ostream& strm, const Mmn<K>& A) { | |
181 | + A.print(strm); | |
182 | + | |
183 | + return strm; | |
184 | +} | |
185 | + | |
186 | +template <class K> | |
187 | +inline void Mmn<K>::print(ostream& strm) const { | |
188 | + strm << "lines: " << m << "\n"; | |
189 | + strm << "cols: " << n << "\n"; | |
190 | + | |
191 | + for(unsigned i=0; i<m; i++) { | |
192 | + for(unsigned j=0; j<n; j++) | |
193 | + strm << _a[i][j] << "\t"; | |
194 | + strm << "\n"; | |
195 | + } | |
196 | +} | |
197 | + | |
198 | +#include "Mmn_tpl.h" | |
199 | +#endif // __MMN_H__ | ... | ... |
math/Mmn_tpl.h
0 → 100755
1 | +using namespace std; | |
2 | + | |
3 | +#include <cstdio> | |
4 | + | |
5 | +#include "Mmn.h" | |
6 | + | |
7 | +/**************************************************************** | |
8 | + * die Klasse "Mmn" * | |
9 | + ****************************************************************/ | |
10 | +//------ Kontruktoren ------------------------------------------- | |
11 | +template <class K> | |
12 | +Mmn<K>::Mmn(K* a, unsigned m, unsigned n) : m(m), n(n), Rg(0), Det_F(false) { | |
13 | + _a=new (K*)[m]; | |
14 | + | |
15 | + for(unsigned i=0; i<m; i++) { | |
16 | + _a[i]=new K[n]; | |
17 | + for(unsigned j=0; j<n; j++) | |
18 | + _a[i][j]=*(a+n*i+j); | |
19 | + } | |
20 | +} | |
21 | + | |
22 | +template <class K> | |
23 | +Mmn<K>::Mmn(unsigned m) : m(m), n(m), Rg(0), Det_F(false) { | |
24 | + _a=new (K*)[m]; | |
25 | + | |
26 | + for(unsigned i=0; i<m; i++) { | |
27 | + _a[i]=new K[n]; | |
28 | + for(unsigned j=0; j<n; j++) | |
29 | + _a[i][j]=(j==i)?1:0; | |
30 | + } | |
31 | +} | |
32 | + | |
33 | +template <class K> | |
34 | +Mmn<K>::Mmn(unsigned m, unsigned n) : m(m), n(n), Rg(0), Det_F(false) { | |
35 | + _a=new (K*)[m]; | |
36 | + for(unsigned i=0; i<m; i++) { | |
37 | + _a[i]=new K[n]; | |
38 | + for(unsigned j=0; j<n; j++) | |
39 | + _a[i][j]=0; | |
40 | + } | |
41 | +} | |
42 | + | |
43 | +template <class K> | |
44 | +Mmn<K>::Mmn(const Mmn<K>& A) | |
45 | + : m(A.m), n(A.n), Rg(A.Rg), Det(A.Det), Det_F(A.Det_F) { | |
46 | + _a=new (K*)[m]; | |
47 | + | |
48 | + for(unsigned i=0; i<m; i++) { | |
49 | + _a[i]=new K[n]; | |
50 | + for(unsigned j=0; j<n; j++) | |
51 | + _a[i][j]=A._a[i][j]; | |
52 | + } | |
53 | +} | |
54 | + | |
55 | +template <class K> | |
56 | +Mmn<K>::~Mmn() { | |
57 | + freeall(); | |
58 | +} | |
59 | +//--------------------------------------------------------------- | |
60 | + | |
61 | +//------ Operatoren --------------------------------------------- | |
62 | +template <class K> | |
63 | +const Mmn<K>& Mmn<K>::operator=(const Mmn<K>& A) { | |
64 | + if(this==&A) | |
65 | + return *this; | |
66 | + | |
67 | + if(!_a || m != A.m || n != A.n) { | |
68 | + freeall(); | |
69 | + | |
70 | + _a=new (K*)[A.m]; | |
71 | + for(unsigned i=0; i<A.m; i++) | |
72 | + _a[i]=new K[A.n]; | |
73 | + } | |
74 | + | |
75 | + m=A.m; | |
76 | + n=A.n; | |
77 | + Rg=A.Rg; | |
78 | + Det=A.Det; | |
79 | + Det_F=A.Det_F; | |
80 | + | |
81 | + for(unsigned i=0; i<m; i++) | |
82 | + for(unsigned j=0; j<n; j++) | |
83 | + _a[i][j]=A._a[i][j]; | |
84 | + | |
85 | + return *this; | |
86 | +} | |
87 | + | |
88 | +template <class K> | |
89 | +Mmn<K> Mmn<K>::operator*(const K& a) const { | |
90 | + Mmn<K> A(m,n); | |
91 | + | |
92 | + for(unsigned i=0; i<m; i++) | |
93 | + for(unsigned j=0; j<n; j++) | |
94 | + A._a[i][j]=_a[i][j]*a; | |
95 | + | |
96 | + return A; | |
97 | +} | |
98 | + | |
99 | +template <class K> | |
100 | +Mmn<K> Mmn<K>::operator%(const Mmn<K>& A) const { | |
101 | + if(n != A.m) | |
102 | + return null(); | |
103 | + | |
104 | + Mmn<K> B(m,A.n); | |
105 | + | |
106 | + for(unsigned i=0; i<m; i++) | |
107 | + for(unsigned j=0; j<A.n; j++) { | |
108 | + B._a[i][j]=0; | |
109 | + | |
110 | + for(unsigned ji=0; ji<n; ji++) | |
111 | + B._a[i][j]+=_a[i][ji]*A._a[ji][j]; | |
112 | + } | |
113 | + | |
114 | + return B; | |
115 | +} | |
116 | + | |
117 | +template <class K> | |
118 | +Mmn<K> Mmn<K>::operator+(const Mmn<K>& A) const { | |
119 | + if(n != A.n || m != A.m) | |
120 | + return null(); | |
121 | + | |
122 | + Mmn<K> B(m,n); | |
123 | + | |
124 | + for(unsigned i=0; i<m; i++) | |
125 | + for(unsigned j=0; j<n; j++) | |
126 | + B._a[i][j]=_a[i][j]+A._a[i][j]; | |
127 | + | |
128 | + return B; | |
129 | +} | |
130 | + | |
131 | +template <class K> | |
132 | +Mmn<K> Mmn<K>::operator-(const Mmn<K>& A) const { | |
133 | + Mmn<K> B(m,n); | |
134 | + | |
135 | + for(unsigned i=0; i<m; i++) | |
136 | + for(unsigned j=0; j<n; j++) | |
137 | + B._a[i][j]=-A._a[i][j]; | |
138 | + | |
139 | + return *this+B; | |
140 | +} | |
141 | +//--------------------------------------------------------------- | |
142 | + | |
143 | +//------ Hilfsfunktionen ---------------------------------------- | |
144 | +template <class K> | |
145 | +void Mmn<K>::freeall(void) { | |
146 | + if(_a) { | |
147 | + for(unsigned i=0; i<m; i++) { | |
148 | + delete [] _a[i]; | |
149 | + } | |
150 | + delete [] _a; | |
151 | + _a=NULL; | |
152 | + } | |
153 | + | |
154 | + m=n=Rg=0; | |
155 | + Det_F=false; | |
156 | +} | |
157 | +//--------------------------------------------------------------- | |
158 | + | |
159 | +//------ Determinantenberechnung -------------------------------- | |
160 | +template <class K> | |
161 | +K Mmn<K>::sarrus(void) const { | |
162 | + return _a[0][0]*_a[1][1]*_a[2][2]\ | |
163 | + +_a[0][1]*_a[1][2]*_a[2][0]\ | |
164 | + +_a[0][2]*_a[1][0]*_a[2][1]\ | |
165 | + -_a[0][1]*_a[1][0]*_a[2][2]\ | |
166 | + -_a[0][0]*_a[1][2]*_a[2][1]\ | |
167 | + -_a[0][2]*_a[1][1]*_a[2][0]; | |
168 | +} | |
169 | + | |
170 | +template <class K> | |
171 | +K Mmn<K>::laplace(void) const { | |
172 | + K detA=0; | |
173 | + Mmn<K> A; | |
174 | + | |
175 | + // analytisches optimieren des Laplace-Algorithmus, durch finden der | |
176 | + // Zeile/Spalte mit den meisten Nullen. | |
177 | + //------------------------------------------------------------------- | |
178 | + unsigned nulls_in_line[m]; | |
179 | + for(unsigned i=0; i<m; nulls_in_line[i++]=0); | |
180 | + unsigned nulls_in_col[n]; | |
181 | + for(unsigned j=0; j<m; nulls_in_col[j++]=0); | |
182 | + unsigned max_nulls=0; | |
183 | + int max_nulls_line=0; | |
184 | + int max_nulls_col=0; | |
185 | + | |
186 | + for(unsigned i=0; i<m; i++) | |
187 | + for(unsigned j=0; j<n; j++) | |
188 | + if(_a[i][j]==(K)0) { | |
189 | + nulls_in_line[i]++; | |
190 | + nulls_in_col[j]++; | |
191 | + | |
192 | + if(nulls_in_line[i]>max_nulls) | |
193 | + max_nulls=nulls_in_line[i]; | |
194 | + if(nulls_in_col[i]>max_nulls) | |
195 | + max_nulls=nulls_in_col[i]; | |
196 | + | |
197 | + // ist eine komplette Zeile oder Spalte 0, so koennen wir | |
198 | + // direkt abbrechen und 0 zurueckgeben. | |
199 | + if(max_nulls==m) | |
200 | + return (K)0; | |
201 | + | |
202 | + max_nulls_line=(max_nulls==nulls_in_line[i])?i:max_nulls_line; | |
203 | + max_nulls_col=(max_nulls==nulls_in_col[j])?j:max_nulls_col; | |
204 | + } | |
205 | + | |
206 | + if(nulls_in_line[max_nulls_line] > nulls_in_col[max_nulls_col]) { | |
207 | + A=T(); | |
208 | + max_nulls_col=max_nulls_line; | |
209 | + } | |
210 | + else | |
211 | + A=*this; | |
212 | + //------------------------------------------------------------------- | |
213 | + | |
214 | + for(unsigned i=0; i<A.m; i++) | |
215 | + if(A._a[i][0]!=(K)0) | |
216 | + detA+=((K)(int)pow((double)-1,(double)(i+max_nulls_col))) | |
217 | + *A._a[i][max_nulls_col] | |
218 | + *A.Aij(i,max_nulls_col).det(); | |
219 | + | |
220 | + return detA; | |
221 | +} | |
222 | + | |
223 | +template <class K> | |
224 | +K Mmn<K>::det(void) const { | |
225 | + K Det=(K)0; | |
226 | + | |
227 | + if(m!=n) { | |
228 | + return Det; | |
229 | + } | |
230 | + else { | |
231 | + switch(m) { | |
232 | + case 1: Det=_a[0][0]; | |
233 | + break; | |
234 | + case 2: Det=_a[0][0]*_a[1][1]-_a[0][1]*_a[1][0]; | |
235 | + break; | |
236 | + case 3: Det=sarrus(); | |
237 | + break; | |
238 | + default: Det=laplace(); | |
239 | + } | |
240 | + | |
241 | + return Det; | |
242 | + } | |
243 | +} | |
244 | + | |
245 | +template <class K> | |
246 | +K Mmn<K>::det(void) { | |
247 | + if(m!=n) { | |
248 | + Det=(K)0; | |
249 | + Det_F=false; | |
250 | + | |
251 | + return Det; | |
252 | + } | |
253 | + else { | |
254 | + switch(m) { | |
255 | + case 1: Det=_a[0][0]; | |
256 | + break; | |
257 | + case 2: Det=_a[0][0]*_a[1][1]-_a[0][1]*_a[1][0]; | |
258 | + break; | |
259 | + case 3: Det=sarrus(); | |
260 | + break; | |
261 | + default: Det=laplace(); | |
262 | + } | |
263 | + | |
264 | + Det_F=true; | |
265 | + return Det; | |
266 | + } | |
267 | +} | |
268 | +//--------------------------------------------------------------- | |
269 | + | |
270 | +//------ Matrizenmanipulationen --------------------------------- | |
271 | +template <class K> | |
272 | +Mmn<K> Mmn<K>::Aij(unsigned i, unsigned j) const { | |
273 | + Mmn<K> A(m-1,n-1); | |
274 | + unsigned _i, _l, _j, _k; | |
275 | + | |
276 | + for(_i=0, _l=0; _i<m; _i++, _l++) { | |
277 | + if(_i==i) _i++; | |
278 | + if(_i>=m) break; | |
279 | + | |
280 | + for(_j=0, _k=0; _j<n; _j++, _k++) { | |
281 | + if(_j==j) _j++; | |
282 | + if(_j>=n) break; | |
283 | + | |
284 | + A._a[_l][_k]=_a[_i][_j]; | |
285 | + } | |
286 | + } | |
287 | + | |
288 | + return A; | |
289 | +} | |
290 | + | |
291 | +template <class K> | |
292 | +Mmn<K> Mmn<K>::Ai(unsigned i) const { | |
293 | + Mmn<K> A(m-1,n); | |
294 | + unsigned _i, l; | |
295 | + | |
296 | + for(_i=0, l=0; i<m; _i++, l++) { | |
297 | + if(_i==i) _i++; | |
298 | + if(_i>=m) break; | |
299 | + | |
300 | + for(unsigned j=0; j<n; j++) | |
301 | + A._a[l][j]=_a[_i][j]; | |
302 | + } | |
303 | + | |
304 | + return A; | |
305 | +} | |
306 | + | |
307 | +template <class K> | |
308 | +Mmn<K> Mmn<K>::Aj(unsigned j) const { | |
309 | + Mmn<K> A(m,n-1); | |
310 | + unsigned _j, k; | |
311 | + | |
312 | + for(unsigned i=0; i<m; i++) | |
313 | + for(_j=0, k=0; _j<n; _j++, k++) { | |
314 | + if(_j==j) _j++; | |
315 | + if(_j>=n) break; | |
316 | + | |
317 | + A._a[i][k]=_a[i][_j]; | |
318 | + } | |
319 | + | |
320 | + return A; | |
321 | +} | |
322 | + | |
323 | +template <class K> | |
324 | +Mmn<K> Mmn<K>::T(void) const { | |
325 | + Mmn<K> A(n,m); | |
326 | + | |
327 | + for(unsigned i=0; i<m; i++) | |
328 | + for(unsigned j=0; j<n; j++) | |
329 | + A._a[j][i]=_a[i][j]; | |
330 | + | |
331 | + return A; | |
332 | +} | |
333 | + | |
334 | +template <class K> | |
335 | +Mmn<K> Mmn<K>::Ad_det(void) const { | |
336 | + Mmn<K> A(n,m); | |
337 | + | |
338 | + for(unsigned i=0; i<m; i++) | |
339 | + for(unsigned j=0; j<n; j++) | |
340 | + A._a[j][i]=((K)(int)pow((double)-1,(double)(i+j)))*Aij(i,j).det(); | |
341 | + | |
342 | + return A; | |
343 | +} | |
344 | + | |
345 | +template <class K> | |
346 | +Mmn<K> Mmn<K>::Ad_inv(void) const { | |
347 | + // Das geht nur wenn die Determinante nicht 0 ist, da sonst die ganze | |
348 | + // Ergebnismatrix automatisch 0 wird, was aber nicht unbedingt sein muß. | |
349 | + // Dies gilt insbesondere Wenn die Matrize eine Null-Zeile oder Spalte | |
350 | + // enthaelt. | |
351 | + K d=Det_F?Det:det(); | |
352 | + | |
353 | + if(d != (K)0) | |
354 | + return d*gauss(INVERSE); | |
355 | + else | |
356 | + return Ad_det(); | |
357 | +} | |
358 | + | |
359 | +template <class K> | |
360 | +Mmn<K> Mmn<K>::inv_Ad(void) const { | |
361 | + K Adet; | |
362 | + | |
363 | + if((Adet=Det_F?Det:det())==(K)0) { | |
364 | + return null(); | |
365 | + } | |
366 | + else { | |
367 | + return Ad_det()*((K)1/Adet); | |
368 | + } | |
369 | +} | |
370 | + | |
371 | +template <class K> | |
372 | +Mmn<K> Mmn<K>::gauss(gauss_typ T) const { | |
373 | + Mmn<K> A=*this; | |
374 | + Mmn<K> B(m); | |
375 | + | |
376 | + for(unsigned i=0; i<A.m; i++) { | |
377 | + unsigned j; | |
378 | + | |
379 | + for(j=i; j<A.n; j++) { | |
380 | + unsigned k; | |
381 | + | |
382 | + for(k=i; k<A.m && A._a[k][j]==(K)0; k++); | |
383 | + if(k==A.m) | |
384 | + continue; | |
385 | + if(k!=i) { | |
386 | + K* tmp=A._a[i]; | |
387 | + A._a[i]=A._a[k]; | |
388 | + A._a[k]=tmp; | |
389 | + | |
390 | + if(T==INVERSE) { | |
391 | + tmp=B._a[i]; | |
392 | + B._a[i]=B._a[k]; | |
393 | + B._a[k]=tmp; | |
394 | + } | |
395 | + } | |
396 | + break; | |
397 | + } | |
398 | + | |
399 | + if(j==A.m) break; | |
400 | + | |
401 | + if(A._a[i][j]!=(K)0) { | |
402 | + K aii_inv=(K)1/A._a[i][j]; | |
403 | + A._a[i][j]=1; | |
404 | + A.Rg++; | |
405 | + B.Rg++; | |
406 | + | |
407 | + for(unsigned k=j+1; k<A.n; k++) | |
408 | + A._a[i][k]*=aii_inv; | |
409 | + if(T==INVERSE) { | |
410 | + for(unsigned k=0; k<B.n; k++) | |
411 | + B._a[i][k]*=aii_inv; | |
412 | + } | |
413 | + | |
414 | + for(unsigned k=0; k<A.m; k++) { | |
415 | + if(k != i) { | |
416 | + K akj_neg=-A._a[k][j]; | |
417 | + | |
418 | + for(unsigned l=j; l<A.n; l++) | |
419 | + A._a[k][l]+=A._a[i][l]*akj_neg; | |
420 | + if(T==INVERSE) { | |
421 | + for(unsigned l=0; l<B.n; l++) | |
422 | + B._a[k][l]+=B._a[i][l]*akj_neg; | |
423 | + } | |
424 | + } | |
425 | + } | |
426 | + } | |
427 | + } | |
428 | + | |
429 | + if(T==TREPPENNORMALE) | |
430 | + return A; | |
431 | + else { | |
432 | + // Es gibt nur eine Inverse wenn Rg(A)=m ist | |
433 | + if(B.Rg==m) | |
434 | + return B; | |
435 | + else | |
436 | + return null(); | |
437 | + } | |
438 | +} | |
439 | +//--------------------------------------------------------------- | |
440 | + | |
441 | +//------ lineare Gleichungssysteme ------------------------------ | |
442 | +template <class K> | |
443 | +Mmn<K> Mmn<K>::solve(void) const { | |
444 | + Mmn<K> A=gauss(TREPPENNORMALE); | |
445 | + Mmn<K> B=Aj(n-1).gauss(TREPPENNORMALE); | |
446 | + | |
447 | + // Gibt es eine Loesung??? | |
448 | + if(B.Rg != A.Rg) | |
449 | + return null(); | |
450 | + else { | |
451 | + K l[B.n][B.n-B.Rg+1]; | |
452 | + K a[B.n][A.n]; | |
453 | + | |
454 | + for(unsigned i=0, j=0; j<B.n && i<B.n; j++) { | |
455 | + if(i>=A.m || A._a[i][j] != (K)1) { | |
456 | + for(unsigned k=0; k<A.n; k++) { | |
457 | + if(k==j) | |
458 | + a[j][k]=(K)-1; | |
459 | + else | |
460 | + a[j][k]=(K)0; | |
461 | + } | |
462 | + } | |
463 | + else { | |
464 | + for(unsigned k=0; k<A.n; k++) | |
465 | + a[j][k]=A._a[i][k]; | |
466 | + i++; | |
467 | + } | |
468 | + } | |
469 | + | |
470 | + unsigned j=0; | |
471 | + for (unsigned i=0; i<B.n; i++) | |
472 | + l[i][j]=a[i][A.n-1]; | |
473 | + j++; | |
474 | + | |
475 | + for(unsigned k=0; k<B.n; k++) { | |
476 | + if(a[k][k]==(K)-1) { | |
477 | + for (unsigned i=0; i<B.n; i++) | |
478 | + l[i][j]=a[i][k]; | |
479 | + j++; | |
480 | + } | |
481 | + } | |
482 | + | |
483 | + return Mmn<K>((K*)l, B.n, B.n-B.Rg+1); | |
484 | + } | |
485 | +} | |
486 | + | |
487 | +template <class K> | |
488 | +Mmn<K> Mmn<K>::special_solve(void) const { | |
489 | + Mmn<K> S=solve(); | |
490 | + Mmn<K> A(S.m,1); | |
491 | + | |
492 | + for(unsigned i=0; i<S.m; i++) { | |
493 | + A._a[i][0]=(K)0; | |
494 | + | |
495 | + for(unsigned j=0; j<S.n; j++) | |
496 | + A._a[i][0]+=S._a[i][j]; | |
497 | + } | |
498 | + | |
499 | + return A; | |
500 | +} | |
501 | + | |
502 | +//--------------------------------------------------------------- | |
503 | +/****************************************************************/ | ... | ... |
math/V_K4.h
0 → 100755
1 | +/** | |
2 | + * \file V_K4.h | |
3 | + * | |
4 | + * \brief Klasse die einen 4er-Vektor mathematisch beschreibt und handled. | |
5 | + * | |
6 | + * Hier gibt alles was man für Vektoren so braucht (Vektorprodukt, | |
7 | + * Skalarprodukt, Addition, Subtraktion, Multiplikation mit Matrize) | |
8 | + * | |
9 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
10 | + * | |
11 | + * \date 04.12.2003 | |
12 | + * | |
13 | + * \version ..2002 [gs]: erste funktionierende Implementation | |
14 | + * \version 18.12.2003 [gs]: Vergleichsoperator hinzugefügt. | |
15 | + */ | |
16 | + | |
17 | +/* | |
18 | + * Copyright (C)2003 Georg Steffers | |
19 | + * | |
20 | + * This program is free software; you can redistribute it and/or modify | |
21 | + * it under the terms of the GNU General Public License as published by | |
22 | + * the Free Software Foundation; either version 2 of the License, or | |
23 | + * (at your option) any later version. | |
24 | + * | |
25 | + * This program is distributed in the hope that it will be useful, | |
26 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | + * GNU General Public License for more details. | |
29 | + * | |
30 | + * You should have received a copy of the GNU General Public License | |
31 | + * along with this program; if not, write to the Free Software | |
32 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
33 | + */ | |
34 | + | |
35 | +#ifndef __V_K4_H__ | |
36 | +#define __V_K4_H__ | |
37 | + | |
38 | +#include <cmath> | |
39 | +#include <iostream> | |
40 | + | |
41 | +#include "Mmn.h" | |
42 | + | |
43 | +/** | |
44 | + * \brief Winkel auf -360 bis +360 beschränken und als double | |
45 | + * handhaben. | |
46 | + * | |
47 | + * Wird ein Winkel < -360 oder > +360 angegeben, so wird sein Vorkommateil | |
48 | + * auf diesen Bereich gestuzt und der Nachkommateil hinzuaddiert. | |
49 | + */ | |
50 | +#define WINKEL(x) ((double)((int)(x)%360)+(double)(x)-(int)(x)) | |
51 | +#define BOGENMASS(x) (WINKEL((x))*M_PI/180) | |
52 | +#define RAD(x) (BOGENMASS((x))) | |
53 | +#define GRAD(x) (WINKEL((x))*180/M_PI) | |
54 | +#define SQR(x) ((x)*(x)) | |
55 | + | |
56 | +using namespace std; | |
57 | + | |
58 | +template <class K> | |
59 | +class V_K4 : public Mmn<K> { | |
60 | + public: | |
61 | + V_K4() : Mmn<K>(4, 1) {} | |
62 | + V_K4(Mmn<K> m) : Mmn<K>(m) {} | |
63 | + V_K4(K* a) : Mmn<K>(a, 4, 1) {} | |
64 | + V_K4(K e1, K e2, K e3, K e4=0) : Mmn<K>(4,1) { | |
65 | + _a[0][0]=e1; _a[1][0]=e2; | |
66 | + _a[2][0]=e3; _a[3][0]=e4; | |
67 | + } | |
68 | + | |
69 | + const K& operator[](unsigned i) const { return _a[i>m-1?m-1:i][0]; } | |
70 | + K& operator[](unsigned i) { return _a[i>m-1?m-1:i][0]; } | |
71 | + K& X(unsigned i) { return (*this)[0]; } | |
72 | + K& Y(unsigned i) { return (*this)[1]; } | |
73 | + K& Z(unsigned i) { return (*this)[2]; } | |
74 | + K& W(unsigned i) { return (*this)[3]; } | |
75 | + | |
76 | + K v_betr(void) const { return sqrt(*this % *this); } | |
77 | + | |
78 | + V_K4<K> v_norm(void) const { return *this * (1/v_betr()); } | |
79 | + | |
80 | + K operator% (const V_K4<K>&) const; | |
81 | + V_K4<K> operator| (const V_K4<K>&) const; | |
82 | + bool operator== (const V_K4<K>& v) const { | |
83 | + if(this->m==v.m && | |
84 | + this->n==v.n) { | |
85 | + for(unsigned i=0; i<m; i++) | |
86 | + for(unsigned j=0; j<n; j++) | |
87 | + if(_a[i][j]!=v._a[i][j]) | |
88 | + return false; | |
89 | + } | |
90 | + else | |
91 | + return false; | |
92 | + | |
93 | + return true; | |
94 | + } | |
95 | +}; | |
96 | + | |
97 | +template <class K> | |
98 | +inline ostream& operator<<(ostream& strm, const V_K4<K>& A) { | |
99 | + A.print(strm); | |
100 | + | |
101 | + return strm; | |
102 | +} | |
103 | + | |
104 | +#include "V_K4_tpl.h" | |
105 | + | |
106 | +/** | |
107 | + * \brief Liefert die Matrize zur Rotation eines Punktes um einen | |
108 | + * beliebigen Vektor | |
109 | + */ | |
110 | +class mat_rot_axe : public Mmn<double> { | |
111 | + public: | |
112 | + mat_rot_axe(double* a) : Mmn<double>(a, 4, 4) {} | |
113 | + mat_rot_axe(double w=0, | |
114 | + V_K4<double> const& axe=V_K4<double>(0,0,1,0)) { | |
115 | + V_K4<double> u(axe.v_norm()); | |
116 | + | |
117 | + double A[4][4]={{SQR(u[0])+cos(RAD(w))*(1-SQR(u[0])), | |
118 | + u[0]*u[1]*(1-cos(RAD(w)))-u[2]*sin(RAD(w)), | |
119 | + u[2]*u[0]*(1-cos(RAD(w)))+u[1]*sin(RAD(w)), | |
120 | + 0}, | |
121 | + {u[0]*u[1]*(1-cos(RAD(w)))+u[2]*sin(RAD(w)), | |
122 | + SQR(u[1])+cos(RAD(w))*(1-SQR(u[1])), | |
123 | + u[1]*u[2]*(1-cos(RAD(w)))-u[0]*sin(RAD(w)), | |
124 | + 0}, | |
125 | + {u[2]*u[0]*(1-cos(RAD(w)))-u[1]*sin(RAD(w)), | |
126 | + u[1]*u[2]*(1-cos(RAD(w)))+u[0]*sin(RAD(w)), | |
127 | + SQR(u[2])+cos(RAD(w))*(1-SQR(u[2])), | |
128 | + 0}, | |
129 | + {0,0,0,1}}; | |
130 | + | |
131 | + *this=mat_rot_axe((double*)A); | |
132 | + } | |
133 | +}; | |
134 | + | |
135 | +/** | |
136 | + * \brief Liefert die Matrize zur Rotation eines Punktes um die | |
137 | + * X-Achse | |
138 | + */ | |
139 | +class mat_rot_x : public Mmn<double> { | |
140 | + public: | |
141 | + mat_rot_x(double* a) : Mmn<double>(a, 4, 4) {} | |
142 | + mat_rot_x(double w=0) { | |
143 | + double A[4][4]={{1,0,0,0}, | |
144 | + {0,cos(RAD(w)),-sin(RAD(w)),0}, | |
145 | + {0,sin(RAD(w)),cos(RAD(w)),0}, | |
146 | + {0,0,0,1}}; | |
147 | + | |
148 | + *this=mat_rot_x((double*)A); | |
149 | + } | |
150 | +}; | |
151 | + | |
152 | +/** | |
153 | + * \brief Liefert die Matrize zur Rotation eines Punktes um die | |
154 | + * Y-Achse | |
155 | + */ | |
156 | +class mat_rot_y : public Mmn<double> { | |
157 | + public: | |
158 | + mat_rot_y(double* a) : Mmn<double>(a, 4, 4) {} | |
159 | + mat_rot_y(double w=0) { | |
160 | + double A[4][4]={{cos(RAD(w)),0,sin(RAD(w)),0}, | |
161 | + {0,1,0,0}, | |
162 | + {-sin(RAD(w)),0,cos(RAD(w)),0}, | |
163 | + {0,0,0,1}}; | |
164 | + | |
165 | + *this=mat_rot_y((double*)A); | |
166 | + } | |
167 | +}; | |
168 | + | |
169 | +/** | |
170 | + * \brief Liefert die Matrize zur Rotation eines Punktes um die | |
171 | + * Z-Achse | |
172 | + */ | |
173 | +class mat_rot_z : public Mmn<double> { | |
174 | + public: | |
175 | + mat_rot_z(double* a) : Mmn<double>(a, 4, 4) {} | |
176 | + mat_rot_z(double w=0) { | |
177 | + double A[4][4]={{cos(RAD(w)),-sin(RAD(w)),0,0}, | |
178 | + {sin(RAD(w)),cos(RAD(w)),0,0}, | |
179 | + {0,0,1,0}, | |
180 | + {0,0,0,1}}; | |
181 | + | |
182 | + *this=mat_rot_z((double*)A); | |
183 | + } | |
184 | +}; | |
185 | + | |
186 | +/** | |
187 | + * \brief Liefert die Matrize zur Verschiebung eines Punktes um | |
188 | + * tx. ty und tz | |
189 | + */ | |
190 | +class mat_translate : public Mmn<double> { | |
191 | + public: | |
192 | + mat_translate(double* a) : Mmn<double>(a, 4, 4) {} | |
193 | + mat_translate(double tx=0, double ty=0, double tz=0) { | |
194 | + double A[4][4]={{1,0,0,tx}, | |
195 | + {0,1,0,ty}, | |
196 | + {0,0,1,tz}, | |
197 | + {0,0,0,1}}; | |
198 | + | |
199 | + *this=mat_translate((double*)A); | |
200 | + } | |
201 | +}; | |
202 | + | |
203 | +/** | |
204 | + * \brief Liefert die Matrize zur Verformung eines Punktes um | |
205 | + * sx. sy und sz | |
206 | + */ | |
207 | +class mat_transform : public Mmn<double> { | |
208 | + public: | |
209 | + mat_transform(double* a) : Mmn<double>(a, 4, 4) {} | |
210 | + mat_transform(double sx=0, double sy=0, double sz=0) { | |
211 | + double A[4][4]={{sx,0,0,0}, | |
212 | + {0,sy,0,0}, | |
213 | + {0,0,sz,0}, | |
214 | + {0,0,0,1}}; | |
215 | + | |
216 | + *this=mat_transform((double*)A); | |
217 | + } | |
218 | +}; | |
219 | + | |
220 | +#endif // __V_K4_H__ | ... | ... |
math/V_K4_tpl.h
0 → 100755
1 | +#include "V_K4.h" | |
2 | + | |
3 | +template <class K> | |
4 | +K V_K4<K>::operator% (const V_K4<K>& A) const { | |
5 | + return (T() % (Mmn<K>)A).a(0,0); | |
6 | +} | |
7 | + | |
8 | +template <class K> | |
9 | +V_K4<K> V_K4<K>::operator| (const V_K4<K>& A) const { | |
10 | + V_K4<K> B; | |
11 | + | |
12 | + // Was jetzt kommt ist eine Loesung (a,b,c) des folgenden Gleichungssystems | |
13 | + // a*v1+b*v2+c*v3=0 und a*w1+b*w2+c*w3=0. Das heißt es ist ein Vektor | |
14 | + // (a,b,c) der wenn man ihn mit den uebergebenen Vektoren v und w mult. | |
15 | + // jeweils Null ergibt. Dieser Sachverhalt bedeutet geometrisch betrachtet | |
16 | + // das dieser Vektor 90 Grad zu beiden übergebenen Vektoren bildet, also | |
17 | + // eine Senkrechte zu der Ebene die diese beiden Vektoren aufziehen | |
18 | + // bildet. (Den Beweis das es eine spezielle Lösung ist bleibe ich hier | |
19 | + // schuldig, wers ausprobieren möchte und nich weis wie kann sich gerne | |
20 | + // an mich wenden.) | |
21 | + B[0]=_a[1][0]*A[2] - _a[2][0]*A[1]; | |
22 | + B[1]=_a[0][0]*A[2] - _a[2][0]*A[0]; | |
23 | + B[2]=_a[0][0]*A[1] - _a[1][0]*A[0]; | |
24 | + B[3]=0; | |
25 | + | |
26 | + return B; | |
27 | +} | ... | ... |
math/sin_cos.cpp
0 → 100755
1 | +using namespace std; | |
2 | + | |
3 | +#include <cmath> | |
4 | + | |
5 | +#include "sin_cos.h" | |
6 | + | |
7 | +const double SIN[360]={sin(0*M_PI/180), sin(1*M_PI/180), sin(2*M_PI/180), sin(3*M_PI/180), sin(4*M_PI/180), | |
8 | + sin(5*M_PI/180), sin(6*M_PI/180), sin(7*M_PI/180), sin(8*M_PI/180), sin(9*M_PI/180), | |
9 | + sin(10*M_PI/180), sin(11*M_PI/180), sin(12*M_PI/180), sin(13*M_PI/180), sin(14*M_PI/180), | |
10 | + sin(15*M_PI/180), sin(16*M_PI/180), sin(17*M_PI/180), sin(18*M_PI/180), sin(19*M_PI/180), | |
11 | + sin(20*M_PI/180), sin(21*M_PI/180), sin(22*M_PI/180), sin(23*M_PI/180), sin(24*M_PI/180), | |
12 | + sin(25*M_PI/180), sin(26*M_PI/180), sin(27*M_PI/180), sin(28*M_PI/180), sin(29*M_PI/180), | |
13 | + sin(30*M_PI/180), sin(31*M_PI/180), sin(32*M_PI/180), sin(33*M_PI/180), sin(34*M_PI/180), | |
14 | + sin(35*M_PI/180), sin(36*M_PI/180), sin(37*M_PI/180), sin(38*M_PI/180), sin(39*M_PI/180), | |
15 | + sin(40*M_PI/180), sin(41*M_PI/180), sin(42*M_PI/180), sin(43*M_PI/180), sin(44*M_PI/180), | |
16 | + sin(45*M_PI/180), sin(46*M_PI/180), sin(47*M_PI/180), sin(48*M_PI/180), sin(49*M_PI/180), | |
17 | + sin(50*M_PI/180), sin(51*M_PI/180), sin(52*M_PI/180), sin(53*M_PI/180), sin(54*M_PI/180), | |
18 | + sin(55*M_PI/180), sin(56*M_PI/180), sin(57*M_PI/180), sin(58*M_PI/180), sin(59*M_PI/180), | |
19 | + sin(60*M_PI/180), sin(61*M_PI/180), sin(62*M_PI/180), sin(63*M_PI/180), sin(64*M_PI/180), | |
20 | + sin(65*M_PI/180), sin(66*M_PI/180), sin(67*M_PI/180), sin(68*M_PI/180), sin(69*M_PI/180), | |
21 | + sin(70*M_PI/180), sin(71*M_PI/180), sin(72*M_PI/180), sin(73*M_PI/180), sin(74*M_PI/180), | |
22 | + sin(75*M_PI/180), sin(76*M_PI/180), sin(77*M_PI/180), sin(78*M_PI/180), sin(79*M_PI/180), | |
23 | + sin(80*M_PI/180), sin(81*M_PI/180), sin(82*M_PI/180), sin(83*M_PI/180), sin(84*M_PI/180), | |
24 | + sin(85*M_PI/180), sin(86*M_PI/180), sin(87*M_PI/180), sin(88*M_PI/180), sin(89*M_PI/180), | |
25 | + sin(90*M_PI/180), sin(91*M_PI/180), sin(92*M_PI/180), sin(93*M_PI/180), sin(94*M_PI/180), | |
26 | + sin(95*M_PI/180), sin(96*M_PI/180), sin(97*M_PI/180), sin(98*M_PI/180), sin(99*M_PI/180), | |
27 | + sin(100*M_PI/180), sin(101*M_PI/180), sin(102*M_PI/180), sin(103*M_PI/180), sin(104*M_PI/180), | |
28 | + sin(105*M_PI/180), sin(106*M_PI/180), sin(107*M_PI/180), sin(108*M_PI/180), sin(109*M_PI/180), | |
29 | + sin(110*M_PI/180), sin(111*M_PI/180), sin(112*M_PI/180), sin(113*M_PI/180), sin(114*M_PI/180), | |
30 | + sin(115*M_PI/180), sin(116*M_PI/180), sin(117*M_PI/180), sin(118*M_PI/180), sin(119*M_PI/180), | |
31 | + sin(120*M_PI/180), sin(121*M_PI/180), sin(122*M_PI/180), sin(123*M_PI/180), sin(124*M_PI/180), | |
32 | + sin(125*M_PI/180), sin(126*M_PI/180), sin(127*M_PI/180), sin(128*M_PI/180), sin(129*M_PI/180), | |
33 | + sin(130*M_PI/180), sin(131*M_PI/180), sin(132*M_PI/180), sin(133*M_PI/180), sin(134*M_PI/180), | |
34 | + sin(135*M_PI/180), sin(136*M_PI/180), sin(137*M_PI/180), sin(138*M_PI/180), sin(139*M_PI/180), | |
35 | + sin(140*M_PI/180), sin(141*M_PI/180), sin(142*M_PI/180), sin(143*M_PI/180), sin(144*M_PI/180), | |
36 | + sin(145*M_PI/180), sin(146*M_PI/180), sin(147*M_PI/180), sin(148*M_PI/180), sin(149*M_PI/180), | |
37 | + sin(150*M_PI/180), sin(151*M_PI/180), sin(152*M_PI/180), sin(153*M_PI/180), sin(154*M_PI/180), | |
38 | + sin(155*M_PI/180), sin(156*M_PI/180), sin(157*M_PI/180), sin(158*M_PI/180), sin(159*M_PI/180), | |
39 | + sin(160*M_PI/180), sin(161*M_PI/180), sin(162*M_PI/180), sin(163*M_PI/180), sin(164*M_PI/180), | |
40 | + sin(165*M_PI/180), sin(166*M_PI/180), sin(167*M_PI/180), sin(168*M_PI/180), sin(169*M_PI/180), | |
41 | + sin(170*M_PI/180), sin(171*M_PI/180), sin(172*M_PI/180), sin(173*M_PI/180), sin(174*M_PI/180), | |
42 | + sin(175*M_PI/180), sin(176*M_PI/180), sin(177*M_PI/180), sin(178*M_PI/180), sin(179*M_PI/180), | |
43 | + sin(180*M_PI/180), sin(181*M_PI/180), sin(182*M_PI/180), sin(183*M_PI/180), sin(184*M_PI/180), | |
44 | + sin(185*M_PI/180), sin(186*M_PI/180), sin(187*M_PI/180), sin(188*M_PI/180), sin(189*M_PI/180), | |
45 | + sin(190*M_PI/180), sin(191*M_PI/180), sin(192*M_PI/180), sin(193*M_PI/180), sin(194*M_PI/180), | |
46 | + sin(195*M_PI/180), sin(196*M_PI/180), sin(197*M_PI/180), sin(198*M_PI/180), sin(199*M_PI/180), | |
47 | + sin(200*M_PI/180), sin(201*M_PI/180), sin(202*M_PI/180), sin(203*M_PI/180), sin(204*M_PI/180), | |
48 | + sin(205*M_PI/180), sin(206*M_PI/180), sin(207*M_PI/180), sin(208*M_PI/180), sin(209*M_PI/180), | |
49 | + sin(210*M_PI/180), sin(211*M_PI/180), sin(212*M_PI/180), sin(213*M_PI/180), sin(214*M_PI/180), | |
50 | + sin(215*M_PI/180), sin(216*M_PI/180), sin(217*M_PI/180), sin(218*M_PI/180), sin(219*M_PI/180), | |
51 | + sin(220*M_PI/180), sin(221*M_PI/180), sin(222*M_PI/180), sin(223*M_PI/180), sin(224*M_PI/180), | |
52 | + sin(225*M_PI/180), sin(226*M_PI/180), sin(227*M_PI/180), sin(228*M_PI/180), sin(229*M_PI/180), | |
53 | + sin(230*M_PI/180), sin(231*M_PI/180), sin(232*M_PI/180), sin(233*M_PI/180), sin(234*M_PI/180), | |
54 | + sin(235*M_PI/180), sin(236*M_PI/180), sin(237*M_PI/180), sin(238*M_PI/180), sin(239*M_PI/180), | |
55 | + sin(240*M_PI/180), sin(241*M_PI/180), sin(242*M_PI/180), sin(243*M_PI/180), sin(244*M_PI/180), | |
56 | + sin(245*M_PI/180), sin(246*M_PI/180), sin(247*M_PI/180), sin(248*M_PI/180), sin(249*M_PI/180), | |
57 | + sin(250*M_PI/180), sin(251*M_PI/180), sin(252*M_PI/180), sin(253*M_PI/180), sin(254*M_PI/180), | |
58 | + sin(255*M_PI/180), sin(256*M_PI/180), sin(257*M_PI/180), sin(258*M_PI/180), sin(259*M_PI/180), | |
59 | + sin(260*M_PI/180), sin(261*M_PI/180), sin(262*M_PI/180), sin(263*M_PI/180), sin(264*M_PI/180), | |
60 | + sin(265*M_PI/180), sin(266*M_PI/180), sin(267*M_PI/180), sin(268*M_PI/180), sin(269*M_PI/180), | |
61 | + sin(270*M_PI/180), sin(271*M_PI/180), sin(272*M_PI/180), sin(273*M_PI/180), sin(274*M_PI/180), | |
62 | + sin(275*M_PI/180), sin(276*M_PI/180), sin(277*M_PI/180), sin(278*M_PI/180), sin(279*M_PI/180), | |
63 | + sin(280*M_PI/180), sin(281*M_PI/180), sin(282*M_PI/180), sin(283*M_PI/180), sin(284*M_PI/180), | |
64 | + sin(285*M_PI/180), sin(286*M_PI/180), sin(287*M_PI/180), sin(288*M_PI/180), sin(289*M_PI/180), | |
65 | + sin(290*M_PI/180), sin(291*M_PI/180), sin(292*M_PI/180), sin(293*M_PI/180), sin(294*M_PI/180), | |
66 | + sin(295*M_PI/180), sin(296*M_PI/180), sin(297*M_PI/180), sin(298*M_PI/180), sin(299*M_PI/180), | |
67 | + sin(300*M_PI/180), sin(301*M_PI/180), sin(302*M_PI/180), sin(303*M_PI/180), sin(304*M_PI/180), | |
68 | + sin(305*M_PI/180), sin(306*M_PI/180), sin(307*M_PI/180), sin(308*M_PI/180), sin(309*M_PI/180), | |
69 | + sin(310*M_PI/180), sin(311*M_PI/180), sin(312*M_PI/180), sin(313*M_PI/180), sin(314*M_PI/180), | |
70 | + sin(315*M_PI/180), sin(316*M_PI/180), sin(317*M_PI/180), sin(318*M_PI/180), sin(319*M_PI/180), | |
71 | + sin(320*M_PI/180), sin(321*M_PI/180), sin(322*M_PI/180), sin(323*M_PI/180), sin(324*M_PI/180), | |
72 | + sin(325*M_PI/180), sin(326*M_PI/180), sin(327*M_PI/180), sin(328*M_PI/180), sin(329*M_PI/180), | |
73 | + sin(330*M_PI/180), sin(331*M_PI/180), sin(332*M_PI/180), sin(333*M_PI/180), sin(334*M_PI/180), | |
74 | + sin(335*M_PI/180), sin(336*M_PI/180), sin(337*M_PI/180), sin(338*M_PI/180), sin(339*M_PI/180), | |
75 | + sin(340*M_PI/180), sin(341*M_PI/180), sin(342*M_PI/180), sin(343*M_PI/180), sin(344*M_PI/180), | |
76 | + sin(345*M_PI/180), sin(346*M_PI/180), sin(347*M_PI/180), sin(348*M_PI/180), sin(349*M_PI/180), | |
77 | + sin(350*M_PI/180), sin(351*M_PI/180), sin(352*M_PI/180), sin(353*M_PI/180), sin(354*M_PI/180), | |
78 | + sin(355*M_PI/180), sin(356*M_PI/180), sin(357*M_PI/180), sin(358*M_PI/180), sin(359*M_PI/180)}; | |
79 | + | |
80 | +const double COS[360]={cos(0*M_PI/180), cos(1*M_PI/180), cos(2*M_PI/180), cos(3*M_PI/180), cos(4*M_PI/180), | |
81 | + cos(5*M_PI/180), cos(6*M_PI/180), cos(7*M_PI/180), cos(8*M_PI/180), cos(9*M_PI/180), | |
82 | + cos(10*M_PI/180), cos(11*M_PI/180), cos(12*M_PI/180), cos(13*M_PI/180), cos(14*M_PI/180), | |
83 | + cos(15*M_PI/180), cos(16*M_PI/180), cos(17*M_PI/180), cos(18*M_PI/180), cos(19*M_PI/180), | |
84 | + cos(20*M_PI/180), cos(21*M_PI/180), cos(22*M_PI/180), cos(23*M_PI/180), cos(24*M_PI/180), | |
85 | + cos(25*M_PI/180), cos(26*M_PI/180), cos(27*M_PI/180), cos(28*M_PI/180), cos(29*M_PI/180), | |
86 | + cos(30*M_PI/180), cos(31*M_PI/180), cos(32*M_PI/180), cos(33*M_PI/180), cos(34*M_PI/180), | |
87 | + cos(35*M_PI/180), cos(36*M_PI/180), cos(37*M_PI/180), cos(38*M_PI/180), cos(39*M_PI/180), | |
88 | + cos(40*M_PI/180), cos(41*M_PI/180), cos(42*M_PI/180), cos(43*M_PI/180), cos(44*M_PI/180), | |
89 | + cos(45*M_PI/180), cos(46*M_PI/180), cos(47*M_PI/180), cos(48*M_PI/180), cos(49*M_PI/180), | |
90 | + cos(50*M_PI/180), cos(51*M_PI/180), cos(52*M_PI/180), cos(53*M_PI/180), cos(54*M_PI/180), | |
91 | + cos(55*M_PI/180), cos(56*M_PI/180), cos(57*M_PI/180), cos(58*M_PI/180), cos(59*M_PI/180), | |
92 | + cos(60*M_PI/180), cos(61*M_PI/180), cos(62*M_PI/180), cos(63*M_PI/180), cos(64*M_PI/180), | |
93 | + cos(65*M_PI/180), cos(66*M_PI/180), cos(67*M_PI/180), cos(68*M_PI/180), cos(69*M_PI/180), | |
94 | + cos(70*M_PI/180), cos(71*M_PI/180), cos(72*M_PI/180), cos(73*M_PI/180), cos(74*M_PI/180), | |
95 | + cos(75*M_PI/180), cos(76*M_PI/180), cos(77*M_PI/180), cos(78*M_PI/180), cos(79*M_PI/180), | |
96 | + cos(80*M_PI/180), cos(81*M_PI/180), cos(82*M_PI/180), cos(83*M_PI/180), cos(84*M_PI/180), | |
97 | + cos(85*M_PI/180), cos(86*M_PI/180), cos(87*M_PI/180), cos(88*M_PI/180), cos(89*M_PI/180), | |
98 | + cos(90*M_PI/180), cos(91*M_PI/180), cos(92*M_PI/180), cos(93*M_PI/180), cos(94*M_PI/180), | |
99 | + cos(95*M_PI/180), cos(96*M_PI/180), cos(97*M_PI/180), cos(98*M_PI/180), cos(99*M_PI/180), | |
100 | + cos(100*M_PI/180), cos(101*M_PI/180), cos(102*M_PI/180), cos(103*M_PI/180), cos(104*M_PI/180), | |
101 | + cos(105*M_PI/180), cos(106*M_PI/180), cos(107*M_PI/180), cos(108*M_PI/180), cos(109*M_PI/180), | |
102 | + cos(110*M_PI/180), cos(111*M_PI/180), cos(112*M_PI/180), cos(113*M_PI/180), cos(114*M_PI/180), | |
103 | + cos(115*M_PI/180), cos(116*M_PI/180), cos(117*M_PI/180), cos(118*M_PI/180), cos(119*M_PI/180), | |
104 | + cos(120*M_PI/180), cos(121*M_PI/180), cos(122*M_PI/180), cos(123*M_PI/180), cos(124*M_PI/180), | |
105 | + cos(125*M_PI/180), cos(126*M_PI/180), cos(127*M_PI/180), cos(128*M_PI/180), cos(129*M_PI/180), | |
106 | + cos(130*M_PI/180), cos(131*M_PI/180), cos(132*M_PI/180), cos(133*M_PI/180), cos(134*M_PI/180), | |
107 | + cos(135*M_PI/180), cos(136*M_PI/180), cos(137*M_PI/180), cos(138*M_PI/180), cos(139*M_PI/180), | |
108 | + cos(140*M_PI/180), cos(141*M_PI/180), cos(142*M_PI/180), cos(143*M_PI/180), cos(144*M_PI/180), | |
109 | + cos(145*M_PI/180), cos(146*M_PI/180), cos(147*M_PI/180), cos(148*M_PI/180), cos(149*M_PI/180), | |
110 | + cos(150*M_PI/180), cos(151*M_PI/180), cos(152*M_PI/180), cos(153*M_PI/180), cos(154*M_PI/180), | |
111 | + cos(155*M_PI/180), cos(156*M_PI/180), cos(157*M_PI/180), cos(158*M_PI/180), cos(159*M_PI/180), | |
112 | + cos(160*M_PI/180), cos(161*M_PI/180), cos(162*M_PI/180), cos(163*M_PI/180), cos(164*M_PI/180), | |
113 | + cos(165*M_PI/180), cos(166*M_PI/180), cos(167*M_PI/180), cos(168*M_PI/180), cos(169*M_PI/180), | |
114 | + cos(170*M_PI/180), cos(171*M_PI/180), cos(172*M_PI/180), cos(173*M_PI/180), cos(174*M_PI/180), | |
115 | + cos(175*M_PI/180), cos(176*M_PI/180), cos(177*M_PI/180), cos(178*M_PI/180), cos(179*M_PI/180), | |
116 | + cos(180*M_PI/180), cos(181*M_PI/180), cos(182*M_PI/180), cos(183*M_PI/180), cos(184*M_PI/180), | |
117 | + cos(185*M_PI/180), cos(186*M_PI/180), cos(187*M_PI/180), cos(188*M_PI/180), cos(189*M_PI/180), | |
118 | + cos(190*M_PI/180), cos(191*M_PI/180), cos(192*M_PI/180), cos(193*M_PI/180), cos(194*M_PI/180), | |
119 | + cos(195*M_PI/180), cos(196*M_PI/180), cos(197*M_PI/180), cos(198*M_PI/180), cos(199*M_PI/180), | |
120 | + cos(200*M_PI/180), cos(201*M_PI/180), cos(202*M_PI/180), cos(203*M_PI/180), cos(204*M_PI/180), | |
121 | + cos(205*M_PI/180), cos(206*M_PI/180), cos(207*M_PI/180), cos(208*M_PI/180), cos(209*M_PI/180), | |
122 | + cos(210*M_PI/180), cos(211*M_PI/180), cos(212*M_PI/180), cos(213*M_PI/180), cos(214*M_PI/180), | |
123 | + cos(215*M_PI/180), cos(216*M_PI/180), cos(217*M_PI/180), cos(218*M_PI/180), cos(219*M_PI/180), | |
124 | + cos(220*M_PI/180), cos(221*M_PI/180), cos(222*M_PI/180), cos(223*M_PI/180), cos(224*M_PI/180), | |
125 | + cos(225*M_PI/180), cos(226*M_PI/180), cos(227*M_PI/180), cos(228*M_PI/180), cos(229*M_PI/180), | |
126 | + cos(230*M_PI/180), cos(231*M_PI/180), cos(232*M_PI/180), cos(233*M_PI/180), cos(234*M_PI/180), | |
127 | + cos(235*M_PI/180), cos(236*M_PI/180), cos(237*M_PI/180), cos(238*M_PI/180), cos(239*M_PI/180), | |
128 | + cos(240*M_PI/180), cos(241*M_PI/180), cos(242*M_PI/180), cos(243*M_PI/180), cos(244*M_PI/180), | |
129 | + cos(245*M_PI/180), cos(246*M_PI/180), cos(247*M_PI/180), cos(248*M_PI/180), cos(249*M_PI/180), | |
130 | + cos(250*M_PI/180), cos(251*M_PI/180), cos(252*M_PI/180), cos(253*M_PI/180), cos(254*M_PI/180), | |
131 | + cos(255*M_PI/180), cos(256*M_PI/180), cos(257*M_PI/180), cos(258*M_PI/180), cos(259*M_PI/180), | |
132 | + cos(260*M_PI/180), cos(261*M_PI/180), cos(262*M_PI/180), cos(263*M_PI/180), cos(264*M_PI/180), | |
133 | + cos(265*M_PI/180), cos(266*M_PI/180), cos(267*M_PI/180), cos(268*M_PI/180), cos(269*M_PI/180), | |
134 | + cos(270*M_PI/180), cos(271*M_PI/180), cos(272*M_PI/180), cos(273*M_PI/180), cos(274*M_PI/180), | |
135 | + cos(275*M_PI/180), cos(276*M_PI/180), cos(277*M_PI/180), cos(278*M_PI/180), cos(279*M_PI/180), | |
136 | + cos(280*M_PI/180), cos(281*M_PI/180), cos(282*M_PI/180), cos(283*M_PI/180), cos(284*M_PI/180), | |
137 | + cos(285*M_PI/180), cos(286*M_PI/180), cos(287*M_PI/180), cos(288*M_PI/180), cos(289*M_PI/180), | |
138 | + cos(290*M_PI/180), cos(291*M_PI/180), cos(292*M_PI/180), cos(293*M_PI/180), cos(294*M_PI/180), | |
139 | + cos(295*M_PI/180), cos(296*M_PI/180), cos(297*M_PI/180), cos(298*M_PI/180), cos(299*M_PI/180), | |
140 | + cos(300*M_PI/180), cos(301*M_PI/180), cos(302*M_PI/180), cos(303*M_PI/180), cos(304*M_PI/180), | |
141 | + cos(305*M_PI/180), cos(306*M_PI/180), cos(307*M_PI/180), cos(308*M_PI/180), cos(309*M_PI/180), | |
142 | + cos(310*M_PI/180), cos(311*M_PI/180), cos(312*M_PI/180), cos(313*M_PI/180), cos(314*M_PI/180), | |
143 | + cos(315*M_PI/180), cos(316*M_PI/180), cos(317*M_PI/180), cos(318*M_PI/180), cos(319*M_PI/180), | |
144 | + cos(320*M_PI/180), cos(321*M_PI/180), cos(322*M_PI/180), cos(323*M_PI/180), cos(324*M_PI/180), | |
145 | + cos(325*M_PI/180), cos(326*M_PI/180), cos(327*M_PI/180), cos(328*M_PI/180), cos(329*M_PI/180), | |
146 | + cos(330*M_PI/180), cos(331*M_PI/180), cos(332*M_PI/180), cos(333*M_PI/180), cos(334*M_PI/180), | |
147 | + cos(335*M_PI/180), cos(336*M_PI/180), cos(337*M_PI/180), cos(338*M_PI/180), cos(339*M_PI/180), | |
148 | + cos(340*M_PI/180), cos(341*M_PI/180), cos(342*M_PI/180), cos(343*M_PI/180), cos(344*M_PI/180), | |
149 | + cos(345*M_PI/180), cos(346*M_PI/180), cos(347*M_PI/180), cos(348*M_PI/180), cos(349*M_PI/180), | |
150 | + cos(350*M_PI/180), cos(351*M_PI/180), cos(352*M_PI/180), cos(353*M_PI/180), cos(354*M_PI/180), | |
151 | + cos(355*M_PI/180), cos(356*M_PI/180), cos(357*M_PI/180), cos(358*M_PI/180), cos(359*M_PI/180)}; | ... | ... |
math/sin_cos.h
0 → 100755
rasterize.cpp
0 → 100755
1 | +/** | |
2 | + * \file rasterize.cpp | |
3 | + * | |
4 | + * \brief Implementation des Software-Rasterizers | |
5 | + * | |
6 | + * Für eine detailierte Beschreibung von Rasterizer und | |
7 | + * Software-Rasterizer schauen Sie bitte unter \ref rasterize.h | |
8 | + * | |
9 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
10 | + * | |
11 | + * \date 04.12.2003 | |
12 | + * | |
13 | + * \version ..2002 [gs]: erste funktionierende Implementation | |
14 | + * \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen | |
15 | + * \version 16.12.2003 [gs]: <ul><li> | |
16 | + * Linienclipping gefixed. Die alte | |
17 | + * Version versuchte Linien zu zeichnen | |
18 | + * die sich nach dem Clipping in | |
19 | + * Area 1001, 1010, 0101, 0110, also den | |
20 | + * Ecken rechtoben, linksoben, | |
21 | + * rechtsunten und linksunten neben dem | |
22 | + * darstellbaren Bereich befanden. | |
23 | + * </li><li> | |
24 | + * Außerdum mussten nach jedem Clipping | |
25 | + * die Masken aktualisiert werden, damit | |
26 | + * der Algoritmus abbricht wenn die | |
27 | + * Linie gezeichnet werden kann. | |
28 | + * Ansosnten führte weiters clipping zu | |
29 | + * fehlerhaften Ergebnissen. | |
30 | + * </li><li> | |
31 | + * draw_polygon_flat ruft jetzt den in | |
32 | + * polygon.h neu geschriebene | |
33 | + * Sutherland-Hodgen Clipper auf und | |
34 | + * zeichnet nur das geclippte Polygon | |
35 | + * das dieser Zurückliefert. | |
36 | + * </li></ul> | |
37 | + * \version 19.12.2003 [gs]: <ul><li> | |
38 | + * draw_polyeder_wire neu geschrieben. (Der | |
39 | + * alte Code existiert noch auskommentiert. | |
40 | + * </li><li> | |
41 | + * draw_polygon_wire geschrieben. Es macht was man | |
42 | + * sich denkt, es zeichnte ein Polygon alse linien. | |
43 | + * </li></ul> | |
44 | + * | |
45 | + * \todo (siehe \ref draw_polygon_flat) | |
46 | + */ | |
47 | + | |
48 | +/* | |
49 | + * Copyright (C)2003 Georg Steffers | |
50 | + * | |
51 | + * This program is free software; you can redistribute it and/or modify | |
52 | + * it under the terms of the GNU General Public License as published by | |
53 | + * the Free Software Foundation; either version 2 of the License, or | |
54 | + * (at your option) any later version. | |
55 | + * | |
56 | + * This program is distributed in the hope that it will be useful, | |
57 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
58 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
59 | + * GNU General Public License for more details. | |
60 | + * | |
61 | + * You should have received a copy of the GNU General Public License | |
62 | + * along with this program; if not, write to the Free Software | |
63 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
64 | + */ | |
65 | + | |
66 | +using namespace std; | |
67 | + | |
68 | +#include <cstdlib> | |
69 | +#include <climits> | |
70 | +#include <cstring> | |
71 | +#include <values.h> | |
72 | + | |
73 | +#include <iostream> | |
74 | + | |
75 | +#include "geometry/polygon.h" | |
76 | +#include "rasterize.h" | |
77 | + | |
78 | +#define CLIP_MASK_LEFT (0x1<<0) | |
79 | +#define CLIP_MASK_RIGHT (0x1<<1) | |
80 | +#define CLIP_MASK_BOTTOM (0x1<<2) | |
81 | +#define CLIP_MASK_TOP (0x1<<3) | |
82 | + | |
83 | +rasterizer::rasterizer(unsigned xs, unsigned ys, canvas_imp* ci) { | |
84 | + x_size=xs; | |
85 | + y_size=ys; | |
86 | + | |
87 | + sinfo=ci; | |
88 | + | |
89 | + zbuf=new (double*)[xs]; | |
90 | + for(unsigned i=0; i<xs; i++) { | |
91 | + zbuf[i]=new double[ys]; | |
92 | + for(unsigned j=0; j<ys; zbuf[i][j++]=MAXDOUBLE); | |
93 | + } | |
94 | + | |
95 | + unsigned sp[]={0,1,2,3}; | |
96 | + vertex v[]={vertex(0,y_size,0,1), | |
97 | + vertex(0,0,0,1), | |
98 | + vertex(x_size,0,0,1), | |
99 | + vertex(x_size,y_size,0,1)}; | |
100 | + | |
101 | + screen_p_vl=vertex_list(v, 4); | |
102 | + screen_p=polygon((unsigned*)sp, 4, &screen_p_vl); | |
103 | +} | |
104 | + | |
105 | +unsigned char* sw_rasterizer::adr_of_point(unsigned x, unsigned y) const { | |
106 | + return sinfo->p_screenbuf + (x+(y*x_size))*sinfo->bytes_per_pixel; | |
107 | +} | |
108 | + | |
109 | +void sw_rasterizer::draw_point_at_paddress(unsigned char** p, | |
110 | + unsigned long col) const { | |
111 | + unsigned long mask = 0xFF; | |
112 | + char shift = 0; | |
113 | + | |
114 | + // farbytes in Little-Endian order in den Puffer | |
115 | + for(int i=0; i<sinfo->bytes_per_pixel; i++) { | |
116 | + **p = (col & mask) >> shift; | |
117 | + (*p)++; | |
118 | + mask <<= 8; | |
119 | + shift += 8; | |
120 | + } | |
121 | +} | |
122 | + | |
123 | +void sw_rasterizer::clear_buffer(void) const { | |
124 | + memset(sinfo->p_screenbuf, 0x00, | |
125 | + (size_t)x_size*y_size*sinfo->bytes_per_pixel); | |
126 | + | |
127 | + for(unsigned i=0; i<x_size; i++) { | |
128 | + for(unsigned j=0; j<y_size; zbuf[i][j++]=MAXDOUBLE); | |
129 | + } | |
130 | +} | |
131 | + | |
132 | +void sw_rasterizer::draw_point(unsigned x, unsigned y, | |
133 | + unsigned long col) const { | |
134 | + unsigned char *p = adr_of_point(x, y); | |
135 | + draw_point_at_paddress(&p, col); | |
136 | +} | |
137 | + | |
138 | +void sw_rasterizer::line(double ax, double ay, double bx, double by, | |
139 | + unsigned long col) const { | |
140 | + /* Line-Clipping (nach Cohen-Sutherland) */ | |
141 | + char clip_mask_a=0; | |
142 | + char clip_mask_b=0; | |
143 | + unsigned x_size=this->x_size-1; | |
144 | + unsigned y_size=this->y_size-1; | |
145 | + | |
146 | + if(ax<0) clip_mask_a |= CLIP_MASK_LEFT; | |
147 | + if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT; | |
148 | + if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM; | |
149 | + if(ay<0) clip_mask_a |= CLIP_MASK_TOP; | |
150 | + | |
151 | + if(bx<0) clip_mask_b |= CLIP_MASK_LEFT; | |
152 | + if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT; | |
153 | + if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM; | |
154 | + if(by<0) clip_mask_b |= CLIP_MASK_TOP; | |
155 | + | |
156 | + if((clip_mask_a & clip_mask_b) != 0) | |
157 | + return; | |
158 | + | |
159 | + double dx=bx-ax; | |
160 | + double dy=by-ay; | |
161 | + double xinc=dx/dy; | |
162 | + double yinc=dy/dx; | |
163 | + | |
164 | + if(clip_mask_a != 0) { | |
165 | + if((clip_mask_a&CLIP_MASK_LEFT)!=0) { | |
166 | + ay+=(0-ax)*yinc; | |
167 | + ax=0; | |
168 | + } | |
169 | + else if(clip_mask_a & CLIP_MASK_RIGHT) { | |
170 | + ay+=(x_size-ax)*yinc; | |
171 | + ax=x_size; | |
172 | + } | |
173 | + | |
174 | + clip_mask_a=0; | |
175 | + if(ax<0) clip_mask_a |= CLIP_MASK_LEFT; | |
176 | + if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT; | |
177 | + if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM; | |
178 | + if(ay<0) clip_mask_a |= CLIP_MASK_TOP; | |
179 | + | |
180 | + if(clip_mask_a & CLIP_MASK_TOP) { | |
181 | + ax+=(0-ay)*xinc; | |
182 | + ay=0; | |
183 | + } | |
184 | + else if(clip_mask_a & CLIP_MASK_BOTTOM) { | |
185 | + ax+=(y_size-ay)*xinc; | |
186 | + ay=y_size; | |
187 | + } | |
188 | + } | |
189 | + | |
190 | + if(clip_mask_b != 0) { | |
191 | + if(clip_mask_b & CLIP_MASK_LEFT) { | |
192 | + by+=(0-bx)*yinc; | |
193 | + bx=0; | |
194 | + } | |
195 | + else if(clip_mask_b & CLIP_MASK_RIGHT) { | |
196 | + by+=(x_size-bx)*yinc; | |
197 | + bx=x_size; | |
198 | + } | |
199 | + | |
200 | + clip_mask_b=0; | |
201 | + if(bx<0) clip_mask_b |= CLIP_MASK_LEFT; | |
202 | + if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT; | |
203 | + if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM; | |
204 | + if(by<0) clip_mask_b |= CLIP_MASK_TOP; | |
205 | + | |
206 | + if(clip_mask_b & CLIP_MASK_TOP) { | |
207 | + bx+=(0-by)*xinc; | |
208 | + by=0; | |
209 | + } | |
210 | + else if(clip_mask_b & CLIP_MASK_BOTTOM) { | |
211 | + bx+=(y_size-by)*xinc; | |
212 | + by=y_size; | |
213 | + } | |
214 | + } | |
215 | + | |
216 | + clip_mask_a=0; | |
217 | + if(ax<0) clip_mask_a |= CLIP_MASK_LEFT; | |
218 | + if(ax>x_size) clip_mask_a |= CLIP_MASK_RIGHT; | |
219 | + if(ay>y_size) clip_mask_a |= CLIP_MASK_BOTTOM; | |
220 | + if(ay<0) clip_mask_a |= CLIP_MASK_TOP; | |
221 | + | |
222 | + clip_mask_b=0; | |
223 | + if(bx<0) clip_mask_b |= CLIP_MASK_LEFT; | |
224 | + if(bx>x_size) clip_mask_b |= CLIP_MASK_RIGHT; | |
225 | + if(by>y_size) clip_mask_b |= CLIP_MASK_BOTTOM; | |
226 | + if(by<0) clip_mask_b |= CLIP_MASK_TOP; | |
227 | + | |
228 | + if((clip_mask_a | clip_mask_b) == (CLIP_MASK_LEFT | CLIP_MASK_TOP) || | |
229 | + (clip_mask_a | clip_mask_b) == (CLIP_MASK_LEFT | CLIP_MASK_BOTTOM) || | |
230 | + (clip_mask_a | clip_mask_b) == (CLIP_MASK_RIGHT | CLIP_MASK_TOP) || | |
231 | + (clip_mask_a | clip_mask_b) == (CLIP_MASK_RIGHT | CLIP_MASK_BOTTOM)) | |
232 | + return; | |
233 | + /* ----------- */ | |
234 | + | |
235 | + /* Linie nach Bresenham */ | |
236 | + int Ax=(int)ax; | |
237 | + int Bx=(int)bx; | |
238 | + int Ay=(int)ay; | |
239 | + int By=(int)by; | |
240 | + | |
241 | + int dX = abs(Bx-Ax); | |
242 | + int dY = abs(By-Ay); | |
243 | + | |
244 | + int Xincr=(Ax > Bx)?-1:1; | |
245 | + int Yincr=(Ay > By)?-1:1; | |
246 | + | |
247 | + if (dX >= dY) { | |
248 | + int dPr = dY<<1; | |
249 | + int dPru = dPr - (dX<<1); | |
250 | + int P = dPr - dX; | |
251 | + | |
252 | + for (; dX>=0; dX--) { | |
253 | + draw_point(Ax, Ay, col); | |
254 | + if (P > 0) { | |
255 | + Ax+=Xincr; | |
256 | + Ay+=Yincr; | |
257 | + P+=dPru; | |
258 | + } | |
259 | + else { | |
260 | + Ax+=Xincr; | |
261 | + P+=dPr; | |
262 | + } | |
263 | + } | |
264 | + } | |
265 | + else { | |
266 | + int dPr = dX<<1; | |
267 | + int dPru = dPr - (dY<<1); | |
268 | + int P = dPr - dY; | |
269 | + | |
270 | + for (; dY>=0; dY--) { | |
271 | + draw_point(Ax, Ay, col); | |
272 | + if (P > 0) { | |
273 | + Ax+=Xincr; | |
274 | + Ay+=Yincr; | |
275 | + P+=dPru; | |
276 | + } | |
277 | + else { | |
278 | + Ay+=Yincr; | |
279 | + P+=dPr; | |
280 | + } | |
281 | + } | |
282 | + } | |
283 | + /*------------------*/ | |
284 | +} | |
285 | + | |
286 | +void sw_rasterizer::draw_polygon_wire(const polygon& p, | |
287 | + unsigned long col) const { | |
288 | + for(unsigned i=0; i<p.card(); i++) { | |
289 | + line((int)p[i][X], (int)p[i][Y], | |
290 | + (int)p[(i+1)%p.card()][X], (int)p[(i+1)%p.card()][Y], col); | |
291 | + } | |
292 | +} | |
293 | + | |
294 | +void sw_rasterizer::draw_polyeder_wire(const polyeder& p, | |
295 | + unsigned long col) const { | |
296 | +/* for(unsigned i=0; i<p.card(); i++) { | |
297 | + int oldx, oldy; | |
298 | + int firstx, firsty; | |
299 | + | |
300 | + oldx=oldy=firstx=firsty=0; | |
301 | + | |
302 | + for(unsigned j=0; j<p[i].card(); j++) { | |
303 | + if(oldx) | |
304 | + line(oldx, oldy, (int)p[i][j][X], (int)p[i][j][Y], col); | |
305 | + | |
306 | + oldx=(int)p[i][j][X], oldy=(int)p[i][j][Y]; | |
307 | + | |
308 | + if(j==0) | |
309 | + firstx=(int)p[i][j][X], firsty=(int)p[i][j][Y]; | |
310 | + } | |
311 | + | |
312 | + line(oldx, oldy, firstx, firsty, col); | |
313 | + }*/ | |
314 | + for(unsigned i=0; i<p.card(); i++) { | |
315 | + for(unsigned j=0; j<p[i].card(); j++) { | |
316 | + line((int)p[i][j][X], (int)p[i][j][Y], | |
317 | + (int)p[i][(j+1)%p.card()][X], | |
318 | + (int)p[i][(j+1)%p.card()][Y], col); | |
319 | + } | |
320 | + } | |
321 | +} | |
322 | + | |
323 | +/** | |
324 | + * \todo Ein funktionierendes z-buffering und texturemapping usw. | |
325 | + * Aktuell ist ein Prototyp-Code für einen z-Buffer drin, | |
326 | + * aber der funktioniert aus irgendeinem Grund nicht richtig. | |
327 | + */ | |
328 | +void sw_rasterizer::draw_polygon_flat(const polygon& p, | |
329 | + unsigned long col) const { | |
330 | + int top=0, bottom=0, o_top=0; | |
331 | + int start_left, end_left; | |
332 | + int start_right, end_right; | |
333 | + | |
334 | + /* Clipping..... */ | |
335 | + /* Sutherland-Hodgman */ | |
336 | + polygon clipped=p.clip_2d(screen_p); | |
337 | + | |
338 | + // Sind nach dem Clipping weniger als 3 Vertices übrig, so ist das | |
339 | + // Polygon nicht mehr im sichtbaren Bereich und darf nicht gezeichnet | |
340 | + // werden. | |
341 | + if(clipped.card()<3) | |
342 | + return; | |
343 | + | |
344 | + // oberes und unterstes Vertex finden... | |
345 | + // außerdem den oberen Vertex fuer die erste rechte und linke Kante | |
346 | + for(unsigned i=1; i<clipped.card(); i++) { | |
347 | + end_left=end_right=top=(clipped[i][Y]<clipped[top][Y])?i:top; | |
348 | + bottom=(clipped[i][Y]>clipped[bottom][Y])?i:bottom; | |
349 | + } | |
350 | + | |
351 | + for(unsigned i=1; i<p.card(); i++) { | |
352 | + o_top=(p[i][Y]<p[o_top][Y])?i:o_top; | |
353 | + } | |
354 | + | |
355 | + // Startpositionen | |
356 | + double act_y=clipped[top][Y]; | |
357 | + int act_ceily=(int)ceil(act_y); | |
358 | + double act_x_l, act_x_r; | |
359 | + double act_z_l, act_z_r; | |
360 | + | |
361 | + // !!! Das erste mal wenn act_z ermittelt wird muss ich die Verchiebung | |
362 | + // auf die Integer Koordinaten (x,y) mit berechnen, da der gezeichnete Punkt | |
363 | + // nicht exact dem geometrischen entspricht. | |
364 | + | |
365 | + // calculate gradients (!!!NICHT VOM GECLIPPTEN!!!) | |
366 | + // nur anwendbar über Werte die über das gesamte Polygon (screenspace) | |
367 | + // linear interpolierbar sind, also nicht gourard-shading, da diese | |
368 | + // Werte nur entlang einer Kante linier sind. | |
369 | + // !!! Ich brauche eine Methode, ein Dreieck zu finden, das einen Punkt | |
370 | + // oben, den zweiten als linke Seite und den dritten als rechte Seite bildet | |
371 | + // dazu muss ich die x,y Werte der Puntke analysieren. Die Lage der | |
372 | + // Punkte ist wichtig, damit die Vorzeichen der Gradienten stimmen, bzw. | |
373 | + // überhaupt erstmal welche berechnet werden können, es gibt Punkt | |
374 | + // kombinationen für die die Gradientenberechnung kein Ergebnis liefert. | |
375 | + // Das ermittelte Dreieck lässt sich dann allerdings zur ermittlung aller | |
376 | + // Gradienten gebrauchen. | |
377 | + | |
378 | + // den obersten Vertex raussuchen, dann den davor und den danach. | |
379 | + // !!!ACHTUNG!!! Bei allen Berechnungen lasse ich im moment einen Fall | |
380 | + // ganz außer acht und zwar den, wenn das Dreiech zu einer Linie | |
381 | + // entartet. | |
382 | + unsigned gr_v0=o_top; | |
383 | + unsigned gr_v1=(o_top+1)%p.card(); | |
384 | + unsigned gr_v2=(o_top-1<0)?o_top-1+p.card():o_top-1; | |
385 | + | |
386 | + // der kleinere X soll gr_v1 sein wenn sein Y größer ist. | |
387 | + if((p[gr_v1][X]>p[gr_v2][X] && p[gr_v1][Y]>=p[gr_v2][Y]) || | |
388 | + (p[gr_v1][X]<p[gr_v2][X] && p[gr_v1][Y]<p[gr_v2][Y])) | |
389 | + swap<unsigned>(gr_v1, gr_v2); | |
390 | + | |
391 | + double dx21=p[gr_v2][X]-p[gr_v1][X]; | |
392 | + double dx10=p[gr_v1][X]-p[gr_v0][X]; | |
393 | + double dy21=p[gr_v2][Y]-p[gr_v1][Y]; | |
394 | + double dy01=p[gr_v0][Y]-p[gr_v1][Y]; | |
395 | + double d_z21=p[gr_v2][Z]-p[gr_v1][Z]; | |
396 | + double d_z10=p[gr_v1][Z]-p[gr_v0][Z]; | |
397 | + | |
398 | + double dx01=p[gr_v0][X]-p[gr_v1][X]; | |
399 | + double dy10=p[gr_v1][Y]-p[gr_v0][Y]; | |
400 | + | |
401 | + double v3_x=p[gr_v0][X]; | |
402 | + double v4_y=p[gr_v0][Y]; | |
403 | + double v3_y=((dy21*dx01) / dx21) + p[gr_v1][Y]; | |
404 | + double v3_z=((d_z21*dx01) / dx21) + p[gr_v1][Z]; | |
405 | + double v4_x=((dx21*dy01) / dy21) + p[gr_v1][X]; | |
406 | + double v4_z=((d_z21*dy01) / dy21) + p[gr_v1][Z]; | |
407 | + | |
408 | + // zuallererst müsste ich mal überprüfen ob alle drei Punkte in | |
409 | + // einer Linie liegen, also dx01/dy01 == dx02/dy02 ist...da ich aber | |
410 | + // noch nicht weiss wie ich diesen Fall behandeln soll ignorier ich | |
411 | + // ihn im moment und nehme die entstehenden Fehler in kauf. | |
412 | + | |
413 | + double d_zdx_denominator=0; | |
414 | + double d_zdy_denominator=0; | |
415 | + double d_zdx, d_zdy; | |
416 | + // zuerst dc/dx ermitteln. (einfach wenn y1==y2) | |
417 | + // zu den Bezeichnern: _x == 1/x, _? == 1/? | |
418 | + if(p[gr_v0][Y] == p[gr_v1][Y]) | |
419 | + d_zdx=(p[gr_v1][Z]-p[gr_v0][Z]) / (p[gr_v1][X]-p[gr_v0][X]); | |
420 | + else if(p[gr_v0][Y] == p[gr_v2][Y]) | |
421 | + d_zdx=(p[gr_v2][Z]-p[gr_v0][Z]) / (p[gr_v2][X]-p[gr_v0][X]); | |
422 | + else if(p[gr_v1][Y] == p[gr_v2][Y]) | |
423 | + d_zdx=(p[gr_v2][Z]-p[gr_v1][Z]) / (p[gr_v2][X]-p[gr_v1][X]); | |
424 | + else { | |
425 | + d_zdx_denominator=(dx21*dy01)+(dx10*dy21); | |
426 | + d_zdx=((d_z21*dy01)+(d_z10*dy21))/d_zdx_denominator; | |
427 | + } | |
428 | + | |
429 | + // jetzt dc/dy...(einfach falls es eine Sekrechte gibt.) | |
430 | + if(p[gr_v0][X] == p[gr_v1][X]) | |
431 | + d_zdy=(p[gr_v1][Z]-p[gr_v0][Z]) / p[gr_v1][Y]-p[gr_v0][Y]; | |
432 | + else if(p[gr_v0][X] == p[gr_v2][X]) | |
433 | + d_zdy=(p[gr_v2][Z]-p[gr_v0][Z]) / p[gr_v2][Y]-p[gr_v0][Y]; | |
434 | + else if(p[gr_v1][X] == p[gr_v2][X]) | |
435 | + d_zdy=(p[gr_v2][Z]-p[gr_v1][Z]) / p[gr_v2][Y]-p[gr_v1][Y]; | |
436 | + else { | |
437 | + d_zdy_denominator=d_zdx_denominator!=0?-d_zdx_denominator: | |
438 | + (dy21*dx01)+(dy10*dx21); | |
439 | + d_zdy=((d_z21*dx01)+(d_z10*dx21))/d_zdy_denominator; | |
440 | + } | |
441 | + | |
442 | +/* if(!strncmp(p.get_id(), "DEBUG", 29)) { | |
443 | + cout << "---Polygon: " << &p << "----------\n"; | |
444 | + | |
445 | + for(unsigned i=0; i<p.card(); i++) { | |
446 | + cout << "p[" << i << "][X]: " << p[i][X] << ", "; | |
447 | + cout << "p[" << i << "][Y]: " << p[i][Y] << ", "; | |
448 | + cout << "p[" << i << "][1/Z]: " << p[i][Z] << ", "; | |
449 | + cout << "p[" << i << "][Z]: " << 1/p[i][Z] << "\n"; | |
450 | + } | |
451 | + for(unsigned i=0; i<clipped.card(); i++) { | |
452 | + cout << "clipped[" << i << "][X]: " << clipped[i][X] << ", "; | |
453 | + cout << "clipped[" << i << "][Y]: " << clipped[i][Y] << ", "; | |
454 | + cout << "clipped[" << i << "][1/Z]: " << clipped[i][Z] << ", "; | |
455 | + cout << "clipped[" << i << "][Z]: " << 1/clipped[i][Z] << "\n"; | |
456 | + } | |
457 | + cout << "gr_v0: " << gr_v0 << " | "; | |
458 | + cout << "gr_v0[X]: " << p[gr_v0][X] << " | "; | |
459 | + cout << "gr_v0[Y]: " << p[gr_v0][Y] << " | "; | |
460 | + cout << "gr_v0[Z]: " << p[gr_v0][Z] << "\n"; | |
461 | + cout << "gr_v1: " << gr_v1 << " | "; | |
462 | + cout << "gr_v1[X]: " << p[gr_v1][X] << " | "; | |
463 | + cout << "gr_v1[Y]: " << p[gr_v1][Y] << " | "; | |
464 | + cout << "gr_v1[Z]: " << p[gr_v1][Z] << "\n"; | |
465 | + cout << "gr_v2: " << gr_v2 << " | "; | |
466 | + cout << "gr_v2[X]: " << p[gr_v2][X] << " | "; | |
467 | + cout << "gr_v2[Y]: " << p[gr_v2][Y] << " | "; | |
468 | + cout << "gr_v2[Z]: " << p[gr_v2][Z] << "\n"; | |
469 | + cout << "d_zdx: " << d_zdx << "\n"; | |
470 | + cout << "d_zdy: " << d_zdy << "\n"; | |
471 | + cout << "-------------------------------\n"; | |
472 | + } */ | |
473 | + | |
474 | + //if(!strncmp(p.get_id(), "DEBUG", 29)) { | |
475 | + // solange zeichnen, bis der unterste y erreicht ist | |
476 | + while(act_ceily < y_size) { | |
477 | + double x_inc_l, x_inc_r, z_inc_l, z_inc_r; | |
478 | + | |
479 | + // naechste linke und rechte Kante finden deren hoehe>0 und | |
480 | + // das linke und rechte x-Increment ermitteln. | |
481 | + if((int)ceil(clipped[end_left][Y]) == act_ceily) { | |
482 | + do { | |
483 | + start_left=end_left; | |
484 | + if(start_left == bottom) { | |
485 | + return; | |
486 | + } | |
487 | + end_left=(end_left-1<0)?end_left-1+clipped.card():end_left-1; | |
488 | + } while((int)ceil(clipped[end_left][Y]) == act_ceily); | |
489 | + | |
490 | + act_y=clipped[start_left][Y]; | |
491 | + act_ceily=(int)ceil(act_y); | |
492 | + | |
493 | + x_inc_l=(clipped[end_left][X]-clipped[start_left][X])/ | |
494 | + (clipped[end_left][Y]-clipped[start_left][Y]); | |
495 | + z_inc_l=x_inc_l*d_zdx; | |
496 | + | |
497 | + act_x_l=clipped[start_left][X]; | |
498 | + // Subpixelkorrektur | |
499 | + act_x_l+=((double)act_ceily-act_y)*x_inc_l; | |
500 | + act_z_l=clipped[start_left][Z]; | |
501 | + act_z_l+=((double)act_ceily-act_y)*z_inc_l; | |
502 | + } | |
503 | + if((int)ceil(clipped[end_right][Y]) == act_ceily) { | |
504 | + do { | |
505 | + start_right=end_right; | |
506 | + if(start_right == bottom) { | |
507 | + return; | |
508 | + } | |
509 | + end_right=(end_right+1)%clipped.card(); | |
510 | + } while((int)ceil(clipped[end_right][Y]) == act_ceily); | |
511 | + | |
512 | + act_y=clipped[start_right][Y]; | |
513 | + act_ceily=(int)ceil(act_y); | |
514 | + | |
515 | + x_inc_r=(clipped[end_right][X]-clipped[start_right][X])/ | |
516 | + (clipped[end_right][Y]-clipped[start_right][Y]); | |
517 | + z_inc_r=x_inc_r*d_zdx; | |
518 | + | |
519 | + act_x_r=clipped[start_right][X]; | |
520 | + // Subpixelkorrektur | |
521 | + act_x_r+=((double)act_ceily-act_y)*x_inc_r; | |
522 | + act_z_r=clipped[start_right][Z]; | |
523 | + act_z_r+=((double)act_ceily-act_y)*z_inc_r; | |
524 | + } | |
525 | + | |
526 | + // bis zu welchem der beiden Vertexe (links o. rechts) muss ich? | |
527 | + unsigned togo=((int)ceil(clipped[end_left][Y])-act_ceily <= | |
528 | + (int)ceil(clipped[end_right][Y])-act_ceily)? | |
529 | + end_left:end_right; | |
530 | + | |
531 | + for(; act_ceily < (int)ceil(clipped[togo][Y]); act_ceily++) { | |
532 | + unsigned char* adr=adr_of_point((act_x_l<act_x_r)? | |
533 | + (int)ceil(act_x_l): | |
534 | + (int)ceil(act_x_r), | |
535 | + act_ceily); | |
536 | + | |
537 | + unsigned len=abs((int)ceil(act_x_r)-(int)ceil(act_x_l)); | |
538 | + int _X=(act_x_l<act_x_r)?(int)ceil(act_x_l):(int)ceil(act_x_r); | |
539 | + | |
540 | + //double act_z=(act_x_l<act_x_r)?act_z_l:act_z_r; | |
541 | + double act_row_z=(act_x_l<act_x_r)?act_z_l:act_z_r; | |
542 | + | |
543 | + for(unsigned i=0; i<len; i++) { | |
544 | + double _Z=1/act_row_z; | |
545 | + //if(zbuf[_X+i][act_ceily] > _Z) { | |
546 | + draw_point_at_paddress(&adr, col); | |
547 | + zbuf[_X+i][act_ceily]=_Z; | |
548 | + //} | |
549 | + // if(!strncmp(p.get_id(), "DEBUG", 29)) { | |
550 | + // printf("%03ld,%03ld,%10.7f ", _X+i, act_ceily, act_row_z); | |
551 | + // } | |
552 | + act_row_z+=d_zdx; | |
553 | + } | |
554 | + | |
555 | + act_x_l+=x_inc_l; | |
556 | + act_x_r+=x_inc_r; | |
557 | + act_z_l+=z_inc_l; | |
558 | + act_z_l+=d_zdy; | |
559 | + act_z_r+=z_inc_r; | |
560 | + act_z_r+=d_zdy; | |
561 | + | |
562 | + // if(!strncmp(p.get_id(), "DEBUG", 29)) { | |
563 | + // cout << "\n"; | |
564 | + // } | |
565 | + } | |
566 | + } | |
567 | + //} | |
568 | +} | ... | ... |
rasterize.h
0 → 100755
1 | +/** | |
2 | + * \file rasterize.h | |
3 | + * | |
4 | + * \brief Methoden um auf ein Canvas zu zeichnen | |
5 | + * | |
6 | + * Der rasterizer stellt Methoden zur verfügung um auf ein canvas zu | |
7 | + * zeichnen. Darunter den Canvas zu leeren, Punkt, Linie, Polygon | |
8 | + * (gefüllt und ungefüllt) und Polyeder zeichnen und die Farbe | |
9 | + * eines bestimmten Punktes im Zeichenpuffer ermitteln. | |
10 | + * Diese Klasse ist abstrakt. Ein Rasterizer wird immer von einem | |
11 | + * Canvas erzeugt werden, damit man einen zu diesem Canvas passenden | |
12 | + * Rasteriser hat. Implementiert ist ein Software-Rasterizer zum zeichnen | |
13 | + * auf ein X11 oder X11-shm Canvas. | |
14 | + * | |
15 | + * \author Georg Steffers <georg@steffers.org> | |
16 | + * | |
17 | + * \date 04.12.2003 | |
18 | + * | |
19 | + * \version ..2002 (Georg Steffers): erste funktionierende Implementation | |
20 | + * \version 04.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen | |
21 | + */ | |
22 | + | |
23 | +/* | |
24 | + * Copyright (C)2003 Georg Steffers | |
25 | + * | |
26 | + * This program is free software; you can redistribute it and/or modify | |
27 | + * it under the terms of the GNU General Public License as published by | |
28 | + * the Free Software Foundation; either version 2 of the License, or | |
29 | + * (at your option) any later version. | |
30 | + * | |
31 | + * This program is distributed in the hope that it will be useful, | |
32 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
33 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
34 | + * GNU General Public License for more details. | |
35 | + * | |
36 | + * You should have received a copy of the GNU General Public License | |
37 | + * along with this program; if not, write to the Free Software | |
38 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
39 | + */ | |
40 | + | |
41 | +#ifndef __rasterizer_h__ | |
42 | +#define __rasterizer_h__ | |
43 | + | |
44 | +#include "canvas_imps/canvas_imp.h" | |
45 | +#include "geometry/polygon.h" | |
46 | +#include "geometry/polyeder.h" | |
47 | + | |
48 | +class rasterizer { | |
49 | + protected: | |
50 | + unsigned x_size; | |
51 | + unsigned y_size; | |
52 | + | |
53 | + canvas_imp* sinfo; | |
54 | + | |
55 | + vertex_list screen_p_vl; | |
56 | + polygon screen_p; | |
57 | + | |
58 | + double** zbuf; | |
59 | + | |
60 | + public: | |
61 | + rasterizer(unsigned = 0, unsigned = 0, canvas_imp* = NULL); | |
62 | + | |
63 | + virtual void clear_buffer(void) const=0; | |
64 | + virtual void draw_point(unsigned x, unsigned y, | |
65 | + unsigned long col) const=0; | |
66 | + virtual void line(double, double, double, double, | |
67 | + unsigned long) const=0; | |
68 | + virtual void draw_polygon_flat(const polygon&, unsigned long) const=0; | |
69 | + virtual void draw_polygon_wire(const polygon&, unsigned long) const=0; | |
70 | + virtual void draw_polyeder_wire(const polyeder&, unsigned long) const=0; | |
71 | + unsigned long get_color(unsigned red, unsigned green, unsigned blue) { | |
72 | + return sinfo->ext_to_native(red, green, blue); | |
73 | + } | |
74 | + | |
75 | + virtual unsigned get_x_size(void) const { return x_size; } | |
76 | + virtual unsigned get_y_size(void) const { return y_size; } | |
77 | +}; | |
78 | + | |
79 | +class sw_rasterizer : public rasterizer { | |
80 | + private: | |
81 | + unsigned char* adr_of_point(unsigned, unsigned) const; | |
82 | + void draw_point_at_paddress(unsigned char**, unsigned long) const; | |
83 | + | |
84 | + public: | |
85 | + sw_rasterizer(unsigned xs, unsigned ys, canvas_imp* ci) : | |
86 | + rasterizer(xs, ys, ci) {} | |
87 | + | |
88 | + void clear_buffer(void) const; | |
89 | + void draw_point(unsigned x, unsigned y, unsigned long col) const; | |
90 | + void line(double, double, double, double, unsigned long) const; | |
91 | + void draw_polygon_flat(const polygon&, unsigned long) const; | |
92 | + void draw_polygon_wire(const polygon&, unsigned long) const; | |
93 | + void draw_polyeder_wire(const polyeder&, unsigned long) const; | |
94 | +}; | |
95 | + | |
96 | +#endif // __rasterize_h__ | ... | ... |
test.cpp
0 → 100755
1 | +#include "math/Mmn.h" | |
2 | +#include <time.h> | |
3 | +#include <sys/timeb.h> | |
4 | + | |
5 | +int main(void) { | |
6 | + double x0=-1, x1=1, y0=0, y1=0; | |
7 | + double x0s=-1, x1s=1, y0s=1, y1s=-2; | |
8 | + time_t secs; | |
9 | + unsigned short ms; | |
10 | + struct timeb tb1; | |
11 | + struct timeb tb2; | |
12 | + int i; | |
13 | + double x, y; | |
14 | + | |
15 | + double a[2][3]={{y1-y0, -(x1-x0), -(x1*y0-y1*x0)}, | |
16 | + {y1s-y0s, -(x1s-x0s), -(x1s*y0s-y1s*x0s)}}; | |
17 | + Mmn<double> mat((double*)a, 2, 3); | |
18 | + | |
19 | + mat.print(); | |
20 | + ftime(&tb1); | |
21 | + for(i=0; i<1000; i++) | |
22 | + mat.solve(); | |
23 | + ftime(&tb2); | |
24 | + | |
25 | + cout << tb1.time << ":" << tb1.millitm << "\n"; | |
26 | + cout << tb2.time << ":" << tb2.millitm << "\n"; | |
27 | + cout << tb2.time-tb1.time << ":" << tb2.millitm-tb1.millitm << "\n"; | |
28 | + | |
29 | + ftime(&tb1); | |
30 | + for(i=0; i<1000; i++) { | |
31 | + x=x0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/ | |
32 | + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(x1-x0); | |
33 | + | |
34 | + y=y0+((((x1s-x0s)*(y0-y0s))+((y1s-y0s)*(x0s-x0)))/ | |
35 | + (((x1-x0)*(y1s-y0s))-((y1-y0)*(x1s-x0s))))*(y1-y0); | |
36 | + } | |
37 | + ftime(&tb2); | |
38 | + | |
39 | + cout << tb1.time << ":" << tb1.millitm << "\n"; | |
40 | + cout << tb2.time << ":" << tb2.millitm << "\n"; | |
41 | + cout << tb2.time-tb1.time << ":" << tb2.millitm-tb1.millitm << "\n"; | |
42 | + | |
43 | + /* | |
44 | + * Fazit: nach einigen Testläufen mit diesem Programm hat sich ergeben, das | |
45 | + * beide Methoden keine messbaren Zeitunterschied im 1000stel Sekundenbereich | |
46 | + + haben, daher faworisiere ich die Methode über das lösen des | |
47 | + * Gleichungssystems, da diese universeller (auch mit 3 Geraden) einsetzbar | |
48 | + * und auch verständlicher ist (man braucht keine Formeln herleiten. | |
49 | + * | |
50 | + * Wenn ich die berechnungen 1000 mal ausführe habe die Gleichungen einen | |
51 | + * deutlichen vorteil. Daher nehme ich wohl doch sie... | |
52 | + */ | |
53 | + return 0; | |
54 | +} | ... | ... |
xwin/Makefile
0 → 100755
1 | +CC=gcc | |
2 | +CPP=g++ | |
3 | +#CFLAGS=-ggdb | |
4 | +CXXFLAGS= | |
5 | +MAKE=make | |
6 | + | |
7 | +INC_X11=-I/usr/X11R6/include | |
8 | + | |
9 | +OBJECTS=canvas_x11.o canvas_x11_shm.o disp_x11.o xclass.o | |
10 | + | |
11 | +%.o: %.cpp | |
12 | + $(CPP) $(CFLAGS) $(CXXFLAGS) $(INC_X11) -c $*.cpp | |
13 | + | |
14 | +.PHONY : all clean | |
15 | + | |
16 | +all: $(OBJECTS) | |
17 | + | |
18 | +clean: | |
19 | + @rm -f *.o | ... | ... |
xwin/canvas_x11.cpp
0 → 100755
1 | +using namespace std; | |
2 | + | |
3 | +#include <cstdlib> | |
4 | + | |
5 | +#include "canvas_x11.h" | |
6 | +#include "../canvas_imps/canvas_imp_rgb.h" | |
7 | + | |
8 | +canvas_x11::canvas_x11(unsigned xs, unsigned ys) : canvas(xs, ys) { | |
9 | + disp=new xdisplay(); | |
10 | + scr=disp->defaultscreen(); | |
11 | + win=new xwindow(scr->getrootwin(), 100, 100, 1, x_size, y_size); | |
12 | + win->map(); | |
13 | + | |
14 | + switch(scr->getvisual()->c_class) { | |
15 | + XVisualInfo vi; | |
16 | + int result; | |
17 | + | |
18 | + case TrueColor: | |
19 | + result=XMatchVisualInfo(disp->getdisplay(), disp->defaultscreenid(), | |
20 | + scr->getdepth(), TrueColor, &vi); | |
21 | + if(result) | |
22 | + sinfo=new canvas_imp_rgb(scr->getvisual()->red_mask, | |
23 | + scr->getvisual()->green_mask, | |
24 | + scr->getvisual()->blue_mask, | |
25 | + scr->getbytespp(), vi.depth/8); | |
26 | + else { | |
27 | + exit(EXIT_FAILURE); | |
28 | + } | |
29 | + break; | |
30 | + | |
31 | + case PseudoColor: | |
32 | + case StaticColor: | |
33 | + case GrayScale: | |
34 | + case StaticGray: | |
35 | + case DirectColor: | |
36 | + exit(EXIT_FAILURE); | |
37 | + } | |
38 | + | |
39 | + sinfo->p_screenbuf=new unsigned char[x_size*y_size*scr->getbytespp()]; | |
40 | + | |
41 | + ximg=XCreateImage(disp->getdisplay(), scr->getvisual(), scr->getdepth(), | |
42 | + ZPixmap, 0, (char*)sinfo->p_screenbuf, | |
43 | + x_size, y_size, scr->getscanlinepad(), 0); | |
44 | +} | |
45 | + | |
46 | +canvas_x11::~canvas_x11() { | |
47 | + delete sinfo; | |
48 | + if(ximg) { | |
49 | + XDestroyImage(ximg); | |
50 | + ximg=NULL; | |
51 | + } | |
52 | + delete disp; | |
53 | +} | |
54 | + | |
55 | +void canvas_x11::create_buffer(void) { | |
56 | + // wenn ich factorys habe sollte ich irgendwie das buffer erzeugen | |
57 | + // auslagern, da ich bei shm den buffer aus dem ximg erzeuge und | |
58 | + // ansonsten andersherum, sonst hab ich noch keine rechte idee wie | |
59 | + // ich das konsistent bewerkstelligen kann... | |
60 | +} | |
61 | + | |
62 | +void canvas_x11::blit_screen(void) { | |
63 | + while(blit != NO_BLIT) {} | |
64 | + | |
65 | + blit=BLIT; | |
66 | + XPutImage(disp->getdisplay(), win->getwindow(), scr->getgc(), | |
67 | + ximg, 0,0,0,0, x_size, y_size); | |
68 | + blit=NO_BLIT; | |
69 | +} | ... | ... |
xwin/canvas_x11.h
0 → 100755
1 | +/** | |
2 | + * \file canvas_x11.h | |
3 | + * | |
4 | + * \brief Ein X11-Canvas | |
5 | + * | |
6 | + * Die X11-Implementaton eines Canvas, hier ist ein XImage der Speicherbereich | |
7 | + * in den geschrieben wird. | |
8 | + * | |
9 | + * \author Georg Steffers <georg@steffers.org> [gs] | |
10 | + * | |
11 | + * \date 04.12.2003 | |
12 | + * | |
13 | + * \version ..2002 [gs]: erste funktionierende Implementation | |
14 | + * \version 04.12.2003 [gs]: beginn der Dokumentation via doxygen | |
15 | + * \version 19.12.2003 [gs]: draw_text hinzugefügt, es schreibt über | |
16 | + * XDrawImageString einen Text in meine | |
17 | + * Window. (Brauche ich für DEBUG-Ausgaben) | |
18 | + */ | |
19 | + | |
20 | +/* | |
21 | + * Copyright (C)2003 Georg Steffers | |
22 | + * | |
23 | + * This program is free software; you can redistribute it and/or modify | |
24 | + * it under the terms of the GNU General Public License as published by | |
25 | + * the Free Software Foundation; either version 2 of the License, or | |
26 | + * (at your option) any later version. | |
27 | + * | |
28 | + * This program is distributed in the hope that it will be useful, | |
29 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
30 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
31 | + * GNU General Public License for more details. | |
32 | + * | |
33 | + * You should have received a copy of the GNU General Public License | |
34 | + * along with this program; if not, write to the Free Software | |
35 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
36 | + */ | |
37 | + | |
38 | +#ifndef __canvas_x11_h__ | |
39 | +#define __canvas_x11_h__ | |
40 | + | |
41 | +#include "xclass.h" | |
42 | +#include "../canvas.h" | |
43 | +#include "../event_source.h" | |
44 | + | |
45 | +class disp_x11; | |
46 | +class canvas_x11 : public canvas { | |
47 | + friend class disp_x11; | |
48 | + | |
49 | + protected: | |
50 | + xdisplay* disp; | |
51 | + xscreen* scr; | |
52 | + xwindow* win; | |
53 | + | |
54 | + XImage* ximg; | |
55 | + | |
56 | + virtual void create_buffer(void); | |
57 | + | |
58 | + public: | |
59 | + virtual void draw_text(int x, int y, char* text, int length) { | |
60 | + XDrawImageString(disp->getdisplay(), | |
61 | + win->getwindow(), | |
62 | + scr->getgc(), | |
63 | + x, y, text, length); | |
64 | + } | |
65 | + | |
66 | + canvas_x11(unsigned, unsigned); | |
67 | + virtual ~canvas_x11(); | |
68 | + | |
69 | + virtual rasterizer* create_rasterizer(void) { | |
70 | + return new sw_rasterizer(x_size, y_size, sinfo); | |
71 | + } | |
72 | + Display* get_display(void) { return disp->getdisplay(); } | |
73 | + Window get_window(void) { return win->getwindow(); } | |
74 | + virtual void open_screen(void) {} | |
75 | + virtual void blit_screen(void); | |
76 | +}; | |
77 | + | |
78 | +class canvas_x11_factory : public canvas_factory { | |
79 | + public: | |
80 | + canvas* create(unsigned xs, unsigned ys) const { | |
81 | + return new canvas_x11(xs, ys); | |
82 | + } | |
83 | +}; | |
84 | + | |
85 | +#endif // __canvas_x11_h__ | ... | ... |
xwin/canvas_x11_shm.cpp
0 → 100755
1 | +using namespace std; | |
2 | + | |
3 | +#include <cstdlib> | |
4 | + | |
5 | +#include "canvas_x11_shm.h" | |
6 | + | |
7 | +canvas_x11_shm::canvas_x11_shm(unsigned xs, unsigned ys) : | |
8 | + canvas_x11(xs, ys) { | |
9 | + XDestroyImage(ximg); | |
10 | + //delete [] sinfo->p_screenbuf; | |
11 | + | |
12 | + ximg = XShmCreateImage(disp->getdisplay(), scr->getvisual(), | |
13 | + scr->getdepth(), ZPixmap, 0, &shminfo, | |
14 | + x_size, y_size); | |
15 | + | |
16 | + shminfo.shmid=shmget(IPC_PRIVATE, ximg->bytes_per_line*ximg->height, | |
17 | + IPC_CREAT | 0777); | |
18 | + | |
19 | + if(shminfo.shmid < 0) { | |
20 | + XDestroyImage(ximg); | |
21 | + ximg=NULL; | |
22 | + exit(EXIT_FAILURE); | |
23 | + } | |
24 | + else { | |
25 | + shminfo.shmaddr=ximg->data=(char*)shmat(shminfo.shmid,0,0); | |
26 | + if(shminfo.shmaddr == (char*)-1) { | |
27 | + XDestroyImage(ximg); | |
28 | + ximg=NULL; | |
29 | + exit(EXIT_FAILURE); | |
30 | + } | |
31 | + else { | |
32 | + shminfo.readOnly=false; | |
33 | + XShmAttach(disp->getdisplay(), &shminfo); | |
34 | + } | |
35 | + } | |
36 | + | |
37 | + sinfo->p_screenbuf=(unsigned char*)(ximg->data); | |
38 | +} | |
39 | + | |
40 | +canvas_x11_shm::~canvas_x11_shm() { | |
41 | + XShmDetach(disp->getdisplay(), &shminfo); | |
42 | + if(ximg) { | |
43 | + XDestroyImage(ximg); | |
44 | + ximg=NULL; | |
45 | + } | |
46 | + shmdt(shminfo.shmaddr); | |
47 | + shmctl(shminfo.shmid, IPC_RMID, NULL); | |
48 | +} | |
49 | + | |
50 | +void canvas_x11_shm::blit_screen(void) { | |
51 | + while(blit != NO_BLIT) {} | |
52 | + | |
53 | + blit=BLIT; | |
54 | + XShmPutImage(disp->getdisplay(), win->getwindow(), scr->getgc(), | |
55 | + ximg, 0,0,0,0, x_size, y_size, false); | |
56 | + blit=NO_BLIT; | |
57 | +} | ... | ... |
xwin/canvas_x11_shm.h
0 → 100755
1 | +#ifndef __canvas_x11_shm_h__ | |
2 | +#define __canvas_x11_shm_h__ | |
3 | + | |
4 | +#include <X11/Xlib.h> | |
5 | +#include <X11/extensions/XShm.h> | |
6 | + | |
7 | +#include <sys/ipc.h> | |
8 | +#include <sys/shm.h> | |
9 | + | |
10 | +#include "canvas_x11.h" | |
11 | +#include "xclass.h" | |
12 | + | |
13 | +class canvas_x11_shm : public canvas_x11 { | |
14 | + protected: | |
15 | + XShmSegmentInfo shminfo; | |
16 | + | |
17 | + virtual void create_buffer(void) {} | |
18 | + | |
19 | + public: | |
20 | + canvas_x11_shm(unsigned, unsigned); | |
21 | + virtual ~canvas_x11_shm(); | |
22 | + | |
23 | + virtual void open_screen(void) {} | |
24 | + virtual void blit_screen(void); | |
25 | +}; | |
26 | + | |
27 | +class canvas_x11_shm_factory : public canvas_factory { | |
28 | + public: | |
29 | + canvas* create(unsigned xs, unsigned ys) const { | |
30 | + return new canvas_x11_shm(xs, ys); | |
31 | + } | |
32 | +}; | |
33 | + | |
34 | +#endif // __canvas_x11_shm_h__ | ... | ... |
xwin/disp_x11.cpp
0 → 100755
1 | +using namespace std; | |
2 | + | |
3 | +#include <cstdlib> | |
4 | +#include <iostream> | |
5 | + | |
6 | +#include "disp_x11.h" | |
7 | + | |
8 | +void disp_x11::go(void) { | |
9 | + XEvent event; | |
10 | + char ch; | |
11 | + KeySym keysym; | |
12 | + bool e_chk; | |
13 | + | |
14 | + canvas_x11* screen=(canvas_x11*)e_src; | |
15 | + xwindow* win=screen->win; | |
16 | + | |
17 | + if(!halt_f) | |
18 | + e_chk=XCheckWindowEvent(win->getxscr()->getxdisp()->getdisplay(), | |
19 | + win->getwindow(), KeyPressMask|ExposureMask, | |
20 | + &event); | |
21 | + else { | |
22 | + e_chk=true; | |
23 | + XWindowEvent(win->getxscr()->getxdisp()->getdisplay(), | |
24 | + win->getwindow(), KeyPressMask|ExposureMask, | |
25 | + &event); | |
26 | + } | |
27 | + if(e_chk) { | |
28 | + switch(event.type) { | |
29 | + case KeyPress: | |
30 | + XLookupString(&event.xkey, &ch, 1, &keysym, NULL); | |
31 | + if(!cb[Key].is_null()) | |
32 | + cb[Key](e_src, (void*)&ch); | |
33 | + break; | |
34 | + | |
35 | + case Expose: | |
36 | + if(event.xexpose.count==0) { | |
37 | + if(!cb[Draw].is_null()) { | |
38 | + //semop(working, &work, 1); | |
39 | + cb[Draw](e_src, (void*)&ch); | |
40 | + //semop(working, &no_work, 1); | |
41 | + } | |
42 | + } | |
43 | + break; | |
44 | + } | |
45 | + } | |
46 | + else { | |
47 | + if(!halt_f) { | |
48 | + if(!cb[Idle].is_null()) { | |
49 | + //semop(working, &work, 1); | |
50 | + cb[Idle](e_src, NULL); | |
51 | + //semop(working, &no_work, 1); | |
52 | + } | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + if(!halt_f) | |
57 | + XSync(win->getxscr()->getxdisp()->getdisplay(), false); | |
58 | +} | |
59 | + | |
60 | +void disp_x11::trigger_event(event ev) { | |
61 | + canvas_x11* screen=(canvas_x11*)e_src; | |
62 | + xwindow* win=screen->win; | |
63 | + | |
64 | + switch(ev) { | |
65 | + case Draw: | |
66 | + XEvent e; | |
67 | + e.type = Expose; | |
68 | + e.xexpose.send_event = true; | |
69 | + e.xexpose.display = win->getxscr()->getxdisp()->getdisplay(); | |
70 | + e.xexpose.window = win->getwindow(); | |
71 | + e.xexpose.x = e.xexpose.y = 0; | |
72 | + e.xexpose.width = e.xexpose.height = 0; | |
73 | + e.xexpose.count = 0; | |
74 | + | |
75 | + XSendEvent(win->getxscr()->getxdisp()->getdisplay(), | |
76 | + win->getwindow(), | |
77 | + true, | |
78 | + ExposureMask, | |
79 | + &e); | |
80 | + break; | |
81 | + | |
82 | + case Stop: | |
83 | + if(!cb[Stop].is_null()) | |
84 | + cb[Stop](e_src, NULL); | |
85 | + } | |
86 | +} | ... | ... |
xwin/disp_x11.h
0 → 100755
1 | +#ifndef __disp_x11_h__ | |
2 | +#define __disp_x11_h__ | |
3 | + | |
4 | +#include "canvas_x11.h" | |
5 | +#include "../dispatcher.h" | |
6 | +#include <sys/types.h> | |
7 | +#include <sys/ipc.h> | |
8 | +#include <sys/sem.h> | |
9 | + | |
10 | +class disp_x11 : public dispatcher { | |
11 | + private: | |
12 | + int working; | |
13 | + struct sembuf work; | |
14 | + struct sembuf no_work; | |
15 | + | |
16 | + public: | |
17 | + canvas_x11* a; | |
18 | + | |
19 | + disp_x11(event_source* w) : dispatcher(w) { | |
20 | + working=semget(IPC_PRIVATE, 1, IPC_CREAT); | |
21 | + work.sem_num=0; | |
22 | + work.sem_op=-1; | |
23 | + work.sem_flg=0; | |
24 | + no_work.sem_num=0; | |
25 | + no_work.sem_op=1; | |
26 | + no_work.sem_flg=0; | |
27 | + } | |
28 | + disp_x11(disp_x11& d) : dispatcher(d) {} | |
29 | + ~disp_x11() { | |
30 | + semctl(working, 0, IPC_RMID, NULL); | |
31 | + } | |
32 | + | |
33 | + void go(void); | |
34 | + void trigger_event(event); | |
35 | +}; | |
36 | + | |
37 | +class disp_x11_factory : public dispatcher_factory { | |
38 | + public: | |
39 | + dispatcher* create(event_source* es) const { | |
40 | + return new disp_x11(es); | |
41 | + } | |
42 | +}; | |
43 | + | |
44 | +#endif // __disp_x11__ | ... | ... |
xwin/xclass.cpp
0 → 100755
1 | +using namespace std; | |
2 | + | |
3 | +#include <cstdio> | |
4 | +#include <cstdlib> | |
5 | +#include <cstring> | |
6 | + | |
7 | +#include "xclass.h" | |
8 | + | |
9 | +xdisplay::xdisplay(char* name) { | |
10 | + if(name) { | |
11 | + display_name=new char[strlen(name)+1]; | |
12 | + strcpy(display_name, name); | |
13 | + } | |
14 | + else { | |
15 | + display_name=NULL; | |
16 | + } | |
17 | + | |
18 | + /* Connect to X server */ | |
19 | + if ((display=XOpenDisplay(display_name)) == NULL) | |
20 | + throw noconnect_exception(); | |
21 | + | |
22 | + wincount=0; | |
23 | + screen_anz=ScreenCount(display); | |
24 | + default_screen=DefaultScreen(display); | |
25 | + screens=new xscreen*[screen_anz]; | |
26 | + | |
27 | + for(int i=0; i<screen_anz; i++) { | |
28 | + screens[i]=new xscreen(this, i); | |
29 | + } | |
30 | + | |
31 | + font_info=NULL; | |
32 | +} | |
33 | + | |
34 | +xdisplay::xdisplay(const xdisplay& xd) { | |
35 | + if(xd.display_name) { | |
36 | + display_name=new char[strlen(xd.display_name)+1]; | |
37 | + strcpy(display_name, xd.display_name); | |
38 | + } | |
39 | + else { | |
40 | + display_name=NULL; | |
41 | + } | |
42 | + | |
43 | + display=xd.display; | |
44 | + wincount=xd.wincount; | |
45 | + screen_anz=xd.screen_anz; | |
46 | + default_screen=xd.default_screen; | |
47 | + screens=new xscreen*[screen_anz]; | |
48 | + | |
49 | + for(int i=0; i<screen_anz; i++) { | |
50 | + screens[i]=(xd.screens)[i]; | |
51 | + } | |
52 | + | |
53 | + font_info=NULL; | |
54 | +} | |
55 | + | |
56 | +xdisplay::~xdisplay() { | |
57 | + if(display_name) | |
58 | + delete [] display_name; | |
59 | + | |
60 | + // das ueberlass ich dem Destructor von xscreen! | |
61 | +// for(int i=0; i<wincount; i++) | |
62 | +// delete wins[i]; | |
63 | +// delete [] wins; | |
64 | + | |
65 | + //for(int i=0; i<screen_anz; i++) | |
66 | + // delete screens[i]; | |
67 | + //delete [] screens; | |
68 | + | |
69 | + XCloseDisplay(display); | |
70 | +} | |
71 | + | |
72 | +xdisplay& xdisplay::operator=(const xdisplay& xd) { | |
73 | + if(xd.display_name) { | |
74 | + display_name=new char[strlen(xd.display_name)+1]; | |
75 | + strcpy(display_name, xd.display_name); | |
76 | + } | |
77 | + else { | |
78 | + display_name=NULL; | |
79 | + } | |
80 | + | |
81 | + display=xd.display; | |
82 | + wincount=xd.wincount; | |
83 | + screen_anz=xd.screen_anz; | |
84 | + default_screen=xd.default_screen; | |
85 | + screens=new xscreen*[screen_anz]; | |
86 | + | |
87 | + for(int i=0; i<screen_anz; i++) { | |
88 | + screens[i]=(xd.screens)[i]; | |
89 | + } | |
90 | + | |
91 | + font_info=NULL; | |
92 | + | |
93 | + return *this; | |
94 | +} | |
95 | + | |
96 | +xscreen* xdisplay::defaultscreen(void) { | |
97 | + return screens[default_screen]; | |
98 | +} | |
99 | + | |
100 | +void xdisplay::loadfont(char* fname) { | |
101 | + /* Load font and get font information structure */ | |
102 | + if((font_info = XLoadQueryFont(display,fname)) == NULL) | |
103 | + throw nofont_exception(); | |
104 | +} | |
105 | + | |
106 | +xscreen::xscreen(xdisplay* d, int screen_num) { | |
107 | + this->screen_num=screen_num; | |
108 | + this->x_disp=d; | |
109 | + | |
110 | + if(screen_num!=-1) { | |
111 | + XPixmapFormatValues* pixmap_formats; | |
112 | + int count; | |
113 | + | |
114 | + screen=XScreenOfDisplay(d->display, screen_num); | |
115 | + | |
116 | + width=WidthOfScreen(screen); | |
117 | + height=HeightOfScreen(screen); | |
118 | + | |
119 | + default_cm=DefaultColormapOfScreen(screen); | |
120 | + black_pixel=XBlackPixelOfScreen(screen); | |
121 | + white_pixel=XWhitePixelOfScreen(screen); | |
122 | + | |
123 | + rootwin=new xwindow(this); // Ich kann nicht this nehmen, | |
124 | + // da das aktuelle Object dem | |
125 | + // Array zugewiesen wird und | |
126 | + // danach weg is. | |
127 | + | |
128 | + vis=DefaultVisual(d->display, 0); | |
129 | + | |
130 | + pixmap_formats=XListPixmapFormats(d->display, &count); | |
131 | + | |
132 | + depth=0; | |
133 | + for(int i=0, result=0; i<count; i++) { | |
134 | + if(pixmap_formats[i].depth > depth) { | |
135 | + // OK, das vi existiert jetzt nur fuer TrueColor, ich muss | |
136 | + // noch fuer alle anderen VisualTypes eins einbauen. | |
137 | + if(XMatchVisualInfo(d->display, d->default_screen, | |
138 | + pixmap_formats[i].depth, TrueColor, &vi)) { | |
139 | + depth=pixmap_formats[i].depth; | |
140 | + bytespp=pixmap_formats[i].bits_per_pixel/8; | |
141 | + scanline_pad=pixmap_formats[i].scanline_pad; | |
142 | + } | |
143 | + } | |
144 | + } | |
145 | + | |
146 | + gc=DefaultGC(d->display, d->defaultscreenid()); | |
147 | + } | |
148 | + else { | |
149 | + screen=NULL; | |
150 | + rootwin=NULL; | |
151 | + } | |
152 | +} | |
153 | + | |
154 | +xscreen::xscreen(const xscreen& scr) { | |
155 | + x_disp=scr.x_disp; | |
156 | + screen_num=scr.screen_num; | |
157 | + screen=scr.screen; | |
158 | + rootwin=scr.rootwin; | |
159 | + | |
160 | + width=scr.width; | |
161 | + height=scr.height; | |
162 | + vis=scr.vis; | |
163 | + | |
164 | + memcpy(&vi, &scr.vi, sizeof(XVisualInfo)); | |
165 | + | |
166 | + depth=scr.depth; | |
167 | + bytespp=scr.bytespp; | |
168 | + scanline_pad=scr.scanline_pad; | |
169 | + | |
170 | + memcpy(&gc, &scr.gc, sizeof(GC)); | |
171 | + | |
172 | + default_cm=scr.default_cm; | |
173 | + black_pixel=scr.black_pixel; | |
174 | + white_pixel=scr.white_pixel; | |
175 | +} | |
176 | + | |
177 | +xscreen::~xscreen() { | |
178 | + delete rootwin; | |
179 | + | |
180 | + XFreeGC(x_disp->display, gc); | |
181 | + XFreeColormap(x_disp->display, default_cm); | |
182 | +} | |
183 | + | |
184 | +xscreen& xscreen::operator=(const xscreen& scr) { | |
185 | + x_disp=scr.x_disp; | |
186 | + screen_num=scr.screen_num; | |
187 | + screen=scr.screen; | |
188 | + rootwin=scr.rootwin; | |
189 | + | |
190 | + width=scr.width; | |
191 | + height=scr.height; | |
192 | + vis=scr.vis; | |
193 | + | |
194 | + memcpy(&vi, &scr.vi, sizeof(XVisualInfo)); | |
195 | + | |
196 | + depth=scr.depth; | |
197 | + bytespp=scr.bytespp; | |
198 | + scanline_pad=scr.scanline_pad; | |
199 | + | |
200 | + memcpy(&gc, &scr.gc, sizeof(GC)); | |
201 | + | |
202 | + default_cm=scr.default_cm; | |
203 | + black_pixel=scr.black_pixel; | |
204 | + white_pixel=scr.white_pixel; | |
205 | + | |
206 | + return *this; | |
207 | +} | |
208 | + | |
209 | +xwindow* xdisplay::getXwinById(Window id) { | |
210 | + int i; | |
211 | + | |
212 | + for(i=0; i<wincount; i++) | |
213 | + if(wins[i]->window == id) | |
214 | + return wins[i]; | |
215 | + | |
216 | + return NULL; | |
217 | +} | |
218 | + | |
219 | +xwindow::xwindow(xscreen* xs) { | |
220 | + screen=xs; | |
221 | + window=XRootWindowOfScreen(xs->screen); | |
222 | + | |
223 | + screen->x_disp->wincount++; | |
224 | + xwindow** temp=new xwindow*[screen->x_disp->wincount]; | |
225 | + | |
226 | + for(int i=0; i<screen->x_disp->wincount-1; i++) | |
227 | + temp[i]=screen->x_disp->wins[i]; | |
228 | + | |
229 | + temp[screen->x_disp->wincount-1]=this; | |
230 | + delete[] screen->x_disp->wins; | |
231 | + screen->x_disp->wins=temp; | |
232 | +} | |
233 | + | |
234 | +xwindow::xwindow(xwindow* win, int x, int y, | |
235 | + unsigned int bwidth, unsigned int width, | |
236 | + unsigned int height) { | |
237 | + screen=win->screen; | |
238 | + | |
239 | + window=XCreateSimpleWindow(screen->x_disp->display, win->window, | |
240 | + x, y, width, height, bwidth, | |
241 | + screen->black_pixel, screen->white_pixel); | |
242 | + | |
243 | + screen->x_disp->wincount++; | |
244 | + xwindow** temp=new xwindow*[screen->x_disp->wincount]; | |
245 | + | |
246 | + for(int i=0; i<screen->x_disp->wincount-1; i++) | |
247 | + temp[i]=screen->x_disp->wins[i]; | |
248 | + | |
249 | + temp[screen->x_disp->wincount-1]=this; | |
250 | + delete[] screen->x_disp->wins; | |
251 | + screen->x_disp->wins=temp; | |
252 | + | |
253 | + XSelectInput(screen->x_disp->display, window, | |
254 | + ExposureMask|KeyPressMask|ButtonPressMask|StructureNotifyMask); | |
255 | +} | |
256 | + | |
257 | +xwindow::xwindow(const xwindow& xw) { | |
258 | + screen=xw.screen; | |
259 | + | |
260 | + window=xw.window; | |
261 | + back=xw.back; | |
262 | + swapinfo=xw.swapinfo; | |
263 | +} | |
264 | + | |
265 | +xwindow& xwindow::operator=(const xwindow& xw) { | |
266 | + screen=xw.screen; | |
267 | + | |
268 | + window=xw.window; | |
269 | + back=xw.back; | |
270 | + swapinfo=xw.swapinfo; | |
271 | + | |
272 | + return *this; | |
273 | +} | |
274 | + | |
275 | +// Dies sollte nochmal in mehrere kleinere Methoden zum einstellen der | |
276 | +// diversen Dinge fuer den WM aufgesplittet werden. | |
277 | +void xwindow::initWM(void) { | |
278 | + XSizeHints* size_hints; // Informationen fuer WM ueber | |
279 | + // minimale Groessen fuer App | |
280 | + XWMHints* wm_hints; // weiter Infos fuer WM z.B. Icon | |
281 | + // Input/Output initialisierung | |
282 | + XClassHint* class_hints; // noch mehr infos fuer WM | |
283 | + | |
284 | + if (!(size_hints = XAllocSizeHints())) { | |
285 | + fprintf(stderr, "failure allocating memory\n"); | |
286 | + exit(1); //throw exception... | |
287 | + } | |
288 | + if (!(wm_hints = XAllocWMHints())) { | |
289 | + fprintf(stderr, "failure allocating memory\n"); | |
290 | + exit(1); //throw exception... | |
291 | + } | |
292 | + if (!(class_hints = XAllocClassHint())) { | |
293 | + fprintf(stderr, "failure allocating memory\n"); | |
294 | + exit(1); //throw exception... | |
295 | + } | |
296 | + | |
297 | + size_hints->flags = PPosition | PSize | PMinSize; | |
298 | + size_hints->min_width = 300; | |
299 | + size_hints->min_height = 200; | |
300 | + | |
301 | + wm_hints->initial_state = NormalState; | |
302 | + wm_hints->input = True; | |
303 | + // wm_hints->icon_pixmap = icon_pixmap; | |
304 | + wm_hints->flags = StateHint | IconPixmapHint | InputHint; | |
305 | + | |
306 | + class_hints->res_name = "jokus"; //screen->x_disp->argv[0]; | |
307 | + class_hints->res_class = "Basicwin"; | |
308 | + | |
309 | +// XSetWMProperties(screen->x_disp->display, window, NULL, NULL, /*&iconName*/ | |
310 | +// screen->x_disp->argv, screen->x_disp->argc, size_hints, | |
311 | +// wm_hints, class_hints); | |
312 | + XStoreName(screen->x_disp->display, window, "jokus"); | |
313 | +} | ... | ... |
xwin/xclass.h
0 → 100755
1 | +/** | |
2 | + * \file xclass.h | |
3 | + * | |
4 | + * \brief Drei Klassen für die zentralen XWindows Objekte. | |
5 | + * | |
6 | + * Verpackt die drei zentralen Elemente für ein XWindows Programm | |
7 | + * in drei Klassen. | |
8 | + * <ul type="circle"> | |
9 | + * <li>\ref xdisplay für das display</li> | |
10 | + * <li>\ref xscreen für alle screens</li> | |
11 | + * <li>\ref xwindow für alle windows</li> | |
12 | + * </ul> | |
13 | + * Dabei ist die Struktur so das zu ein display aus 1-n screens bestehen | |
14 | + * In denen dann wiederum jeweils 1-n windows existieren. Es existiert | |
15 | + * mindestens das rootwindow. | |
16 | + * Alle in dieser Datei definierten Klassen arbeiten sehr eng zusammen, | |
17 | + * daher ist jede friend der aller anderen. | |
18 | + * | |
19 | + * \author Georg Steffers <georg@steffers.org> | |
20 | + * | |
21 | + * \date 04.12.2003 | |
22 | + * | |
23 | + * \version ..2001 (Georg Steffers): erste implementation | |
24 | + * \version 2001-2003 (Georg Steffers): diverse Modifikationen | |
25 | + * \version 05.12.2003 (Georg Steffers): beginn der Dokumentation via doxygen | |
26 | + */ | |
27 | + | |
28 | +/* | |
29 | + * Copyright (C)2003 Georg Steffers | |
30 | + * | |
31 | + * This program is free software; you can redistribute it and/or modify | |
32 | + * it under the terms of the GNU General Public License as published by | |
33 | + * the Free Software Foundation; either version 2 of the License, or | |
34 | + * (at your option) any later version. | |
35 | + * | |
36 | + * This program is distributed in the hope that it will be useful, | |
37 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
38 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
39 | + * GNU General Public License for more details. | |
40 | + * | |
41 | + * You should have received a copy of the GNU General Public License | |
42 | + * along with this program; if not, write to the Free Software | |
43 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
44 | + */ | |
45 | + | |
46 | +#ifndef __xclass_h__ | |
47 | +#define __xclass_h__ | |
48 | + | |
49 | +#include <X11/Xlib.h> | |
50 | +#include <X11/Xutil.h> | |
51 | +#include <X11/Xos.h> | |
52 | +#include <X11/Xatom.h> | |
53 | +#include <X11/keysym.h> | |
54 | +#include <X11/extensions/Xdbe.h> | |
55 | + | |
56 | +class xscreen; | |
57 | +class xwindow; | |
58 | + | |
59 | +/** | |
60 | + * \brief Das Display ist die Verbindung zum X-Server | |
61 | + * | |
62 | + * Verbindung zum X-Server, entwerder über TCP/IP oder | |
63 | + * Unix Domain Sockets. Je nach Server und Hardware auf der dieser | |
64 | + * läft kann dieser 1-n screens zur verfügung stellen. | |
65 | + * Es existiert zumindest der \ref default_screen. | |
66 | + */ | |
67 | +class xdisplay { | |
68 | + friend class xscreen; //!< Da ein xscreen sehr eng mit einem xdisplay | |
69 | + //! zusammenarbeitet | |
70 | + friend class xwindow; //!< Da ein xwindow sehr eng mit einem xdisplay | |
71 | + //! zusammenarbeitet | |
72 | + | |
73 | + private: | |
74 | + // Exceptionklassen | |
75 | + class noconnect_exception {}; //!< no connection to display | |
76 | + class nofont_exception {}; //!< no font-file to load | |
77 | + | |
78 | + Display* display; //!< \brief Der Descriptor für die eigentliche | |
79 | + //! Verbindung zum X-Server | |
80 | + char* display_name; //!< \brief Hardwarename des Displays | |
81 | + //! | |
82 | + //! Wenn display_name NULL ist, so wird für | |
83 | + //! den Hardwarenamen der Wert der in der | |
84 | + //! Environmentvariable \$DISPLAY steht genommen. | |
85 | + | |
86 | + int screen_anz; //<! Anzahl moeglicher screens dieses Displays | |
87 | + int default_screen; //<! default screen dieses Displays | |
88 | + xscreen** screens; //<! Liste aller screens dieses Displays | |
89 | + | |
90 | + int wincount; //<! Anzahle der existierenden Windows | |
91 | + xwindow** wins; //<! Referenz zu allen Windows | |
92 | + | |
93 | + XFontStruct* font_info; //<! Fontinformationen | |
94 | + | |
95 | + public: | |
96 | + xdisplay(char* name=NULL); //!< Defaultkonstruktor | |
97 | + xdisplay(const xdisplay&); //!< Copyconstruktor | |
98 | + ~xdisplay(); //!< Destruktor | |
99 | + | |
100 | + xdisplay& operator=(const xdisplay&); //!< Zuweisungsoperator | |
101 | + | |
102 | + // Queryfunktionen... | |
103 | + Display* getdisplay(void) { return display; } | |
104 | + XFontStruct* getfont(void) { return font_info; } | |
105 | + xwindow* getXwinById(Window id); | |
106 | + xscreen* defaultscreen(void); | |
107 | + int defaultscreenid(void) { return default_screen; } | |
108 | + void loadfont(char* name="9x15"); | |
109 | +}; | |
110 | + | |
111 | +class xscreen { | |
112 | + friend class xwindow; | |
113 | + friend class xdisplay; | |
114 | + | |
115 | + private: | |
116 | + xdisplay* x_disp; | |
117 | + | |
118 | + int screen_num; | |
119 | + Screen* screen; | |
120 | + xwindow* rootwin; | |
121 | + | |
122 | + unsigned int width; | |
123 | + unsigned int height; | |
124 | + | |
125 | + Visual* vis; | |
126 | + XVisualInfo vi; | |
127 | + | |
128 | + int depth; | |
129 | + int bytespp; | |
130 | + int scanline_pad; | |
131 | + GC gc; | |
132 | + | |
133 | + Colormap default_cm; | |
134 | + unsigned long black_pixel; | |
135 | + unsigned long white_pixel; | |
136 | + | |
137 | + public: | |
138 | + xscreen(xdisplay* disp=NULL, int screen_num=-1); | |
139 | + xscreen(const xscreen&); | |
140 | + ~xscreen(); | |
141 | + | |
142 | + xscreen& operator=(const xscreen&); | |
143 | + | |
144 | + // queryfunktionen..... | |
145 | + Screen* getscreen(void) { return screen; } | |
146 | + int getscreennum(void) {return screen_num; } | |
147 | + xdisplay* getxdisp(void) { return x_disp; } | |
148 | + Visual* getvisual(void) { return vis; } | |
149 | + int getdepth(void) { return depth; } | |
150 | + int getbytespp(void) { return bytespp; } | |
151 | + int getscanlinepad(void) { return scanline_pad; } | |
152 | + GC getgc(void) { return gc; } | |
153 | + unsigned getwidth(void) { return width; } | |
154 | + unsigned getheight(void) { return height; } | |
155 | + xwindow* getrootwin(void) { return rootwin; } | |
156 | + Colormap getdefaultcm(void) { return default_cm; } | |
157 | + unsigned long blackpixel(void) { return black_pixel; } | |
158 | + unsigned long whitepixel(void) { return white_pixel; } | |
159 | + unsigned long getcolor(unsigned short, unsigned short, | |
160 | + unsigned short); | |
161 | +}; | |
162 | + | |
163 | +class xwindow { | |
164 | + friend class xscreen; | |
165 | + friend class xdisplay; | |
166 | + | |
167 | + private: | |
168 | + xscreen* screen; | |
169 | + | |
170 | + Window window; | |
171 | + XdbeBackBuffer back; | |
172 | + XdbeSwapInfo swapinfo; | |
173 | + | |
174 | + public: | |
175 | + xwindow(xwindow*, int, int, unsigned int, | |
176 | + unsigned int, unsigned int); | |
177 | + xwindow(xscreen* screen); | |
178 | + xwindow(const xwindow&); | |
179 | + xwindow() { | |
180 | + screen=NULL; | |
181 | + } | |
182 | + ~xwindow() { | |
183 | + XDestroyWindow(screen->x_disp->display, window); | |
184 | + } | |
185 | + | |
186 | + xwindow& operator=(const xwindow&); | |
187 | + | |
188 | + xscreen* getxscr(void) { return screen; } | |
189 | + Window getwindow(void) { return window; } | |
190 | + void initWM(void); | |
191 | + void map(void) { XMapWindow(screen->x_disp->display, window); } | |
192 | +}; | |
193 | + | |
194 | +#endif // __xclass_h__ | ... | ... |
Please
register
or
login
to post a comment