Skip to content

Commit

Permalink
refactored code a little. Plotted 3D derivative and checked it using …
Browse files Browse the repository at this point in the history
…FEM. Everything is now OK.
  • Loading branch information
jonathantompson committed Mar 14, 2015
1 parent 5809ac8 commit ba046c0
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Perlin3DDeriv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
// data[(m-1)+(n-1)*7+(p-1)*7*8] = 1;

for (size_t i = 0; i < npts; i++) {
vec4 s_and_deriv = Perlin3DDeriv(vec2(X[i], Y[i], Z[i]));
vec4 s_and_deriv = Perlin3DDeriv(vec3(X[i], Y[i], Z[i]));
out[i] = s_and_deriv.x;
dout[i*3] = s_and_deriv.y;
dout[i*3+1] = s_and_deriv.z;
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
**matlabnoise - Jonathan's Matlab noise library (C++ port of GPU-Noise-Lib)**
**matlabnoise - Matlab noise library**
---------
---------
![Image of Perlin Gradient Field](grad_field.jpg)

**Overview**
--------

This is just a mex wrapper around a C++ port of Brian Sharpe's GPU-Noise-Lib: https://github.com/BrianSharpe/GPU-Noise-Lib
This is just a mex wrapper around a C++ port of Brian Sharpe's GPU-Noise-Lib: https://github.com/BrianSharpe/GPU-Noise-Lib (Thanks Brian for putting together such an awesome GLSL library!).

Not everything from the above library has been ported and implemented. ```noise_common.cpp``` contains the GLSL port.
Not everything from the above library has been ported and implemented. ```noise_common.cpp``` contains the GLSL port.

Note that I did not attempt to optimize the code here in any way. In fact, because of the generous use of copy constructors I am relying quite heavily on the optimizing compiler here. Still, it's significantly faster than the same code in Matlab (even properly vectorized).
Note that I did not attempt to optimize the code here in any way. In fact, because of the generous use of copy constructors I am relying quite heavily on the optimizing compiler here. Still, it's significantly faster than the same code in Matlab (even when properly vectorized).

The following functions from Brian's work have been exposed:
- Perlin2D
Expand All @@ -19,7 +19,7 @@ The following functions from Brian's work have been exposed:
- Perlin2DDeriv
- Perlin3DDeriv

Clearly, I'm just using it as a fast Perlin noise implementation in Matlab. However, given that I have already written the vec2, vec3 and vec4 classes it will be quick work porting more functions from GPU-Noise_Lib.
Clearly, I'm just using it as a fast Perlin noise implementation in Matlab. However, given that I have already written the vec2, vec3 and vec4 classes it will be quick work porting more functions from GPU-Noise-Lib.

**Compilation**
---------------
Expand Down
2 changes: 1 addition & 1 deletion compile_mex.m
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mex -v -largeArrayDims -I.\ Perlin4D.cpp noise_common.cpp vec2.cpp vec3.cpp vec4.cpp
mex -v -largeArrayDims -I.\ Perlin3D.cpp noise_common.cpp vec2.cpp vec3.cpp vec4.cpp
mex -v -largeArrayDims -I.\ Perlin2D.cpp noise_common.cpp vec2.cpp vec3.cpp vec4.cpp
% mex -v -largeArrayDims -I.\ Perlin3DDeriv.cpp noise_common.cpp vec2.cpp vec3.cpp vec4.cpp
mex -v -largeArrayDims -I.\ Perlin3DDeriv.cpp noise_common.cpp vec2.cpp vec3.cpp vec4.cpp
mex -v -largeArrayDims -I.\ Perlin2DDeriv.cpp noise_common.cpp vec2.cpp vec3.cpp vec4.cpp


Expand Down
16 changes: 16 additions & 0 deletions plot_2D_scalar_and_grad.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
function [ ] = plot_2D_scalar_and_grad( A, gradA )

xdim = size(A, 2);
ydim = size(A, 1);

Ap = A - min(A(:));
Ap = Ap / max(Ap(:));
d = ceil(xdim / 15); % decimation ratio
imshow(repmat(Ap,1,1,3)); hold on;
[V, U] = ndgrid(1:ydim, 1:xdim); colormap default;
contour(U, V, Ap, 'LineWidth', 1.5);
[V, U] = ndgrid(1:d:ydim, 1:d:xdim);
quiver(U, V, squeeze(gradA(1,1:d:end,1:d:end)), squeeze(gradA(2,1:d:end,1:d:end)));

end

13 changes: 13 additions & 0 deletions plot_3D_scalar.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function [ ] = plot_3D_scalar( noise )

noise = noise - min(noise(:));
noise = noise / max(noise(:));
h = contourslice(noise, [], [], [1,10,20,30], 16);
set(h, 'LineWidth', 1.5);
view(3);
axis tight

grid on;

end

29 changes: 29 additions & 0 deletions plot_3D_scalar_and_grad.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
function [ ] = plot_3D_scalar_and_grad( noise, gradNoise )

xdim = size(noise, 3);
ydim = size(noise, 2);
zdim = size(noise, 1);

nslices = 4;
d = ceil(zdim / nslices);
slices = 1:d:zdim;

noise = noise - min(noise(:));
noise = noise / max(noise(:));
h = contourslice(noise, slices, [], [], 16);
set(h, 'LineWidth', 1.5);
view(3);
axis tight
grid on;
hold on;

d = ceil(xdim / 5); % decimation ratio
gradNoise = gradNoise(:, slices, 1:d:end, 1:d:end);
dX = squeeze(gradNoise(1,:,:,:));
dY = squeeze(gradNoise(2,:,:,:));
dZ = squeeze(gradNoise(3,:,:,:));
[D, V, U] = ndgrid(slices, 1:d:ydim, 1:d:xdim);
quiver3(D, V, U, dX, dY, dZ);

end

17 changes: 0 additions & 17 deletions plot_scalar_and_grad.m

This file was deleted.

76 changes: 55 additions & 21 deletions test_mex.m
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
clearvars; clc; close all;
% This script will just plot the scalar fields and check the derivatives
% using FEM (central differences).

ydim = 512;
xdim = 512;
xdim = 511;
frequency = 1;

% 2D Grid
Expand All @@ -17,18 +19,35 @@
title('Perlin2D');

% 2D Gradient
[noise, gradNoise] = Perlin2DDeriv(X, Y);
plot_scalar_and_grad(noise, gradNoise);
% title('Perlin2DDeriv');
[noise_deriv, gradNoise] = Perlin2DDeriv(X, Y);
figure;
plot_2D_scalar_and_grad(noise_deriv, gradNoise);
title('Perlin2DDeriv');

err = abs(noise_deriv - noise);
assert(max(err(:)) < 1e-6, ...
'scalar field from Perlin2DDeriv does not match Perlin2D!');

% addpath('C:\Users\IggyMenou\Documents\NYU\detection_nets\matlab\export_fig');
% export_fig('grad_field.jpg', gcf, '-jpg', '-a4');

% Check the gradient using finite differences (central)
epsilon = 1e-6;
[pos, posGrad] = Perlin2DDeriv(X + epsilon, Y);
[neg, negGrad] = Perlin2DDeriv(X - epsilon, Y);
dx = (pos - neg) / (2 * epsilon);
[pos, posGrad] = Perlin2DDeriv(X, Y + epsilon);
[neg, negGrad] = Perlin2DDeriv(X, Y - epsilon);
dy = (pos - neg) / (2 * epsilon);
gradNoiseFEM = permute(cat(3, dx, dy), [3 1 2]);
err = abs(gradNoiseFEM - gradNoise);
assert(max(err(:)) < 1e-8, 'FEM derivative does not match!');

% 3D Grid
xdim = 63;
ydim = 64;
xdim = 64;
zdim = 64;
[V, U, D] = ndgrid(1:ydim, 1:xdim, 1:zdim);
zdim = 65;
[D, V, U] = ndgrid(1:zdim, 1:ydim, 1:xdim);
X = 2 * (U - 1) ./ (xdim - 1) - 1; % [-1, 1]
Y = 2 * (V - 1) ./ (ydim - 1) - 1; % [-1, 1]
Z = 2 * (D - 1) ./ (zdim - 1) - 1; % [-1, 1]
Expand All @@ -37,14 +56,35 @@
Z = Z * frequency;
figure;
noise = Perlin3D(X, Y, Z);
noise = noise - min(noise(:));
noise = noise / max(noise(:));
h = contourslice(noise, [], [], [1,10,20,30], 16);
set(h, 'LineWidth', 1.5);
view(3);
axis tight
plot_3D_scalar(noise);
title('Perlin3D');
grid on;

% 3D Gradient
[noise_deriv, gradNoise] = Perlin3DDeriv(X, Y, Z);
err = abs(noise_deriv - noise);
assert(max(err(:)) < 1e-6, ...
'scalar field from Perlin3DDeriv does not match Perlin3D!');

figure;
plot_3D_scalar_and_grad(noise_deriv, gradNoise);
title('Perlin3DDeriv');
set(gcf,'Renderer','OpenGL')
title('Perlin3DDeriv');

% Check the gradient using finite differences (central)
epsilon = 1e-6;
[pos, posGrad] = Perlin3DDeriv(X + epsilon, Y, Z);
[neg, negGrad] = Perlin3DDeriv(X - epsilon, Y, Z);
dx = (pos - neg) / (2 * epsilon);
[pos, posGrad] = Perlin3DDeriv(X, Y + epsilon, Z);
[neg, negGrad] = Perlin3DDeriv(X, Y - epsilon, Z);
dy = (pos - neg) / (2 * epsilon);
[pos, posGrad] = Perlin3DDeriv(X, Y, Z + epsilon);
[neg, negGrad] = Perlin3DDeriv(X, Y, Z - epsilon);
dz = (pos - neg) / (2 * epsilon);
gradNoiseFEM = permute(cat(4, dx, dy, dz), [4 1 2 3]);
err = abs(gradNoiseFEM - gradNoise);
assert(max(err(:)) < 1e-8, 'FEM derivative does not match!');

% Now just do a time series of a 3D grid (because I can't visualize 4D
% noise :-) )
Expand All @@ -53,12 +93,6 @@
subplot(2,2,i);
W = ones(size(X,1), size(X,2), size(X,3)) * i;
noise = Perlin4D(X, Y, Z, W);
noise = noise - min(noise(:));
noise = noise / max(noise(:));
h = contourslice(noise, [], [], [1,10,20,30], 16);
set(h, 'LineWidth', 1.5);
view(3);
axis tight
plot_3D_scalar(noise);
title(['Perlin4D w=', num2str(i)]);
grid on;
end

0 comments on commit ba046c0

Please sign in to comment.