Array after an element is > 0 change all elements to that value until next non zero value - arrays

I have an array that is for example
[0.0, 0.0, 55.0, 0.0, 0.0, 55.0, 55.0, 22.0, 0.0, 55.0]
How can I change the element with 0 value if the previous value > 0? so
[0.0, 0.0, 55.0, 0.0, 0.0, 55.0, 55.0, 22.0, 0.0, 55.0]
becomes
[0.0, 0.0, 55.0, 55.0, 55.0, 55.0, 55.0, 22.0, 22.0, 55.0]
I have tried the following and it removes the zeros and nothing else.
func weightArrayRemovedZero(array: [Double])->[Double]{
var arrayToAlter = [Double]()
for(index,item) in array.enumerated() {
print("The \(item) is at index:\(index)")
if item == 0.0 {
if index > 0 && index < array.count - 1 {
if array[index - 1] != 0.0 {
let nonZeroElement = array[index - 1]
arrayToAlter.append(nonZeroElement)
}
}
} else {
arrayToAlter.append(item)
}
}
return arrayToAlter
}

map seems to be the natural approach to me:
var last = 0.0
let mapped = values.map { elem -> (Double) in
last = elem > 0.0 ? elem : last
return last
}
Generally speaking, map is your go to when you want to change one collection into another collection with a one-to-one element mapping.

Try this out
var array = [0.0, 0.0, 55.0, 0.0, 0.0, 55.0, 55.0, 22.0, 0.0, 55.0]
array.enumerated().forEach {
array[$0] = $1 == 0 &&
array.indices.contains($0 - 1) &&
array[$0 - 1] > 0 ? array[$0 - 1] : $1
}
print(array)

Another option:
var array = [0.0, 0.0, 55.0, 0.0, 0.0, 55.0, 55.0, 22.0, 0.0, 55.0]
for i in array.indices {
if i == 0 { continue }
if array[i] == 0 && array[i-1] != 0 {
array[i] = array[i-1]
}
}
// [0, 0, 55, 55, 55, 55, 55, 22, 22, 55]

Related

Associating values from multiple arrays

I have a custom object containing three arrays. The first array contains the names of monitoring datapoints, the second array contains values for each datapoint, and the third array contains the time stamp of each poll. The object looks like this:
dataSourceName : linux_interface
dataPoints : {InMbps, InUtilizationPercent, OutDiscardPercent, OutMbps, StatusFlap...}
values : {0.0121 0.0001 0.0 0.0156 0.0002 0.0 4294967295 1138904370 0.0 1.0 0.0 1.0833 1511.5917 2.6167 0.0
0.0 0.0 0.0 1950.1667 2.9583 10000.0 1.0 1142955859 0.0, 0.0018 0.0 0.0 0.0011 0.0 0.0 4294967295
1138904370 0.0 0.9917 0.0 0.9917 226.7833 0.425 0.0 0.0 0.0 0.0 131.525 0.325 10000.0 1.0 1142943859
0.0, 0.001 0.0 0.0 0.0005 0.0 0.0 4294967295 1138904370 0.0 1.0 0.0 1.0 127.0833 0.3 0.0 0.0 0.0 0.0
58.3333 0.2 10000.0 1.0 1142931859 0.0, 0.0061 0.0001 0.0 0.0155 0.0002 0.0 4294967295 1138904370 0.0
1.0 0.0 1.2 762.4417 1.7 0.0 0.0 0.0 0.0 1936.5667 2.2083 10000.0 1.0 1142919858 0.0...}
time : {1567700449000, 1567700329000, 1567700209000, 1567700089000...}
nextPageParams :
I am trying to count the number of times the value of "StatusFlap" is "1" in a given amount of time (say, 10 minutes). Using the following code (where $datapoints in my object), I can get all of the values, but I do not know how to line those up with timestamps. Any thoughts?
$index = [array]::indexOf($datapoints.datapoints, 'StatusFlap')
$values = Foreach ($obj in $datapoints.values) {
$obj[$index]
}
A sample of the object in JSON format, looks like this:
{
"dataSourceName": "linux_interface",
"dataPoints": [
"InMbps",
"InUtilizationPercent",
"OutDiscardPercent",
"OutMbps",
"OutUtilizationPercent",
"StatusFlap",
"BasicSpeed",
"ifLastChange",
"InBroadcastPkts",
"InDiscards",
"InErrors",
"InMulticastPkts",
"InOctets",
"InUcastPkts",
"OutBroadcastPkts",
"OutDiscards",
"OutErrors",
"OutMulticastPkts",
"OutOctets",
"OutUcastPkts",
"Speed",
"Status",
"sysUptime",
"InDiscardPercent"
],
"values": [
[
0.0121,
0.0001,
0.0,
0.0156,
0.0002,
0.0,
4294967295,
1138904370,
0.0,
1.0,
0.0,
1.0833,
1511.5917,
2.6167,
0.0,
0.0,
0.0,
0.0,
1950.1667,
2.9583,
10000.0,
1.0,
1142955859,
0.0
],
[
0.0018,
0.0,
0.0,
0.0011,
0.0,
0.0,
4294967295,
1138904370,
0.0,
0.9917,
0.0,
0.9917,
226.7833,
0.425,
0.0,
0.0,
0.0,
0.0,
131.525,
0.325,
10000.0,
1.0,
1142943859,
0.0
],
[
0.001,
0.0,
0.0,
0.0005,
0.0,
0.0,
4294967295,
1138904370,
0.0,
1.0,
0.0,
1.0,
127.0833,
0.3,
0.0,
0.0,
0.0,
0.0,
58.3333,
0.2,
10000.0,
1.0,
1142931859,
0.0
],
"time": [
1567700449000,
1567700329000,
1567700209000
],
"nextPageParams": ""
}

How to subtract [[Float]] with another [Float] in swift 4? [duplicate]

This question already has answers here:
How to multiply two arrays element-wise
(5 answers)
Is there an easy way to compute difference between two arrays [duplicate]
(2 answers)
Closed 3 years ago.
I want to subtract the two float arrays.
let array1 = [[0,5.2000003,0.44705883,0,0,0,1.882353,0,0.49411765,0,0,0,0,0,2.447059,1.5294118,0,0,0,4.5176473],[0,5.2000003,0.44705883,0,0,0,1.882353,0,0.49411765,0,0,0,0,0,2.447059,1.5294118,0,0,0,4.5176473],[0,5.2000003,0.44705883,0,0,0,1.882353,0,0.49411765,0,0,0,0,0,2.447059,1.5294118,0,0,0,4.5176473]]
let array2 = [0.23529412, 1.7411765, 0.23529412, 0.0, 0.28235295, 0.0, 0.0, 0.5882353, 0.87058824, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.1529412]
The desired output I want is array2 should be subtracted from all the elements from array1. Is there to avoid forloop?
Output expected : [[-0.23529412, 3.4588237, 0.21176471, 0.0, -0.28235295, 0.0, 1.882353, -0.5882353, -0.3764706, 0.0, 0.0, 0.0, 0.0, 0.0, 2.447059, 1.5294118, 0.0, 0.0, 0.0, 1.364706], [-0.23529412, 3.4588237, 0.21176471, 0.0, -0.28235295, 0.0, 1.882353, -0.5882353, -0.3764706, 0.0, 0.0, 0.0, 0.0, 0.0, 2.447059, 1.5294118, 0.0, 0.0, 0.0, 1.364706], [-0.23529412, 3.4588237, 0.21176471, 0.0, -0.28235295, 0.0, 1.882353, -0.5882353, -0.3764706, 0.0, 0.0, 0.0, 0.0, 0.0, 2.447059, 1.5294118, 0.0, 0.0, 0.0, 1.364706]]
Use zip(_:_:) and map(_:) on array1 and array2, i.e.
let array3 = zip(array1, array2).map({ $0.0 - $0.1 })
print(array3) //[-0.23529412, 3.4588238000000002, 0.21176471000000002, 0.0, -0.28235295, 0.0, 1.882353, -0.5882353, -0.37647059, 0.0, 0.0, 0.0, 0.0, 0.0, 2.447059, 1.5294118, 0.0, 0.0, 0.0, 1.3647061000000003]
Edit:
If the array1 and array2 are of type [[Float]] and [Float],
let array1 = [[0,5.2000003,0.44705883,0,0,0,1.882353,0,0.49411765,0,0,0,0,0,2.447059,1.5294118,0,0,0,4.5176473],[0,5.2000003,0.44705883,0,0,0,1.882353,0,0.49411765,0,0,0,0,0,2.447059,1.5294118,0,0,0,4.5176473],[0,5.2000003,0.44705883,0,0,0,1.882353,0,0.49411765,0,0,0,0,0,2.447059,1.5294118,0,0,0,4.5176473]]
let array2 = [0.23529412, 1.7411765, 0.23529412, 0.0, 0.28235295, 0.0, 0.0, 0.5882353, 0.87058824, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.1529412]
let output = array1.map({ return zip($0, array2).map({ $0.0 - $0.1 }) }) //[[-0.23529412, 3.4588238000000002, 0.21176471000000002, 0.0, -0.28235295, 0.0, 1.882353, -0.5882353, -0.37647059, 0.0, 0.0, 0.0, 0.0, 0.0, 2.447059, 1.5294118, 0.0, 0.0, 0.0, 1.3647061000000003], [-0.23529412, 3.4588238000000002, 0.21176471000000002, 0.0, -0.28235295, 0.0, 1.882353, -0.5882353, -0.37647059, 0.0, 0.0, 0.0, 0.0, 0.0, 2.447059, 1.5294118, 0.0, 0.0, 0.0, 1.3647061000000003], [-0.23529412, 3.4588238000000002, 0.21176471000000002, 0.0, -0.28235295, 0.0, 1.882353, -0.5882353, -0.37647059, 0.0, 0.0, 0.0, 0.0, 0.0, 2.447059, 1.5294118, 0.0, 0.0, 0.0, 1.3647061000000003]]

Simple structure initialization in Swift (4)?

I'm new to Swift and trying to port some code. I have this from an old project:
typedef struct {
float Position[3];
float Normal[3];
float TexCoord[2]; // New
} iconVertex;
const iconVertex iconVertices[] = {
{{0.0,0.0, 0.0}, {0, 0, 1.0}, {0, 0}},
{{1.0, 0.0, 0.0}, {0, 0, 1.0}, {1, 0}},
{{0.0, 1.0, 0.0}, {0, 0, 1.0}, {0, 1}},
{{1.0, 1.0, 0.0}, {0, 0, 1.0}, {1, 1}},
};
Is there any way to do that same array initialization in Swift?
Thanks!
In Swift you can use Structs to define your objects and create an init method that receives the parameters that you need to initialise.
struct IconVertex {
var position: [Double]
var normal: [Double]
var textCoord: [Double]
init(position: [Double], normal: [Double], textCoord: [Double]) {
self.position = position
self.normal = normal
self.textCoord = textCoord
}
}
let iconVertices: [IconVertex] = [
IconVertex(position: [0.0,0.0, 0.0], normal: [0, 0, 1.0], textCoord: [0, 0]),
IconVertex(position: [1.0, 0.0, 0.0], normal: [0, 0, 1.0], textCoord: [1, 0]),
IconVertex(position: [0.0, 1.0, 0.0], normal: [0, 0, 1.0], textCoord: [0, 1]),
IconVertex(position: [1.0, 1.0, 0.0], normal: [0, 0, 1.0], textCoord: [1, 1])]

Why Do I Always Zoom in When Picking? (OpenGL)

I have the following code:
#define GLUT_DISABLE_ATEXIT_HACK
#include <GL/glut.h>
#include <GL/gl.h>
#include <math.h>
#include <stdio.h>
GLfloat ctrlptsBezier[4][4][3] =
{
{
{-2.0, -2.0, 1.0},
{-0.5, -2.0, 0.0},
{0.5, -2.0, 0.0},
{2.0, -2.0, 1.0}},
{
{-2, -0.5, -1.0},
{-0.5, -0.5, 0.0},
{0.5, -0.5, 0.0},
{2.0, -0.5, 0.0}},
{
{-2, 0.5, 0.0},
{-0.5, 0.5, -2.0},
{0.5, 0.5, 0.0},
{2.0, 0.5, 0.0}},
{
{-2.0, 2.0, 1.0},
{-0.5, 2.0, 0.0},
{0.5, 2.0, 0.0},
{2.0, 2.0, 1.0}}
};
int uSteps = 30;
int vSteps = 30;
bool shade = false;
GLfloat black [] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat blue[] = { 0.0, 0.0, 1.0, 1.0 };
GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
GLfloat peach[] = { 1.0, 0.5, 0.5, 1.0 };
GLfloat purple[] = { 0.5, 0.0, 0.5, 1.0 };
GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 };
//Initial eye/viewpoint coords.
double xPos = -20.0, zPos = -20.0;
double eyeHeight = 4.5;
double eyeIncline = -0.5;
double theta = 0.0; //Rotation angle in rads
//Movement params (camera)
double posIncr = 0.25;
double thetaIncr = 0.1;
#define BUFSIZE 512 //Pick buffer size
void setObjLight( bool s )
{
int shadeNumber = GL_FLAT;
if ( shade == true )
shadeNumber = GL_SMOOTH;
glShadeModel(shadeNumber);
}
void setLights(void)
{
setObjLight(shade);
}
void drawRoom(void)
{
GLfloat floor_color[] = { 0.5, 0.5, 0.5, 1.0 }; //Grey floor
GLfloat blue_wall[] = { 0.0, 0.0, 1.0, 1.0 };
GLfloat green_wall[] = { 0.0, 1.0, 0.0, 1.0 };
GLfloat purple_wall[] = { 0.5, 0.0, 0.5, 1.0 };
//FLOOR
glMaterialfv(GL_FRONT, GL_DIFFUSE, floor_color);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-25.0, 0.0, -25.0);
glVertex3f( 25.0, 0.0, -25.0);
glVertex3f( 25.0, 0.0, 25.0);
glVertex3f(-25.0, 0.0, 25.0);
glEnd();
//WALLS
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, blue_wall);
glPushMatrix();
glTranslatef(0.0, 0.0, 25.0);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-25.0,-25.0,0.0);
glVertex3f(25,-25.0,0);
glVertex3f(25, 25, 0);
glVertex3f(-25, 25, 0);
glEnd();
glPopMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, green_wall);
glPushMatrix();
glTranslatef(0.0, 0.0, -25.0);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-25.0,-25.0,0.0);
glVertex3f(25,-25.0,0);
glVertex3f(25, 25, 0);
glVertex3f(-25, 25, 0);
glEnd();
glPopMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, purple_wall);
glPushMatrix();
glTranslatef(25.0, 0.0, 0.0);
glRotatef(90.0, 0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-25.0,-25.0,0.0);
glVertex3f(25,-25.0,0);
glVertex3f(25, 25, 0);
glVertex3f(-25, 25, 0);
glEnd();
glPopMatrix();
}
void drawShapes()
{
//SPHERE
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, blue);
glNormal3f(0.0, 1.0, 0.0);
glTranslatef(0.0, 2.0, 0.0);
glLoadName(1);
glutSolidSphere (2.0, 20, 16);
glPopMatrix();
glFlush();
//CONE
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, purple);
glNormal3f(0.0, 1.0, 0.0);
glTranslatef(5.0, 0.0, 0.0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glLoadName(2);
glutSolidCone (2.0, 3, 20, 16);
glPopMatrix();
glFlush();
glLoadName(0);
}
void drawBezier()
{
glEnable(GL_MAP2_VERTEX_3);
glPushMatrix();
glTranslatef(10, 2, 15);
glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
glPushMatrix();
glTranslatef(13, 2, 18);
glRotatef(-90, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, red);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
glPushMatrix();
glTranslatef(7, 2, 18);
glRotatef(90, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
glPushMatrix();
glTranslatef(10, 2, 21);
glRotatef(180, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, peach);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
glPushMatrix();
glTranslatef(10, 5, 18);
glRotatef(90.0, 1.0, 0.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, black);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
//Sphere for filler
glPushMatrix();
glTranslatef(10, 2, 18);
glRotatef(90.0, 1.0, 0.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
glutSolidSphere(3.0, 20, 16);
glPopMatrix();
glFlush();
}
void drawScene(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
double atx = xPos + cos(theta);
double atz = zPos + sin(theta);
double atHeight = eyeHeight + eyeIncline;
gluLookAt(xPos, eyeHeight, zPos, atx, atHeight, atz, 0.0, 1.0, 0.0);
glPushMatrix();
setLights();
drawRoom();
drawShapes();
glLoadName(3);
drawBezier();
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawScene();
glutSwapBuffers();
}
void setProjection(void)
{
gluPerspective(60.0, 1.0, 0.1, 100.0);
}
void init(void)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_LIGHTING);
glEnable(GL_FLAT); //Flat shading initially
glShadeModel(GL_FLAT);
//LIGHTING
GLfloat specular[]= {1.0, 1.0, 1.0, 1.0};
GLfloat diffuse[]= {1.0, 1.0, 1.0, 1.0};
GLfloat ambient[]= {1.0, 1.0, 1.0, 1.0};
GLfloat shininess= {100.0};
GLfloat light_ambient[]= {0.0, 0.0, 0.0, 1.0};
GLfloat light_diffuse[]= {1.0, 1.0, 1.0, 1.0};
GLfloat light_specular[]= {1.0, 1.0, 1.0, 1.0};
GLfloat light_position[]= {10.0, 10.0, 10.0, 0.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
// /LIGHTING
glEnable(GL_NORMALIZE);
glClearColor (0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
}
void specialKey(int k, int x, int y) //Camera movement commands with arrow keys
{
switch (k) {
case GLUT_KEY_UP:
xPos += posIncr * cos(theta);
zPos += posIncr * sin(theta);
break;
case GLUT_KEY_DOWN:
xPos -= posIncr * cos(theta);
zPos -= posIncr * sin(theta);
break;
case GLUT_KEY_LEFT:
theta -= thetaIncr;
break;
case GLUT_KEY_RIGHT:
theta += thetaIncr;
break;
case GLUT_KEY_PAGE_UP:
eyeIncline += 0.5;
break;
case GLUT_KEY_PAGE_DOWN:
eyeIncline -= 0.5;
break;
case GLUT_KEY_HOME:
eyeHeight += 0.5;
break;
case GLUT_KEY_END:
eyeHeight -= 0.5;
break;
default:
return;
}
glutPostRedisplay();
}
void key(unsigned char k, int x, int y)
{
if ( k == 27 ) //ESC to close
exit(0);
glutPostRedisplay();
}
void processHits(GLint hits, GLuint buffer[])
{
unsigned int j;
GLuint names, *ptr;
float z1, z2;
printf ("hits = %d\n", hits);
ptr = (GLuint *) buffer;
shade = !shade;
setLights();
glutPostRedisplay();
for (int i = 0; i < hits; i++)
{ /* for each hit */
names = *ptr;
printf (" number of names for hit = %d\n", names); ptr++;
z1 = (float) *ptr/0x7fffffff; ptr++;
z2 = (float) *ptr/0x7fffffff; ptr++;
printf(" z1 is %g;",z1);
printf(" z2 is %g\n", z2);
printf (" the name is ");
for (j = 0; j < names; j++) { /* for each name */
printf ("%d ", *ptr); ptr++;
}
printf ("\n");
}
}
void pick( int button, int state, int x, int y )
{
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];
if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN) {
return;
}
glSelectBuffer(BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT, viewport);
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport); //5x5 pixel area around the mouse for selecting
gluPerspective(75, 1.0, 0.1, 100); //NEED
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glInitNames();
glPushName(0);
drawScene();
glPopMatrix();
glFlush();
hits = glRenderMode(GL_RENDER); //# of hits assigned
processHits(hits, selectBuf);
}
void reshape(int w, int h){
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75, w/h,1,150);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow("Room");
init();
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutSpecialFunc(specialKey);
glutReshapeFunc(reshape);
glutMouseFunc(pick);
glutMainLoop();
return 0;
}
Forgive me for the length. I am trying to get picking to work so that I can select one object at a time to do things with. According to my print outs, it is functioning as I expect, except for one hurdle: When you pick an object, you end up extremely zoomed in, basically inside the selected shape. I have combed my code, and made some changes/debugging efforts, but I can't find the problem line. Can anyone point me in the right direction as to why picking gives this strange behavior?
Your function pick change the projection matrix with gluperspective (to zoom on the picking area), but it fails to restore the previous matrix state: it can be easily fixed by wrapping the the drawing part of the function with a set of glPushMatrix and glPopMatrix while in matrix GL_PROJECTION mode.
void pick( int button, int state, int x, int y )
{
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];
if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN) {
return;
}
glSelectBuffer(BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix(); // save projection settings
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT, viewport);
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport); //5x5 pixel area around the mouse for selecting
gluPerspective(75, 1.0, 0.1, 100); //NEED
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glInitNames();
glPushName(0);
drawScene();
// restore previous projection settings
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glFlush();

webgl drawElements:attribs not setup correctly (repeated n times)

So, I've begun a rather instantaneous trip into the world of visual, 3-d programming. I'm currently heavily invested in webgl with a rather strong background in JavaScript and most web-oriented languages but this is my first graphics language.
While trying to draw my first rather simple shape, I've run into an error I can't seem to locate a solution for. It reads in chrome as a:
WebGL: INVALID_OPERATION: drawElements:attribs not setup correctly (repeated n times)
where n is a number that varies seemingly randomly. The code in question is here:
var tessVertexPositionBuffer;
var tessVertexColorBuffer;
var tessVertexIndexBuffer;
function initBuffers () {
tessVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, tessVertexPositionBuffer);
var vertices = [
//innerfront
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
//innerleft
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
//innerback
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
//innerright
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
//topfront
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-2.0, 2.0, 2.0,
2.0, 2.0, 2.0,
//topleft
-1.0, 1.0, 1.0,
-2.0, 2.0, 2.0,
-1.0, 1.0, -1.0,
-2.0, 2.0, -2.0,
//topback
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
-2.0, 2.0, -2.0,
2.0, 2.0, -2.0,
//topright
1.0, 1.0, 1.0,
2.0, 2.0, 2.0,
1.0, 1.0, -1.0,
2.0, 2.0, -2.0,
//outerfront
-2.0, 2.0, 2.0,
2.0, 2.0, 2.0,
-2.0, -2.0, 2.0,
2.0, -2.0, 2.0,
//outerleft
-2.0, 2.0, 2.0,
-2.0, -2.0, 2.0,
-2.0, 2.0, -2.0,
-2.0, -2.0, -2.0,
//outerback
-2.0, 2.0, -2.0,
2.0, 2.0, -2.0,
-2.0, -2.0, -2.0,
2.0, -2.0, -2.0,
//outerright
2.0, 2.0, 2.0,
2.0, -2.0, 2.0,
2.0, 2.0, -2.0,
2.0, -2.0, -2.0,
//bottomfront
2.0, 2.0, 2.0,
-2.0, 2.0, 2.0,
-2.0, -2.0, 2.0,
2.0, -2.0, 2.0,
//bottomleft
-1.0, -1.0, 1.0,
-2.0, -2.0, 2.0,
-1.0, -1.0, -1.0,
-2.0, -2.0, -2.0,
//bottomback
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
-2.0, -2.0, -2.0,
2.0, -2.0, -2.0,
//bottomright
1.0, -1.0, 1.0,
2.0, -2.0, 2.0,
1.0, -1.0, -1.0,
2.0, -2.0, -2.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
tessVertexPositionBuffer.itemSize = 3;
tessVertexPositionBuffer.numItems = 64;
tessVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, tessVertexColorBuffer);
var colors = [
[0.7, 0.7, 0.7, 1.0], //all inner sides
[0.7, 0.7, 0.7, 1.0],
[0.7, 0.7, 0.7, 1.0],
[0.7, 0.7, 0.7, 1.0],
[0.7, 0.0, 0.7, 1.0], //all top sides
[0.7, 0.0, 0.7, 1.0],
[0.7, 0.0, 0.7, 1.0],
[0.7, 0.0, 0.7, 1.0],
[0.7, 0.7, 0.0, 1.0], //all outer sides
[0.7, 0.7, 0.0, 1.0],
[0.7, 0.7, 0.0, 1.0],
[0.7, 0.7, 0.0, 1.0],
[0.0, 0.7, 0.7, 1.0], //all bottom sides
[0.0, 0.7, 0.7, 1.0],
[0.0, 0.7, 0.7, 1.0],
[0.0, 0.7, 0.7, 1.0],
];
var unpackedColors = [];
for (var i in colors) {
var color = colors[i];
for (var j=0; j< 4; j++) {
unpackedColors = unpackedColors.concat(color);
}
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
tessVertexColorBuffer.itemSize = 4;
tessVertexColorBuffer.numItems = 64;
tessVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, tessVertexIndexBuffer);
var tessVertexIndices = [
0, 1, 2, 0, 2, 3,
4, 5, 6, 5, 6, 7,
8, 9, 10, 9, 10, 11,
12, 13, 14, 13, 14, 15,
16, 17, 18, 17, 18, 19,
20, 21, 22, 21, 22, 23,
24, 25, 26, 25, 26, 27,
28, 29, 30, 29, 30, 31,
32, 33, 34, 33, 34, 35,
36, 37, 38, 37, 38, 39,
40, 41, 42, 41, 42, 43,
44, 45, 46, 45, 46, 47,
48, 49, 50, 48, 50, 51,
52, 53, 54, 53, 54, 55,
56, 57, 58, 57, 58, 59,
60, 61, 62, 61, 62, 63
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(tessVertexIndices), gl.STATIC_DRAW);
tessVertexIndexBuffer.itemSize = 1;
tessVertexIndexBuffer.numItems = 96;
}
and the actual drawing of the buffers is here:
gl.bindBuffer(gl.ARRAY_BUFFER, tessVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vetexPositionAttribute, tessVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, tessVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, tessVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, tessVertexIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, tessVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
Now, this is relatively verbatim from learningwebgl, I'm really just trying to draw a simple shape. I'm relatively certain that my problem lies in my buffer types because I honestly don't uderstand much about them (and most literature on webGl I've found is either novice with a general understanding of the language or of the HYPERSUPERPRO variety).
I've checked over the actual vertex positions/colors/indices multiple times and unless I've just become familiar with the code enough that I'm blind to the simple errors, I can't find an error there.
Looks like your problem is just a small typo. The second line of your "actual drawing of buffers" code should be he following:
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, tessVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
You were missing the first r in vertexPositionAttribute on that line.
I modified the lesson 4 LearningWebGL tutorial to use your code (with the fixed typo) and I have a link to it here.
If you notice there is a blue triangle and a yellow triangle being drawn at the exact same position in space which causes some flickering. I'm not sure if that was intentional.

Resources