A ERROR about Sprite::init() in cocos2dx - cocos2d-x

i want create a game like don't touch block. when i create a Block, i want let Sprite can init.code is here:
#pragma once
#include<iostream>
#include "cocos2d.h"
#include "Block.h"
USING_NS_CC;
Block* CreateWithArgs(Color3B color, Size size, std::string label, float fontsize, Color4B textcolor)
{
auto b = new Block();
b->initWithArgs(color, size, label, fontsize, textcolor);
b->autorelease();
return b;
}
bool initWithArgs(Color3B color, Size size, std::string label, float fontsize, Color4B textcolor)
{
Sprite::init();
return true;
}
but when i code this , i foud the error in Sprite::init(); VS2012 tell me "Don't have access to protected members (in cocos2d: : Sprite class declaration)"

You are writing C functions:
Block* CreateWithArgs(Color3B color, Size size, std::string label, float fontsize, Color4B textcolor)
bool initWithArgs(Color3B color, Size size, std::string label, float fontsize, Color4B textcolor)
In C++ class methods need to be prefixed with the name of the class, for instance assuming class is MySprite:
Block* MySprite::CreateWithArgs(Color3B color, Size size, std::string label, float fontsize, Color4B textcolor)
bool MySprite::initWithArgs(Color3B color, Size size, std::string label, float fontsize, Color4B textcolor)

Related

Shadertoy shader import to libgdx

I have searched everywhere but got no reference.
I want to use this shader from shadertoy to my libgdx project, so I tried to import simple shader first from: https://www.shadertoy.com/view/XsffRs
I modified it a bit like this but got no success:
/*
* Original shader from: https://www.shadertoy.com/view/XsffRs
*/
#ifdef GL_ES
precision mediump float;
#endif
uniform float time;
uniform vec2 resolution;
// shadertoy emulation
#define iTime time
#define iResolution resolution
// --------[ Original ShaderToy begins here ]---------- //
#define TAU 6.28318531
float C,S;
mat2 rot(float a){
return mat2(C=cos(a),S=sin(a),-S,C);
}
float map(vec3 p) {
p.yz*=rot(p.z*(.03*sin(iTime*3.)));
p.xz*=rot(p.z*(.03*cos(iTime*3.)));
float m=TAU/6.,
l=length(p.xy),
a=mod(atan(p.y,p.x)-p.z*.5+iTime*5.,m)-.5*m;
return length(vec2(a*l,l-2.))-.8;
}
void main(void)
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
uv-=.5;
uv.x*=iResolution.x/iResolution.y;
vec3 ro=vec3(uv,-3.),rd=normalize(vec3(uv,1.)),mp=ro;
float i=0.;
for (int ii=0;ii<30;++ii) {
i++;
float md=map(mp);
if (abs(md)<.001)break;
mp+=rd*md;
}
float r=i/30.;
float d=length(mp-ro)*.1;
vec3 c=mix(vec3(.2,.5,.7)*d*d,vec3(.2,.4,.8)*r/d,r*r);
c=sqrt(c);
gl_FragColor = vec4(c,1.);
}
Code for ShaderProgram
public void create () {
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
batch = new SpriteBatch();
ShaderProgram.pedantic = false;
shader = new ShaderProgram(Gdx.files.internal("vert.vert"), Gdx.files.internal("frag.frag"));
if(!shader.isCompiled())
shader.getLog();
}
public void render () {
time+=Gdx.graphics.getDeltaTime();
shader.begin();
shader.setUniformf("resolution", new Vector2(width, height));
shader.setUniformf("time", time);
shader.end();
batch.begin();
batch.setShader(shader);
batch.end();
}
Shader is running without error but getting black screen.
Edit: It works by drawing dummy texture
Texture t = new Texture(new Pixmap(width,height, Pixmap.Format.RGB565));
with spritebatch, but don't know why is dummy texture required?
In order to see the shader in action you need to draw something, the code is only specifying that the shader is going to be used but nothing is being drawn with it
batch.begin();
batch.setShader(shader);
batch.draw(new Texture(new Pixmap(width,height, Pixmap.Format.RGB565),0,0);
batch.end();

CUDA thrust device pointer with transform copy crash

In CUDA 9.2 I have something like this:
#ifdef __CUDA_ARCH__
struct Context { float n[4]; } context;
#else
typedef __m128 Context;
#endif
struct A { float k[2]; };
struct B { float q[4]; };
struct FTransform : thrust::unary_function<A, B>
{
const Context context;
FTransform(Context context) : context(context){}
__device__ __host__ B operator()(const A& a) const
{
B b{{a.k[0], a.k[1], a.k[0]*context.n[0], a.k[1]*context.n[1]}};
return b;
}
};
void DoThrust(B* _bs, const Context& context, A* _as, uint32_t count)
{
thrust::device_ptr<B> bs = thrust::device_pointer_cast(_bs);
thrust::device_ptr<A> as = thrust::device_pointer_cast(_as);
FTransform fTransform(context);
auto first = thrust::make_transform_iterator(as, fTransform);
auto last = thrust::make_transform_iterator(as + count, fTransform);
thrust::copy(first, last, bs);
}
int main(int c, char **argv)
{
const uint32_t Count = 4;
Context context;
A* as;
B* bs;
cudaMalloc(&as, Count*sizeof(A));
cudaMalloc(&bs, Count*sizeof(B));
A hostAs[Count];
cudaMemcpy(as, hostAs, Count * sizeof(A), cudaMemcpyHostToDevice);
DoThrust(bs, context, as, Count);
B hostBs[Count];
cudaMemcpy(hostBs, bs, Count * sizeof(B), cudaMemcpyDeviceToHost);//crash
return 0;
}
Then when I call a standard cudaMemcpy() call later on the results I get the exception "an illegal memory access was encountered".
If I replace the thrust code with a non-thrust equivalent there is no error and everything works fine. Various combinations of trying to copy to device_vectors etc I get different crashes that seem to be thrust trying to release the device_ptr's for some reason - so maybe it is here for some reason?
== UPDATE ==
Ok that was confusing it appears it's due to the functor FTransform context member variable in my actual more complicated case. This specifically:
struct FTransform : thrust::unary_function<A, B>
{
#ifdef __CUDA_ARCH__
struct Context { float v[4]; } context;
#else
__m128 context;
#endif
...
};
So I guess it's an alignment problem somehow => in fact it is, as this works:
#ifdef __CUDA_ARCH__
struct __align__(16) Context { float v[4]; } context;
#else
__m128 context;
#endif
The solution is to ensure that if you use aligned types in thrust functor members (such as __m128 SSE types) that are copied to the GPU, that they are defined as aligned both during NVCC's CPU and GPU code build passes - and not accidentally assume even if a type may seem to naturally align to it's equivalent in the other pass that it will be ok, as otherwise bad hard to understand things may happen.
So for example the _ align _(16) is necessary in code like this:
struct FTransform : thrust::unary_function<A, B>
{
#ifdef __CUDA_ARCH__
struct __align__(16) Context { float v[4]; } context;
#else
__m128 context;
#endif
FTransform(Context context) : context(context){}
__device__ __host__ B operator()(const A& a) const; // function makes use of context
};

calling Thrust device_vector from a device function

I have a struct Cap which inside I have a thrust::device_vector of another structure. When I compile the code, I get an error which complains about calling a host function (thrust::device_vector<FloatIntPair>) from a device function SphericalFaceManager::makeCaps. When I add __host__ __device__ instead of only __device__ to the member functions and constructors the code then compiles but I receive a warning same as aforementioned error and I think it copies data between host and device. My question is how can I access to device vectors in my classes avoiding any data transfer between CPU and GPU?
Hereafter you can find the code:
struct ParticleID {
Int solver;
Int ngb;
Int oldNgb;
LLInt no;
LLInt masterNo;
__device__ ParticleID() {
solver = -8;
ngb = 0;
oldNgb = 0;
no = 0;
masterNo = -1;
}
};
struct BaseParticle {
Float h;
Float3 pos;
ParticleID id;
__device__ BaseParticle(const Float3& _pos, const Float& _h, const ParticleID& _id) :
h(_h), pos(_pos), id(_id) { }
};
struct FloatIntPair{
Float first;
Int second;
__device__ FloatIntPair(const Float& _first, Int _second) : first(_first), second(_second) { }
__device__ FloatIntPair(const FloatIntPair& sample) : first(sample.first), second(sample.second) { }
static struct {
__device__ bool operator()(const FloatIntPair& a, const FloatIntPair& b) { return a.first < b.first; }
} LessOp;
};
struct Cap {
Float3 eX;
Float3 eY;
Float radius;
Float height;
Float3 center;
Float3 normal;
BaseParticle* aP;
BaseParticle* bP;
thrust::device_vector<FloatIntPair> vertices; // The ordered list of vertices generated from intersections by other circles
__device__ inline Float findAngle(const Float3& vertex) const {
Float result;
Float3 r = (vertex - center);
result = atan2(r|eY,r|eX);
return result += (result < 0.0) * (2.0 * _PI);
}
__device__ void insertVertex(const Float3& vertex, Int id) {
Float theta;
if (!vertices.empty())
theta = findAngle(vertex);
else {
eX = normalVec(vertex - center);
eY = normal ^ eX;
theta = 0.0;
}
vertices.push_back(FloatIntPair(theta,id));
}
__device__ Cap(BaseParticle* _aP, BaseParticle* _bP) : aP(_aP), bP(_bP) {
//Compute normal, center, radius
Float d = mag(bP->pos - aP->pos);
if(d == 0.0){
normal = Vector1(0.0);
center = aP->pos;
radius = height = 0.0;
} else {
normal = (bP->pos - aP->pos) / d;
Float x = (d * d - bP->h * bP->h + aP->h * aP->h) / (2.0 * d);
center = aP->pos + normal * x;
if (x >= aP->h) {
radius = height = 0.0;
return;
}
radius = sqrt(aP->h * aP->h - x * x);
height = min(2.0 * aP->h, aP->h - x);
Float3 vec001 = Vector(0.0,0.0,1.0);
Float3 vec011 = Vector(0.0,1.0,1.0);
eX = normalVec(vec001 ^ normal);
if (mag2(eX) < geoEps()) {
eX = eX = normalVec(vec011 ^ normal);
}
eY = normal ^ eX;
}
}
};
class SphericalFaceManager {
BaseParticle* particle;
Int baseSigma;
public:
thrust::device_vector<Cap> caps;
thrust::device_vector<Float3> vertexPool;
__device__ void makeCaps();
};
__device__ void SphericalFaceManager::makeCaps() {
BaseParticle* aP;
BaseParticle* bP;
Cap aCap(aP,bP);
}
You cannot use thrust vectors (or std::vector) directly in device code. This is mentioned in various other SO questions such as here
If you want to use the data in a thrust::device_vector in device code, you should pass a pointer to the data as a functor initializing parameter. Various other SO questions give examples of this, such as here
Likewise, you cannot use vector methods, e.g. .empty() or .push_back() in device code.
You will need to replace these with ordinary C-style allocators and C-style indexed data access.
For a multi-threaded implementation of push_back in device code, I would recommend something like this. That is a fully worked example that demonstrates how to allocate space for the vector and how each thread can use it for insertVertex for example.

How to implement properly an inline function in the device that returns a vector to another device function?

I want to implement properly an inlined device function that fill out a vector of dynamic size and return the filled vector like:
__device__ inline thrust::device_vector<double> make_array(double zeta, int l)
{
thrust::device_vector<double> ret;
int N =(int)(5*l+zeta); //the size of the array will depend on l and zeta, in a complex way...
// Make sure of sufficient memory allocation
ret.reserve(N);
// Resize array
ret.resize(N);
//fill it:
//for(int i=0;i<N;i++)
// ...;
return ret;
}
My goal is to use the content of the returned vector in another device function like:
__device__ inline double use_array(double zeta,int l)
{
thrust::device_vector<double> array = make_array(zeta, l);
double result = 0;
for(int i=0; i<array.size(); i++)
result += array[i];
return result;
}
How can I do it properly? my feeling is that a thrust vector is designed for this type of task, but I want to do it properly. What is the standard CUDA approach to this task?
thrust::device_vector is not usable in device code.
However you can return a pointer to a dynamically allocated area, like so:
#include <assert.h>
template <typename T>
__device__ T* make_array(T zeta, int l)
{
int N =(int)(5*l+zeta); //the size of the array will depend on l and zeta, in a complex way...
T *ret = (T *)malloc(N*sizeof(T));
assert(ret != NULL); // error checking
//fill it:
//for(int i=0;i<N;i++)
// ret[i] = ...;
return ret;
}
The inline keyword should not be necessary. The compiler will aggressively inline functions wherever possible.

opengl -- how to call a function and draw it from the beginning (from menu option)

i have the following code ,which draws mandelbrot set.I created a menu with an option "black&white" which i want to draw the mandelbrot in black and white color.I haven't figured how to do this (if it can be done this way).mandelbrot is called through the display function ,but how can i call mandelbrot_black?
Also, if someone knows hot to make "zoom" in my code...here...http://stackoverflow.com/questions/5705554/how-to-do-zoom-in-my-code-mandelbrot
void mandelbrot();
void mandelbrot_black();
GLsizei width = 600;
GLsizei height = 600;
GLfloat AspectRatio;
int max = 500;
double xpos=0,ypos=0;
int CLEARFLAG=1;
double xmax = 2.0;
double xmin = -2.0;
double ymax = 2.0;
double ymin = -2.0;
using namespace std;
void display()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-2, width, -2, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT );
mandelbrot();
glutSwapBuffers();
}
void reshape(GLsizei w, GLsizei h) {
width=w; height=h;
glViewport(0,0,width,height);
glutPostRedisplay();
}
void setXYpos(int px, int py)
{
xpos=xmin+(xmax-xmin)*px/width;
ypos=ymax-(ymax-ymin)*py/height;
}
void mouse(int button, int state, int x, int y)
{
if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN) {CLEARFLAG=0; setXYpos(x,y);}
glutPostRedisplay();
}
void mandelbrot()
{
...}
void mandelbrot_black(){
...}
void mymenu(int n)
{
switch(n) {
case 1: zoom_in();break;
case 2: zoom_out();break;
case 3: mandelbrot_black();break;
case 4: exit(0);
}
glutPostRedisplay();
}
void SetupMenu()
{
glutCreateMenu(mymenu);
glutAddMenuEntry("zoom in",1);
glutAddMenuEntry("zoom out",2);
glutAddMenuEntry("black&white",3);
glutAddMenuEntry("exit",4);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutCreateWindow("Mandelbrot");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Your display function needs to draw either mandelbrot() or mandelbrot_black() depending on the current state (which can/should be a global variable).
//in global scope
static bool black = false;
...
//in display()
if(black)
mandelbrot_black();
else
mandelbrot();
Change black accordingly in mymenu(). You still need to attach your menu to a mouse button and call SetupMenu().