Related
I'm trying to draw a Minecraft-like textured cube in WGPU. I have a vertex buffer and an index buffer. I'm using Repeat for adress_mode on the texture sampler. I use texture coordinates greater or smaller than 0 to repeat the dirt texture. The front, right and left faces render properly. However, the texture coordinates of the back and top faces are messed up. I didn't add the bottom face yet as I wanted to get these working first. The back texture gets drawn twice and inside out and the top one is completely messed up.
Here's the code:
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Vertex {
pub position: [f32; 3],
pub tex_coords: [f32; 2]
}
/// We arrange the vertices in counter-clockwise order: top, bottom left, bottom right.
pub const VERTICES: &[Vertex] = &[
// FRONT
Vertex {position: [-1.0, -1.0, 0.0], tex_coords: [0.0, 1.0]}, // 0
Vertex {position: [1.0, -1.0, 0.0], tex_coords: [1.0, 1.0]}, // 1
Vertex {position: [1.0, 1.0, 0.0], tex_coords: [1.0, 0.0]}, // 2
Vertex {position: [-1.0, 1.0, 0.0], tex_coords: [0.0, 0.0]}, // 3
// RIGHT
Vertex {position: [1.0, -1.0, -2.0], tex_coords: [2.0, 1.0]}, // 4
Vertex {position: [1.0, 1.0, -2.0], tex_coords: [2.0, 0.0]}, // 5
// LEFT
Vertex {position: [-1.0, -1.0, -2.0], tex_coords: [-1.0, 1.0]},
Vertex {position: [-1.0, 1.0, -2.0], tex_coords: [-1.0, 0.0]},
];
pub const INDICES: &[u16] = &[
// FRONT
0, 1, 2,
2, 3, 0,
// RIGHT
1, 4, 5,
5, 2, 1,
// LEFT
6, 0, 3,
3, 7, 6,
// BACK
6, 4, 5,
5, 7, 6,
// TOP
3, 2, 5,
5, 7, 3
];
My texture sampler:
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::Repeat,
address_mode_v: wgpu::AddressMode::Repeat,
address_mode_w: wgpu::AddressMode::Repeat,
mag_filter: wgpu::FilterMode::Nearest,
min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest,
..Default::default()
});
Look at the first triangle of your BACK face: it uses vertices 6, 4, and 5. In that order, those vertices are:
Vertex {position: [-1.0, -1.0, -2.0], tex_coords: [-1.0, 1.0]}, // 6
Vertex {position: [1.0, -1.0, -2.0], tex_coords: [2.0, 1.0]}, // 4
Vertex {position: [1.0, 1.0, -2.0], tex_coords: [2.0, 0.0]}, // 5
The u texture coordinates span a range from -1 to 2 horizontally. So, they span 3 copies of the repeating texture, and 3 copies will be drawn in the space of your cube face.
It seems that you're trying to share vertices between different cube faces, and wrap the texture around them continuously. But the problem is that, in texture space, there is always going to be a “seam” at one of the edges of your block where instead of repeating again you start over from a low number (-1 in your code) — it's the same kind of problem as texture mapping a sphere. So, at least one edge must have non-shared vertices.
However, in the long run, you will probably want to stop sharing any vertices between different cube faces. This is because in order to do lighting, vertices must (usually) include normal vectors, and normals are different for each face. As a general rule in computer graphics, vertices can be shared between triangles when they are representing a smoothly curved (or flat) surface, but at any sharp edge, like the edges and corners of a cube, you must make separate vertices for each face.
You can still share vertices between the two triangles that make up one cube face.
I have some 2D data with x and y coordinates both within [0,1], plotted using pcolormesh.
Now I want to symmetrize the plot to [-0.5, 0.5] for both x and y coordinates. In Matlab I was able to achieve this by changing x and y from e.g. [0, 0.2, 0.4, 0.6, 0.8] to [0, 0.2, 0.4, -0.4, -0.2], without rearranging the data. However, with pcolormesh I cannot get the desired result.
A minimum example is shown below, with data represented simply by x+y:
import matplotlib.pyplot as plt
import numpy as np
x,y = np.mgrid[0:1:5j,0:1:5j]
fig,(ax1,ax2,ax3) = plt.subplots(1,3,figsize=(9,3.3),constrained_layout=1)
# original plot spanning [0,1]
img1 = ax1.pcolormesh(x,y,x+y,shading='auto')
# shift x and y from [0,1] to [-0.5,0.5]
x = x*(x<0.5)+(x-1)*(x>0.5)
y = y*(y<0.5)+(y-1)*(y>0.5)
img2 = ax2.pcolormesh(x,y,x+y,shading='auto') # similar code works in Matlab
# for this specific case, the following is close to the desired result, I can just rename x and y tick labels
# to [-0.5,0.5], but in general data is not simply x+y
img3 = ax3.pcolormesh(x+y,shading='auto')
fig.colorbar(img1,ax=[ax1,ax2,ax3],orientation='horizontal')
The corresponding figure is below, any suggestion on what is missed would be appreciated!
Let's look at what you want to achieve in a 1D example.
You have x values between 0 and 1 and a dummy function f(x) = 20*x to produce some values.
# x = [0, .2, .4, .6, .8] -> [0, .2, .4, -.4, -.2] -> [-.4, .2, .0, .2, .4])
# fx = [0, 4, 8, 12, 16] -> [0, 4, 8, 12, 16] -> [ 12, 16, 0, 4, 8]
# ^ only flip and shift x not fx ^
You could use np.roll() to achieve the last operation.
I used n=14 to make the result better visible and show that this approach works for arbitrary n.
import numpy as np
import matplotlib.pyplot as plt
n = 14
x, y = np.meshgrid(np.linspace(0, 1, n, endpoint=False),
np.linspace(0, 1, n, endpoint=False))
z = x + y
x_sym = x*(x <= .5)+(x-1)*(x > .5)
# array([[ 0. , 0.2, 0.4, -0.4, -0.2], ...
x_sym = np.roll(x_sym, n//2, axis=(0, 1))
# array([[-0.4, -0.2, 0. , 0.2, 0.4], ...
y_sym = y*(y <= .5)+(y-1)*(y > .5)
y_sym = np.roll(y_sym, n//2, axis=(0, 1))
z_sym = np.roll(z, n//2, axis=(0, 1))
# array([[1.2, 1.4, 0.6, 0.8, 1. ],
# [1.4, 1.6, 0.8, 1. , 1.2],
# [0.6, 0.8, 0. , 0.2, 0.4],
# [0.8, 1. , 0.2, 0.4, 0.6],
# [1. , 1.2, 0.4, 0.6, 0.8]])
fig, (ax1, ax2) = plt.subplots(1, 2)
img1 = ax1.imshow(z, origin='lower', extent=(.0, 1., .0, 1.))
img2 = ax2.imshow(z_sym, origin='lower', extent=(-.5, .5, -.5, .5))
I want to create a while loop in python which will give an output as a list [0.00, 0.05, 0.10, 0.15,...., 1.00]
I tried doing it by following method:
alpha=0
alphalist=list()
while alpha<=1:
alphalist.append(alpha)
alpha+=0.05
print(alphalist)
I got the output as [0, 0.05, 0.1, 0.15000000000000002, 0.2, 0.25, 0.3, 0.35, 0.39999999999999997, 0.44999999999999996, 0.49999999999999994, 0.5499999999999999, 0.6, 0.65, 0.7000000000000001, 0.7500000000000001, 0.8000000000000002, 0.8500000000000002, 0.9000000000000002, 0.9500000000000003]
But What I want is this: [0.00, 0.05, 0.10, 0.15,...., 1.00]
This is the result of floating-point error. 0.05 isn't really the rational number 1/20 to begin with, so any arithmetic involving it may differ from what you expect.
Dividing two integers, rather than starting with a floating-point value, helps mitigate the problem.
>>> [x/100 for x in range(0, 101, 15)]
[0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0]
There are some numbers that can cause imprecisions with the floating number system computers use. You're just seeing an example of that.
What I would do, if you want to continue using the while loop this way, is to add another line with
alpha = round(alpha,2)
Using matplotlib, python3.6. I am trying to create some quiverkeys for a quiver plot but having a hard time getting the label colors to match certain arrows. Below is a simplified version of the code to show the issue. When I use the same color (0.3, 0.1, 0.2, 1.0 ) for a vector at (1,1) and as 'labelcolor' of a quiverkey I see 2 different colors.
q=plt.quiver([1, 2,], [1, 1],
[[49],[49]],
[0],
[[(0.6, 0.8, 0.5, 1.0 )],
[(0.3, 0.1, 0.2, 1.0 )]],
angles=[[45],[90]])
plt.quiverkey(q, .5, .5, 7, r'vector2', labelcolor=(0.3, 0.1, .2, 1),
labelpos='S', coordinates = 'figure')
Supposedly you meant to be using the color argument of quiver to set the actual colors.
import matplotlib.pyplot as plt
q=plt.quiver([1, 2,], [1, 1], [5,0], [5,5],
color=[(0.6, 0.8, 0.5, 1.0 ), (0.3, 0.1, 0.2, 1.0 )])
plt.quiverkey(q, .5, .5, 7, r'vector2', labelcolor=(0.3, 0.1, .2, 1),
labelpos='S', coordinates = 'figure')
plt.show()
Else, the C argument is interpreted as the values to map to colors according to the default colormap. Since you only have two arrows, only the first two values from the 8 numbers in the array given to the C argument are taken into account. But the colormap normalization uses all of those values, such that it ranges between 0.1 and 1.0. The call
q=plt.quiver([1, 2,], [1, 1], [5,0], [5,5],
[(0.6, 0.8, 0.5, 1.0 ), (0.3, 0.1, 0.2, 1.0 )])
is hence equivalent to
q=plt.quiver([1, 2,], [1, 1], [5,0], [5,5],
[0.6, 0.8], norm=plt.Normalize(vmin=0.1, vmax=1))
resulting in the first arrows color to be the value of 0.6 in the viridis colormap normalized between 0.1 and 1.0, and the second arrow to 0.8 in that colormap.
This becomes apparent if we add plt.colorbar(q, orientation="horizontal"):
I am trying to use a vtkLookupTable in order to set the colors for my mesh. I started with vtkColorTransferFunction which worked fined except that it does not enable me to set opacities for various colors.
vtkLookupTable offers this opportunity, but I am having problems to get it working.
My vtkPolyData have scalars value set that determine the color they shall get. Overall 7 values, set with the scalars 0 to 6.
My vtkLookupTable looks like this:
vtkLookupTable lut = new vtkLookupTable();
lut.SetNumberOfColors(7);
double opacity = 0.3;
lut.SetTableValue(0, 0, 0, 1, opacity);
lut.SetTableValue(1, 0, 1.0, 0, opacity);
lut.SetTableValue(2, 0.6, 1.0, 0.0, opacity);
lut.SetTableValue(3, 1.0, 1.0, 0.0, 0.7);
lut.SetTableValue(4, 1.0, 0.8, 0.0, opacity);
lut.SetTableValue(5, 1.0, 0.4, 0.0, opacity);
lut.SetTableValue(6, 1.0, 0.0, 0.0, 1);
If I use a vtkColorTransferFunction with the same values (just no opacity) it works. Anyone any idea why this is not working? I should be same?
Thanks for help.
From your pseudocode, two lines may be missing.
lut.SetTableRange(0.0,6.0)
lut.Build()
Do you call these functions?
If it is not this problem then it may be because of the polydatamapper you are using. Can you submit a whole pipeline for your problem?
As a guide the following code will need to be called to allow your scalar values to be
added to the mapper and visualised correctly.
mapper.SetLookupTable(lut)
mapper.SetScalarVisibility(1)
mapper.SetScalarRange(0.0,6.0)