[c++] zo min mogelijk hertekenen op scherm

Pagina: 1
Acties:

  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
Afbeeldingslocatie: http://members.lycos.nl/deruud/plutje.jpg
(paint roeleert btw)

C++:
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
#define CBM_MAX_OBJ     64 // blablabla

class cVierkant
{
 public:
   int x, y, w, h;
};

cVierkant Object[CBM_MAX_OBJ]

int VergInt(const void *p, const void *q)
{
    return *(int *)p < *(int *)q ? -1 :
           *(int *)p > *(int *)q;
}

// --------------------------------------------------------------------
// Opdelen
// vierkant array bevat dus al de waarden die je in de afbeelding ziet
// --------------------------------------------------------------------

int xs = 0;
int ys = 0;

int xsplit[1024];
int ysplit[1024];

for( int i = 0; i < CBM_MAX_OBJ; i++ )
{
    if( Object[i] != NULL )
    {
        // X / X+W
        if( !IsInArray(xsplit,1024,Object[i]->x) )
        {
            xsplit[xs] = Object[i]->x;
            xs++;
        }
        if( !IsInArray(xsplit,1024,Object[i]->x+Object[i]->w) )
        {
            xsplit[xs] = Object[i]->x+Object[i]->w;
            xs++;
        }
        // Y / Y+H
        if( !IsInArray(ysplit,1024,Object[i]->y) )
        {
            ysplit[ys] = Object[i]->y;
            ys++;
        }
        if( !IsInArray(ysplit,1024,Object[i]->y+Object[i]->h) )
        {
            ysplit[ys] = Object[i]->y+Object[i]->h;
            ys++;
        }
    }
}

// Sorteer de arrays
qsort(xsplit,xs,sizeof(*xsplit),VergInt);
qsort(ysplit,ys,sizeof(*ysplit),VergInt);

// En nu hebben we een huge piece of memory waar alles al in gesplit is, en delen we dit grote blok op in de kleinere stukken zoals je in t 2e plaatje ziet
// .........................


2 vierkantjes welke elkaar overlappen (1e plaatje). Nu heb ik dus geen zin om teveel naar het scherm te tekenen, dus heb ik iets gefixt wat het scherm met de objecten in stukken opdeeld (2e plaatje+source).
Heel leuk allemaal, maar verder in het programma wil ik kijken op welk cVierkant de muis staat. Aangezien de source een array met alle blokken afleverd, zou ik vanuit daar de coordinaten van de muis kunnen gaan vergelijken, maar ja als ik niet weet welke stukken allemaal bij een bepaald cVierkant horen.... Dus had ik het idee om bij het splitsen niet alleen de coordinaten op te slaan, maar ook een pointer naar het cVierkant waar deze splitsing bij hoort. Nu zit ik al een paar dagen te prutsen/denken/slapen etc. maar ik komt er niet uit.
Ik hoop dat het een beetje duidelijk is, anders roept u maar :?

Zou iemand een kleine hand kunnen toesteken?

Alvast bedankt voor de moeite nemen om deze lap te lezen :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:01

.oisyn

Moderator Devschuur®

Demotivational Speaker

kun je niet gewoon alle cVierkanten afgaan (van front naar back) en kijken of de muispositie in de huidige cVierkant valt? (en dus kijk je verder niet naar de gesplitste blokken)

Wat je ook kunt doen is alles in een binary search tree zetten... dan krijg je een vorm van binary space partitioning

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
.oisyn schreef op 09 september 2002 @ 22:21:
kun je niet gewoon alle cVierkanten afgaan (van front naar back) en kijken of de muispositie in de huidige cVierkant valt? (en dus kijk je verder niet naar de gesplitste blokken)
jawel en dat gebruik ik ook, maar waar die blokken bij horen moet ik eigenlijk weten zodat ik als een cVierkant (deze bevat bv een plaatje ofzo) geupdated moet worden, dat ik dan alleen de blokken teken welke bij dat cVierkant horen....
.oisyn schreef op 09 september 2002 @ 22:21:
Wat je ook kunt doen is alles in een binary search tree zetten... dan krijg je een vorm van binary space partitioning
maar een bsp kan toch alleen maar in een richting? groter dan x of kleiner dan x ?
code:
1
2
3
4
     x
    / \
   /   \
 <x     >x


* denkt dat zn uitleg n beetje fout was...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:01

.oisyn

Moderator Devschuur®

Demotivational Speaker

hmm ok je wilt dus het huidige blok vinden, en dus niet alleen het cVierkant. Ik weet niet wat je datastructuur is, maar uit je code kan ik iig wel opmaken dat ie vaag is ;)

je hebt 2 arrays van ints, voor x en y. Hoe werkt dat precies?

(bsp trees worden gebruikt bij CSG, Constructive Solid Geometry. CSG is een manier om volume te representeren, gebruik makend van convexe objecten. Op die objecten kun je boolean operaties uitvoeren (or, and, xor, enz.), en op die manier kun je een hele virtuele wereld opbouwen. Alle objecten bij elkaar 'gebooleand' resulteert in een grote zoekboom waarbij je steeds test of de huidige positie zich aan de linker of rechterkant van een snijvlak bevindt. Als je bij een van de bladeren komt kun je zien of je dan in de leegte bent, of in solid space (in jouw geval dus een cVierkant). Dit is ook de techniek die wordt gebruikt in 3d spellen als quake en unreal)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
xsplit bevat unieke waarden. Een waarde kan ingevuld worden door x of x+w (van cVierkant)

(en bij ysplit uiteraard ook maar geen x waarden maar y :))

als ik bijvoorbeeld 2 cVierkanten heb:
C++:
1
2
3
cVierkant V1(0,0,50,50);
cVierkant V2(50,0,50,50);
// dus in formaat x, y, w, h


V2.x wordt dus niet opgenomen in het array omdat deze al bestaat (V1.x+V1.w)
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// nu gebruiken we de xsplit en ysplit arrays om de blokken te maken
for( j = 0; j < ys; j++ )
{
    for( i = 0; i < xs; i++ )
    {
        if( i+1 >= xs )
            w = SCREEN_W;    // Breedte van scherm
        else
            w = xsplit[i+1]-xsplit[i];

        if( j+1 >= ys )
            h = SCREEN_H;    // Hoogte van scherm
        else
            h = ysplit[j+1]-ysplit[j];
            
        // Hier maken we dus een nieuw blok aan met (x,y,w,h) xsplit[i], ysplit[i],w,h en daar kopieren we de inhoud naartoe (dat wat er op die plek moet staan)
    }
}


ja sorry maar vager kan ik t helaas niet uitleggen :?


is t misschien beter om moeite te gaan doen en die BSP tree te inplementeren??

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Houd gewoon een stapel regions bij van alle objecten, die mogen meteen iedere gewenste vorm zijn, kun je van elkaar 'subtracten' (want dat wil je hier) en dan heb je de wondere wereld van InvalidateRgn tot je beschikking.

offtopic:
Oisyn schrap die lelijke hond eens uit je icoon! ;)

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Region functions reference

En dan vooral bij CombineRgn kijken naar de laatste parameter :)

Professionele website nodig?


  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
Hmm ja dan is deze lap code idd helemaal niet nodig. Ik leg gewoon de bovenliggende cVierkanten over deze heen, en waar deze dan pixels overlapt, geef ik aan dat ie deze niet moet tekenen... (dmv deze de kleur (R,G,B) (255,0,255) te geven, welke niet wordt getekend).

Ik denk dat ik eruit bent. Hartstikke bedankt!

  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
curry684 schreef op 10 september 2002 @ 11:23:
Region functions reference

En dan vooral bij CombineRgn kijken naar de laatste parameter :)
dat was het probleem :) ik kan er geen windows functies in gebruiken. maar toch bedankt

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Deruud schreef op 10 september 2002 @ 11:26:
dat was het probleem :) ik kan er geen windows functies in gebruiken. maar toch bedankt
Oeps, doordat je CVierkant gebruikt (met leading C) dacht ik dat je MFC aan het schrijven was... maar sowieso heb je een region-encapsulatie die alleen rectangles aan hoeft te kunnen zo zelf geschreven.... :)

Professionele website nodig?


  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
curry684 schreef op 10 september 2002 @ 11:34:
[...]

Oeps, doordat je CVierkant gebruikt (met leading C) dacht ik dat je MFC aan het schrijven was... maar sowieso heb je een region-encapsulatie die alleen rectangles aan hoeft te kunnen zo zelf geschreven.... :)
die c ervoor vind ik wel handig ziet ik dat t een klasse is...

ik gaat er meteen mee aan de slagh!

Verwijderd

Ik heb me hier ook ooit mee bezig gehouden... (rotwerk, maar wel leuk)
Ik splitste die rectangles alleen maar op bij het tekenen. Met het controleren of de muiscursor over het plaatje gaat moet je idd gewoon van boven naar beneden werken (in layers). Op deze manier had ik nergens problemen mee. Ik weet niet of er meer moet gebeuren dan controleren of de muiscursor over een vierkantje komt, zo niet is dit idee (zoals .oisyn zei) voldoende.
En echt reden om de gesplitte rectangles op te slaan in een datastructuur is er ook niet, het opsplitsen kost relatief geen rekenkracht vergeleken met het tekenen zelf. Dus gewoon op het moment van hertekenen herberekenen.

  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
ik ga het nu zo proberen:
code:
1
2
3
4
5
6
7
+---------+
|1        |
|     +--------+
|     |2       |
+-----+        |
      |        |
      +--------+


Op het moment van het afbeelden van de cVierkanten maak ik kopieen van de inhoud. Voor cVierkant 1 wordt het dus zo
code:
1
2
3
4
5
+---------+
|1        |
|     +---+
|     |   |     
+-----+---+

waarbij de rechteronderhoek de kleur (R,G,B)(255,0,255) krijgt. De functie die iets naar het scherm blit, slaat deze kleur over, zodat dit stuk dus niet hertekend wordt.
Dit wordt dus op het scherm getekend. er wordt nu dus niet over cVierkant 2 getekend.
code:
1
2
3
4
5
+---------+
|1        |
|     +---+
|     |
+-----+

Dit is (denk ik) simpeler te realiseren dan alles steeds op te splitsen.

[ Voor 0% gewijzigd door ruuds op 10-09-2002 13:08 . Reden: tiepo ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:01

.oisyn

Moderator Devschuur®

Demotivational Speaker

werken met color keys is wel langzamer dan alleen die regions doen die gedaan moeten worden... dat is omdat de pixels wel geprocessed worden, en als ze een bepaalde kleur hebben dan worden ze pas gereject

Als je met regions werkt bekijk je al die pixels niet

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Deruud schreef op 10 september 2002 @ 13:02:
ik ga het nu zo proberen:
code:
1
2
3
4
5
6
7
+---------+
|1        |
|     +--------+
|     |2       |
+-----+        |
      |        |
      +--------+


Op het moment van het afbeelden van de cVierkanten maak ik kopieen van de inhoud. Voor cVierkant 1 wordt het dus zo
code:
1
2
3
4
5
+---------+
|1        |
|     +---+
|     |   |     
+-----+---+

waarbij de rechteronderhoek de kleur (R,G,B)(255,0,255) krijgt. De functie die iets naar het scherm blit, slaat deze kleur over, zodat dit stuk dus niet hertekend wordt.
Dit wordt dus op het scherm getekend. er wordt nu dus niet over cVierkant 2 getekend.
code:
1
2
3
4
5
+---------+
|1        |
|     +---+
|     |
+-----+

Dit is (denk ik) simpeler te realiseren dan alles steeds op te splitsen.
doe dan (R,G,B)(0,255,255) dat is wel zo'n lelijke kleur, wil je toch niet gebruiken. :P
Maar als je dat vlakje als nog helemaal met rood gaat vullen, vul je hem toch ook?? zonde van die tijd die je juist wilde sparen...
of begrijp ik iets verkeerd.

  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
edit: onzin

  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
maar ik vraag me dan af hoe ik in godsnaam iets van een cVierkant zou kunnen substracten...
Ik heb het idee dat het dus alleen met opsplitsen kan, waar ik dus niet uitkom.

Dus jullie zeggen dat ik toch het beste alles kan opsplitsen... Maar hoe vind ik dan uit welk gesplitste deel bij welk cVierkant hoort.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

1 region bevat 0 tot x vierkanten (is de simpelste implementatie). Vervolgens kun je dus als je 1 region van een andere region aftrekt zoveel resultaat vierkanten laten ontstaan als je wilt, en deze met wat simpele code weer tot zo min mogelijk vierkanten laten reduceren.

Professionele website nodig?


  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
als ik nou zorg dat ik eerst dit heb (zie posts hierboven), en dan op een of andere manier dit blok weer opsplits, door te kijken waar die kleur zit die die niet moet tekenen, en dan wat stukken samenvoeg:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
input:
+---------+
|1        |
|     +---+
|     | x |     
+-----+---+

(x is dus die onzichtbare kleur)

wordt dus 

+---------+
|1a   |1b |
|-----+---+
|1c   |
+-----+

na samenvoegen

+---------+
|     |1b |
|     +---+
|1a+1c|
+-----+


maarja dan moet ik wel kleuren gaan zoeken, en ik denk dat dat een beetje traag is.... (alhoewel ik dit alleen hoef te berekenen als er een cVierkant wordt: verplaatst, geresized, toegevoegd of verwijderd)

Verwijderd

Deruud schreef op 11 september 2002 @ 11:18:
maarja dan moet ik wel kleuren gaan zoeken, en ik denk dat dat een beetje traag is.... (alhoewel ik dit alleen hoef te berekenen als er een cVierkant wordt: verplaatst, geresized, toegevoegd of verwijderd)
Hoezo moet je kleuren zoeken, je hebt toch de coordinaten van je regions? Door die coordinaten te vergelijken kun je makkelijk bepalen of je twee regions kunt "mergen" tot een.

En als je toch gaat berekenen welke regions er getekend moeten worden, waarom blit je dan gewoon niet exact die regions naar het scherm? Dan heb je die extra kleur niet nodig.

Je moet dus gewoon een lijst van cVierkanten of regions implementeren, gesorteerd op z-order (als je voor regions kiest moet je bij elke region opnemen tot welke cVierkant hij behoort). Bepalen in welk cVierkant je muis staat is dan gewoon die lijst doorlopen totdat je een region/cVierkant gevonden hebt dat de muiscoordinaten omsluit.

  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
die coordinaten heb ik ja... maar wat het oorspronkelijke probleem was: hoe houd ik bij bij welk cVierkant die horen. Ik heb het ook al geprobeerd door voor dat x/ysplit array geen int te gebruiken maar een of andere klasse die een int-waarden EN een pointer naar het cVierkant bevat.

in welk cVierkant de muis staat heb ik ook al, maar het ging erom dat als ik ergens op zon cVierkant stond, dat ik kon zien bij welk subblok (in dat cVierkant) die muispositie hoorde

Verwijderd

Ik denk dat je een hele moeilijke weg bewandelt met die xsplit/ysplit arrays, want je hebt geen z-order opgenomen en weet dus niet of het ene vierkant boven of onder het andere vierkant ligt.

Mijn voorstel is dan ook om gewoon een (double linked) list te maken van vierkanten, gesorteerd op z-order (dus het vierkant dat als bovenste op het scherm ligt, zit ook bovenaan de lijst). Je muiscoordinaten bepalen is dan een fluitje van een cent: beginnen bij het bovenste vierkant in de lijst en vervolgens afdalen totdat je een vierkant hebt gevonden dat de coordinaten omsluit.

Het tekenen is wat complexer: begin bij het te tekenen vierkant in de lijst en definieer dat als te tekenen region. Vervolgens werk je je weg naar boven in de lijst, waarbij je alle vierkanten die je tegenkomt aftrekt van de bestaande region(s) ("opsplitsen" dus). Je eindigt dan met een lijst van regions die vanaf het betreffende vierkant naar het scherm geblit moeten worden.

[ Voor 0% gewijzigd door Verwijderd op 11-09-2002 13:35 . Reden: typo ]


  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 13:54
Mijn voorstel is dan ook om gewoon een (double linked) list te maken van vierkanten, gesorteerd op z-order (dus het vierkant dat als bovenste op het scherm ligt, zit ook bovenaan de lijst). Je muiscoordinaten bepalen is dan een fluitje van een cent: beginnen bij het bovenste vierkant in de lijst en vervolgens afdalen totdat je een vierkant hebt gevonden dat de coordinaten omsluit.
dit hebben we al, maar maar in 1 richting (van laag->hoog)
Het tekenen is wat complexer: begin bij het te tekenen vierkant in de lijst en definieer dat als te tekenen region. Vervolgens werk je je weg naar boven in de lijst, waarbij je alle vierkanten die je tegenkomt aftrekt van de bestaande region(s) ("opsplitsen" dus). Je eindigt dan met een lijst van regions die vanaf het betreffende vierkant naar het scherm geblit moeten worden.
ik denk dat dat wel een goede manier is ja. Deze substracting hoef ik maar 1x te doen als een cVierkant niet veranderd.
Dan zal ik eerst maar eens een substract functietje gaan schrijven....
Pagina: 1