cocos3d dynamically create 3D box - cocos3d

I am new in cocos3d but i know cocos2d. i want to create 3d box dynamically. so what i did inside cc3layer is
-(void) initializeControls {
[self schedule:#selector(create_box:) interval:2 ];
}
-(void)create_box:(id)sender{
[self unschedule:#selector(mov_cel:)];
[[testWorld sharedcontescWorld] world_create_box];
}
and in cc3world class is
static testWorld *_sharedcontescWorld=nil;
+(testWorld *)sharedcontescWorld{
#synchronized([testWorld class]){
if (!_sharedcontescWorld)
[self alloc];
return _sharedcontescWorld;
}return nil;
}
+(id)alloc{
#synchronized([testWorld class]) {
_sharedcontescWorld = [super alloc];
return _sharedcontescWorld;
}return nil;
}
-(void) world_create_box{
int minx=-50;
int maxx=50;
float posx=(float)(minx+arc4random()%maxx);
CC3MeshNode* aNode;
aNode = [CC3BoxNode nodeWithName: #"Simple box"];
CC3BoundingBox bBox;
bBox.minimum = cc3v(-10.0, -10.0, -10.0);
bBox.maximum = cc3v( 10.0, 10.0, 10.0);
[aNode populateAsSolidBox: bBox];
[aNode setLocation:cc3v(posx,0,0)];
aNode.material = [CC3Material material];
[self addChild:aNode];
id move3d=[CC3MoveTo actionWithDuration:1 moveTo:cc3v(posx,0,100)];
id remove=[CCCallFuncND actionWithTarget:self selector:#selector(removeObj:)];
[aNode runAction:[CCSequence actions:move3d,remove,nil]];
}
but it doesn't work......can anyone help me?

Do you have a camera and light set up as well?
Without camera info it's a hard to tell, but I think you might either not be looking at the cube (camera missing or aimed wrong), or the cube is too big and you're inside it.
Try it with a camera and light, and some more modest sizes.
Here's some example code that worked for me in the cocos3d XCode project template:
// Create the camera, place it back a bit, and add it to the world
CC3Camera* cam = [CC3Camera nodeWithName: #"Camera"];
cam.location = cc3v( 0.0, 0.0, 10.0 );
[self addChild: cam];
// Create a light, place it back and to the left at a specific
// position (not just directional lighting), and add it to the world
CC3Light* lamp = [CC3Light nodeWithName: #"Lamp"];
lamp.location = cc3v( -2.0, 0.0, 0.0 );
lamp.isDirectionalOnly = NO;
[cam addChild: lamp];
float maxx=5.0;
float posx=CCRANDOM_MINUS1_1()*maxx;
CC3BoxNode* aNode;
aNode = [CC3BoxNode nodeWithName: #"Simple box"];
CC3BoundingBox bBox;
bBox.minimum = cc3v(-1.0, -1.0, -1.0);
bBox.maximum = cc3v( 1.0, 1.0, 1.0);
[aNode populateAsSolidBox: bBox];
[aNode setLocation:cc3v(posx,0.0f,-5.0f)];
aNode.material = [CC3Material material];
[self addChild:aNode];
id move3d=[CC3MoveTo actionWithDuration:1.0f moveTo:cc3v(posx*-1.0,0.0f,-5.0f)];
// id remove=[CCCallFuncND actionWithTarget:self selector:#selector(removeChild:)];
[aNode runAction:[CCSequence actions:move3d,/*remove,*/nil]];
Notes:
cocos3d readme has instructions to install the XCode project templates, if you haven't yet.
I replaced all the "Hello World" object code in the template with this stuff (note it's the same camera and light code/comments); you can leave it but you'll have some words in front of your box.
Changed CC3MeshNode to CC3BoxNode for clarity, but totally CC3MeshNode works too.
Replaced arc4random() with the cocos2d helper function
CCRANDOM_MINUS1_1() just for ease of reading (and to share this
cocos2d gem).
Commented out the CCFuncCallND because I didn't have a removeObj function. Hope you do. ;)
Hope that helps.

I have not started with cocos3d but I have found this code on stackoverflow that works
CC3BoundingBox bounds = makeBounds(9.5, 5.0, 4.0, 0, 0, 0);
CC3MeshNode *cube = [[CC3MeshNode alloc] init];
[cube populateAsSolidBox:bounds];

There is a CC3BoxNode class to help you do that. Eg:
CC3BoxNode *box = [CC3BoxNode nodeWithName:#"MyBox"];
[box populateAsSolidBox:CC3BoxMake(-1, -1, -1, 1, 1, 1)];
[self addChild:box];
This would create a 2x2x2 box with its origin point in its absolute center.
Hope that helps.

Related

QOpenGLWidget with custom framebuffer and multiple render targets

Related to my other question, I'm trying to render a segmentation mask to enable object picking. But I am not able to achieve the desired result.
Option 1 did not work at all. I was not able to retrieve the content of color attachment 1, or check if it existed at all (I created the attachment using only native OpenGL calls).
Using this post, I was able to reproduce the green.png and red.png images by creating a custom frame buffer with a second color attachment which is then bound and drawn to (all in paintGL()).
Somehow I had to use the person's frame buffer creation code because when I created the frame buffer myself there was always a warning saying toImage called for missing color attachment, although I attached the color attachment and textures() called on the frame buffer returned two objects. I then tried to insert my rendering code after
GLfloat red[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
f->glClearBufferfv(GL_COLOR, 0, red);
GLfloat green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
f->glClearBufferfv(GL_COLOR, 1, green);
but this still resulted in the red and green image. But the code renders fine when using the normal default framebuffer. I adapted the shader to (short version for testing purposes):
void main() {
gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0);
gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);
}
Since I was able to produce the red and green image, I'm assuming there must be a way to retrieve the frag data with this custom framebuffer. The solution I have right now is a complete (!) copy of the program and another dedicated fragment shader which's sole purpose is to render the segmentation, and perform all OpenGL draw calls a second time. As you can guess, this is a somewhat ugly solution, although the scenery is not that large and my computer is able to handle it easily. Has anyone got an idea/link?
If you want to write to multiple render targets in a Fragment shader, then you have to declare multiple output variables:
#version 330
layout(location = 0) out vec4 fragData0;
layout(location = 1) out vec4 fragData1;
void main()
{
fragData0 = vec4(1.0, 1.0, 1.0, 1.0);
fragData1 = vec4(0.0, 0.0, 0.0, 1.0);
}
From GLSL version 1.1 (#version 110, OpenGL 2.0) to GLSL version 1.5 (#version 150, OpenGL 3.2), the same can be achieved by writing to the built in fragment shader output variable gl_FragData.
void main()
{
gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0);
gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);
}
See also Fragment Shader Outputs - Through The Ages
To use multiple render targets in Qt, a 2nd color attachment has to be add to the framebuffer and the list of color buffers has to be specified by glDrawBuffers:
QOpenGLShaderProgram *program;
QOpenGLFramebufferObject *fb;
int fb_width;
int fb_height,
fb = new QOpenGLFramebufferObject( fb_width, fb_height );
fb->addColorAttachment( fb_width, fb_height );
glViewport(0, 0, fb_width, fb_height);
fb->bind();
glClearColor(0, 0, 0, 1);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
program->bind();
// ..... do the drawing
program->release();
fb->release();
The OpenGL texture objects which are attached to the framebuffer, can be accessed:
QVector<GLuint> fb_textrues = fb->textures();

Show image using babylonjs

I am new to Babylonjs and i want to display/show image using BabylonJs and also i want to move the image using keyboard(like left arrow key, right arrow key, up arrow key, and down arrow key) with collision detection and i also want to disable all mouse events .
I have wrote below code for showing image but i think that is not right way..
var playerMaterial = new BABYLON.StandardMaterial("ground", scene);
playerMaterial.diffuseTexture = new BABYLON.Texture("/images/mail.png", scene);
playerMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
player.material = playerMaterial;
player.position.y = 1;
player.position.x = -84;
player.size = 20;
Can someone help me how to do (if you can share the source code that may help even better)?
Thanks
Raviranjan
Your code looks basically right, assuming you also have a camera and light source. Here is a playground entry.
And, for posterity, here is that code:
var scene = new BABYLON.Scene(engine);
//Create a light
var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(-60, 60, 80), scene);
//Create an Arc Rotate Camera - aimed negative z this time
var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, 1.0, 210, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
//Creation of a repeated textured material
var materialPlane = new BABYLON.StandardMaterial("texturePlane", scene);
materialPlane.diffuseTexture = new BABYLON.Texture("textures/grass.jpg", scene);
materialPlane.specularColor = new BABYLON.Color3(0, 0, 0);
materialPlane.backFaceCulling = false;//Allways show the front and the back of an element
//Creation of a plane
var plane = BABYLON.Mesh.CreatePlane("plane", 120, scene);
plane.rotation.x = Math.PI / 2;
plane.material = materialPlane;
I started with one of their demos, then hacked away most of the stuff to get the minimal example. I left in the backFaceCulling = false (as otherwise the image is only visible from one direction), and added in your specularColor setting.
An alternative approach is to replace the diffuseTexture with emissiveTexture:
materialPlane.emissiveTexture = new BABYLON.Texture("textures/grass.jpg", scene);
Then you can comment out the light, and it will still be visible. (In fact, if you leave the light pointing at it, it will be overexposed.)
(I would recommend starting a new question for your keyboard control and collision detection questions. Or work through the babylon samples and tutorial videos.)
var playerMaterial = new BABYLON.StandardMaterial("ground", scene);
playerMaterial.diffuseTexture=new BABYLON.Texture("./yourImage.png", scene);
playerMaterial.bumpTexture=new BABYLON.Texture("./yourImage.png", scene);
i use that for parallax i help maybe

OpenGL + QT: render to texture and display it back

After some trouble I've managed to correctly render to texture inside a Frame Buffer Object in a Qt 4.8 application: I can open an OpenGL context with a QGLWidget, render to a FBO, and use this one as a texture.
Now I need to display the texture rendered in a QPixmap and show it in some other widget in the gui. But.. nothing is shown.
Those are some pieces of code:
// generate texture, FBO, RBO in the initializeGL
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// now in paintGL
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
// .... render into texture code ....
if(showTextureInWidget==false) {
showTextureInWidget = true;
char *pixels;
pixels = new char[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4];
glReadPixels(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
QPixmap qp = QPixmap(pixels);
QLabel *l = new QLabel();
// /* TEST */ l->setText(QString::fromStdString("dudee"));
l->setPixmap(qp);
QWidget *d = new QWidget;
l->setParent(d);
d->show();
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind
// now draw the scene with the rendered texture
I see the Widget opened but.. there is nothing inside it. If I decomment the test line.. I see the "dudee" string so I know that there is a qlabel but.. no image from the QPixmap.
I know that the original data are ´unsigned char´ and I'm using ´char´ and I've tried with some different color parameters (´GL_RGBA´, ´GL_RGB´ etc) but I don't think this is the point.. the point is that I don't see anything..
Any advice? If I have to post more code I will do it!
Edit:
I haven't posted all the code, but the fact I'd like to be clear is that the texture is correctly rendered as a texture inside a cube. I'm just not able to put it back in the cpu from gpu
Edit 2:
Thanks to the peppe answer I found out the problem: I needed a Qt object that accept as a constructor some raw pixels data. Here is the complete snippet:
uchar *pixels;
pixels = new uchar[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4];
for(int i=0; i < (TEXTURE_WIDTH * TEXTURE_HEIGHT * 4) ; i++ ) {
pixels[i] = 0;
}
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glReadPixels( 0,0, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
qi = QImage(pixels, TEXTURE_WIDTH, TEXTURE_HEIGHT, QImage::Format_ARGB32);
qi = qi.rgbSwapped();
QLabel *l = new QLabel();
l->setPixmap(QPixmap::fromImage(qi));
QWidget *d = new QWidget;
l->setParent(d);
d->show();
Given that that's not all of your code and -- as you say -- the texture is correctly filled, then there's a little mistake going on here:
glReadPixels(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);
QPixmap qp = QPixmap(pixels);
The QPixmap(const char *) ctor wants a XPM image, not raw pixels. You need to use one of the QImage ctors to create a valid QImage. (You can also pass ownership to the QImage, solving the fact that you're currently leaking pixels...)
Once you do that, you'll figure out that
the image is flipped vertically, as OpenGL has the origin in the bottom left corner, growing upwards/rightwards, while Qt assumes origin in the top left, growing to downwards/rightwards;
the channels might be swapped -- i.e. OpenGL is returning data with the wrong endianess. I don't remember in this case if using glPixelStorei(GL_PACK_SWAP_BYTES) or GL_UNSIGNED_INT_8_8_8_8 as the type may help, eventually you need to resort to a CPU-side loop to fix your pixel data :)

Cocos3d: Crashing when loading scene in separate thread or background thread:

I am trying to load several big models in code and show the scenes. Generally, it is taking long time for loading and showing scene on screen as it need to extract lot of resources from a pod model.
So, i thought of populate the first scene in main thread and remaining others in a separate thread. But, it is crashing when i move my part code into separate thread. Here is my sample code:
-(void) loadFirstScene
{
CC3PODResourceNode* podRezNode = [CC3PODResourceNode nodeWithName: #"FirstModel"];
podRezNode.resource = [IntroducingPODResource resourceFromFile: #"FirstModel.pod"];
podRezNode.shouldCullBackFaces = NO;
podRezNode.location = cc3v(0.0, -10.0, 0.2);
podRezNode.isTouchEnabled = YES;
[self addChild: podRezNode];
[NSThread detachNewThreadSelector:#selector(loadScenesInThread) toTarget:self
withObject:nil];
}
// Crashing if i add the below function in separate thread or background thread
-(void) loadScenesInThread
{
CC3PODResourceNode* podRezNode = [CC3PODResourceNode nodeWithName: #"SecondModel"];
podRezNode.resource = [IntroducingPODResource resourceFromFile: #"SecondModel.pod"];
podRezNode.shouldCullBackFaces = NO;
podRezNode.location = cc3v(0.0, -10.0, -5.0);
podRezNode.isTouchEnabled = YES;
[self addChild: podRezNode];
podRezNode = [CC3PODResourceNode nodeWithName: #"ThirdModel"];
podRezNode.resource = [IntroducingPODResource resourceFromFile: #"ThirdModel.pod"];
podRezNode.shouldCullBackFaces = NO;
podRezNode.location = cc3v(0.0, -10.0, -5.0);
podRezNode.isTouchEnabled = YES;
[self addChild: podRezNode];
// .. do more
}
Could someone guide me how would i handle such situation?
You can not create or access OpenGL resources in a thread that's different from the thread the OpenGL context was created on. Your only option is to use any "async" method cocos2d offers, or example for loading textures.

conversion from quickdraw to quartz 2D

I have an old code that uses,
Rect r;
GetPortBounds(some_bitmap,&r);
PixMapHandle somehandle = GetGWorldPixMap(some_bitmap);
if(LockPixels(somehandle)){
TPixel *data = (TPixel *) GetPixBaseAddr(somehandle);
long row_bytes = GetPixRowBytes(somehandle);
// doing something
UnlockPixels(somehandle);
}
Can anyone help me with the replacement code in quartz 2d
To modify a bitmap with Quartz you can initialize a CGContextRef with the image and draw to that context with CGContextDraw... routines.
(I wrote the following sample code for a NSView subclass. It's a bit inefficient. If you use the code, separate the stuff you can keep around in iVars.)
- (void)drawRect:(NSRect)dirtyRect
{
//Load an image ...
NSImage* image = [[NSImage alloc] initWithContentsOfFile:#"/Library/Desktop Pictures/Grass Blades.jpg"];
CGImageRef testImage = [[[image representations] objectAtIndex:0] CGImage];
[image release];
CGDataProviderRef dataProvider = CGImageGetDataProvider(testImage);
//... and retrieve its pixel data
CFDataRef imageData = CGDataProviderCopyData(dataProvider);
void* pixels = (void*)CFDataGetBytePtr(imageData);
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
//Init a quartz context that uses the pixel data memory as buffer
CGContextRef drawContext = CGBitmapContextCreate(pixels, CGImageGetWidth(testImage), CGImageGetHeight(testImage), CGImageGetBitsPerComponent(testImage), CGImageGetBytesPerRow(testImage), colorspace, CGImageGetBitmapInfo(testImage));
CGContextSetRGBFillColor(drawContext, 0.8, 0.8, 0.8, 1.0);
//Do something with the newly created context
CGContextFillRect(drawContext, CGRectMake(20.0, 20.0, 200.0, 200.0));
CGColorSpaceRelease(colorspace);
CGImageRef finalImage = CGBitmapContextCreateImage(drawContext);
//Draw the modified image to the screen
CGContextDrawImage([[NSGraphicsContext currentContext] graphicsPort], dirtyRect, finalImage);
CFRelease(imageData);
CGImageRelease(finalImage);
CGContextRelease(drawContext);
}

Resources