Related
so i tried to implement perlin noise in c++ and render it in raylib. well, i failed to implement it correctly and get crazy results.
]
After printing several variables i detected that perlinNoise function returns bigger values than [-1; 1] interval. can anyone tell me why it is doing that? maybe i dont calculate gradient vectors correctly? because as i see values are not repeating.
#include <math.h>
#include <iostream>
#include <vector>
#include "raylib.h"
using namespace std;
int p[] = {
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7,
225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190,
6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117,
35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136,
171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158,
231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46,
245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209,
76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86,
164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5,
202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16,
58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44,
154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253,
19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97,
228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51,
145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184,
84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156,
180, 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233,
7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203,
117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125,
136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146,
158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55,
46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73,
209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159,
86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47,
16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2,
44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39,
253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246,
97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205,
93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61,
156, 180};
float fade(float t) { return t * t * t * (t * (6 * t - 15) + 10); }
float lerp(float a0, float a1, float t) { return a0 + t * (a1 - a0); }
float dotp(Vector2 a, Vector2 b) { return a.x * b.x + a.y * b.y; }
Vector2 grad(int a) {
Vector2 v[8] = {
{sqrt(3) / 2.0, 0.5f}, {-sqrt(3) / 2.0, 0.5f},
{-sqrt(3) / 2.0, -0.5f}, {sqrt(3) / 2.0, -0.5f},
{sqrt(2) / 2, sqrt(2) / 2}, {-sqrt(2) / 2, sqrt(2) / 2},
{-sqrt(2) / 2, -sqrt(2) / 2}, {sqrt(2) / 2, -sqrt(2) / 2},
};
return v[a % 8];
}
float perlinNoise(float x, float y) {
// 1 - Topleft, 2 - topright, 3 - bottom left, 4 - bottom right
int xInd = (int)floor(x) % 256;
int yInd = (int)floor(y) % 256;
x -= floor(x);
y -= floor(y);
Vector2 DirectionTopRight = {x - 1.0, y};
Vector2 DirectionTopLeft = {x, y};
Vector2 DirectionBottomRight = {x - 1.0, y - 1.0};
Vector2 DirectionBottomLeft = {x, y - 1.0};
Vector2 GradientTopRight = grad(p[p[xInd + 1] + yInd]);
Vector2 GradientTopLeft = grad(p[p[xInd] + yInd]);
Vector2 GradientBottomRight = grad(p[p[xInd + 1] + yInd + 1]);
Vector2 GradientBottomLeft = grad(p[p[xInd] + yInd + 1]);
float dotTopRight = dotp(DirectionTopRight, GradientTopRight);
float dotTopLeft = dotp(DirectionTopLeft, GradientTopLeft);
float dotBottomRight = dotp(DirectionBottomRight, GradientBottomRight);
float dotBottomLeft = dotp(DirectionBottomLeft, GradientBottomLeft);
// Fade Values
float u = fade(x);
float v = fade(y);
/*if (fabs(u - 0.5f) > 0.5f || fabs(v - 0.5f) > 0.5f) {
std::cout << u << "\t" << v << "\n";
}*/
return lerp(lerp(dotTopRight, dotTopLeft, u),
lerp(dotBottomLeft, dotBottomRight, u), v);
}
int main(void) {
const int screenWidth = 512;
const int screenHeight = 512;
InitWindow(screenWidth, screenHeight, "perlins go brrrrrrrrrrrrr");
SetTargetFPS(60);
while (!WindowShouldClose()) {
BeginDrawing();
ClearBackground(BLACK);
for (float y = 0; y < 512; y++) {
for (float x = 0; x < 512; x++) {
float n = perlinNoise(x / 256, y / 256);
// if (n < 0 || n > 255) std::cout << n << "\n";
n += 1;
n /= 2;
int c = round(n * 255);
Color col{c, c, c, (unsigned char)255};
DrawPixel(x, y, col);
}
}
EndDrawing();
}
CloseWindow();
return 0;
}
Update: i was not using normalized vectors. but still get same but better results; (i updated code)
As i see values are not repeating on the same points!
Update 2: Well i had some typo in my code about returning part and i fixed it but now grids are not "connected" to each other. (updated code)
After the initial fixes, there's just one last step to make. You got the corners order mixed up - for bilinear interpolation, we are first interpolating along one axis, then along another, and the vertices have to come in proper order every time.
return lerp(lerp(dotTopLeft, dotTopRight, u),
lerp(dotBottomLeft, dotBottomRight, u), v);
(I debugged this after rewriting it in Python, so it is possible that I have missed something else, but hopefully not... Feel free to ask questions if it is not working). The result I've got:
As a side note, the reason you pass values over 1 to the Perlin noise generator is to generate higher octaves. You are using the 2nd octave in your code, passing x / 64, y / 64 yields the 4th octave which looks like this:
Superimposing them allows for generation of more complex patterns. The reason I mention this is that calling the noise generator like perlinNoise(x/256, y/256) while iterating up to 511 conceals this purpose a little bit - a more idiomatic way would be
perlinNoise(x / w * octave, y / h * octave)
That way, you are clearly iterating over pixels of your target window, using fractional coordinates for noise generation and using the scale for the desired level of detail explicitly. A common use case adds several scales of noise, but dampens higher frequency ones so that the resulting surface looks somewhat realistic.
You can even use different scales for x and y! It can look pretty creative, too:
list1 = [185, 184, 183, 182, 181, 180, 179, 178, 207, 177, 176, 206, 175, 174, 173, 172, 171, 170, 169, 205, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 204, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 203, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 202, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 201, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 200, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 199, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 198, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 197, 11, 196, 10, 9, 8]
delim = [182, 175, 164, 151, 138, 125, 112, 99, 86, 73, 60, 47, 34, 21, 11]
How can I split the list, with the delim list and still keep the delim values?
the result I'm looking for is
newList = [ [185,184, 183], [182, 181, 180, 179, 178, 207, 177, 176, 206], [175, 174 .......
I have to use Python 2.7, because the "Main" application I'm automating for is still using 2.7 for its scripting language
I'm not sure how to get a loop to change what item it uses in the 'delim' list when it 'hits' the previous item in the 'delim' list
edit: OK I'm getting close.... just have to solve a IndexError
newList, currList, currDelimIndex = [], [], 0
for i in list1:
if i == delim[currDelimIndex]:
newList.append(currList)
currDelimIndex += 1
currList = [i]
else:
currList.append(i)
Thanks!
Here is what I came up with, if anyone has a better solution, feel free to share
list1 = [185, 184, 183, 182, 181, 180, 179, 178, 207, 177, 176, 206, 175, 174, 173, 172, 171, 170, 169, 205, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 204, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 203, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 202, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 201, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 200, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 199, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 198, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 197, 11, 196, 10, 9, 8]
delim = [182, 175, 164, 151, 138, 125, 112, 99, 86, 73, 60, 47, 34, 21, 11]
newList, currList, currDelimIndex = [], [], 0
for edge in list1:
if edge == delim [currDelimIndex]:
newList.append(currList)
if currDelimIndex < len(delim) - 1:
currDelimIndex += 1
currList = [edge]
else:
currList.append(edge)
newList.append(currList) # append the last group
I'm going to have trouble verbalizing this, so I'll just include some code and describe what I need to do afterward instead:
import pandas as pd
start = [1, 5, 102, 300]
end = [3, 90, 150, 304]
df1 = pd.DataFrame({'start':start, 'end':end})
df2 = pd.DataFrame([0, 3, 10, 14, 100, 101, 102, 113, 300])
df2.columns=["bp_pos"]
So, for every start-end pair, I need to check if any of my values in df2 fall within that range. If they do, I need to exclude that index from df2.
I have this working. The problem is that my I have 22 df1s, and each one is a few million rows, and my df2 is also a few million rows. This gets really slow with my solution, which looks something like:
for idx, row in df1.iterrows():
df2 = df2.loc[~((row['start'] <= df2['bp_pos']) &
(row['end'] >= df2['bp_pos']))]
I'm hoping to get a faster solution than what I have above. Are there faster solutions you can think of? I'm using Python 2.7.12, and Pandas/NumPy solutions accepted. (Sorry if the code above doesn't actually work- I don't have Python on the PC I'm posting from)
I would get an array of your values that you want to exclude, then use normal pandas indexing:
vals = np.concatenate([np.arange(x,y) for x,y in zip(start,end)])
df2[~df2['bp_pos'].isin(vals)]
bp_pos
0 0
1 3
4 100
5 101
Just as further explanation: vals ends up being an array of all your ranges:
>>> vals
array([ 1, 2, 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, 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, 300, 301, 302, 303])
I have been using _list = np.unique(np.stack(np.meshgrid(*_load), -1).reshape(-1, len(_load)), axis=0) to generate a list of all possible combinations, which worked fine on list of list that look like,
[[1, 2, 3], [8, 4, 5, 6, 7], [8, 4, 5, 6, 7], [8, 4, 5, 6, 7], [8, 4, 5, 6, 7], [9, 10, 11, 12, 13, 14], [9, 10, 11, 12, 13, 14], [9, 10, 11, 12, 13, 14], [9, 10, 11, 12, 13, 14], [9, 10, 11, 12, 13, 14]]
Howeveer, if I want to find all possibles on something like
[[3, 4, 69, 134, 39, 42, 46, 15, 99, 20, 120, 123, 93], [130, 5, 7, 139, 14, 143, 33, 48, 50, 51, 52, 53, 55, 58, 60, 62, 67, 84, 85, 87, 91, 105, 106, 107, 111, 121, 127], [130, 5, 7, 139, 14, 143, 33, 48, 50, 51, 52, 53, 55, 58, 60, 62, 67, 84, 85, 87, 91, 105, 106, 107, 111, 121, 127], [1, 132, 133, 135, 138, 11, 12, 142, 16, 147, 24, 25, 27, 28, 29, 30, 31, 35, 36, 40, 47, 54, 57, 63, 66, 68, 70, 71, 72, 140, 76, 81, 83, 88, 90, 92, 144, 98, 100, 103, 109, 110, 112, 114, 118, 122], [1, 132, 133, 135, 138, 11, 12, 142, 16, 147, 24, 25, 27, 28, 29, 30, 31, 35, 36, 40, 47, 54, 57, 63, 66, 68, 70, 71, 72, 140, 76, 81, 83, 88, 90, 92, 144, 98, 100, 103, 109, 110, 112, 114, 118, 122], [128, 129, 2, 131, 6, 8, 9, 10, 13, 141, 17, 18, 19, 21, 22, 23, 26, 32, 34, 37, 38, 41, 43, 44, 45, 49, 137, 56, 59, 61, 64, 65, 73, 74, 75, 77, 78, 79, 80, 82, 86, 89, 94, 95, 96, 97, 101, 102, 145, 104, 108, 146, 113, 115, 116, 117, 119, 136, 124, 125, 126], [128, 129, 2, 131, 6, 8, 9, 10, 13, 141, 17, 18, 19, 21, 22, 23, 26, 32, 34, 37, 38, 41, 43, 44, 45, 49, 137, 56, 59, 61, 64, 65, 73, 74, 75, 77, 78, 79, 80, 82, 86, 89, 94, 95, 96, 97, 101, 102, 145, 104, 108, 146, 113, 115, 116, 117, 119, 136, 124, 125, 126], [128, 129, 2, 131, 6, 8, 9, 10, 13, 141, 17, 18, 19, 21, 22, 23, 26, 32, 34, 37, 38, 41, 43, 44, 45, 49, 137, 56, 59, 61, 64, 65, 73, 74, 75, 77, 78, 79, 80, 82, 86, 89, 94, 95, 96, 97, 101, 102, 145, 104, 108, 146, 113, 115, 116, 117, 119, 136, 124, 125, 126], [128, 129, 2, 131, 6, 8, 9, 10, 13, 141, 17, 18, 19, 21, 22, 23, 26, 32, 34, 37, 38, 41, 43, 44, 45, 49, 137, 56, 59, 61, 64, 65, 73, 74, 75, 77, 78, 79, 80, 82, 86, 89, 94, 95, 96, 97, 101, 102, 145, 104, 108, 146, 113, 115, 116, 117, 119, 136, 124, 125, 126]]
I get a MemoryError in python, obviously I need to change my approach, any ideas? I was thinking I would need to end up writing the intermittent events to file, but I don't know how to get these built ins to do that.
Your algorithm is fine, but your result is unrepresentable.
Note in particular that your np.unique is useless, because each load[i] contains no duplicates, so the size of the result is the product of the lengths of the lists times the number of lists
>>> np.prod([len(i) for i in second_example], dtype=np.int64) * 9
2498897217529908
Assuming optimistically that each integer is a uint8, that's 2.2 PiB (Pebibytes), which far exceeds current RAM configurations.
Even if you don't try to put the whole result in memory at once, even iterating over this is going to take a long time - assuming a generous 4GHz processor and a single clock cycle per result, you're looking at longer than a week to finish
I'm attempting to have the y list comprehension skip x if x =0 but the y list comprehension isn't producing the results I want.
x = [i for i in range(101)]
y = [i**2 for i in x if x>0]
So the output should be something like this:
x = [0, 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]
>>> y
[ 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801, 10000]
However, I'm still getting a 0 in the y list.
Thanks.
x = [i for i in range(101)]
y = [i**2 for i in x if i>0]
Note i > 0. You can think of the part that comes right after the "for" as the members of the set you are interested in, and the part after "in" as the set you are selecting from.