logo
Main

Forums

Downloads

Unreal-Netiquette

Donate for Oldunreal:
Donate

borderline

Links to our wiki:
Wiki

Walkthrough

Links

Tutorials

Unreal Reference

Usermaps

borderline

Contact us:
Submit News
Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Going procedural with Perlin (Read 234 times)
Bleeder91[NL]
Betatester
Offline


Personal Text:

Posts: 905
Location: Location, Location, Location.
Joined: Oct 4th, 2009
Gender: Male
Going procedural with Perlin
Jul 17th, 2017 at 3:51pm
Print Post  
I'm trying to mimic minecraft's procedural generation which has worked out well so far, apart from the constant crashing because of the overload of meshes/actors being drawn. My world's flat, however, and I would like to get some Perlin noise in here. I've tried 2 variants and tried my best converting them to Unrealscript, but both fail at doing what I want them to do.
What I need is a single function that I can give a vector location and it will return a float or int of the height that the Z axis will be. (no caves yet)

Short code from the Perlin wiki (Link):
Code (C++)
Select All
final function vector DotGridGradient(int iX, int iY, float X, float Y)
{
	local vector v1,v2;
	local float dX,dY;

	dX=X-iX; dY=Y-iY;
	v1.X=iY; v1.Y=iX; v1.Z=0;
	v2.X=iY; v2.Y=iX; v2.Z=1;
	return (dX*v1+dY*v2);
}

final function float Perlin(float X, float Y)
{
	local vector n0,n1;
	local float ix0, ix1;
	local int x0,x1,y0,y1;
	local float sX,sY;

	x0=int(X); x1=x0+1; y0=int(Y); y1=y0+1; sX=X-x0; sY=Y-y0;
	n0=DotGridGradient(x0, y0, X, Y); n1=DotGridGradient(x1, y0, X, Y);
	ix0=lerp(n0.X, n1.Y, sX);
	n0=DotGridGradient(x0, y1, X, Y); n1=DotGridGradient(x1, y1, X, Y);
	ix1=lerp(n0.X, n1.Y, sX);
	return lerp(ix0, ix1, sY);
} 

This one keeps returning me numbers waaay higher/lower than I expected (-334895 to 664321 depending on vector distance from [0,0])

Long code from some other place(Link):
Code (C++)
Select All
function float GetMePerlin(vector p, optional out vector derivs)
{
	local int xi0,yi0,zi0, xi1,yi1,zi1;
	local float tx,ty,tz;
	local float u,v,w;
	local float x0,y0,z0,x1,y1,z1;
	local float a,b,c,d,e,f,g,h;
	local float du,dv,dw;
	local float k0,k1,k2,k3,k4,k5,k6,k7;

 xi0 = int(p.x) & 254;
 yi0 = int(p.y) & 254;
 zi0 = int(p.z) & 254;

 xi1 = (xi0+1) & 254;
 yi1 = (yi0+1) & 254;
 zi1 = (zi0+1) & 254;

 tx = p.x - int(p.x);
 ty = p.y - int(p.y);
 tz = p.z - int(p.z);

 u = quintic(tx);
 v = quintic(ty);
 w = quintic(tz);

// generate vectors going from the grid points to p
 x0 = tx; x1 = tx - 1;
 y0 = ty; y1 = ty - 1;
 z0 = tz; z1 = tz - 1;

 a = gradientDotV(byte(xi0+yi0+zi0), x0, y0, z0);
 b = gradientDotV(byte(xi1+yi0+zi0), x1, y0, z0);
 c = gradientDotV(byte(xi0+yi1+zi0), x0, y1, z0);
 d = gradientDotV(byte(xi1+yi1+zi0), x1, y1, z0);
 e = gradientDotV(byte(xi0+yi0+zi1), x0, y0, z1);
 f = gradientDotV(byte(xi1+yi0+zi1), x1, y0, z1);
 g = gradientDotV(byte(xi0+yi1+zi1), x0, y1, z1);
 h = gradientDotV(byte(xi1+yi1+zi1), x1, y1, z1);

 du = quinticDeriv(tx);
 dv = quinticDeriv(ty);
 dw = quinticDeriv(tz);

 k0 = a;
 k1 = (b - a);
 k2 = (c - a);
 k3 = (e - a);
 k4 = (a + d - b - c);
 k5 = (a + f - b - e);
 k6 = (a + g - c - e);
 k7 = (b + c + e + h - a - d - f - g);

derivs.x = du *(k1 + k4 * v + k5 * w + k7 * v * w);
derivs.y = dv *(k2 + k4 * u + k6 * w + k7 * v * w);
derivs.z = dw *(k3 + k5 * u + k6 * v + k7 * v * w);

return k0 + k1 * u + k2 * v + k3 * w + k4 * u * v + k5 * u * w + k6 * v * w + k7 * u * v * w;
}

function float quinticDeriv(float t)
{
	return 30 * t * t * (t * (t - 2) + 1);
}

function float quintic(float t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}


function float gradientDotV(byte perm, float x, float y, float z)
{
	switch (perm & 15)
	{
		case 0: return x + y; // (1,1,0)
		case 1: return -x + y; // (-1,1,0)
		case 2: return x - y; // (1,-1,0)
		case 3: return -x - y; // (-1,-1,0)
		case 4: return x + z; // (1,0,1)
		case 5: return -x + z; // (-1,0,1)
		case 6: return x - z; // (1,0,-1)
		case 7: return -x - z; // (-1,0,-1)
		case 8: return y + z; // (0,1,1),
		case 9: return -y + z; // (0,-1,1),
		case 10: return y - z; // (0,1,-1),
		case 11: return -y - z; // (0,-1,-1)
		case 12: return y + x; // (1,1,0)
		case 13: return -x + y; // (-1,1,0)
		case 14: return -y + z; // (0,-1,1)
		case 15: return -y - z; // (0,-1,-1)
	}
}  

This one returns me 0 whatever I put in.

Obviously I have no idea what I'm doing and apart from being able to (hopefully) convert it correctly I am clueless as to what this thing actually does. So who's got the spare time to help me figure this one out? Cheesy
  
Back to top
 
IP Logged
 
Bleeder91[NL]
Betatester
Offline


Personal Text:

Posts: 905
Location: Location, Location, Location.
Joined: Oct 4th, 2009
Gender: Male
Re: Going procedural with Perlin
Reply #1 - Jul 19th, 2017 at 8:11am
Print Post  
Third attempt with code for Simplex Noise. This one seems to be working well, though I need to smooth out the distribution a bit (Link). I'll post a screenshot when I got it working right!

Code (C++)
Select All
//=============================================================================
// UCTerraGen. Procedural generation using Simplex Noise.
//=============================================================================
class UCTerraGen expands Actor abstract;
const F2=0.366025;
const G2=0.211324;

var const vector NoiseV[12];
var const int NoiseP[256];

final static function float Gener8(float xin, float yin)
{
	local float n0,n1,n2;
	local float s,t,X0,Y0,x0a,y0a;
	local float x1,y1,x2,y2,t0,t1,t2;
	local int i,j,i1,j1,ii,jj,gi0,gi1,gi2;

	// Noise contributions from the three corners
    // Skew the input space to determine which simplex cell we're in
    s = (xin+yin)*F2;

	// Hairy factor for 2D
	i = int(xin+s);
	j = int(yin+s);
	t = (i+j)*G2;
	X0 = i-t;

	// Unskew the cell origin back to (x,y) space
	Y0 = j-t;
	x0a = xin-X0;
	y0a = yin-Y0;

	// Offsets for second (middle) corner of simplex in (i,j) coords
    if(x0a>y0a) { i1=1; j1=0; }
    else { i1=0; j1=1; } // lower triangle, XY order: (0,0)->(1,0)->(1,1)

	// upper triangle, YX order: (0,0)->(0,1)->(1,1)
    // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
    // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
    // c = (3-sqrt(3))/6
    x1 = x0a - i1 + G2;

	// Offsets for middle corner in (x,y) unskewed coords
	y1 = y0a - j1 + G2;
	x2 = x0a - 1.0 + 2.0 * G2;
	y2 = y0a - 1.0 + 2.0 * G2;

	// Work out the hashed gradient indices of the three simplex corners
	ii = i & 255;
	jj = j & 255;
	gi0 = GetRandomNoiseP(ii   +GetRandomNoiseP(jj)) % 12;
	gi1 = GetRandomNoiseP(ii+i1+GetRandomNoiseP(jj+j1)) % 12;
	gi2 = GetRandomNoiseP(ii+1 +GetRandomNoiseP(jj+1)) % 12;

	// Calculate the contribution from the three corners
	t0 = 0.5 - x0a*x0a-y0a*y0a;
	if(t0<0) n0 = 0.0;
	else
	{
		t0 *= t0;
		n0 = t0 * t0 * NoiseDot(gi0, x0a, y0a); 
		// (x,y) of grad3 used for 2D gradient
	}
	t1 = 0.5 - x1*x1-y1*y1;
	if(t1<0) n1 = 0.0;
	else
	{
		t1 *= t1;
		n1 = t1 * t1 * NoiseDot(gi1, x1, y1); log(Default.NoiseP[1]);
	}
	t2 = 0.5 - x2*x2-y2*y2;
	if(t2<0) n2 = 0.0;
	else
	{
		t2 *= t2;
		n2 = t2 * t2 * NoiseDot(gi2, x2, y2);
	}

	// Add contributions from each corner to get the final noise value.
	// The result is scaled to return values in the interval [-1,1].
	return 70.0 * (n0 + n1 + n2);
}

final static function byte GetRandomNoiseP(int Nr)
{
	return Default.NoiseP[Nr%256];
}

final static function float NoiseDot(int Nr, float X, float Y)
{
	return Default.NoiseV[Nr].X*X + Default.NoiseV[Nr].Y*Y;
}

defaultproperties
{
	NoiseV(0)=(1,1,0)
	NoiseV(1)=(-1,1,0)
	NoiseV(2)=(1,-1,0)
	NoiseV(3)=(-1,-1,0)
	NoiseV(4)=(1,0,1)
	NoiseV(5)=(-1,0,1)
	NoiseV(6)=(1,0,-1)
	NoiseV(7)=(-1,0,-1)
	NoiseV(8)=(0,1,1)
	NoiseV(9)=(0,-1,1)
	NoiseV(10)=(0,1,-1)
	NoiseV(11)=(0,-1,-1)
	NoiseP(0)=51
	NoiseP(1)=160
	NoiseP(2)=137
	NoiseP(3)=91
	NoiseP(4)=90
	NoiseP(5)=15
	NoiseP(6)=131
	NoiseP(7)=13
	NoiseP(8)=201
	NoiseP(9)=95
	NoiseP(10)=96
	NoiseP(11)=53
	NoiseP(12)=194
	NoiseP(13)=233
	NoiseP(14)=7
	NoiseP(15)=225
	NoiseP(16)=140
	NoiseP(17)=36
	NoiseP(18)=103
	NoiseP(19)=30
	NoiseP(20)=69
	NoiseP(21)=142
	NoiseP(22)=8
	NoiseP(23)=99
	NoiseP(24)=37
	NoiseP(25)=240
	NoiseP(26)=21
	NoiseP(27)=10
	NoiseP(28)=23
	NoiseP(29)=190
	NoiseP(30)=6
	NoiseP(31)=148
	NoiseP(32)=247
	NoiseP(33)=120
	NoiseP(34)=234
	NoiseP(35)=75
	NoiseP(36)=0
	NoiseP(37)=26
	NoiseP(38)=197
	NoiseP(39)=62
	NoiseP(40)=94
	NoiseP(41)=252
	NoiseP(42)=219
	NoiseP(43)=203
	NoiseP(44)=117
	NoiseP(45)=35
	NoiseP(46)=11
	NoiseP(47)=32
	NoiseP(48)=57
	NoiseP(49)=177
	NoiseP(50)=33
	NoiseP(51)=88
	NoiseP(52)=237
	NoiseP(53)=149
	NoiseP(54)=56
	NoiseP(55)=87
	NoiseP(56)=174
	NoiseP(57)=20
	NoiseP(58)=125
	NoiseP(59)=136
	NoiseP(60)=171
	NoiseP(61)=168
	NoiseP(62)=68
	NoiseP(63)=175
	NoiseP(64)=74
	NoiseP(65)=165
	NoiseP(66)=71
	NoiseP(67)=134
	NoiseP(68)=139
	NoiseP(69)=48
	NoiseP(70)=27
	NoiseP(71)=166
	NoiseP(72)=77
	NoiseP(73)=146
	NoiseP(74)=158
	NoiseP(75)=231
	NoiseP(76)=83
	NoiseP(77)=111
	NoiseP(78)=229
	NoiseP(79)=122
	NoiseP(80)=60
	NoiseP(81)=211
	NoiseP(82)=133
	NoiseP(83)=230
	NoiseP(84)=220
	NoiseP(85)=105
	NoiseP(86)=92
	NoiseP(87)=41
	NoiseP(88)=55
	NoiseP(89)=46
	NoiseP(90)=245
	NoiseP(91)=40
	NoiseP(92)=244
	NoiseP(93)=102
	NoiseP(94)=143
	NoiseP(95)=54
	NoiseP(96)=65
	NoiseP(97)=25
	NoiseP(98)=63
	NoiseP(99)=161
	NoiseP(100)=1
	NoiseP(101)=216
	NoiseP(102)=80
	NoiseP(103)=73
	NoiseP(104)=209
	NoiseP(105)=76
	NoiseP(106)=132
	NoiseP(107)=187
	NoiseP(108)=208
	NoiseP(109)=89
	NoiseP(110)=18
	NoiseP(111)=169
	NoiseP(112)=200
	NoiseP(113)=196
	NoiseP(114)=135
	NoiseP(115)=130
	NoiseP(116)=116
	NoiseP(117)=188
	NoiseP(118)=159
	NoiseP(119)=86
	NoiseP(120)=164
	NoiseP(121)=100
	NoiseP(122)=109
	NoiseP(123)=198
	NoiseP(124)=173
	NoiseP(125)=186
	NoiseP(126)=3
	NoiseP(127)=64
	NoiseP(128)=52
	NoiseP(129)=217
	NoiseP(130)=226
	NoiseP(131)=250
	NoiseP(132)=124
	NoiseP(133)=123
	NoiseP(134)=5
	NoiseP(135)=202
	NoiseP(136)=38
	NoiseP(137)=147
	NoiseP(138)=118
	NoiseP(139)=126
	NoiseP(140)=255
	NoiseP(141)=82
	NoiseP(142)=85
	NoiseP(143)=212
	NoiseP(144)=207
	NoiseP(145)=206
	NoiseP(146)=59
	NoiseP(147)=227
	NoiseP(148)=47
	NoiseP(149)=16
	NoiseP(150)=58
	NoiseP(151)=17
	NoiseP(152)=182
	NoiseP(153)=189
	NoiseP(154)=28
	NoiseP(155)=42
	NoiseP(156)=223
	NoiseP(157)=183
	NoiseP(158)=170
	NoiseP(159)=213
	NoiseP(160)=119
	NoiseP(161)=248
	NoiseP(162)=152
	NoiseP(163)=2
	NoiseP(164)=44
	NoiseP(165)=154
	NoiseP(166)=163
	NoiseP(167)=70
	NoiseP(168)=221
	NoiseP(169)=153
	NoiseP(170)=101
	NoiseP(171)=155
	NoiseP(172)=167
	NoiseP(173)=43
	NoiseP(174)=172
	NoiseP(175)=9
	NoiseP(176)=129
	NoiseP(177)=22
	NoiseP(178)=39
	NoiseP(179)=253
	NoiseP(180)=19
	NoiseP(181)=98
	NoiseP(182)=108
	NoiseP(183)=110
	NoiseP(184)=79
	NoiseP(185)=113
	NoiseP(186)=224
	NoiseP(187)=232
	NoiseP(188)=178
	NoiseP(189)=185
	NoiseP(190)=112
	NoiseP(191)=104
	NoiseP(192)=218
	NoiseP(193)=246
	NoiseP(194)=97
	NoiseP(195)=228
	NoiseP(196)=251
	NoiseP(197)=34
	NoiseP(198)=242
	NoiseP(199)=193
	NoiseP(200)=238
	NoiseP(201)=210
	NoiseP(202)=144
	NoiseP(203)=12
	NoiseP(204)=191
	NoiseP(205)=179
	NoiseP(206)=162
	NoiseP(207)=241
	NoiseP(208)=81
	NoiseP(209)=51
	NoiseP(210)=145
	NoiseP(211)=235
	NoiseP(212)=249
	NoiseP(213)=14
	NoiseP(214)=239
	NoiseP(215)=107
	NoiseP(216)=49
	NoiseP(217)=192
	NoiseP(218)=214
	NoiseP(219)=31
	NoiseP(220)=181
	NoiseP(221)=199
	NoiseP(222)=106
	NoiseP(223)=157
	NoiseP(224)=184
	NoiseP(225)=84
	NoiseP(226)=204
	NoiseP(227)=176
	NoiseP(228)=115
	NoiseP(229)=121
	NoiseP(230)=50
	NoiseP(231)=45
	NoiseP(232)=127
	NoiseP(233)=4
	NoiseP(234)=150
	NoiseP(235)=254
	NoiseP(236)=138
	NoiseP(237)=236
	NoiseP(238)=205
	NoiseP(239)=93
	NoiseP(240)=222
	NoiseP(241)=114
	NoiseP(242)=67
	NoiseP(243)=29
	NoiseP(244)=24
	NoiseP(245)=72
	NoiseP(246)=243
	NoiseP(247)=141
	NoiseP(248)=128
	NoiseP(249)=195
	NoiseP(250)=78
	NoiseP(251)=66
	NoiseP(252)=215
	NoiseP(253)=61
	NoiseP(254)=156
	NoiseP(255)=180
} 

« Last Edit: Jul 19th, 2017 at 11:31am by Bleeder91[NL] »  
Back to top
 
IP Logged
 
Bleeder91[NL]
Betatester
Offline


Personal Text:

Posts: 905
Location: Location, Location, Location.
Joined: Oct 4th, 2009
Gender: Male
Re: Going procedural with Perlin
Reply #2 - Jul 19th, 2017 at 12:01pm
Print Post  
Alright, I got this now:



I still have to address the issue of FPS and crashing due to the high amount of blocks being drawn...
1,572,864 blocks spawned in 201309ms. Seems legit.
« Last Edit: Jul 19th, 2017 at 5:51pm by Bleeder91[NL] »  
Back to top
 
IP Logged
 
BobIsUnreal
God Member
*****
Offline


Guy who has too much time
invested to quit now

Posts: 732
Joined: Apr 12th, 2010
Gender: Male
Re: Going procedural with Perlin
Reply #3 - Jul 20th, 2017 at 1:10am
Print Post  
select all static mesh > convert to brush > rebuild , cry.
  

[REM_img]http://i.imgur.com/V3OSsDu.gif.disable[/img]http://i.imgur.com/JOu38Gs.gif
Back to top
IP Logged
 
Bleeder91[NL]
Betatester
Offline


Personal Text:

Posts: 905
Location: Location, Location, Location.
Joined: Oct 4th, 2009
Gender: Male
Re: Going procedural with Perlin
Reply #4 - Jul 20th, 2017 at 6:36am
Print Post  
The thing is, the map itself is completely empty. This is spawned in real-time.
It has a random seed and spawns all the blocks on startup. All I need to do now is actually have it load/unload chunks because this drains my CPU extremely fast with multiple players. I can remove/build blocks already so the concept of minecraft in unreal is possible.

I'm also not sure if I should stick with a normal mesh or go back to static. With static I seem to crash more often because of how many blocks are rendered at a time.
  
Back to top
 
IP Logged
 
dustinechoes849
Senior Member
****
Offline


General Protection Fault!

Posts: 297
Location: C:\Unreal\System\
Joined: Feb 28th, 2015
Gender: Male
Re: Going procedural with Perlin
Reply #5 - Jul 20th, 2017 at 8:24am
Print Post  
That looks rad! Cheesy
How did you implement placing/removing blocks? Does the DP's alt-fire place blocks (with primary destroying 'em)?
  


don't bother trying to message me over AIM, I haven't used that in years lol
I have a Discord, the number thingie is #6413
Back to top
IP Logged
 
Bleeder91[NL]
Betatester
Offline


Personal Text:

Posts: 905
Location: Location, Location, Location.
Joined: Oct 4th, 2009
Gender: Male
Re: Going procedural with Perlin
Reply #6 - Jul 20th, 2017 at 8:44am
Print Post  
It's a quick experiment for now. LMB places, RMB destroys. walk+LMB is stone bricks. Terrain's grass on top, 3 layers of Dirt, then some Stone and Gravel and finally Bedrock at the bottom. Once I have chunkloading made I can look into caves and tools etc.
I have it running on my server.
  
Back to top
 
IP Logged
 
dustinechoes849
Senior Member
****
Offline


General Protection Fault!

Posts: 297
Location: C:\Unreal\System\
Joined: Feb 28th, 2015
Gender: Male
Re: Going procedural with Perlin
Reply #7 - Jul 21st, 2017 at 3:51am
Print Post  
Bleeder91[NL] wrote on Jul 20th, 2017 at 8:44am:
I have it running on my server.


what's the IP? Shocked
  


don't bother trying to message me over AIM, I haven't used that in years lol
I have a Discord, the number thingie is #6413
Back to top
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint
Bookmarks: del.icio.us Digg Facebook Google Google+ Linked in reddit StumbleUpon Twitter Yahoo