[DX / Wiskunde] Hoogte en hoek van 3D terrein

Pagina: 1
Acties:
  • 116 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Goeiemiddag,

Ik ben hier bezig aan een hobby project in DirectX waarbij ik een terrein genereer van een height map en hier wat models op neer plant (in de hoop dat het ooit nog eens een rts wordt :) ). Nou wil ik de hoogte van het terrein op een gegeven punt berekenen en de hoek die het terrein daar maakt, zodat m'n tank modellen mooi het terrein volgen. Met m'n huidig algoritme lukt dit aardig:

Afbeeldingslocatie: http://www.netforge.nl/rommel/heuvel.jpg

Het probleem:

Alleen af en toe 'hapert' het. Over het algmeen volgen de modellen netjes het terrein in de goede hoek, maar soms 'verspingt' de hoogte heel even of de hoek klopt net niet helemaal. Het algoritme dat ik gebruik heb ik zelf bedacht met vele uren bloed, zweet en tranen (minimaal hoor! :+) , maar m'n wiskunde is niet echt m'n sterkste kant schijnbaar. De code voor het algoritme:

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
public TerrainPositionInfo GetTerrainPositionInfo( float x, float z )
{

    float xIndexF = (( x - minBounds.X ) /stepX);
    float zIndexF = (( (maxBounds.Z - minBounds.Z) - (z - minBounds.Z) ) /stepZ);

    int xIndex = (int)Math.Floor(xIndexF);
    int zIndex = (int)Math.Floor(zIndexF);

    float diffX = xIndexF - ((float)xIndex);
    float diffZ = zIndexF - ((float)zIndex);

    float heightAtPoint = heights[xIndex, zIndex];
    
    float angleX = 0.0f;
    float angleZ = 0.0f;

    // split algorithm because of triangles (see notes)
    if (diffX > diffZ) // use method 1
    {
        if (xIndex < numCellsHigh && zIndex < numCellsHigh)
        {
            float hP1 = heightAtPoint;
            float hP2 = heights[xIndex, zIndex + 1];
            float hP3 = heights[xIndex + 1, zIndex + 1];

            float r = (hP3 - hP2) * diffX;
            float s = (hP2 - hP1) * diffZ;

            float interpolation = r + s;

            angleX = (float)Math.Atan( r / stepX);
            angleZ = (float)Math.Atan( s / stepZ);
            
            heightAtPoint = hP1 + interpolation;
        }
    }
    else // use method 2
    {
        if (xIndex < numCellsHigh && zIndex < numCellsHigh)
        {
            float hP1 = heightAtPoint;
            float hP3 = heights[xIndex + 1, zIndex + 1];
            float hP4 = heights[xIndex + 1, zIndex];

            float r = (hP4 - hP1) * diffX;
            float s = (hP3 - hP4) * diffZ;
            
            float interpolation = r + s;

            angleX = (float)Math.Atan( r / stepX);
            angleZ = (float)Math.Atan( s / stepZ);
            
            heightAtPoint = hP1 + interpolation;
        }
    }


    return new TerrainPositionInfo(heightAtPoint, angleX, angleZ);
}


hPi = hoogte van punt i (zie beneden)
height[,] = hoogtemap
r = hoogteverschil van punt tot hP1 geprojecteerd op z-as (dus alleen van x component)
s = hoogteverschil van punt tot hP1 geprojecteerd op x-as (dus alleen van z component)

Dit zou moeten werken omdat ik m'n terrein heb opgedeeld in cellen, die vervolgens zijn opgedeel in triangles. Als de diffX > diffZ, dan zou bevind het model zich op de bovenste triangle en gebruikt hij de eerste methode. Anders gebruikt hij de methode 2 voor de onderste triangle:

Afbeeldingslocatie: http://www.netforge.nl/rommel/grid.gif

...

Hmmm... hoe langer ik erover nadenk, hoe minder logisch m'n algoritme is... de gedachte zelf klopt ergens wel, maar nu ik het zo zie ben ik verbaasd dat het uberhaupt werkt :) Ik ga weer even verder knutselen met m'n nieuwe inzichten, maar als iemand een algoritme hiervoor heeft liggen of z'n licht hier even op wilt laten schijnen, dan hoor ik het natuurlijk graag _/-\o_

Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
is het niet gewoon de richtingscoefficient berekenen op een bepaald punt van een 3D grafiek? (dus normal berekenen op punt, dan een vlak nemen loodrecht op normal en je model op dat vlak plaatsen.)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Zoiets moet het zijn ja, maar ik heb nu zo'n 15 pagina's formules uitgetekend en zie zo langzamerhand door de bomen het bos niet meer :) Ik ga er nog eens met frisse moed aan beginnen, maar als iemand nog algoritmes of tutorials hiervoor heeft, dan ben ik nog steeds zeer geinteresseerd :Y)

Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op zondag 15 mei 2005 @ 14:27:
Zoiets moet het zijn ja, maar ik heb nu zo'n 15 pagina's formules uitgetekend en zie zo langzamerhand door de bomen het bos niet meer :) Ik ga er nog eens met frisse moed aan beginnen, maar als iemand nog algoritmes of tutorials hiervoor heeft, dan ben ik nog steeds zeer geinteresseerd :Y)
Die normals heb je al, nl. die heb je al berekend in je terrain geometry (toch?)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Daar heb ik me een beetje makkelijk vanaf gemaakt. Ik stop nl alle vetices in een Mesh object en roep daar ComputeNormals() op aan :+ ... Ik heb het de hele tijd proberen op te lossen met calculus, maar volgens mij kan ik het inderdaad beter met lineare algebra (vectors) oplossen, dus ik ga m'n boek hierover maar eens zoeken en afstoffen.

Bedankt voor de tips in ieder geval!