Archived

This topic is now archived and is closed to further replies.

nexguy

Converting c++ to VB

Recommended Posts

I need to convert the c++ code written by druid called "Spectral Synthesis for Creating Terrain" located here on this website http://www.gamedev.net/reference/programming/features/noiseterrain It has been a long time since I have worked with c++ and I just cannot remember/grasp some of the concepts. I have converted almost all of it (it is pretty short), but I still have a few questions. Will anyone help me? Chris

Share this post


Link to post
Share on other sites
Here is the code... There is a function that he uses called spline() that I found in some of his other code.. it is at the bottom. He also uses SRANDOM. I found the definition of it in some of this other code... it is this...


  
#define RANDMASK RAND_MAX
#define MRANDOM (float)(rand() & (RANDMASK))/(RANDMASK)
#define SRANDOM ((MRANDOM) * 2) - 1


// Here is the main code.



/*
* fracSynthPass(...)
*
* generate basic points
* interpolate along spline & scale
* add to existing hbuffer
*/

void fracSynthPass( float *hbuf, float freq, float zscale, int xres, int zres )
{

int i;
int x, z;
float *val;
int max;
float dfx, dfz;
float *zknots, *knots;
float xk, zk;
float *hlist;
float *buf;

// how many to generate (need 4 extra for smooth 2d spline interpolation)

max = freq + 2;
// delta x and z - pixels per spline segment

dfx = xres / (freq-1);
dfz = zres / (freq-1);

// the generated values - to be equally spread across buf

val = (float*)calloc( sizeof(float)*max*max, 1 );
// intermediately calculated spline knots (for 2d)

zknots = (float*)calloc( sizeof(float)*max, 1 );

// horizontal lines through knots

hlist = (float*)calloc( sizeof(float)*max*xres, 1 );
// local buffer - to be added to hbuf

buf = (float*)calloc( sizeof(float)*xres*zres, 1 );

// start at -dfx, -dfz - generate knots

for( z=0; z < max; z++ )
{
for( x=0;x < max;x++ )
{
val[z*max+x] = SRANDOM;
}
}

// interpolate horizontal lines through knots

for( i=0;i < max;i++ )
{
knots = &val[i*max];
xk = 0;
for( x=0;x < xres;x++ )
{
hlist[i*xres+x] = spline( xk/dfx, 4, knots );
xk += 1;
if( xk >= dfx )
{
xk -= dfx;
knots++;
}
}
}

// interpolate all vertical lines

for( x=0;x < xres;x++ )
{
zk = 0;
knots = zknots;
// build knot list

for( i=0;i < max;i++ )
{
knots[i] = hlist[i*xres+x];
}
for( z=0;z < zres;z++ )
{
buf[z*xres+x] = spline( zk/dfz, 4, knots ) * zscale;
zk += 1;
if( zk >= dfz )
{
zk -= dfz;
knots++;
}
}
}

// update hbuf

for( z=0;z < zres;z++ )
for( x=0;x < xres;x++ )
hbuf[z*xres+x] += buf[z*xres+x];

free( val );
free( buf );
free( hlist );
free( zknots );
}


// here is the spline function code


float spline( float x, int nknots, float *knot )
{
int span;
int nspans = nknots - 3;
float c0, c1, c2, c3; // coefficients of the cubic


if( nspans < 1)
{
// illegal

return 0;
}

// find the appropriate 4-point span of the spline

x = (x < 0 ? 0 : (x > 1 ? 1 : x)) * nspans;
span = (int) x;
if( span >= nknots -3 )
span = nknots - 3;
x -= span;
knot += span;

// evaluate the span cubic at x using horner's rule

c3 = CR00*knot[0] + CR01*knot[1]
+ CR02*knot[2] + CR03*knot[3];
c2 = CR10*knot[0] + CR11*knot[1]
+ CR12*knot[2] + CR13*knot[3];
c1 = CR20*knot[0] + CR21*knot[1]
+ CR22*knot[2] + CR23*knot[3];
c0 = CR30*knot[0] + CR31*knot[1]
+ CR32*knot[2] + CR33*knot[3];

return ((c3*x + c2)*x + c1)*x + c0;
}

// here are the definitions of CR00 thru CR33


#define CR00 -0.5
#define CR01 1.5
#define CR02 -1.5
#define CR03 0.5
#define CR10 1.0
#define CR11 -2.5
#define CR12 2.0
#define CR13 -0.5
#define CR20 -0.5
#define CR21 0.0
#define CR22 0.5
#define CR23 0.0
#define CR30 0.0
#define CR31 1.0
#define CR32 0.0
#define CR33 0.0


I hope I provided enough info.

Chris

[edited by - Yann L on May 7, 2003 6:38:15 PM]

Share this post


Link to post
Share on other sites
Here is what I have so far...
I know it is not the most optimized, but I can do that later.

Thank you for any help


  
Public Sub fracSynthPass(ByRef hbuf() As Double, freq As Double, zscale As Double, xres As Integer, zres As Integer)
Dim SRANDOM As Double
SRANDOM = (((Rnd And (32767)) / (32767)) * 2) - 1
Dim i As Integer
Dim x As Integer
Dim z As Integer
Dim val() As Double
Dim max As Integer
Dim dfx As Double
Dim dfz As Double
Dim zknots() As Double
Dim knots() As Double
Dim xk As Double
Dim zk As Double
Dim hlist() As Double
Dim buf() As Double
max = freq + 2
' // delta x and z - pixels per spline segment

dfx = xres / (freq - 1)
dfz = zres / (freq - 1)
'
' // the generated values - to be equally spread across buf

ReDim val(max * max)
' // intermediately calculated spline knots (for 2d)

ReDim zknots(max)
'
' // horizontal lines through knots

ReDim hlist(max * xres)
' // local buffer - to be added to hbuf

ReDim buf(xres * zres)
'
For z = 0 To max
For x = 0 To max
val(z * max + x) = (((Rnd And (32767)) / (32767)) * 2) - 1
Next
Next

Dim knotscounter As Integer
knotscounter = 0
For i = 0 To max
knots(xk) = val(i * max)
xk = 0
For x = 0 To xres
hlist(i * xres + x) = spline(xk / dfx, 4, knots)
xk = xk + 1
If xk >= dfx Then
xk = xk - dfx
knotscounter = knotscounter + 1
End If
Next
Next

knotscounter = 0
For x = 0 To xres
zk = 0
ReDim knots(UBound(zknots, 1))
For i = 0 To UBound(zknots, 1)
knots(i) = zknots(i)
Next
For i = 0 To max
knots(i) = hlist(i * xres + x)
Next
For z = 0 To zres
buf(z * xres + x) = spline(zk / dfz, 4, knots) * zscale
zk = zk + 1
If zk >= dfz Then
zk = zk - dfz
knotscounter = knotscounter + 1
End If
Next
Next

For z = 0 To zres
For x = 0 To xres
hbuf(z * xres + x) = hbuf(z * xres + x) + buf(z * xres + x)
Next
Next
End Sub


Function spline(x As Double, nknots As Integer, knot() As Double) As Double
'// basis matrix for spline interpolation

Dim CR00 As Double
Dim CR01 As Double
Dim CR02 As Double
Dim CR03 As Double
Dim CR10 As Double
Dim CR11 As Double
Dim CR12 As Double
Dim CR13 As Double
Dim CR20 As Double
Dim CR21 As Double
Dim CR22 As Double
Dim CR23 As Double
Dim CR30 As Double
Dim CR31 As Double
Dim CR32 As Double
Dim CR33 As Double
CR00 = -0.5
CR01 = 1.5
CR02 = -1
CR03 = 0.5
CR10 = 1
CR11 = -2
CR12 = 2
CR13 = -0
CR20 = -0
CR21 = 0
CR22 = 0.5
CR23 = 0
CR30 = 0
CR31 = 1
CR32 = 0

Dim span As Integer
Dim nspans As Integer
nspans = nknots - 3
Dim c0 As Double
Dim c1 As Double
Dim c2 As Double
Dim c3 As Double

If nspans < 1 Then
'illegal
spline = 0
Exit Function
End If

If x < 0 Then
x = 0
Else
If x > 1 Then
x = 1 * nspans
Else
x = x * nspans
End If
End If

span = CInt(x)

If span >= nknots - 3 Then
span = nknots - 3
End If

x = x - span
knot = knot + span

' // evaluate the span cubic at x using horner's rule

c3 = CR00 * knot(0) + CR01 * knot(1) + CR02 * knot(2) + CR03 * knot(3)
c2 = CR10 * knot(0) + CR11 * knot(1) + CR12 * knot(2) + CR13 * knot(3)
c1 = CR20 * knot(0) + CR21 * knot(1) + CR22 * knot(2) + CR23 * knot(3)
c0 = CR30 * knot(0) + CR31 * knot(1) + CR32 * knot(2) + CR33 * knot(3)

spline = ((c3 * x + c2) * x + c1) * x + c0
End Function


[edited by - Yann L on May 7, 2003 6:39:05 PM]

Share this post


Link to post
Share on other sites
nexguy, if you''re posting more than a few lines of code, then please use the source tags. Thanks.

Other than that, I really can''t help you, sorry. I''ve never used VB in my life...

Share this post


Link to post
Share on other sites
quote:
Original post by nexguy
Here is what I have so far...
I know it is not the most optimized, but I can do that later.

Thank you for any help



      
Public Sub fracSynthPass(ByRef hbuf() As Double, freq As Double, zscale As Double, xres As Integer, _
zres As Integer) 'when text goes out of the immediate window(not debug mode), _ you can use the underscore char to tell the
_ compiler that the statement continues on the next line
Dim SRANDOM As Double
SRANDOM = (((Rnd And (32767)) / (32767)) * 2) - 1
Dim i As Integer
Dim x As Integer
Dim z As Integer
Dim val() As Double
Dim max As Integer
Dim dfx As Double
Dim dfz As Double
Dim zknots() As Double
Dim knots() As Double
Dim xk As Double
Dim zk As Double
Dim hlist() As Double
Dim buf() As Double
max = freq + 2
' // delta x and z - pixels per spline segment

dfx = xres / (freq - 1)
dfz = zres / (freq - 1)
'
' // the generated values - to be equally spread across buf

ReDim val(max * max)
' // intermediately calculated spline knots (for 2d)

ReDim zknots(max)
'
' // horizontal lines through knots

ReDim hlist(max * xres)
' // local buffer - to be added to hbuf

ReDim buf(xres * zres)
'
For z = 0 To max
For x = 0 To max
val(z * max + x) = (((Rnd And (32767)) / (32767)) * 2) - 1
Next
Next

Dim knotscounter As Integer
knotscounter = 0
For i = 0 To max
knots(xk) = val(i * max)
xk = 0
For x = 0 To xres
hlist(i * xres + x) = spline(xk / dfx, 4, knots)
xk = xk + 1
If xk >= dfx Then
xk = xk - dfx
knotscounter = knotscounter + 1
End If
Next
Next

knotscounter = 0
For x = 0 To xres
zk = 0
ReDim knots(UBound(zknots, 1))
For i = 0 To UBound(zknots, 1)
knots(i) = zknots(i)
Next
For i = 0 To max
knots(i) = hlist(i * xres + x)
Next
For z = 0 To zres
buf(z * xres + x) = spline(zk / dfz, 4, knots) * zscale
zk = zk + 1
If zk >= dfz Then
zk = zk - dfz
knotscounter = knotscounter + 1
End If
Next
Next

For z = 0 To zres
For x = 0 To xres
hbuf(z * xres + x) = hbuf(z * xres + x) + buf(z * xres + x)
Next
Next
End Sub


Function spline(x As Double, nknots As Integer, knot() As Double) As Double
'// basis matrix for spline interpolation

Dim CR00 As Double
Dim CR01 As Double
Dim CR02 As Double
Dim CR03 As Double
Dim CR10 As Double
Dim CR11 As Double
Dim CR12 As Double
Dim CR13 As Double
Dim CR20 As Double
Dim CR21 As Double
Dim CR22 As Double
Dim CR23 As Double
Dim CR30 As Double
Dim CR31 As Double
Dim CR32 As Double
Dim CR33 As Double
CR00 = -0.5
CR01 = 1.5
CR02 = -1
CR03 = 0.5
CR10 = 1
CR11 = -2
CR12 = 2
CR13 = -0
CR20 = -0
CR21 = 0
CR22 = 0.5
CR23 = 0
CR30 = 0
CR31 = 1
CR32 = 0

Dim span As Integer
Dim nspans As Integer
nspans = nknots - 3
Dim c0 As Double
Dim c1 As Double
Dim c2 As Double
Dim c3 As Double

If nspans < 1 Then
'illegal
spline = 0
Exit Function
End If

If x < 0 Then
x = 0
Else
If x > 1 Then
x = 1 * nspans
Else
x = x * nspans
End If
End If

span = CInt(x)

If span >= nknots - 3 Then
span = nknots - 3
End If

x = x - span
knot = knot + span

' // evaluate the span cubic at x using horner's rule

c3 = CR00 * knot(0) + CR01 * knot(1) + CR02 * knot(2) + CR03 * knot(3)
c2 = CR10 * knot(0) + CR11 * knot(1) + CR12 * knot(2) + CR13 * knot(3)
c1 = CR20 * knot(0) + CR21 * knot(1) + CR22 * knot(2) + CR23 * knot(3)
c0 = CR30 * knot(0) + CR31 * knot(1) + CR32 * knot(2) + CR33 * knot(3)

spline = ((c3 * x + c2) * x + c1) * x + c0
End Function


[edited by - Yann L on May 7, 2003 6:39:05 PM]

and a little bit of thought: vb uses broken english, except for function calls not made by you, or other people/companies ie:

private sub form_load()

list1.additem "vb uses english for basic function calls"
list1.refresh

end sub



------------------------------------------------------------
I really need to update this signature...

[edited by - demonrazor2003 on May 8, 2003 9:44:51 AM]

Share this post


Link to post
Share on other sites
Ok, maybe I should ask specific questions.

What would be the VB equivilant to these c/c++ lines of code:

c++: zknots = (float*)calloc( sizeof(float)*max, 1 );
VB?: ReDim zknots(max)

c++: val[z*max+x] = SRANDOM;
VB?: val1(z*max+x) = ???? ''val is a reserved word in VB
''What is SRANDOM? (located in code
''above)

c++: knots = &val[i*max];
VB?: This will require some rewriting I think. In c++ it looks like knots is pointing to a "row" of val. How could I do this in VB?

Thanks

Share this post


Link to post
Share on other sites
quote:
Original post by nexguy
c++: zknots = (float*)calloc( sizeof(float)*max, 1 );



if this does what i think and zknots is supposed to be an array.. then i would probably be careful with further tutorials. first param is number of elements and second the size of each element in bytes.
so is there any trick about this function or reason why someone would call the function in what seems to be a pretty perverted way to me? whats the reason to allocate 4*max elements with size 1 instead of max elements with size 4 if thats what it's going to hold?

quote:

c++: knots = &val[i*max];
VB?: This will require some rewriting I think. In c++ it looks like knots is pointing to a "row" of val. How could I do this in VB?


using a 2d array should probably be the same (i expect vb has something like that)

srandom could be replaced by whatever random number generating function you prefer (not writing all #defines in one line would make it a lot easier to follow whats going on ,-) )



[edited by - Trienco on May 8, 2003 12:57:12 PM]

Share this post


Link to post
Share on other sites
quote:

whats the reason to allocate 4*max elements with size 1 instead of max elements with size 4 if thats what it''s going to hold?


Irrelevant, both are totally equal. You can perfectly say, that the array is going to hold 4*max elements with the size of a byte each. Calloc is going to multiply both values to find the total number of memory to allocate, and simply zero out that area. It doesn''t matter in what order you specify the parameters, if the resulting number of bytes is correct.

Share this post


Link to post
Share on other sites
quote:
Original post by nexguy
Ok, maybe I should ask specific questions.

What would be the VB equivilant to these c/c++ lines of code:

c++: zknots = (float*)calloc( sizeof(float)*max, 1 );
VB?: ReDim zknots(max)

c++: val[z*max+x] = SRANDOM;
VB?: val1(z*max+x) = ???? ''val is a reserved word in VB
''What is SRANDOM? (located in code
''above)

c++: knots = &val[i*max];
VB?: This will require some rewriting I think. In c++ it looks like knots is pointing to a "row" of val. How could I do this in VB?

Thanks



zknots = ( float*)blah blah blah
He is dynamically allocating memory. I don''t think you can do this in VB. To accomplish the same effect in VB you would need to create an array that is larger than the highest value of the variable ''max''. ie: DIM zKnots[1000]

val[z*max+x] = SRANDOM
val is an image or some other 2D array, but he''s using it like a 1D array. the z*max+x is the same as val[x][z]. VAL is reserved in VB, so use a different name. This isn''t a problem because in the C/C++ case above, val is a variable name (and array / block of memory). ie: zKnots[x][z] = SRANDOM.

knots = &val[i * max]
This is a C/C++ trick, and your assumptions are correct. What he''s doing is getting the memory adress for a row from the "2D array" val.. Since VB doesnt want you to mess with memory address and the like, you can ensure code compatibility by:

knotsIndex = i;

In the C/C++ code, whenever you see the knots variable being used like this:
a = *knots + n (or *knots + n = a)

Substitute it for:

a = val[n][knotsIndex] ( or val[n][knotsIndex] = a)


Hope this helps,
Will


Share this post


Link to post
Share on other sites
i never doubted that the result would be the same, just using calloc in that fashion doesnt make any sense to me. why not malloc or calloc how its "meant" to be used? i see this code and cant help wondering if there is any special reason to do that.. for example something strange going on that will make it more efficient..

but maybe i just shouldnt try to see a reason behind everything ,-) after all, its even hard to understand why they bothered to offer a special alloc function like calloc in the first place when the difference to malloc is minimal

[edited by - Trienco on May 8, 2003 3:41:37 PM]

Share this post


Link to post
Share on other sites
I used the same idea you just described. I used an index for val instead of pointing knots to it. So for:

knots = &val[i*max];
something = knots[j]; //assignment i made up
somefunction(i,j,knots); //call to some function i made up

I use

knotsIndex = i*max
something = val(knotsIndex)
somefunction(i,j,knotsCounter,val) //I now have to pass val
//and change the function

The point of this code was to generate terrain. Am I to understand that located in hbuf[] is an array of size xres*zres and it is supposed to emulate a 2D array of point heights?

Thanks


Share this post


Link to post
Share on other sites
As Edotorpedo said earlier val() converts a string value to a double.

//-----------------------------------------------
EXAMPLE:
Dim Sample As String
Dim StringValue As Double

Sample = "20"
StringValue = val(Sample)

StringValue now equals 20
//------------------------------------------------

So in this example:
knotsIndex = i*max
something = val(knotsIndex)
somefunction(i,j,knotsCounter,val)

Disregard the val()!!!!!
You could just use:

knotsIndex = i*max
''//--DONT NEED THIS! something = val(knotsIndex)
somefunction(i, j, knotsCounter, knotsIndex)


Also, since ''i'' is in a for loop you could just say:
somefunction(i, j, knotsCounter, i * max)

-UltimaX-

"You wished for a white christmas... Now go shovel your wishes!"

Share this post


Link to post
Share on other sites
quote:
Original post by UltimaX
As Edotorpedo said earlier val() converts a string value to a double.



That''s only in Basic. In the C source he''s trying to port, "val" is an array, so he must create an equivilant array in this basic code.

NexGuy:
You don''t need to use y*width + x. Since your in Basic, you can stick to array[x][y]. You''ll probably find the code makes more sense if you do.

The reason people you''re seeing the y*width+x is for speed purposes later on. Notably the code you provided will calculate the y*width once for each, and just use additions (instead of a the multiply) to affect the X coordinate.

Cheers,
Will


Share this post


Link to post
Share on other sites
what is SRANDOM in C++??? (i use vb, so i really dont know )
if it is what i think it is, the equivalent is RND([lowerNum,higerNum]) and put in the first sub to be called(ie: main, or form_load) the statement ''RANDOMIZE''. that is all, i think...

------------------------------------------------------------
I really need to update this signature...

Share this post


Link to post
Share on other sites

Well, didn''t read the c++ code completely, but in VB:

rnd() returns value between 0 and 1. Say you need a random number between 2-5 you can write:

dim a as integer

a = cint(rnd() * 5) + 2

In order to not produce the same random numbers every time you start your application, you will need to put the following line in your form_load sub:

randomize timer

Hope this helps a bit.

Edo

Share this post


Link to post
Share on other sites
As it turns out, SRANDOM returns a float between -1 and 1. I believe the equivilant VB code would be...

x = Rnd * 2 - 1

Is there a better/similar algorithm out there to (fractally) generate terrain, so that you can take any part of the terrain and use it to generate more detailed terrain?

Chris

Share this post


Link to post
Share on other sites
You could do multiple octaves of perlin noise to create a heightmap( and to refine landscape ), and then use the noise data to create a landscape outta the height data?
The reason for the question mark is because i''ve never actually read over the perlin noise spec, ever, and this is just information that i guessed should fit from my understanding of the algorithm. That said, im probably wrong

Share this post


Link to post
Share on other sites