I'm using c# in Unity (though this question isn't specific to either) and need to get all possible combinations of the two vectors:
(x, y, z) and (-x, -y, -z)
so the result would be:
(x, y, z)
(-x, y, z)
(-x, -y, z)
(-x, -y, -z)
(x, -y, z)
(x, -y, -z)
(x, y, -z)
(-x, y, -z)
I know x, y and z. The origin is in the centre of the cube all I need is to get each corner of the cube's x, y, z position.
The points I need to get:
The absolutely simplest, fastest, and easiest to understand way to make the eight combinations is hard-coding the eight combinations of signs:
IList<int[]> MakeCombinations(int x, int y, int z) {
return new[] {
new[] { x, y, z}
, new[] { x, y, -z}
, new[] { x, -y, z}
, new[] { x, -y, -z}
, new[] {-x, y, z}
, new[] {-x, y, -z}
, new[] {-x, -y, z}
, new[] {-x, -y, -z}
};
}
If you prefer a solution with a little more programming, you can do it like this (I am using arrays for vectors; you could use your specific class):
int[] data = new[] {x, y, z};
IList<int[]> all = new List<int[]>();
for (int mask = 0 ; mask != 8 ; mask++) {
int[] next = new[] {data[0], data[1], data[2]};
if ((mask & 0x01) != 0) next[0] *= -1;
if ((mask & 0x02) != 0) next[1] *= -1;
if ((mask & 0x04) != 0) next[2] *= -1;
all.add(next);
}
The combination of pluses and minuses in front of the vector component is modeled with a single three-bit number mask. When bit at position N is set, the N-th component is taken with the negative sign; otherwise, it is taken with a positive sign.
Related
Say we have code like;
if (x > 6) {
x = 6;
}
if (x < -6) {
x = -6;
}
Can we reduce this to one check and one update?
We could do this, but we lose the sign.
if (abs(x) > 6) {
x = 6;
}
(i'm not assuming any particular language)
Using the sign function, you could use
x = sign(x) * min(6, abs(x))
Or, if you prefer the copysign function [where copysign(x, y) returns a float with the magnitude (absolute value) of x but the sign of y],
x = copysign(min(6, abs(x)), x)
I have a very basic question about C++ integration in R via Rcpp. Suppose I want to implement a simple function like this one in C++:
inte = function(x, y, a, b){
model = approxfun(x, y)
return(integrate(model, a, b)$value)
}
So a very basic approach would be to call R's function 'integrate' as much as needed:
// [[Rcpp::export]]
double intecxx(Function inte, NumericVector x, NumericVector y,
double a, double b) {
NumericVector res;
res = inte(x, y, a, b);
return res[0];
}
However, I need to use this 'intecxx' in many other parts of my C++ code, so calling it from somewhere else results in 'inte' not being available in the scope. Any help is appreciated.
If you are willing to modify intecxx by hardcoding the call to inte inside the body, rather than trying to pass it as a parameter, you could use this approach:
#include <Rcpp.h>
/*** R
inte = function(x, y, a, b){
model = approxfun(x, y)
return(integrate(model, a, b)$value)
}
.x <- 1:10
set.seed(123)
.y <- rnorm(10)
*/
// [[Rcpp::export]]
double intecxx(Rcpp::NumericVector x, Rcpp::NumericVector y, double a, double b) {
Rcpp::NumericVector res;
Rcpp::Environment G = Rcpp::Environment::global_env();
Rcpp::Function inte = G["inte"];
res = inte(x, y, a, b);
return res[0];
}
I defined inte in the same source file as intecxx to ensure that it is available in the global environment, and therefore callable from within intecxx through G.
R> inte(.x, .y, 1, 10)
[1] 1.249325
R> intecxx(.x, .y, 1, 10)
[1] 1.249325
R> all.equal(inte(.x, .y, 1, 10),intecxx(.x, .y, 1, 10))
[1] TRUE
Recently i attended an interview where i was asked to write a recursive java code for (x^y)^z.
function power(x,y){
if(y==0){
return 1;
}else{
x*=power(x,y-1);
}
}
I could manage doing it for x^y but was not getting a solution for including the z also in the recursive call.
On asking for a hint, they told me instead of having 2 parameters in call u can have a array with 2 values. But even then i dint get the solution. can u suggest a solution both ways.
This is the solution I would use in python, but you could easily have done it in javascipt or any other language too:
def power(x, y):
if y == 0:
return 1
if y == 1:
return x
return x * power(x, y - 1)
def power2(x, y, z):
return power(power(x, y), z)
You can then use power2 to return your result. In another language you could probably overload the same function but I do not think this is possible in Python for this scenario.
For your javascript code, all you really needed to add to your solution was a second function along the lines of:
function power2(x,y,z)
{
return power(power(x, y), z);
}
As you can see, the solution itself is also recursive despite defining a new function (or overloading your previous one).
Michael's solution in Java Language
public void testPower()
{
int val = power(2, 3, 2);
System.out.println(val);
}
private int power(int x, int y, int z)
{
return power(power(x, y), z);
}
private int power(int x, int y)
{
if (y == 0)
{
return 1;
}
if (y == 1)
{
return x;
}
return x * power(x, y - 1);
}
output is 64
I'm trying to draw a simple grid on a canvas. First I did this
function start()
{
var x = 0;
var y = 0;
for (x = 0; x < 500; x += 50)
{
line(0 + x, 50 + y, 50 + x, 50 + y, 1, "#111");
line(50 + x, 0 + y, 50 + x, 50 + y, 1, "#111");
if (x == 450)
{
x = -50;
y += 50;
}
if (y == 500)
{
x = 500;
}
}
}
It works fine. But I want to be able to easily change the size of the grid and canvas. So I did this:
function start()
{
var x = 0;
var y = 0;
var cW = canvas.width;
var cH = canvas.hight;
var gS = 50; //gS = gridSpace
for (x = 0; x < cW; x += gS)
{
line(0 + x, gS + y, gS + x, gS + y, 1, "#111");
line(gS + x, 0 + y, gS + x, gS + y, 1, "#111");
if (x == cW - gS)
{
x = -gS;
y += gS;
}
if (y == cH)
{
x = cW;
}
}
}
It does not work! Please help me.
PS. I'm using a library.
`
You might want to approach this a little differently. I'm not entirely sure of what you're trying to accomplish here, but here are some pointers/questions that may guide you toward what you're trying to do:
When drawing a grid, you are drawing a series of horizontal lines and a series of vertical lines. Use two loops to simplify that process.
For the horizontal lines, the y-value varies, but the x-coords for the line endpoints stay the same (e.g. 0 and cW). The converse applies to the vertical lines.
What kind of spacing are you really trying to achieve? Typically you're looking at either dividing the space into a certain number of areas (say 6 rows and 4 columns), or spacing that doesn't adapt to the specific canvas you're drawing on (this is what you're code seems to be trying to do). So, the first will adapt to the size of the canvas while the latter will just display more/fewer rows/columns as the canvas size varies.
I hope that helps you solve your problem, please let me know if you need any more help!
One possibility, is that you have height spelled incorrectly. I believe javascript, if this is javascript, won't complain about incorrectly named variables. (I could be wrong on that).
var cH = canvas.hight;
should be
var cH = canvas.height;
I am trying to display a mathematical surface f(x,y) defined on a XY regular mesh using OpenGL and C++ in an effective manner:
struct XYRegularSurface {
double x0, y0;
double dx, dy;
int nx, ny;
XYRegularSurface(int nx_, int ny_) : nx(nx_), ny(ny_) {
z = new float[nx*ny];
}
~XYRegularSurface() {
delete [] z;
}
float& operator()(int ix, int iy) {
return z[ix*ny + iy];
}
float x(int ix, int iy) {
return x0 + ix*dx;
}
float y(int ix, int iy) {
return y0 + iy*dy;
}
float zmin();
float zmax();
float* z;
};
Here is my OpenGL paint code so far:
void color(QColor & col) {
float r = col.red()/255.0f;
float g = col.green()/255.0f;
float b = col.blue()/255.0f;
glColor3f(r,g,b);
}
void paintGL_XYRegularSurface(XYRegularSurface &surface, float zmin, float zmax) {
float x, y, z;
QColor col;
glBegin(GL_QUADS);
for(int ix = 0; ix < surface.nx - 1; ix++) {
for(int iy = 0; iy < surface.ny - 1; iy++) {
x = surface.x(ix,iy);
y = surface.y(ix,iy);
z = surface(ix,iy);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix + 1, iy);
y = surface.y(ix + 1, iy);
z = surface(ix + 1,iy);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix + 1, iy + 1);
y = surface.y(ix + 1, iy + 1);
z = surface(ix + 1,iy + 1);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix, iy + 1);
y = surface.y(ix, iy + 1);
z = surface(ix,iy + 1);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
}
}
glEnd();
}
The problem is that this is slow, nx=ny=1000 and fps ~= 1.
How do I optimize this to be faster?
EDIT: following your suggestion (thanks!) regarding VBO
I added:
float* XYRegularSurface::xyz() {
float* data = new float[3*nx*ny];
long i = 0;
for(int ix = 0; ix < nx; ix++) {
for(int iy = 0; iy < ny; iy++) {
data[i++] = x(ix,iy);
data[i++] = y(ix,iy);
data[i] = z[i]; i++;
}
}
return data;
}
I think I understand how I can create a VBO, initialize it to xyz() and send it to the GPU in one go, but how do I use the VBO when drawing. I understand that this can either be done in the vertex shader or by glDrawElements? I assume the latter is easier? If so: I do not see any QUAD mode in the documentation for glDrawElements!?
Edit2:
So I can loop trough all nx*ny quads and draw each by:
GL_UNSIGNED_INT indices[4];
// ... set indices
glDrawElements(GL_QUADS, 1, GL_UNSIGNED_INT, indices);
?
1/. Use display lists, to cache GL commands - avoiding recalculation of the vertices and the expensive per-vertex call overhead. If the data is updated, you need to look at client-side vertex arrays (not to be confused with VAOs). Now ignore this option...
2/. Use vertex buffer objects. Available as of GL 1.5.
Since you need VBOs for core profile anyway (i.e., modern GL), you can at least get to grips with this first.
Well, you've asked a rather open ended question. I'd suggest using modern (3.0+) OpenGL for everything. The point of just about any new OpenGL feature is to provide a faster way to do things. Like everyone else is suggesting, use array (vertex) buffer objects and vertex array objects. Use an element array (index) buffer object too. Most GPUs have a 'post-transform cache', which stores the last few transformed vertices, but this can only be used when you call the glDraw*Elements family of functions. I also suggest you store a flat mesh in your VBO, where y=0 for each vertex. Sample the y from a heightmap texture in your vertex shader. If you do this, whenever the surface changes you will only need to update the heightmap texture, which is easier than updating the VBO. Use one of the floating point or integer texture formats for a heightmap, so you aren't restricted to having your values be between 0 and 1.
If so: I do not see any QUAD mode in the documentation for glDrawElements!?
If you want quads make sure you're looking at the GL 2.1-era docs, not the new stuff.