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