Code: running example
#include <iostream>
#include <cooperative_groups.h>
namespace cg = cooperative_groups;
__global__ void transpose_block(float* mat, size_t sx, size_t sy)
{
constexpr size_t size = 8;
auto tile = cg::tiled_partition<size>(cg::this_thread_block());
auto ix = tile.thread_rank();
float col[size];
for (size_t iy = 0; iy < size; ++iy)
col[iy] = mat[ix + iy * sx];
auto val = [&tile, &col](int ix, int iy) { return tile.shfl(col[iy], ix); };
for (size_t iy = 0; iy < size; ++iy)
mat[ix + iy * sx] = val(iy, ix);
}
void print_mat(float* mat, size_t sx, size_t sy)
{
printf("{\n");
for (size_t iy = 0; iy < sy; ++iy)
{
printf("\t{ ");
for (size_t ix = 0; ix < sx; ++ix)
printf("%6.1f, ", mat[ix + iy * sx]);
printf("},\n");
}
printf("}\n");
}
int main()
{
constexpr size_t sx = 8;
constexpr size_t sy = 8;
float* mat;
cudaMallocManaged(&mat, sx * sy * sizeof(float));
for (size_t iy = 0; iy < sy; ++iy)
for (size_t ix = 0; ix < sx; ++ix)
mat[ix + sx * iy] = ix + sx * iy;
print_mat(mat, sx, sy);
transpose_block<<<1, 8>>>(mat, sx, sy);
cudaDeviceSynchronize();
print_mat(mat, sx, sy);
cudaFree(mat);
}
I'm trying to transpose an 8x8 block by saving the columns locally for each of the 8 threads and then writing a lambda that would essentially give me access to the entire block using warp shuffle:
// tile = the cooperative group that holds all 8 threads
// col = local vector that holds all 8 column values of column[tile.thread_rank()]
auto val = [&tile, &col](int ix, int iy) { return tile.shfl(col[iy], ix); };
This doesn't work and I just cannot find the reason why.
When I run your code I get output like this:
{
{ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, },
{ 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, },
{ 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, },
{ 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, },
{ 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, },
{ 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, },
{ 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, },
{ 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, },
}
{
{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, },
{ 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, },
{ 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, },
{ 27.0, 27.0, 27.0, 27.0, 27.0, 27.0, 27.0, 27.0, },
{ 36.0, 36.0, 36.0, 36.0, 36.0, 36.0, 36.0, 36.0, },
{ 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, },
{ 54.0, 54.0, 54.0, 54.0, 54.0, 54.0, 54.0, 54.0, },
{ 63.0, 63.0, 63.0, 63.0, 63.0, 63.0, 63.0, 63.0, },
}
Let's start by making sure you understand how a shuffle op works so that we can at least explain that output. Your shuffle op exchanges data like this:
tile.shfl(col[iy], ix)
^ ^
| The lane that I go to to get the value I will return.
The value I publish to other lanes.
So when you do that shuffle op in the for-loop:
for (size_t iy = 0; iy < size; ++iy)
mat[ix + iy * sx] = val(iy, ix);
Let's first note that although the order of parameters in your lambda definition is (ix, iy) you are passing val(iy, ix). Confusing! Maybe you like programming that way. I find it confusing.
Anyway, what we observe is that the first index (you are passing iy) will be used to select the lane to copy the value from. Therefore all 8 lanes will target the same source lane on each iteration of the for loop. This explains why the values are constant in the output across a row. The second index (you are passing ix) will be used to select the column entry to publish to other lanes. Since ix is zero for thread 0, 1 for thread 1, etc., and also loop-invariant, we observe that thread 0 always publishes its col[0], thread 1 always publishes its col[1], and so on. This explains the pattern as we look down a column in the output.
You might think at this point that it was a mistake to pass iy for ix and ix for iy, but if we reverse the order of values that we pass, then the output matrix simply duplicates the input matrix (exercise left to the reader.)
We're going to have to be more inventive than that. If we are going to keep the loop variable iy unmodified, on the first pass of the for loop, we would like thread 0 to keep its value in col[0], we would like thread 1 to retrieve its value from col[1] of thread 0, and we would like thread 2 to get the value of col[2] of thread 0, and so on. On the first pass of the for-loop, we would like the entire column from thread 0 to be passed to the other threads. But this is impossible with a shuffle - we can only publish one value (per thread) at a time.
Therefore we reach the conclusion that the naive approach of processing the matrix row-by-row will not work. We must be more inventive than that. After some headscratching, you may realize that a suitable pattern can be obtained using an xor operation on the thread index. Effectively, the xor indexing pattern creates a set of swaps or exchanges around the main diagonal. Rather than try and describe it in great detail, I refer you here (and here). The original posting there in the "suggested solution" block shows the xor pattern, and how it is used to specify both the column value to publish, as well as the source lane, for each thread's shuffle op.
If we apply that concept to your code, we could come up with this modification to your kernel:
$ cat t2170.cu
#include <iostream>
#include <cooperative_groups.h>
namespace cg = cooperative_groups;
__global__ void transpose_block(float* mat, size_t sx, size_t sy)
{
constexpr size_t size = 8;
auto tile = cg::tiled_partition<size>(cg::this_thread_block());
auto ix = tile.thread_rank();
float col[size];
for (size_t iy = 0; iy < size; ++iy)
col[iy] = mat[ix + iy * sx];
auto val = [&tile, &col](int ix, int iy) { return tile.shfl(col[iy], ix); };
for (size_t idx = 1; idx < size; ++idx){
size_t iy = threadIdx.x^idx;
mat[ix + iy * sx] = val(iy, iy);}
}
void print_mat(float* mat, size_t sx, size_t sy)
{
printf("{\n");
for (size_t iy = 0; iy < sy; ++iy)
{
printf("\t{ ");
for (size_t ix = 0; ix < sx; ++ix)
printf("%6.1f, ", mat[ix + iy * sx]);
printf("},\n");
}
printf("}\n");
}
int main()
{
constexpr size_t sx = 8;
constexpr size_t sy = 8;
float* mat;
cudaMallocManaged(&mat, sx * sy * sizeof(float));
for (size_t iy = 0; iy < sy; ++iy)
for (size_t ix = 0; ix < sx; ++ix)
mat[ix + sx * iy] = ix + sx * iy;
print_mat(mat, sx, sy);
transpose_block<<<1, 8>>>(mat, sx, sy);
cudaDeviceSynchronize();
print_mat(mat, sx, sy);
cudaFree(mat);
}
$ nvcc -arch=sm_70 -o t2170 t2170.cu
$ compute-sanitizer ./t2170
========= COMPUTE-SANITIZER
{
{ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, },
{ 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, },
{ 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, },
{ 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, },
{ 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, },
{ 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, },
{ 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, },
{ 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, },
}
{
{ 0.0, 8.0, 16.0, 24.0, 32.0, 40.0, 48.0, 56.0, },
{ 1.0, 9.0, 17.0, 25.0, 33.0, 41.0, 49.0, 57.0, },
{ 2.0, 10.0, 18.0, 26.0, 34.0, 42.0, 50.0, 58.0, },
{ 3.0, 11.0, 19.0, 27.0, 35.0, 43.0, 51.0, 59.0, },
{ 4.0, 12.0, 20.0, 28.0, 36.0, 44.0, 52.0, 60.0, },
{ 5.0, 13.0, 21.0, 29.0, 37.0, 45.0, 53.0, 61.0, },
{ 6.0, 14.0, 22.0, 30.0, 38.0, 46.0, 54.0, 62.0, },
{ 7.0, 15.0, 23.0, 31.0, 39.0, 47.0, 55.0, 63.0, },
}
========= ERROR SUMMARY: 0 errors
$
Related
I'm using ResponsiveReactGridLayout and I want to change it's cols programatically.
When I upload an image, I want my ResponsiveReactGridLayout'cols is changed base on the image size.
I tried below and got error:
Unhandled Runtime Error
Error: ResponsiveReactGridLayout: cols entry for breakpoint lg is missing!
Is there other way to do that. Thank you for your helping guys
constructor(props) {
super(props);
this.state = {
cols: { lg: 12, md: 12, sm: 12, xs: 12, xxs: 12 },
rowHeight: 100,
// rows: 3,
// cols: 12,
items: _.range(0, 36).map(function (i, key, list) {
return {
i: i.toString(),
x: i % 12,
y: Math.floor(i / 12),
w: 1,
h: 1,
initCell: true,
draggable: false,
static: true,
isBounded: true,
};
}),
newCounter: 0,
dimensions: { height: 0, width: 0 },
};
this.onImgLoad = this.onImgLoad.bind(this);
this.onAddItem = this.onAddItem.bind(this);
this.onBreakpointChange = this.onBreakpointChange.bind(this);
}
onImgLoad({ target: img }) {
let numCols = Math.round(img.offsetWidth / 100);
let numRows = Math.round(img.offsetHeight / 100);
console.log(numCols + ' ' + numRows);
this.setState({
cols: { lg: numCols, md: numCols, sm: numCols, xs: numCols, xxs: numCols },
rowHeight: 100,
items:_.range(0, numCols * numRows).map(function (i, key, list) {
return {
i: i.toString(),
x: i % numCols,
y: Math.floor(i / numCols),
w: 1,
h: 1,
initCell: true,
draggable: false,
static: true,
isBounded: true,
};
}),
cols: { lg: numCols, md: numCols, sm: numCols, xs: numCols, xxs: numCols },
dimensions: { height: img.offsetHeight, width: img.offsetWidth },
newCounter: 0,
});
console.log(img.offsetHeight + " " + img.offsetWidth);
}
<img onLoad={this.onImgLoad} src={src} />
<ResponsiveReactGridLayout
{...this.props}
onLayoutChange={this.onLayoutChange}
onBreakpointChange={this.onBreakpointChange}
onDrop={this.onDrop}
measureBeforeMount={false}
useCSSTransforms={this.state.mounted}
cols={this.state.cols}
// rowHeight={this.state.rowHeight}
compactType={null}
isResizable={false}
// preventCollision={true}
allowOverlap={true}
isDroppable={true}
isBounded={true}
margin={[0, 0]}
style={{
backgroundImage: "url(" + src + ")",
backgroundPosition: "center",
backgroundSize: "100% 100%",
backgroundRepeat: "no-repeat",
}}>
</ResponsiveReactGridLayout>
Click this link to see error
Error Image
I'm creating a simple code to read minecraft json and generate on the screen, cube textures work without problems, but textures like the torch are bad, the idea is to be able to read any minecraft json and reproduce it on the screen, I tried to map, but I could not.
Every image becomes a face of the cube I wish I could shape it to be the size of the read texture.
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace OpenGLTestes
{
public partial class Form1 : Form
{
int downX, downY;
float xangle, yangle, fov;
int texTop;
int texBottom;
int texSideFront;
int texSideBack;
int texSideLeft;
int texSideRight;
string AppPath = Application.StartupPath + "\\Images\\";
System.Drawing.Imaging.PixelFormat ForBitmapData = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
OpenTK.Graphics.OpenGL.PixelFormat ForTextImage2D = OpenTK.Graphics.OpenGL.PixelFormat.Bgr;
private int UploadTexture(string pathname)
{
// Create a new OpenGL texture object
int id = GL.GenTexture();
// Select the new texture
GL.BindTexture(TextureTarget.Texture2D, id);
//Verificando o tipo de Imagem
if (pathname.Substring(pathname.Length - 3, 3).ToUpper() == "PNG")
{
ForBitmapData = System.Drawing.Imaging.PixelFormat.Format32bppArgb;
ForTextImage2D = OpenTK.Graphics.OpenGL.PixelFormat.Bgra;
}
else
{
ForBitmapData = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
ForTextImage2D = OpenTK.Graphics.OpenGL.PixelFormat.Bgr;
}
// Load the image
Bitmap bmp = new Bitmap(pathname);
// Lock image data to allow direct access
System.Drawing.Imaging.BitmapData bmp_data = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
ForBitmapData);
// Import the image data into the OpenGL texture
GL.TexImage2D(TextureTarget.Texture2D,
0,
PixelInternalFormat.Rgba,
bmp_data.Width,
bmp_data.Height,
0,
ForTextImage2D,
OpenTK.Graphics.OpenGL.PixelType.UnsignedByte,
bmp_data.Scan0);
// Unlock the image data
bmp.UnlockBits(bmp_data);
// Configure minification and magnification filters
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS , (int)TextureMagFilter.Nearest);
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureMagFilter.Nearest);
// Return the OpenGL object ID for use
return id;
}
public Form1()
{
InitializeComponent();
}
private void glControl_Load(object sender, EventArgs e)
{
GL.ClearColor(Color.Blue);
//xangle = 45;
//yangle = 25;
//Lighting
GL.Enable(EnableCap.Lighting);
//GL.Enable(EnableCap.ColorMaterial); //para o Light não afetar a cor do material
//Definindo a Light0
float[] Light_Position = {10,10,20};
GL.Light(LightName.Light0, LightParameter.Position, Light_Position);
float[] Light_Difuse = { 1.0f, 1.0f, 1.0f }; //color light
GL.Light(LightName.Light0, LightParameter.Diffuse, Light_Difuse);
float[] Light_Ambient = { 10.0f, 10.0f, 10.0f };//color light Ambiente
GL.Light(LightName.Light0, LightParameter.Ambient, Light_Ambient);
GL.Enable(EnableCap.Light0);
//Texturing
GL.Enable(EnableCap.Texture2D);
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); //Mapea a mesma imagem de varios tamanhos
texTop = UploadTexture(AppPath + "torch.png");
texBottom = UploadTexture(AppPath + "torch.png");
texSideBack = UploadTexture(AppPath + "torch.png");
texSideFront = UploadTexture(AppPath + "torch.png");
texSideLeft = UploadTexture(AppPath + "torch.png");
texSideRight = UploadTexture(AppPath + "torch.png");
//GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
}
private void glControl_Paint(object sender, PaintEventArgs e)
{
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.Clear(ClearBufferMask.DepthBufferBit);
Matrix4 perspetiva = Matrix4.CreatePerspectiveFieldOfView(1.0f, 4 / 3, 1, 10000); //Setup Perspective
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity(); // load the identity matrix
GL.LoadMatrix(ref perspetiva);
Matrix4 camera = Matrix4.LookAt(200, 50, 0, 0, 0, 0, 0, 1, 0); //Setup camera
GL.MatrixMode(MatrixMode.Modelview); //Load Camera
GL.LoadIdentity();
GL.LoadMatrix(ref camera);
GL.Viewport(0, 0, glControl.Width, glControl.Height); //Size of window
GL.Enable(EnableCap.DepthTest); //Enable correct Z Drawings
GL.DepthFunc(DepthFunction.Less) ; //Enable correct Z Drawings
GL.Rotate((yangle * -1), 0, 0, 1);
GL.Rotate(xangle, 0, 1, 0);
int Tam = 45;
//Front
GL.BindTexture(TextureTarget.Texture2D, texSideFront);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.White);
GL.Normal3(1.0, 0.0, 0.0);
GL.TexCoord2(1, 1);
GL.Vertex3(Tam, -Tam, Tam);
GL.TexCoord2(0, 1);
GL.Vertex3(Tam, -Tam, -Tam);
GL.TexCoord2(0, 0);
GL.Vertex3(Tam, Tam, -Tam);
GL.TexCoord2(1, 0);
GL.Vertex3(Tam, Tam, Tam);
GL.End();
//Back
GL.BindTexture(TextureTarget.Texture2D, texSideBack);
GL.Begin(PrimitiveType.Quads);
GL.Color4(Color.Cyan);
GL.Normal3(-1.0, 0.0, -1.0);
GL.TexCoord2(1, 1);
GL.Vertex3(-Tam, -Tam, Tam);
GL.TexCoord2(0, 1);
GL.Vertex3(-Tam, -Tam, -Tam);
GL.TexCoord2(0, 0);
GL.Vertex3(-Tam, Tam, -Tam);
GL.TexCoord2(1, 0);
GL.Vertex3(-Tam, Tam, Tam);
GL.End();
//Right
GL.BindTexture(TextureTarget.Texture2D, texSideRight);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Yellow);
GL.Normal3(0.0, 0.0, -1.0);
GL.TexCoord2(1, 1);
GL.Vertex3(-Tam, -Tam, -Tam);
GL.TexCoord2(0, 1);
GL.Vertex3(Tam, -Tam, -Tam);
GL.TexCoord2(0, 0);
GL.Vertex3(Tam, Tam, -Tam);
GL.TexCoord2(1,0);
GL.Vertex3(-Tam, Tam, -Tam);
GL.End();
//Top
GL.BindTexture(TextureTarget.Texture2D, texTop);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Normal3(0.0, 1.0, 0.0);
GL.TexCoord2(0, 0);
GL.Vertex3( Tam, Tam, Tam);
GL.TexCoord2(1, 0);
GL.Vertex3( Tam, Tam,-Tam);
GL.TexCoord2(1, 1);
GL.Vertex3(-Tam, Tam,-Tam);
GL.TexCoord2(0, 1);
GL.Vertex3(-Tam, Tam, Tam);
GL.End();
//Botton
GL.BindTexture(TextureTarget.Texture2D, texBottom);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Blue);
GL.Normal3(0.0, -1.0, 0.0);
GL.TexCoord2(1, 1);
GL.Vertex3( Tam,-Tam, Tam);
GL.TexCoord2(1, 0);
GL.Vertex3( Tam,-Tam,-Tam);
GL.TexCoord2(0, 0);
GL.Vertex3(-Tam,-Tam,-Tam);
GL.TexCoord2(0, 1);
GL.Vertex3(-Tam,-Tam, Tam);
GL.End();
//Right
GL.BindTexture(TextureTarget.Texture2D, texSideRight);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.White);
GL.Normal3(0.0, 0.0, 1.0);
GL.TexCoord2(1, 1);
GL.Vertex3(-Tam, -Tam, Tam);
GL.TexCoord2(0, 1);
GL.Vertex3(Tam, -Tam, Tam);
GL.TexCoord2(0,0);
GL.Vertex3(Tam, Tam, Tam);
GL.TexCoord2(1, 0);
GL.Vertex3(-Tam, Tam, Tam);
GL.End();
glControl.VSync = true;
glControl.SwapBuffers();
}
private void glControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
downX = e.X;
downY = e.Y;
}
private void glControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.X == downX && e.Y == downY) return;
if (e.Button == MouseButtons.Left)
{
xangle += (e.X - downX) * 0.05f;
yangle += (e.Y - downY) * 0.05f;
glControl.Invalidate();
glControl.Refresh();
}
}
}
}
Example:
template_torch.json
{
"ambientocclusion": false,
"textures": {
"particle": "#torch"
},
"elements": [
{ "from": [ 7, 0, 7 ],
"to": [ 9, 10, 9 ],
"shade": false,
"faces": {
"down": { "uv": [ 7, 13, 9, 15 ], "texture": "#torch" },
"up": { "uv": [ 7, 6, 9, 8 ], "texture": "#torch" }
}
},
{ "from": [ 7, 0, 0 ],
"to": [ 9, 16, 16 ],
"shade": false,
"faces": {
"west": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" },
"east": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" }
}
},
{ "from": [ 0, 0, 7 ],
"to": [ 16, 16, 9 ],
"shade": false,
"faces": {
"north": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" },
"south": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" }
}
}
]
}
I am trying to learn how to program OpenGL. Right now I am writing a program that draws to cubes. I have each cube stored in a separate VBO. This is the code for this.
void
init()
{
enum { Vertices, Colors, Elements, NumVBOs };
GLuint buffers[NumVBOs];
glGenVertexArrays(NumVAOs,VAO);
{
GLfloat vertices[][3] = {
{ -0.5, -0.5, -0.5 },
{ 0.5, -0.5, -0.5 },
{ 0.5, 0.5, -0.5 },
{ -0.5, 0.5, -0.5 },
{ -0.5, -0.5, 0.5 },
{ 0.5, -0.5, 0.5 },
{ 0.5, 0.5, 0.5 },
{ -0.5, 0.5, 0.5 }
};
GLfloat cubeColors[][3] = {
{ 0.0, 0.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ 0.0, 1.0, 0.0 },
{ 0.0, 1.0, 1.0 },
{ 1.0, 0.0, 0.0 },
{ 1.0, 0.0, 1.0 },
{ 1.0, 1.0, 0.0 },
{ 1.0, 1.0, 1.0 },
};
GLubyte indices[][4] = {
{ 0, 1, 2, 3 },
{ 4, 7, 6, 5 },
{ 0, 4, 5, 1 },
{ 3, 2, 6, 7 },
{ 0, 3, 7, 4 },
{ 1, 5, 6, 2 }
};
glBindVertexArray(VAO[Cube1]);
glGenBuffers(NumVBOs, buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors]);
glBufferData(GL_ARRAY_BUFFER,sizeof(cubeColors),cubeColors,GL_STATIC_DRAW);
glColorPointer(3,GL_FLOAT,0,BUFFER_OFFSET(0));
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
GL_STATIC_DRAW);
}
{
GLfloat vertices2[][3] = {
{ -0.5, -0.5, -1.5 },
{ 0.5, -0.5, -1.5 },
{ 0.5, 0.5, -1.5 },
{ -0.5, 0.5, -1.5 },
{ -0.5, -0.5, -2.5 },
{ 0.5, -0.5, -2.5 },
{ 0.5, 0.5, -2.5 },
{ -0.5, 0.5, -2.5 }
};
GLfloat cubeColors2[][3] = {
{ 0.0, 0.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ 0.0, 1.0, 0.0 },
{ 0.0, 1.0, 1.0 },
{ 1.0, 0.0, 0.0 },
{ 1.0, 0.0, 1.0 },
{ 1.0, 1.0, 0.0 },
{ 1.0, 1.0, 1.0 },
};
GLubyte indices2[][4] = {
{ 0, 1, 2, 3 },
{ 4, 7, 6, 5 },
{ 0, 4, 5, 1 },
{ 3, 2, 6, 7 },
{ 0, 3, 7, 4 },
{ 1, 5, 6, 2 }
};
glBindVertexArray(VAO[Cube2]);
glGenBuffers(NumVBOs, buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2,
GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors]);
glBufferData(GL_ARRAY_BUFFER,sizeof(cubeColors2),cubeColors2,GL_STATIC_DRAW);
glColorPointer(3,GL_FLOAT,0,BUFFER_OFFSET(0));
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2,
GL_STATIC_DRAW);
}
glEnable(GL_DEPTH_TEST);
}
When this is called in display()
glBindVertexArray[VAO[Cube1]];
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
glBindVertexArray[VAO[Cube2]];
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
The program only draws Cube2. However, if I insert
glBindVertexArray[VAO[Cube1]];
at the end of init(), it will draw Cube1 only instead.
Right now I am confused. I would like to be able to use VAOs for more complicated applications but am stuck at this point.
glBindVertexArray[VAO[Cube1]];
Should have been
glBindVertexArray(VAO[Cube1]);
I've been trying to display a model on my screen (a simple UVSphere from Blender). I first exported it to .fbx format and then transformed to .g3db format with gdx-conv-win32.exe. I have this code so far, but all it shows me is a blank black screen... it only works with the model found in this tutorial (an .obj model) https://xoppa.github.io/blog/loading-models-using-libgdx/
package com.mygdx.game.screens;
/.../ imports
public class GameScreen extends MenuScreens {
public Environment environment;
public PerspectiveCamera cam;
public CameraInputController camController;
public ModelBatch modelBatch;
public Model model;
public ModelInstance instance;
AssetManager manager = new AssetManager();
public boolean loading;
public Array<ModelInstance> instances;
public GameScreen(ProjectSurvival game){
super();
this.game = game;
modelBatch = new ModelBatch();
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
environment.add(new DirectionalLight().set(0.9f, 0.9f, 0.9f, 20f, 20f, 20f));
environment.add(new PointLight().set(1, 1, 1, 20, 20, 20, 500));
instances = new Array<ModelInstance>();
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(1f, 1f, 1f);
cam.lookAt(0,0,0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
manager = new AssetManager();
manager.load("ship.g3db", Model.class);
loading = true;
}
private void doneLoading() {
Model test = manager.get("ship.g3db", Model.class);
ModelInstance shipInstance = new ModelInstance(test);
instances.add(shipInstance);
loading = false;
}
#Override
public void show() {
}
#Override
public void render(float delta) {
//super.render(delta);
if (loading && manager.update()) {
doneLoading();
System.out.println("loaded");
}
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(instances, environment);
modelBatch.end();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
super.dispose();
modelBatch.dispose();
model.dispose();
instances.clear();
manager.dispose();
}
}
There are several other similar topics, but none of them solves my problem... please I need help!
EDIT:
Here's my g3dj file ( I cut some parts of it cause it's extremely long):
{
"version": [ 0, 1],
"id": "",
"meshes": [
{
"attributes": ["POSITION", "NORMAL", "TEXCOORD0"],
"vertices": [
-0.724124, 0.035572, -0.598984, -0.742302, -0.159337, -0.650807, 0.028780, 0.420519,
-0.691568, 0.068115, -0.634070, -0.791498, -0.084201, -0.605335, 0.021021, 0.407816,
-0.694079, 0.034096, -0.634070, -0.878414, 0.254219, -0.404614, 0.026918, 0.405321,
// deleted (...)
-0.846887, -0.041603, -0.403719, -0.887509, -0.132389, -0.441267, 0.051316, 0.489956,
-0.826199, -0.040587, -0.445113, -0.867977, -0.072359, -0.491256, 0.049283, 0.474874,
-0.803523, -0.039472, -0.485435, -0.859127, -0.022919, -0.511185, 0.047232, 0.459797
],
"parts": [
{
"id": "Mesh_part1",
"type": "TRIANGLES",
"indices": [
0, 1, 2, 1, 0, 3, 4, 2, 5, 2, 4, 0,
2, 6, 7, 6, 2, 1, 5, 7, 8, 7, 5, 2,
0, 9, 3, 3, 9, 10, 9, 11, 10, 11, 9, 12,
9, 4, 13, 4, 9, 0, 12, 13, 14, 13, 12, 9,
// deleted (...)
3610, 3613, 3614, 137, 3614, 3613, 3614, 137, 133, 3606, 3612, 3596,
3612, 3606, 3613, 112, 3613, 3606, 3613, 112, 137, 3614, 3608, 3610,
3608, 3614, 3615, 3615, 3539, 3608, 3539, 3615, 3543, 133, 3615, 3614,
3615, 133, 134, 134, 3543, 3615, 3543, 134, 14
]
}
]
}
],
"materials": [
{
"id": "Material.001",
"ambient": [ 0.200000, 0.200000, 0.200000],
"diffuse": [ 0.800000, 0.800000, 0.800000],
"emissive": [ 0.000000, 0.000000, 0.000000],
"opacity": 0.000000,
"specular": [ 0.200000, 0.200000, 0.200000],
"shininess": 20.000000
}
],
"nodes": [
{
"id": "Sphere",
"rotation": [-0.707107, 0.000000, 0.000000, 0.707107],
"scale": [ 100.000000, 100.000000, 100.000000],
"translation": [ 0.000000, 101.334976, 0.000000],
"parts": [
{
"meshpartid": "Mesh_part1",
"materialid": "Material.001",
"uvMapping": [[]]
}
]
}
],
"animations": []
}
Since there is no accepted answer:
As described by #Xoppa In you file the opacity is set to zero, set it to 1.0000 in the gd3j file
"opacity": 0.000000
// TODO 1: find what is the property of the material in blender
// TODO 2: add to troubleshooting guide
Had the same problem but with converting LWO (Light Wave) objects to g3db / g3dj. Problem was that when LightWave is exporting to FBX format it doesn't add info about textures (I'm not actually sure if FBX format supports textures at all?). Then I switched exporting to .OBJ but again I had the problem that textures in png format are not supported. Only after using .jpg textures it started working. After that opacity was set correctly to 1. With textures it can't handle converter is setting opacity to 0.
I am getting the json data from back-end to draw the line. the problem what i am getting is, even if the data is being as null ( out of 20 say 5 doesn't have data ) i am getting line drawn in.
what i expect is, I don't want to draw the lines once the data has the values as null.
example data :
[
{
"ActualPercentage": 48.78,
"PlanPercentage": 44.05,
"Week": "2015-10-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 45.25,
"Week": "2015-11-29T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 46.45,
"Week": "2015-12-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 47.65,
"Week": "2016-01-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 48.85,
"Week": "2016-02-28T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 50.05,
"Week": "2016-03-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 51.25,
"Week": "2016-04-29T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 100,
"Week": "2016-05-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 100,
"Week": "2016-06-29T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 100,
"Week": "2016-07-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": 100, //let this line alone stop here.
"Week": "2016-08-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null, //still drawing!?
"Week": "2016-09-29T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null,
"Week": "2016-10-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null,
"Week": "2016-11-29T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null,
"Week": "2016-12-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null,
"Week": "2017-01-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null,
"Week": "2017-02-27T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null,
"Week": "2017-03-30T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null,
"Week": "2017-04-29T18:30:00.000Z"
},
{
"ActualPercentage": 100,
"PlanPercentage": null,
"Week": "2017-05-30T18:30:00.000Z"
}
]
I am drawing 2 lines here. let first line draw as fill data and second one let stop up to it's find the value.
how to do this?
here is my code :
var that = this;
var parseDate = d3.time.format("%Y%m%d").parse;
var width = this.width;
var height = this.height;
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var toolTipScale = d3.scale.linear().domain([height + 90, 80]).range([0, 100]);
var iScale = d3.scale.linear().domain([width + 80, 80]).range([this.datas.length, 0]);
var color = d3.scale.ordinal()
.domain(["ActualPercentage", "PlanPercentage", "WeeklyActual", "WeeklyPlan"])
.range(["#FF0000", "#009933" , "#FFFFFF", "#ff0099"]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(-height)
.ticks(d3.time.month, 1)
.tickFormat(d3.time.format("%Y-%b"))
.tickSubdivide(true)
.orient("bottom")
.outerTickSize(0); //removing right border as the way top too.
var yAxis = d3.svg.axis().scale(y).tickSize( -width ).tickSubdivide(true).orient("left").outerTickSize(0);
var line = d3.svg.line()
// .interpolate("basis")
.x(function(d) { return x(d.date); })
.defined(function(d) { return d.y; })
.y(function(d) { return y(d.temperature); });
var svg = this.svg;
var div = d3.select("body").append("div")
.attr("class", "tooltips")
.style("opacity", 0);
color.domain(d3.keys(this.datas[0]).filter(function(key) {
return key !== "Week" && key !== "Value" && key !== 'WeeklyActual' && key !== 'WeeklyPlan'
}));
this.datas.forEach(function(d) {
var dateObj = new Date(d.Week);
var month = dateObj.getUTCMonth() + 1; //months from 1-12
var day = dateObj.getUTCDate();
var year = dateObj.getUTCFullYear();
d.Week = new Date(month+'/'+day+'/'+year );
// console.log( d.Week );
});
var cities = color.domain().map(function(name) {
return {
name: name,
values: that.datas.map(function(d) {
return {date: d.Week, temperature: (+d[name]) };
})
};
});
x.domain(d3.extent(this.datas,
function(d) {
return d.Week;
})
);
y.domain([
d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }),
d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr('class', 'text-xaxis')
.style("text-anchor", "end")
// .attr('dx', -40)
// .attr('dy', 60)
.attr("transform", function(d) {
return "rotate(-65)"
});
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll("text")
.attr('class', 'text-yaxis')
.attr('dx', -10)
var city = svg.selectAll(".city")
.data(cities)
.enter().append("g")
.attr('id', function(d) {
return d.name;
})
.attr("class", "city");
var path = city.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", function(d) { return color(d.name); });
var totalLength = [
path[0][0].getTotalLength(),
path[0][1].getTotalLength()
];
path
.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2000)
.ease("linear")
.attr("stroke-dashoffset", 0);
var circles = city.selectAll("circle")
.data(function(d) {
return d.values
})
.enter()
.append("circle")
.attr("r", 3.5)
.attr("cx", function(d, i) {
return x(d.date)
})
.attr("cy", function(d) {
return y(d.temperature)
})
.style('cursor', 'pointer')
.attr("fill", "transparent")
.attr("stroke", "yellow")
.attr("stroke-width", 0);
circles.transition().duration(3000).attr("stroke-width", 2);
circles.on("mouseover", function(d, i) {
div.transition().duration(200).style("opacity", 0.9);
var data = d3.select(this.parentNode).select("path").data()[0];
var date = d.date;
var dateValues = date.getDate() +'/' + (date.getMonth() + 1) +'/' + date.getFullYear();
div.html( "<span>"+ data.name + ": </span><span>" + dateValues + '</span><span>' + d.temperature +'</span>')
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 60) + "px");
})
.on("mouseout", function(d, i) {
div.transition().duration(500).style("opacity", 0);
})
from the idea of softwarenewbie7331 I have modified the code like this: ( Y values )
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.defined(function(d) { return d.temperature })
.y(function(d) { return y(d.temperature); });
this is working fine for me.