Related
I made rotating cube using glium, but only one face is colored.
I am using Gouraud shading(from glium tutorial) for lighting.
The cube is made by defined 24 vertices and 6 normals.
Rotation is made by two matrices:
let m = [
[1.0, 0.0, 0.0, 0.0],
[0.0, t.cos(), -t.sin(), 0.0],
[0.0, t.sin(), t.cos(), 0.0],
[0.0, 0.0, 0.0, 1.0f32]
];
let n = [
[t.cos(), 0.0, t.sin(), 0.0],
[0.0, 1.0, 0.0, 0.0],
[-t.sin(), 0.0, t.cos(), 0.0],
[0.0, 0.0, 0.0, 1.0f32]
];
Fragment shader(glsl):
#version 150
in vec3 v_normal;
out vec4 color;
uniform vec3 u_light;
void main() {
float brightness = dot(normalize(v_normal), normalize(u_light));
vec3 dark_color = vec3(0.6, 0.0, 0.0);
vec3 regular_color = vec3(1.0, 0.0, 0.0);
color = vec4(mix(dark_color, regular_color, brightness), 1.0);
}
light:
let light = [-1.0, 0.4, 0.9f32];
The light should hit another face of cube in some point of rotation.
I try changing direction of light, that don't change anything.
Have anybody some idea?
for more info about the cube see this: my previous q. (some info like rotation is not actual here)
Images of the cube:
I think you have your normal direction in eye space and light direction in world space. So you have to convert light direction into camera (eye) space before passing into the shader, something like that (pseudo code):
normalize(VIEW_MATRIX * light)
Also, for the brightness I think you don't want to have negative value, so it have to be in a form
max(dot(N, L), 0.0)
I would recommend to read an introduction article about lighting, for example on learnOpenGL - https://learnopengl.com/Lighting/Basic-Lighting where you can see a description on what direction are for and how to prepare them.
or some GLSL tutorials about having light direction in camera space - https://www.lighthouse3d.com/tutorials/glsl-tutorial/directional-lights/
Is it possible to set the lower and/or upper parts of a colorbar based on ranges of values? For example, given the ROYGBIV colormap below and optionally an offset and a range value, I'd like to change the colors below offset and/or above range. In other words, suppose offset = 20 and range = 72, I'd like to color all the values less than or equal to 20 in black and all values greater than or equal to 72 in white. I'm aware of the methods set_under and set_over, but they require changing the parameters vmin and vmax (as far as I know), which is not what I want. I want to keep the original minimum and maximum values (e.g., vmin = 0 and vmax = 100), and only (optionally) change the colors of the extremities.
ROYGBIV = {
"blue": ((0.0, 1.0, 1.0),
(0.167, 1.0, 1.0),
(0.333, 1.0, 1.0),
(0.5, 0.0, 0.0),
(0.667, 0.0, 0.0),
(0.833, 0.0, 0.0),
(1.0, 0.0, 0.0)),
"green": ((0.0, 0.0, 0.0),
(0.167, 0.0, 0.0),
(0.333, 0.0, 0.0),
(0.5, 1.0, 1.0),
(0.667, 1.0, 1.0),
(0.833, 0.498, 0.498),
(1.0, 0.0, 0.0)),
"red": ((0.0, 0.5608, 0.5608),
(0.167, 0.4353, 0.4353),
(0.333, 0.0, 0.0),
(0.5, 0.0, 0.0),
(0.667, 1.0, 1.0),
(0.833, 1.0, 1.0),
(1.0, 1.0, 1.0))
}
rainbow_mod = matplotlib.colors.LinearSegmentedColormap("rainbow_mod", ROYGBIV, 256)
I found one way to do it using ListedColormap as explained here. The basic idea is to obtain the RGBA lists/tuples of the colors in the LinearSegmentedColormap object (numpy array) and replace the first or last few lists with replicates of the desired color.
It looks something like this:
under_color = [0.0, 0.0, 0.0, 1.0] # black (alpha = 1.0)
over_color = [1.0, 1.0, 1.0, 1.0] # white (alpha = 1.0)
all_colors = rainbow_mod(np.linspace(0, 1, 256))
vmin = 0.0
vmax = 100.0
all_colors[:int(np.round((20.0 - vmin) / (vmax - vmin) * 256)), :] = under_color
all_colors[int(np.round((72.0 - vmin) / (vmax - vmin) * 256)):, :] = over_color
rainbow_mod_list = matplotlib.colors.ListedColormap(all_colors.tolist())
I generate a bunch of 5-elements vectors with
def beam(n):
# For performance considerations, see
# https://software.intel.com/en-us/blogs/2016/06/15/faster-random-number-generation-in-intel-distribution-for-python
try:
import numpy.random_intel
generator = numpy.random_intel.multivariate_normal
except ModuleNotFoundError:
import numpy.random
generator = numpy.random.multivariate_normal
return generator(
[0.0,
0.0,
0.0,
0.0,
0.0
],
numpy.array([
[1.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 0.2]
]),
int(n)
)
This vector will be multiplied by 5x5 matrices (element wise) and checked for boundaries. I use this:
b = beam(1e5)
bound = 1000
s = (b[:, 0]**2 + b[:, 3]**2) < bound**2
#b[np.where(s)] (equivalent performances)
b[s] # <= returned value from a function
It seems that this operation with 100k elements is quite time consuming (3ms on my machine).
Would there be an obvious (or less obvious) way to perform this
operation (the where part, the random generation is there to give an example) ?
As your components are uncorrelated one obvious speedup would be to use the univariate normal instead of the multivariate:
>>> from timeit import repeat
>>> import numpy as np
>>>
>>> kwds = dict(globals=globals(), number=100)
>>>
>>> repeat('np.random.multivariate_normal(np.zeros((5,)), np.diag((1,1,1,1,0.2)), (100,))', **kwds)
[0.01475344318896532, 0.01471381587907672, 0.013099645031616092]
>>> repeat('np.random.normal((0,0,0,0,0), (1,1,1,1,np.sqrt(0.2)), (100, 5))', **kwds)
[0.003930734936147928, 0.004097769036889076, 0.004246715921908617]
Further, as it stands your condition is extremely unlikely to fail. So, just check s.all() and if True do nothing.
I cannot find out the mistake I made, could anyone help me? Thanks very much!
import math
def GASSEM():
a0 = [12,-2,1,0,0,0,0,0,0,0,13.97]
a1 = [-2,12,-2,1,0,0,0,0,0,0,5.93]
a2 = [1,-2,12,-2,1,0,0,0,0,0,-6.02]
a3 = [0,1,-2,12,-2,1,0,0,0,0,8.32]
a4 = [0,0,1,-2,12,-2,1,0,0,0,-23.75]
a5 = [0,0,0,1,-2,12,-2,1,0,0,28.45]
a6 = [0,0,0,0,1,-2,12,-2,1,0,-8.9]
a7 = [0,0,0,0,0,1,-2,12,-2,1,-10.5]
a8 = [0,0,0,0,0,0,1,-2,12,-2,10.34]
a9 = [0,0,0,0,0,0,0,1,-2,12,-38.74]
A = [a0,a1,a2,a3,a4,a5,a6,a7,a8,a9] # 10x11 matrix
interchange=[0,0,0,0,0,0,0,0,0,0,0]
for i in range (1,10):
median = abs(A[i-1][i-1])
for m in range (i,10): #pivoting
if abs(A[m][i-1]) > median:
median = abs(A[m][i-1])
interchange = A[i-1]
A[i-1] = A[m]
A[m] = interchange
for j in range(i,10): #creating upper triangle matrix
A[j] = [A[j][k]-(A[j][i-1]/A[i-1][i-1])*A[i-1][k] for k in range(0,11)]
for t in range (0,10): #print the upper triangle matrix
print(A[t])
The output is not an upper triangle matrix, I'm getting lost in the for loops...
When I run this code, the output is
[12, -2, 1, 0, 0, 0, 0, 0, 0, 0, 13.97]
[0.0, 11.666666666666666, -1.8333333333333333, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.258333333333333]
[0.0, 0.0, 11.628571428571428, -1.842857142857143, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -5.886428571428571]
[0.0, 0.0, -2.220446049250313e-16, 11.622235872235873, -1.8415233415233416, 1.0, 0.0, 0.0, 0.0, 0.0, 6.679281326781327]
[0.0, 0.0, -3.518258683818212e-17, 0.0, 11.622218698800275, -1.8415517150256329, 1.0, 0.0, 0.0, 0.0, -22.185475397706252]
[0.0, 0.0, 1.3530439218911067e-17, 0.0, 0.0, 11.62216239813737, -1.841549039580908, 1.0, 0.0, 0.0, 24.359991632712457]
[0.0, 0.0, 5.171101701700419e-18, 0.0, 0.0, 0.0, 11.622161705324444, -1.84154850220678, 1.0, 0.0, -3.131238144426707]
[0.0, 0.0, -3.448243038110395e-19, 0.0, 0.0, 0.0, 0.0, 11.62216144141611, -1.8415485389982904, 1.0, -13.0921440313208]
[0.0, 0.0, -4.995725026226573e-19, 0.0, 0.0, 0.0, 0.0, 0.0, 11.622161418001749, -1.8415485322346454, 8.534950160892514]
[0.0, 0.0, -4.9488445836100553e-20, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 11.622161417603511, -36.26114362292296]
This effectively is upper triangular. The absolute value of the 'non-zero' entries in the third column of the lower triangle are all less than 10e-15. Given that other values are 1 or greater, these small numbers look like floating point subtraction errors in A[j][k] - (A[j][i-1]/A[i-1][i-1])*A[i-1][k] that can be considered to be 0. Without more investigation, I don't know why the non-zero values are limited to this column.
For this data, the condition abs(A[m][i-1]) > median is never true, so the if block code is not tested.
This is part of code that's supposed to draw 2 cubes of side 0.3 next to each other
When I get instead is this: http://imageshack.us/photo/my-images/189/89254345.png/
(they are halfway into each other) I tried printing the transforms and they look alright:
1
1.0, 0.0, 0.0, 0.0
0.0, 1.0, 0.0, 0.0
0.0, 0.0, 1.0, 0.0
0.0, 0.0, 0.0, 1.0
2
1.0, 0.0, 0.0, 0.3
0.0, 1.0, 0.0, 0.0
0.0, 0.0, 1.0, 0.0
0.0, 0.0, 0.0, 1.0
It's as if the second box was only moved by 0.15 but if I multiply dx by 2 things break when more cuboids of different dimensions get added with transforms across the y or z axis
private BranchGroup rootGroup;
public void addBox(float dx){
Cuboid Cuboid1 = new Cuboid(0.3f ,0.3f, 0.3f, appearence);
TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();
Vector3f vector = new Vector3f(dx, 0f, 0f);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(Cuboid1);
rootGroup.addChild(tg);
}
public void addBoxes(){
for(int i=0;i<2;i++){
addBox(i*0.3f);
}
}
The cuboid class is from here: http://www.java2s.com/Code/Java/3D/Java3DBoxandacustomCuboidimplementation.htm
It looks like you're creating a cuboid which is 0.6 in size so it will have +0.3 and -0.3 X,Y,Z values for the first box as the center point of the cuboid is 0,0,0.
The second box is the same but offset by 0.3 in one axis which gives 0.3-0.3=0.0 and +0.3+0.3 = 0.6 values in one of the axes.
This will give two boxes that overlap half way on one axis which seems to match your picture.
Perhaps you mean to create a box with width/height/depth of 0.3/2 and translate it by 0.3/2 so that the center of the box is at 0.15,0.15 and use a scale factor of 0.15 instead of 0.3?