Schrift
[thread]5091[/thread]

3D im Canvas (Seite 2)

Leser: 2


<< |< 1 2 >| >> 18 Einträge, 2 Seiten
Crian
 2005-09-29 16:42
#44646 #44646
User since
2003-08-04
5873 Artikel
ModeratorIn
[Homepage]
user image
Dann schreib Dir Deine eigene Umrechnung 3D->2D und benutz die normale Canvas. Wird aber vermutlich eklig und laaangsam.
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
DocJunioR
 2005-09-29 17:49
#44647 #44647
User since
2005-08-29
53 Artikel
BenutzerIn
[default_avatar]
genau dies war ja meine Frage - ob das schonmal wer gemacht hat, sodass ich da entlastet würde.
Naja gut, muss ich wohl mal selber ran
Crian
 2005-09-30 15:26
#44648 #44648
User since
2003-08-04
5873 Artikel
ModeratorIn
[Homepage]
user image
Dafür würde ich dann aber ein eigenes Widget schreiben. Du kannst Dich dann mal nach Bibliotheken für 3D->2D umsehen, da musst Du garantiert das Rad nicht neu erfinden, und wenn es nur ist, die Algorithmen zu übernehmen.

Ach ja: Und melde Dich, wenn Du dabei Probleme hast und insbesondere wenn das Widget fertig ist :-)
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
DocJunioR
 2005-10-06 14:37
#44649 #44649
User since
2005-08-29
53 Artikel
BenutzerIn
[default_avatar]
Zur Berechnung von 3D nach 2D nutzt man einfach die Formeln

X' = x / z
Y' = y / z

Das Ganze funktioniert aber nur solange der Koordinatenursprung in der Mitte des Bildes liegt.
Ergo muss ich erst sämtliche Punkte relativ zum Beobachter verteilen und dann berechnen. :0

Die Rotation ist da schon komplexer, geht aber auch noch - nur müsste ich dann wahrscheinlich nen sinus und cosinus vorberechnen :cool:
DocJunioR
 2005-10-07 12:09
#44650 #44650
User since
2005-08-29
53 Artikel
BenutzerIn
[default_avatar]
das Problem das hier stand hab ich gelöst.
Hier meine package:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#!/usr/bin/perl -w
#######################################
# ms3d.pm # perl 5
#############
# my small 3d engine
#
#
######################################
use strict;
use warnings;

package prj::ms3d;

use Tk;
use Tk::Canvas;


sub new
{
my $this = shift;
my $thisref = ref($this) || $this;
my $self
= undef;
my $parentwin = $_[0];

$self->{width} = $_[1];
$self->{height} = $_[2];
$self->{tris} = undef;
$self->{cnt} = 0;

$self->{canvas} = $parentwin->Canvas(-height => $self->{height}, -width => $self->{width})->pack();

bless ($self, $thisref);

}

sub addTriangle
{
my $self = shift;
push (@{$self->{tris}}, \@_);
$self->{cnt}++;
}

sub translate
{
my $self = shift;
my $tx = $_[0];
my $ty = $_[1];
my $tz = $_[2];

my @tridata;

for (my $i = 0; $i <$self->{cnt}; $i++)
{

my @data = @{$self->{tris}[$i]};

$data[0] += $tx;
$data[1] += $ty;
$data[2] += $tz;

$data[3] += $tx;
$data[4] += $ty;
$data[5] += $tz;

$data[6] += $tx;
$data[7] += $ty;
$data[8] += $tz;

${$self->{tris}}[$i] = \@data;

}
}


sub scale
{
my $self = shift;
my $tx = $_[0];
my $ty = $_[1];
my $tz = $_[2];

if ($tx == 0){ $tx = 1; }
if ($ty == 0){ $ty = 1; }
if ($tz == 0){ $tz = 1; }

my @tridata;

for (my $i = 0; $i <$self->{cnt}; $i++)
{
my @data = @{$self->{tris}[$i]};

$data[0] *= $tx;
$data[1] *= $ty;
$data[2] *= $tz;

$data[3] *= $tx;
$data[4] *= $ty;
$data[5] *= $tz;

$data[6] *= $tx;
$data[7] *= $ty;
$data[8] *= $tz;

${$self->{tris}}[$i] = \@data;
}
}

sub rotate
{
my $self = shift;
my $dir = $_[0];
my $alpha = $_[1];

my $sinal = sin(3.14 * ($alpha / 180));
my $cosal = cos(3.14 * ($alpha / 180));


for (my $i = 0; $i <$self->{cnt}; $i++)
{

my @data = @{$self->{tris}[$i]};

if ($dir eq 'x')
{

$data[0] = $data[0];

$data[1] = $data[1] * $cosal - $data[3] * $sinal;

$data[2] = $data[1] * $sinal + $data[3] * $cosal;


$data[3] = $data[3];

$data[4] = $data[4] * $cosal - $data[5] * $sinal;

$data[5] = $data[4] * $sinal + $data[5] * $cosal;


$data[6] = $data[6];

$data[7] = $data[7] * $cosal - $data[8] * $sinal;

$data[8] = $data[7] * $sinal + $data[8] * $cosal;
} elsif ($dir eq 'y') {

$data[0] = $data[2] * $sinal + $data[0] * $cosal;

$data[1] = $data[1];

$data[2] = $data[2] * $cosal - $data[0] * $sinal;


$data[3] = $data[5] * $sinal + $data[3] * $cosal;

$data[4] = $data[4];

$data[5] = $data[5] * $cosal - $data[3] * $sinal;


$data[6] = $data[8] * $sinal + $data[6] * $cosal;

$data[7] = $data[7];

$data[8] = $data[8] * $cosal - $data[6] * $sinal;
} elsif ($dir eq 'z') {

$data[0] = $data[0] * $cosal - $data[1] * $sinal;

$data[1] = $data[0] * $sinal + $data[1] * $cosal;

$data[2] = $data[2];


$data[3] = $data[3] * $cosal - $data[4] * $sinal;

$data[4] = $data[3] * $sinal + $data[4] * $cosal;

$data[5] = $data[5];


$data[6] = $data[6] * $cosal - $data[7] * $sinal;

$data[7] = $data[6] * $sinal + $data[7] * $cosal;

$data[8] = $data[8];
}

${$self->{tris}}[$i] = \@data;

}
}


sub redraw
{
my $self = shift;
my @vdt = undef;
my $dhh = $self->{height} / 2;
my $dwh = $self->{width} / 2;

foreach my $tridata (@{$self->{tris}})
{
@vdt = @$tridata;

$self->{canvas}->createPolygon (


$self->calc3d ($vdt[0], $vdt[2]) * $dwh,


$self->calc3d ($vdt[1], $vdt[2]) * $dhh,


$self->calc3d ($vdt[3], $vdt[5]) * $dwh,


$self->calc3d ($vdt[4], $vdt[5]) * $dhh,


$self->calc3d ($vdt[6], $vdt[8]) * $dwh,


$self->calc3d ($vdt[7], $vdt[8]) * $dhh,




-outline =>$vdt[9],



-fill =>$vdt[9]


);
}

}

sub calc3d
{
my $self = shift;
my $erg = $_[0] / $_[1] + 0.5;
return $erg;
}

return 1;


benutzt werden kann das Ganze so:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
############
# my small 3d engine
#
#
######################################
use strict;
use warnings;

use prj::ms3d;
use Tk;

my $mw = MainWindow->new();
my $dc = prj::ms3d->new($mw, 320, 240, );
$dc->addTriangle(0,0,1, -1,1,1, 1,1,1, "red");
$dc->rotate('x', 90);
$dc->addTriangle(0,0,1, 1,-1,1, 0,1,1, "blue");
$dc->scale(0.1, 0.1, 1);
$dc->translate(0.5, 0.5,0);

$dc->redraw();
MainLoop();


Irgendwie funktioniert die Rotation noch nicht so ganz.
Ich würd ja gern noch nen Timer in den Eventloop einbauen - hat wer nen plan, wie?\n\n

<!--EDIT|DocJunioR|1128676079-->
ptk
 2005-10-10 19:25
#44651 #44651
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Müsstest du in redraw() nicht erst einmal alle vorhandenen Canvas items löschen? Vielleicht ist es auch effizienter, wenn du nur die Koordinaten der vorhandenen Polygone manipulierst (mit coords())
DocJunioR
 2005-10-11 15:39
#44652 #44652
User since
2005-08-29
53 Artikel
BenutzerIn
[default_avatar]
das löschen ist inzwischen drin. fiel mir dann auch auf.
Crian
 2005-11-08 17:46
#44653 #44653
User since
2003-08-04
5873 Artikel
ModeratorIn
[Homepage]
user image
[quote=DocJunioR,06.10.2005, 12:37]Zur Berechnung von 3D nach 2D nutzt man einfach die Formeln

X' = x / z
Y' = y / z[/quote]
Nunja...

es gibt viele mögliche Projektionen von 3D auf 2D und dann auch noch viele Möglichkeiten, wie die Ebene im Raum liegen kann ...

Man kann auch einfach die dritte Koordinate weglassen, auch das ist eine Projektion, wenn auch meistens nicht die gewünschte.

Wenn man schon so eine Klasse schreibt, sollte man die Möglichkeit einbauen, die Ebene im Raum drehen und verschieben zu können.
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
<< |< 1 2 >| >> 18 Einträge, 2 Seiten



View all threads created 2005-09-28 14:42.