cocos3d Programming Guide

Why are you here??
 
Visit the wiki on the new, shinier, and vastly improved Cocos3D website, instead!!


The cocos3d framework is a sophisticated 3D application development framework for the iOS platform. This document describes the framework components and provides guidelines and best practices for building cocos3d iOS applications.

[toc=”2,3,4″ title=”In this Guide:”]

cocos3d is a significant extension to cocos2d, a popular, well-designed framework for building iOS games and applications that play out in 2D (or 2.5D isometric projection). Although on the one hand it is possible to start with the cocos3d Application template and develop a 3D application without knowing too much about the workings of cocos2d, to get the most out of this document, you should familiarize yourself with cocos2d. You can learn more about cocos2d at the cocos2d Wiki.

CC3Layer

CC3Layer is one of two key classes that each application will subclass and customize. The other class you will subclass and customize in your application is CC3World, described below.

Although cocos3d is a full 3D modeling and rendering engine, all 3D rendering occurs within CC3Layer, a special cocos2d CCLayer subclass. Since it is a type of CCLayer, instances of CC3Layer fit seamlessly into the cocos2d CCNode hierarchy, allowing 2D nodes such as controls, labels, and health bars to be drawn under, over, or beside 3D model objects. With this design, 2D objects, 3D objects, and sound can interact with each other to create a rich, synchronized audio-visual experience. CC3Layer acts as the bridge between the 2D and 3D worlds.

You can add a CC3Layer instance anywhere in the visual node hierarchy of a cocos2d application. Although for the purposes of most games, the CC3Layer instance will usually be sized to cover the complete screen, a CC3Layer instance can be set to any size and added to a 2D parent visual CCNode. So, your application could have a 2D scene that contains a smaller 3D scene embedded into it via a small CC3Layer instance attached to a parent 2D CCLayer.

Conversely, since CC3Layer is a type of CCNode, you can add child CCNodes to it as well, mixing 2D nodes on top or below the 3D scene that is playing out within the CC3Layer. Generally, this is the way most applications will combine 2D and 3D components, with a main 3D scene overlaid with 2D controls such as joysticks, fire buttons, dashboards, etc. Any CCNode that is added to the CC3Layer using the standard addChild: method will appear overlaid on top of the 3D scene. You can also add 2D CCNodes behind the 3D action as well, by using the addChild:z: method, with a negative Z-order. Although this is generally not a common requirement, it can be used to provide a 2D skybox behind the 3D action.

When customizing your application’s subclass of CC3Layer, you will typically override the following two template methods:

  • initializeControls – this method is where you can add your 2D controls into the CC3Layer, and otherwise generally initialize your layer. This method is invoked automatically from any of the init methods of the layer.
  • update: – if you have scheduled regular updates using the standard CCNode scheduleUpdate method, this update: method will be called periodically. This is where you can update any of the 2D controls you’ve added, or pass data from dynamic controls such as sliders or joysticks to your CC3World instance. If you override this method, be sure to call invoke the superclass implementation so it can pass the update notice to the CC3World instance.

CC3World

Although CC3Layer forms the bridge between the 2D and 3D visual worlds, it remains primarily a cocos2D layer, and no 3D activity actually takes place within CC3Layer. All 3D activity, from model management to rendering, takes place within, and is the responsibility of, your application’s customized CC3World subclass.

As with CC3Layer, there are several key template methods that you will typically override in your application’s subclass of CC3World:

  • initializeWorld – This method is where you populate the 3D models of your world. This can be accomplished through a combination of instantiting model objects directly and loading them from model data files exported from a 3D editor. The CC3World instance forms the base of a structural tree of nodes. Model objects are added as nodes to this root node instance using the addChild: method.
  • updateBeforeTransform: and updateAfterTransform: – If you have scheduled regular updates through CCLayer, these CC3World methods will be invoked automatically as part of the scheduled update, respectively before and after the transformation matrices of the nodes of the world have been recalculated, respectively, and before and after the same methods are invoked on the descendants of your CC3World.
  • nodeSelected:byTouchEvent:at: – If your application is configured to support allowing the user to select 3D nodes using touch events, this template callback method will automatically be invoked when a touch event occurs. See the section on touch events for more information about handling the selection of 3D nodes by user touch events.

As the names imply, the difference between the two update methods is that updateBeforeTransform: is invoked before the transformation matrix of the node is recalculated, whereas the updateAfterTransform: is invoked after. Therefore, if you want to move, rotate or scale a node, you should do so in the udpateBeforeTransform: method, to have your changes automatically applied to the transformation matrix of the node.

However, the global transform properties of each node (globalLocation, globalRotation, and globalScale) are determined as part of the calculation of the transformation matrix of that node. Therefore, if you want to make use of the current global properties, you should do so in the updateAfterTransform: method. The global properties of a node can be used to test for collisions, or end conditions of movements, etc.

Sometimes, you may find the need to change the location, rotation, or scale properties of a node in the updateAfterTransform: method, for example as part of collision detection and reaction. If you do, you should invoke the updateTransformMatrices method on the top-most node that is affected, to have those changes immediately applied to the transformation matrix.

You do not need to do anything in either update methods for 3D objects that are acting predictably, such as those on trajectories, or those controlled by CCActions. Their behaviour is handled by the nodes and actions themselves.

In addition to these main template methods, you may find the following CC3World methods useful during operation, or simply useful to understand:

  • addChild: – Familiar from cocos2d, you can add child nodes (CC3Nodes) to your 3D world.
  • addContentFromPODResourceFile: & addContentFromPODFile: –  These are convenience methods for loading POD files directly into the CC3World, and are added by the PVRPOD category if your application uses the module for loading 3D models from POD formatted files.
  • getNodeNamed: – Retrieves the node with the specified name that was previously added to the 3D world. Useful for grabbing hold of a node that was added as part of a file load.
  • activeCamera – Property returns (or sets) the 3D camera that is viewing the objects in the 3D world. You do not need to set this property. It will be automatically set to the first camera node added via one of the add... methods (even if the camera is buried deep within a loaded node hierarchy). However, if you have multiple cameras, you can flip between them by setting this property.
  • ambientLight – This is the color of the ambient light of the 3D world. This is independent of any distinct lights that are added as child nodes.
  • createGLBuffers – This method causes all contained vertex data held by contained mesh nodes to be buffered to Vertex Buffer Objects (VBO’s) in the GL engine and usually into hardware buffers accessible to the GPU. This is an optional step, but highly recommended for improving performance. You can also invoke this method at any level in the node structural hierarchy if for some reason you want to load some, but not all, mesh data in the 3D world into VBO’s.
  • releaseRedundantData – After the createGLBuffer method has been invoked, this method can be used to release the data in main memory that is now redundant for meshes that have been buffered to the GL engine. You can also invoke this method at any level in the node structural hierarchy if for some reason you want to release some, but not all, mesh data from main memory. You can also exempt individual vertex arrays from releasing data by setting the shouldReleaseRedundantData property to NO on the individual vertex array.
  • updateTransformMatrices – If you make changes to the location, rotation and scale properties of a node within the updateAfterTransform: method, those changes will not automatically be applied to the transformation matrix of the node, since it has already been calculated when the udpateAfterTransform: method is invoked. However, you can use the udpateTransformMatrices to have those changes immediately applied to the transformation matrices of a node and all its descendants.
  • play & pause – these enable the operation of the update: method. When the CC3World is paused, the updateBeforeTransform: and updateAfterTransform: methods are skipped, along with updates of all other 3D nodes.
  • cleanCaches – automatically invoked during low memory conditions within the application. This gives you the chance to dump any unneeded resources, for example, 3D objects that are far away, not part of this scene, etc.

Many of the responsibilities handled by CC3World are divided by the implementation into private template methods that you can override in your subclass, to customize behaviour in a modular way.

CC3Node

All the objects in the 3D world, including models, cameras, lights, and the CC3World itself, are known as nodes. CC3Node is the base of the 3D node class hierarchy. Nodes can be assembled into structural assemblies using parent/child relationships. Moving, rotating, or hiding a node moves, rotates or hides all the children (and other ancestors) in concert.

This design will no doubt feel familiar to you as being analogous to CCNodes in cocos2d, and the two node hierarchies do follow the same design pattern. However, CCNodes and CC3Nodes cannot be mixed in the same structural assembly, primarily because CC3Nodes must keep track of location, rotation and scaling in three dimensions instead of two. Nevertheless, the structural concepts between the two node families are consistent.

You assemble 3D nodes using the addChild: method. All nodes have an identifying tag and can have a name. You can retrieve a specified node in an assembly with the getNodeNamed: and getNodeTagged: methods.

All nodes have location, rotation, and scale properties (plus a couple of others). You move, rotate, and scale CC3Nodes by setting these properties. And, again, as with cocos2d nodes, the values of these properties are measured relative to the node’s parent node.

You can override the updateBeforeTransform: and updateAfterTransform: methods of a node subclass that acts predictively, such as those following a trajectory, to update these transform properties. See the discussion on CC3World above regarding the difference between these two methods.

So, the wheels of a car can be child nodes on a car node. Each wheel node can rotate on its axis, and move up and down relative to the car as if on suspension via the location property of each wheel node, and all the while, the whole car assembly may be travelling and bouncing down a dirt road simply by manipulating the location property of the car node.

Any node can be the target of a CCAction, to simply and easily control the movement and behaviour of the node in sophisticated ways. In addition, any node may be configured to respond to finger touch events by the user. See the sections on actions and touch events for more information on this interactivity.

You can use the createGLBuffers method to cause all contained vertex data held by contained mesh nodes to be buffered to VBO’s in the GL engine. Generally, you should invoke this method at the highest level in the structure, CC3World, but you can also invoke this method at any level in the node structural hierarchy if for some reason you want to load some, but not all, mesh data in the 3D world into VBO’s. Once data is loaded into GL VBO’s, you can use the releaseRedundantData method to release the data from your main application memory.

CC3MeshNode

CC3MeshNode puts the ‘3’ in 3D. An instance of CC3MeshNode contains the 3D mesh data for a 3D object, plus the material, texture, or solid color that covers the surface of the object.

Each CC3MeshNode instance can be covered in only a single material, texture, or color. However, like any node, mesh nodes can be assembled into a node structure. Moving the parent node will move all of the child mesh nodes in concert, along with their materials and textures. So, a multi-colored beach-ball could be one parent node and several child mesh nodes, each corresponding to a differently colored panel on the beach-ball. The parent ball node can be moved, rotated and scaled, and all component mesh nodes will be affected in unison.

Materials, Textures and Colors

The visible characteristics of the surface of a mesh node is determined by either the material it is covered with, or the pure, solid color it is painted with. As mentioned above, each mesh node can be covered with only one material, or one solid color.

The mesh node holds an instance of a CC3Material to describe the visual characteristics of the surface of the mesh. CC3Material includes properties to set the various coloring characteristics of the surface, including the ambient, diffuse and specular reflective colors, the emissive color, and the surface shininess. It also includes properties to determine how the colors should blend with the colors from objects behind the mesh node, permitting effects such as translucency.

In addition to basic coloring, each CC3Material instance can hold an instance of CC3Texture to cover the surface of the mesh with a texture image.

The combination of coloring properties, blending properties, and textures interact with lighting conditions to create complex and realistic surface visual characteristics for the mesh.

There are two mechanisms for changing the coloring and opacity of a material covering a mesh node.

  • To achieve the highest level of detail, accuracy and realism, you can individually set the explicit ambientColor, diffuseColor, specularColor, emissiveColor, shininess, sourceBlend, and destinationBlend properties. This suite of properties gives you the most complete control over the appearance of the material and its interaction with lighting conditions and the colors of the objects behind it, allowing you to generate rich visual effects.
  • At a simpler level, CC3Material also supports the cocos2d <CCRGBAProtocol> protocol. You can use the color and opacity properties of this protocol to set the most commonly used coloring and blending characteristics simply and easily. Setting the color property changes both the ambient and diffuse colors of the material in tandem. Setting the opacity property also automatically sets the source and destination blend functions to appropriate values for the opacity level. By using the color and opacity properties, you will not be able to achieve the complexity and realism that you can by using the more detailed properties, but you can achieve good effect with much less effort. And by supporting the <CCRGBAProtocol> protocol, the coloring and translucency of nodes with materials can be changed using standard cocos2d CCTint and CCFade actions, making it easier for you to add dynamic coloring effects to your nodes.

If the mesh node does not contain a material, it will be painted with the color defined in the pureColor property. This color is painted as is, pure and solid, and is not affected by the lighting conditions. In most cases, this looks artificial, and is not recommended for realistic scene coloring. But in some circumstances, such as cartoon effects, it may be useful.

CC3MeshModel

Underpinning CC3MeshNode is CC3MeshModel, which in turn holds the raw vertex data in several CC3VertexArray instances. The management of mesh data is spread across these three classes (CC3MeshNode, CC3MeshModel, and CC3VertexArray) to enable data reuse and reduce memory requirements. A single mesh model instance can be used in any number of individual mesh nodes, each covered with a different material, and placed in a different location. Whether you’re talking about hordes of zombies, or a twelve-place dinner setting laid out on a table, a single mesh model instance, with one copy of the raw vertex data can be reused in an number of similar nodes.

CC3VertexArrays

Each mesh model instance (typically an instance of the concrete subclass CC3VertexArrayMeshModel) holds several CC3VertexArray instances, one for each type of vertex data, such as vertex locations, normals, vertex colors, texture coordinate mapping, and vertex indices. And reuse can be applied at this level as well. A single vertex array instance can be attached to many mesh models. So, if you have the need for two teapot meshes, one textured, and one painted a solid color, you can use two separate instances of CC3VertexArrayMeshModel, each containing the same instances of the vertex locations and vertex normals arrays (CC3VertexLocations and CC3VertexNormals, respectively), but only the mesh model for the textured teapot would also contain a texture coordinate vertex array (CC3VertexTextureCoordinates) instance. With this arrangement, there is only ever one copy of the underlying vertex data.

CC3LineNode & CC3PlaneNode

CC3LineNode and CC3PlaneNode are specialized subclasses of CC3MeshNode that simplify the creation and drawing of lines and planes using vertex arrays, respectively.

Duplicating 3D Models

In order to allow you to create hordes of invading armies, the CC3Node class supports the <NSCopying> protocol. To duplicate a node is simply a matter of invoking the copy method on that node. In addition, there is a copyWithName: method that duplicates the node, and gives the new copy its own name.

Copying a CC3Node creates a deep copy. This means that not only is the node itself copied, but copies are created of most components of the node, including the material, and any descendant child nodes. This allows the properties and structure of the duplicate node to be changed separately from those of the original node. For instance, the new node can be positioned, rotated, scaled, colored, or assigned a different texture from that of the original. Similarly, the child nodes of the duplicate may be modified separately, without affecting the original, or any other copies. You can copy an automobile node, and remove one of the wheels of the duplicate, while retaining all four wheels on the original. If a deep copy were not performed, changing parameters in the duplicate node, or its children, would result in the same changes appearing in all other copies of the original node.

There is one big exception to this deep copying. Since mesh data is for the most part static, and is designed to be shared between instances of CC3MeshNode, mesh data is not copied, but is automatically shared between the original node and all its copies. Specifically, when an instance of CC3MeshNode is copied, a copy is made of the encapsulated CC3Material instance and is retained by the duplicate node, but the encapsulated CC3MeshModel is not duplicated. Instead, the single CC3MeshModel instance is retained by both the original node and the duplicate, and is henceforth shared by both nodes. This shallow-copying of the mesh data ensures that only one copy of the mesh data appears in the device memory.

The following additional rules apply to duplicating a CC3Node:

  • The tag property is not copied. The duplicate node is assigned a new unique value for its tag property. This is to ensure that the tag property is unique across all nodes, including duplicates, and allows you to identify a duplicate as distinct from the original, even if the name property is left the same.
  • The duplicate will initially have no parent. That will automatically be set when the duplicate node is added as a child to a parent node somewhere in the world. This applies to the specific node on which the copy or copyWithName: method was invoked. Any descendants of this node will be assigned to their parents after they are copied, so that the overall structure of the node assembly below the invoking node will be replicated in its entirety.
  • Like mesh data, underlying textures are not duplicated (although the CC3Texture instance itself is). Nor is node animation data duplicated.

If you create your own subclass of CC3Node, or any of its existing subclasses, and your new subclass adds state, you must implement the populateFrom: method, including invoking the same superclass method as part of it, to ensure that state is transferred correctly from the original node to the duplicate, whenever an instance of your node class is duplicated.

CC3Camera & CC3Light

These are special nodes that represent the camera and lights in the 3D world. Cameras and lights are directional, and are examples of CC3TargettingNode, which, in addition to being able to move and rotate like other nodes, can be assigned a target or targetLocation at which to point. A target can be any other CC3Node in the scene, and the camera or light can be told to track the target as it moves.

Controlling CC3Nodes with CCActions

If you’ve used cocos2d, you’re no doubt familiar with the family of CCActions, used to control the movement, coloring, visibility, and activities of CCNodes.

In cocos3d, CC3Nodes can similarly be manipulated and controlled by CCActions. Some features, such as tinting and fading can manipulated by standard cocos2d actions. However, because the 3D coordinate system is different than the 2D coordinate system, specialized 3D versions of movement, rotation, scaling, and animation actions are required. This family of 3D actions can be found as subclasses of the base CC3TransformTo interval action. In addition, there are several cocos3d action subclasses that handle material-tinting.

The 3D family of actions can, of course, be used with standard cocos2d combination actions such as the family of ease actions, sequence actions, etc.

CC3Node Animation

Any CC3Node can be animated with key-frame animation data held in a CC3NodeAnimation instance within the CC3Node instance. Typically, this animation data is loaded from the 3D model files exported from your 3D editor, but you can also assemble this data programmatically using the simple CC3ArrayNodeAnimation subclass of CC3NodeAnimation. Like mesh data, the CC3NodeAnimation instances are stateless, and each may be shared by multiple CC3Node instances, so that animation data need not be duplicated redundantly.

Any or all of the transformation properties: location, rotation, and scale, may be animated using CC3NodeAnimation or CC3ArrayNodeAnimation. If you need to animate other characteristics of your nodes, you can subclass these classes to add additional animation capabilities.

Once animation data is associated with a CC3Node, the node can be animated with repeated invocations of the establishAnimationFrameAt: method on the node itself, passing in a frame time, which is a floating point value between zero and one, with zero representing the first animation frame, and one representing the last animation frame.

In order to perform smooth animation, by default, the CC3NodeAnimation will interpolate animation data between frames if the timing value passed in through the establishAnimationFrameAt: method is between actual frame times. This is controlled by the shouldInterpolate property on the CC3NodeAnimation instance. By default, this property is set to YES, but may be set to NO if heavy interpolation interferes with frame rates.

For node assemblies, you will typically want to animate the whole assembly in concert. To support this, the establishAnimationFrameAt: method automatically invokes the same method on each child node, passing the same animation frame time to each child node. Thus, animating a character, by invoking that method on the character node itself, will automatically forward the same invocation to each component child node of the character, such as the character’s limbs, or any weapon the character might be holding. As a result, all components of the character will move in sync with the character, as it is animated.

However, you can turn animation of any node in the assembly off, including selectively turning off animation of specific child nodes, via the disableAnimation method on that child node. You can turn the animation of whole sub-assemblies of nodes off via the disableAllAnimation method.

Fractional animation of individual movements is possible by simply limiting the range of frame times that are sent with the establishAnimationFrameAt: method. For example, if your character animation includes a run frame sequence and a jump frame sequence, you can invoke one or the other by simply starting and ending your animation at the frame times associated with the specific movement you want to invoke.

Controlling Animation with Actions

Although you can arrange to invoke the establishAnimationFrameAt: method of your animated CC3Node directly, in most cases it is much easier to use an instance of CC3Animate to control the animation of a node.

CC3Animate is a type of CCActionInterval, and will run through the animation frames automatically over a configurable time duration. Moreover, when instantiating the CC3Animate, you can restrict the frames to a particular range, to allow fractional animation of specific movements.

Selecting CC3Nodes with User Touch Events

To allow the user to interact with the objects in your 3D world, you can enable the selection of 3D objects using standard iOS finger touch events.

The first step in enabling touch activity is to set the isTouchEnabled property of the CC3Layer to YES. Typically you will do this in the initializeControls method of your customized CC3Layer class. This causes the CC3Layer to register itself to receive touch events from iOS.

As such, your CC3Layer will receive and process kCCTouchBegan, kCCTouchEnded, and kCCTouchCancelled events. By default, your CC3Layer will not receive or process kCCTouchMoved events, because these are both quite voluminous and seldom used. However, you can configure your customized CC3Layer subclass to receive and handle kCCTouchMoved events by copying the commented-out ccTouchMoved:withEvent: method from the CC3Layer implementation and paste it into the implementation of your customized CC3Layer subclass, with the commenting removed.

The second step is to set the isTouchEnabled property to YES, in any CC3Nodes that you want the user to be able to select with a touch event. So, for example, let’s say your 3D world had a bowl of fruit on a table, you might want the user to be able to select a piece of fruit, but not the bowl or the table objects. In this case, you would set the isTouchEnabled property to YES on the CC3Node instances representing each piece of fruit, but not on the CC3Node instances that represent the bowl or table. Please also note that, to be touchable, the node must have its visible property set to YES.

Once these two steps have been completed, the nodeSelected:byTouchEvent:at: callback method of your customized CC3World subclass will automatically be invoked on each touch event. This callback includes the CC3Node instance that was touched, the type of touch, and the 2D location of the touch point, in the local coordinates of the CC3Layer.

If the touch occurred at a point under which there is no touchable CC3Node, the callback nodeSelected:byTouchEvent:at: method will still be invoked, but the node will be nil, to indicate that a touch event occurred, but not on a touchable node.

For node assemblies, the node passed to the nodeSelected:byTouchEvent:at: method will not necessarily be the individual component or leaf node that was touched. Instead, it will be the closest structural ancestor of the leaf node that has its isTouchEnabled property set to YES.

For example, if the node representing a wheel of a car is touched, it may be more desireable to identify the car as being the object of interest to be selected, instead of the wheel. In this case, setting the isTouchEnabled property to YES on the car, but leaving it as NO on each wheel, will allow a wheel to be touched, but the node received by the nodeSelected:byTouchEvent:at: callback will be the node that represents the car as a whole.

Selection Artifacts

When using translucent nodes, you might notice that when a translucent node is displayed over the raw background color of the CC3Layer, it will appear to flicker slightly when a touch event occurs. This is a side effect of the mechanism used to identify the 3D node that is under the 2D touch point.

The selection mechanism uses a color-picking algorithm, which momentarily paints each node with a unique color and then reads the color at the touch point to identify the node. The scene is then immediately drawn a second time with proper coloring. Since this second scene rendering occurs within the same rendering frame as the first, the second rendering completely overwrites the first, and the user is completely unaware than the first pass occurred.

The only exception to this is when a translucent node has no opaque nodes behind it. In this case, because the underlying layer background color is not redrawn on the second rendering pass, some of the solid coloring used to paint the node during the selection rendering pass will “leak through” the transparency of the second rendering pass. In effect, for one frame, the translucent node does not have the layer background color behind it, causing a momentary flicker.

It is important to realize that this effect does not occur when the translucent node has opaque nodes behind it in the 3D scene. This is because the opaque background nodes will be redrawn as well, and it will be these background nodes that will be seen through the translucent node, as they should be.

Therefore, if you have translucent nodes and are using touch selection, to avoid this slight flicker be sure to include an opaque skybox node at the back of your 3D scene, over which the other nodes of your scene will be drawn.

Projecting 3D Locations to 2D

The projectedLocation property of CC3Node holds the location of the 3D node in the 2D coordinate system of the window. It acts as a bridge between the 3D coordinate system and the 2D coordinate system. Knowing the projectedLocation of a 3D node allows you to relate it to a 2D controls such as a targetting reticle, or to a touch event.

The projectedLocation is a 3D vector. As you would expect, the X– and Y-components provide the location of the 3D node on the screen, in the 2D coordinate system of the CC3Layer. If the 3D node is located somewhere out of the view of the camera, and therefore not displayable within the layer, these values will be outside the range given by the contentSize of the CC3Layer. Following from this, either coordinate value may be negative, indicating that the node is located to the left, or below, the view of the camera.

The Z-component of the projectedLocation contains the straight-line distance between the 3D node and the camera, as measured in the coordinates of your 3D world. This value may be negative, indicating that the 3D node is actually behind the camera. In most cases, of course, you will be interested in nodes that are in front of the camera, and the Z-component of the projectedLocation can help you identify that.

CC3Node also supports the related projectedPosition property. It is derived from the projectedLocation property and, for the most part, contains the same X– and Y– coordinates as projectedLocation, but as a 2D CGPoint, which is immediately usable by the cocos2d framework.

However, as a 2D point, the projectedPosition lacks the needed ability to distinguish whether the node is in front of, or behind, the camera. Since this information is almost always needed, the point is encoded so that, if the 3D node is actually behind the plane of the camera, both the X– and Y-components of the projectedPosition will contain the large negative value -CGFLOAT_MAX. If you use projectedPosition, you can test for this value to determine whether the 3D node is in front of, or behind, the camera.

For most nodes, these properties are not calculated automatically. In the update: method of your CC3World you can have them calculated for a node of interest by passing the node to the projectNode: method of the activeCamera.

However, for CC3Billboard nodes, the projectedLocation and projectedPosition properties are calculated automatically on each update. A CC3Billboard is a 3D node that can hold an instance of a 2D cocos2d CCNode, and display that 2D node at the projectedPosition of the CC3Billboard node. Since the 2D node is drawn in 2D, it always appears to face the camera, and is always drawn over all 3D content. The contained CCNode can be any cocos2d node, and it can be configured to automatically scale to the correct perspective sizing, shrinking as the CC3Billboard moves away from the camera, and growing as the CC3Billboard approaches the camera. A common use of CC3Billboard is to display information about a 3D node, such as a textual name label or a health-bar for a game character.

Pluggable 3D Model Loading

Sophisticated 3D games are dependent on loading 3D models from resources created in 3D editors such as Blender, Cheetah3D, Maya, 3ds Max, and Cinema 4D. Since the number of possible file formats is significant, and can evolve, the loading of model data is handled by pluggable loaders and frameworks. When building your application with cocos3d, you only need to include the loaders that you use.

The pluggable loading framework is based around two template classes:

  • The resource class, which takes care of loading and parsing the 3D data file, creating instances of nodes, mesh models, vertex arrays, materials, textures, cameras, lights, etc., and assembles them into a node hierarchy. This will be a subclass of CC3Resource, and is tailored to parsing and assembling a specific data file format.
  • The resource node class. This will be a subclass of CC3ResourceNode, and as such, is actually a type of CC3Node. It wraps the CC3Resource instance, extracts populated nodes from it, and adds them as child nodes to itself. This node can be used like any other CC3Node instance, and is usually simply added as a child to your CC3World instance. You can move, rotate, scale, or hide all the components loaded from a file simply by manipulating the properties of the CC3ResourceNode instance.

In addition to these two template classes, a pluggable loading package will usually contain specialized subclasses of  CC3MeshNode, CC3Material, CC3Camera, etc., in order to set the properties easily from the data loaded from the file. But once created, these objects behave like any other node of their type.

A pluggable loading package may also add categories to base classes as a convenience. Thus, the PowerVR POD file loading package adds a category to CC3World that adds the method addContentFromPODResourceFile: as a convenience for loading POD files directly into your CC3World.

The initial loading package available with cocos3d is for PowerVR POD files.

Automatic Frustum Culling and Bounding Volumes

In a 3D world, the camera is always pointing in some direction, and generally, is only seeing a fraction of the objects in the 3D world. It is therefore a waste of precious time and resources to try to draw all of these objects that will not be seen.

The task of determining which objects don’t need to be drawn, and then removing them from the rendering pipeline is known as culling. There are two types of culling: frustum culling, which is the removal of objects that are not within the field of view of the camera, and occlusion culling, which is the removal of objects that are within the field of view of the camera, but can’t be seen because they are being visually blocked by other objects. For example, they might be located in another room in your the map, or might be hiding behind a large rock. At this time, cocos3d does not perform any kind of occlusion culling.

cocos3d performs frustum culling automatically. Objects that are outside the view of the camera will not be drawn. This is accomplished by specifying a bounding volume for each mesh node. Each node holds onto an instance of a CC3NodeBoundingVolume, which it delegates to when determining whether it should draw itself to the GL engine. All mesh nodes in cocos3d have a default bounding volume that is reasonably accurate, and for the most part, you won’t even need to think about bounding volumes. However, we’ll describe the operation of bounding volumes here, for those situations where the application may want to improve on the default behaviour.

The trick with bounding volumes is to strike a balance between the time it takes to determine whether a node should be rendered, and the time it would take to simply blindly render the object. To that end, different kinds of bounding volumes can be specified, some of which are very fast, but perhaps less accurate, and others that are very accurate, but time consuming.

Accuracy is important because acn inaccurate bounding volume can either result in the effort of rendering an object being performed when the objects won’t be seen, or worse, an object might be culled, when in fact at least part of it would really be seen if it were drawn. This second type of inaccuracy, over-zealous culling results in objects strangely popping in and out of existence, particularly around the edges of the camera’s field of view. Since this behaviour is generally undesirable, you should stay away from creating bounding volumes that are overly-zealous. The bounding volumes included by default in cocos3d always ensure that all vertices are included within the bounding volume, so that objects are never culled when they are actually partially visible.

The family of cocos3d bounding volumes includes a number of different subclasses, each performing a different type of boundary test. The two most commonly used are a spherical bounding volume, represented by subclasses of CC3NodeSphericalBoundingVolume, and axially-aligned-bounding-box (AABB) bounding volumes, represented by subclasses of CC3NodeBoundingBoxVolume.

Checking spherical boundaries against the camera frustum is very fast. However, for most non-spherical real-world 3D objects, such as a human character, or automobile, a sphere that completely envelopes the object is much larger than the object. The result is that near the periphery of the camera’s view, the sphere may be partially inside the frustum, but the object is not. The result is that the object will be rendered (because the sphere can be “seen” by the camera), even though the object itself will not be seen.

Bounding boxes are often more accurate for many real-world objects, but are more expensive to test against the camera frustum, because all eight points that define the volume must be tested against the frustum.

At the extreme end of the scale, the most accurate bounding volume would be to test every single vertex in the mesh against the camera’s frustum. By definition, this will result in almost perfect accuracy, but at the large cost of testing all the vertices. In many cases, since the GPU can generally do this faster than the CPU, there is no cost savings in testing all vertices. For this reason, cocos3d does not yet include a default all-vertex bounding volume test. However, such a bounding volume could easily be added and used by the application.

Bounding volumes, whether they be point, spherical, boxes, or custom, are calculated and defined automatically by the vertices in the mesh node. In addition, they scale automatically as the node is scaled.

Finally, to make use of both fast boundary tests to exclude objects that are clearly far from the camera’s field of view, and also more accurate boundary tests for objects that are at the edges of the camera’s field of view, cocos3d also includes the CC3NodeTighteningBoundingVolumeSequence bounding volume. Instances of this class hold an array of other bounding volumes, and tests the node against them in sequential order. As soon as one contained bounding volume indicates that the node is definitely outside the camera’s field of view, the node is rejected and not drawn.

The trick is to order the contained bounding volumes so that fast, but broad, tests are performed early in the sequence, so they can reject the node if it is clearly nowhere near the camera’s field of view. Subsequent bounding volumes in the sequence should be less broad, but will not be tested unless the earlier bounding volumes have accepted the node as being visible.

By default, mesh nodes in cocos3d make use of a tightening sequence that contains first a spherical bounding volume and then an AABB bounding volume. For the most part, this will likely be sufficient, and you won’t even have to think about bounding volumes. However, some applications may benefit from custom bounding volumes.

Rendering Order

The underlying OpenGL ES engine uses a pipeline of commands for manipulating the state of the rendering engine. The switching of some states can be a costly exercise. Consequently, it is often useful for the application to consider the order in which objects are rendered to the engine. For example, if several objects make use of the same texture, it is usually beneficial to draw all of these objects one after the other, before drawing an object that is covered with a different texture.

To that end, the drawing order of the objects within a CC3World can be configured by the application for optimal performance. The CC3World instance holds onto an instance of a CC3NodeSequencer, and delegates the ordering of nodes for drawing to that sequencer. If no node sequencer is supplied to the CC3World, the world will draw nodes hierarchically, following the structural hierarchy of its children. In most cases, this will not be the optimal ordering.

As with bounding volumes discussed above, there are a number of different types of node sequencers, and establishing a different ordering is simply a matter of plugging and configuring a different sequencer into your CC3World.

There are two key types of sequencers, CC3NodeArraySequencers, which hold a collection of nodes, grouped in some defined order, and CC3BTreeNodeSequencers, which hold a B-tree of other sequencers, allowing groupings of groupings of nodes, ad infinitum. You can assemble a complex sequence definition, by assembling different types of sequencers into a structural B-tree hierarchy.

Every sequencer contains in instance of a CC3NodeEvaluator subclass. A node evaluator tests a node against some criteria, and returns a boolean result indicating whether the node is accepted or rejected, effectively giving each sequencer a chance to answer the question “Do you want this node?”. Using this mechanism, a B-tree sequencer can determine which of its child sequencers wants to take care of ordering any particular node.

A simple example might help here. Both Imagination Technologies (the supplier of the iOS GPU’s) and Apple recommend that all opaque objects should be drawn before translucent objects. In addition, the translucent objects themselves should be drawn in Z-order, which is the reverse order of distance from the camera, with the farther translucent objects being drawn first, and the nearer translucent objects drawn over them.

This drawing order can be accomplished with a B-tree sequencer containing two array sequencers: the first with an evaluator that tests the node for opacity, and the second with an evaluator that tests the node for translucency. The array sequencer holding the opaque nodes can simply hold them in the order they are added. However, the array sequencer holding the translucent nodes needs to order the nodes by their Z-order.

This structure looks as follows:

  • CC3BTreeNodeSequencer (CC3LocalContentNodeAcceptor)
    • CC3NodeArraySequencer (CC3OpaqueNodeAcceptor)
    • CC3NodeArrayZOrderSequencer (CC3TranslucentNodeAcceptor)

When testing a node, the B-tree sequencer will first ask the child sequencer with the opacity test if it is interested in the node, before asking the second sequencer. The result is that the first sequencer will contain opaque nodes in the order they were added, and the second will contain translucent nodes in Z-order.

Because nodes may be moving around from frame to frame, be aware that Z-ordering requires that the nodes in the CC3NodeArrayZOrderSequencer be sorted on each and every frame update. This can have significant performance implications if there are a large number of translucent nodes. To improve performance, ensure that translucent nodes really are visibly translucent (don’t waste time sorting translucent nodes that can’t be seen as translucent by the user), and keep the number of translucent nodes to a minimum.

The requirement that this example illustrates is so common that CC3BTreeNodeSequencer includes the class method sequencerLocalContentOpaqueFirst, to create just such a sequencer assembly. There are also the class methods sequencerLocalContentOpaqueFirstGroupTextures and sequencerLocalContentOpaqueFirstGroupMeshes, which take the concept a bit further and group the opaque nodes so that opaque nodes with the same texture or mesh are drawn together, one after the other, before other opaque nodes are drawn. As above, in each of these sequencers, the translucent nodes are sorted by Z-order.

By default, CC3World uses a sequencer created by the sequencerLocalContentOpaqueFirst method, thereby drawing opaque nodes first, in the order they were added, then translucent nodes in Z-order.

Updating vs Drawing

By design, both cocos2d and cocos3d support a clear separation between updating and drawing activities, and each is invoked on a separate loop. In addition to helping to keep your application code organized, there are good performance reasons for separating updating from drawing. OpenGL ES is designed as a state engine pipeline, designed for a steady stream of rendering commands, with ideally no data traveling back upstream to the application. This allows the GPU to keep its own time. Keeping the application rendering loop lean and mean, helps the GPU operate at the full frame rate, and leaves open options for scaling back the update rate separately if needed, or breaking the update loop into several passes, or possibly even multi-threading the updates, in extreme cases.

With all this in mind, you should keep the code you write in the updateBeforeTransform: and updateAfterTransform: methods of any CC3Node subclass free of drawing or rendering operations. Similarly, should you override the drawWithVisitor: or draw methods in any CC3Node subclass, you should only perform rendering operations, and keep those methods free of model updates.

OpenGL ES State Management

As mentioned above in the discussion of rendering order, the performance of the OpenGL ES state machine pipeline is slowed down by frequent state changes. And the OpenGL ES engine incurs costs when performing state machine changes that really didn’t need to happen because the engine already was in that state. To that end, the application should do its best to ensure that GL engine state changes are only made if state really is changing.

To ensure that, cocos3d shadows the state of the GL engine outside of the GL engine itself. When an attempt is made to change state, cocos3d first checks to see if the GL engine is already in that state, by checking the value of the shadow state. Only if the state is changing from that of the shadow state is it propagated to the GL engine.

This state shadow tracking is automatic, and most application developers can safely ignore it. However, some sophisticated applications may need to interact with this framework, so I’ll give an overview of it here.

In cocos3d, this shadow state is managed by a singleton instance of CC3OpenGLES11Engine. All calls to the GL engine are made through this singleton instance.

The CC3OpenGLES11Engine singleton instance contains a number of instances of subclasses of CC3OpenGLES11StateTrackerManager, each geared towards tracking a particular grouping of GL state, such as capabilities, or lighting, materials, etc. Each of these tracker managers is accessed through a property in the CC3OpenGLES11Engine singleton instance. Each tracker manager exposes individual elements of state through properties.

For shadow tracking to work, it is absolutely critical that all GL state changes are handled by the shadow tracker. So, when adding functionality to cocos3d for your application, if you need to make calls to the GL engine, be sure to do so through the proper shadow tracker! A few examples of how to make a GL call through a shadow tracker, and the GL call that it replaces are:

  • [[CC3OpenGLES11Engine engine].serverCapabilities.texture2D enable] <-> glEnable(GL_TEXTURE_2D)
  • [CC3OpenGLES11Engine engine].materials.ambientColor.value = kCCC4FBlue <-> glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (GLfloat*)&kCCC4FBlue)
  • [CC3OpenGLES11Engine engine].state.scissor.value = self.activeCamera.viewport <-> glScissor(vp.x, vp.y, vp.w, vp.h), where vp = self.activeCameraViewport

Since it is critical that all GL calls be processed through the state shadow trackers, but cocos2d does not use state shadow tracking, you may be wondering how the shadow trackers know what the value a GL state has at the time that rendering control is passed to the cocos3d framework from cocos2d.

Each primitive state tracker has an originalValueHandling property, which tells that tracker how to determine the original value. The enumerated value of this property can tell the tracker to do one of the following:

  • simply ignore the current state at the beginning of each rendering frame
  • read the current state at the beginning of each rendering frame
  • read the current state at the beginning of the first rendering frame and assume that value always

In addition, for the last two options, the enumeration can be modified to tell the tracker to restore that original state back to the GL engine, because cocos2d is assuming it to have stayed the same.

The original value state is set to the optimal value for combining cocos2d and cocos3d, generally either ignoring the value, or reading it once on the first frame. However, if your application varies from frame to frame and you find that the initial value can change from frame to frame at the point that cocos3d takes over, you can modify the originalValueHandling property of the associated state tracker to read the value on every frame.

Keep in mind that this reading interrupts the the flow of the GL pipeline significantly, and should generally be avoided at all costs. A better solution is to ensure that your cocos2d code leaves GL state with consistent values from frame to frame at the time cocos3d takes over.


Posted

in

by

Tags:

Comments

184 responses to “cocos3d Programming Guide”

  1. This sounds amazing! I’ve been creating our art assets for our Cocos2D game using Maya 3D and using 2D png snapshots. Can I export a mesh created in Maya as an FBX object? Will my shaders import too? Or do I have to download the Collada plug-in to use my Maya objects with the Cocos3D library? Thanks again for the library, awesome work! 😉 Elizabeth

    1. Hi Elizabeth…

      Unfortunately, with this initial release, cocos3d supports importing via the POD file format only. We plan to add other file formats as we move forward.

      The PowerVR SDK (link in article above) does include an exporter from Maya to POD files, but not for Mac. If you’re using Mac, It looks like your best bet might be to export your meshes from Maya to Collada, and then use the Collada2POD converter in the PowerVR SDK.

      I’ll be posting an article on this site in the next few days, with instructions on configuring the Collada2POD tool for exporting to cocos3d. Keep an eye out for it.

      Regarding shaders…no. cocos3d, like cocos2d, uses OpenGLES 1.1, so it doesn’t currently support shaders. Unfortunately, you’ll have to export as meshes, materials and textures for the time being.

      Thanks…

      …Bill

      1. thanks, looking forward to your next article on using Collada2POD.

        1. Hi Elizabeth…

          Well…wait no longer! 🙂

          I’ve posted the article here.

          …Bill

    2. ashok

      thanks great job!

      some example not available. put some examples. so we can use more!.

      1. Hi Ashok…

        After the next release, we will be working on an new website, which will include better explanations, examples, and hopefully tutorials.

        In the meantime, your best source of examples is the CC3DemoMashUp demo app that comes with cocos3d. It contains examples of using most of the features.

        …Bill

  2. iostriz

    Great!
    I’ve been missing this for a while now. I have a question: are other devices supported too? Like iPad, Mac…

    Igor

    1. All iOS devices are supported. cocos3d has been tested on iPad.

      Mac support has not been tested. Based on the experience of cocos2d, we expect that there will be a few small issues around OpenGL on Mac…but mostly just about changing calls, etc. It’s something we will address at some point if Mac is a popular platform requirement.

      …Bill

  3. wave_1102

    Very great job! Thanks, Bill.

  4. Jesus

    Does this engine supports things like:

    – gabbing a 3D object?
    – collision detection between objects?

    It looks very cool from the demo app.

    1. Hi Jesus…

      Can you clarify what you mean by ‘gabbing’? If you meant ‘grabbing’…as in manipulating or moving an object…then yes. If not, please clarify.

      Collision detection is up to the app for now (as with the simple bouncing ball in the CC3DemoMashUp). Each node contains a bounding volume that can help with that.

      We will be integrating a proper physics engine into cocos3d in the future. Please refer to the development roadmap for more info.

      …Bill

      1. Jesus

        Yes I meant grabbing, such as detecting when an object was touched.

        How is this achieved? I didn’t find a class that provides this functionality.

        As for collision detection. I think the bounding volume will do for now, thanks. Looking forward to the physics engine 🙂

        1. Hi Jesus…

          Ahh…you mean grabbing via a user touch…not programatically.

          There’s nothing automatic yet. However…you can do some crude detection as follows:

          You can use the projectedPosition property of a CC3Node to determine where on the screen it is. Then you can use some kind of 2D radius measurement from your touch point to determine whether you are close enough to consider it ‘grabbed’.

          The projectedPosition property is not set for all nodes automatically. You can either set it for the nodes you are interested in as part of your custom CC3World update: method (via [self.activeCamera projectNode: myNode]). Or you can add a CC3Billboard as a child to your CC3Node. The projectedPosition property of all CC3Billboards are updated automatically.

          If your node stays more or less in the same orientation (not rotating about), like, say, a character running around in a game, you could attach a 2D CCNode to the CC3Billboard, and size it so that it visually covers the 3D model. You could then use the boundingBox of the 2D CCNode as a visual 2D bounding area of your 3D object. By default, the CCNode will grow and shrink proportionally as the 3D object moves toward and away from the camera, so it should stay in sync. If you use a CCLayerColor as the 2D node, then you could color it to show how it covers as you lay it out, and then make it invisible during game play.

          Have a look at the text label attached to the robot arm in the CC3DemoMashUp example project for how CC3Billboards can be used.

          Unfortunately, if you have 3D objects that overlap visually, and you want to be able to touch either, this technique will indicate that both have been touched. You’ll have to have some kind of manual ordering to keep track of which object is of more interest to you.

          Admittedly, this is a crude technique. You’ve given us some things to think about. This is certainly a feature that needs proper support in a touch device. I’ll make sure it makes it into an upcoming release on the roadmap.

          Thanks…

          …Bill

          1. salman

            > and size it so that it visually covers the 3D model

            Hi Bill,

            Could you give me a hint how to do that?

            1. Hi Salman…

              You would just do it visually. You could used a CCLayerColor, configured with a background color so you can see it, as the cocos2d node being held by the billboard.

              Then play with a combination of sizing that layer and the unityScaleDistance property of CC3Billboard to line it up with 3D object. Once things are working, turn off the color of the CCLayerColor node.

              However…before you run off and do that, I should let you know that we are releasing an update to cocos3d next week that includes proper 3D object picking. Keep an eye out for it.

              …Bill

              1. salman

                Hi Bill,

                Thanks for the touch event support in the current version.

                I still have a question regarding the API
                – (void) nodeSelected: (CC3Node *) aNode byTouchEvent: (uint) touchTypeat:(CGPoint) touchPoint

                The touchPoint is the location in 2D coordinate system of the CC3Layer where the touch occurred.

                In case I will move the aNode selected by the touch event, how I can set the aNode.location with the correct CC3Vector?

                Basically my question is how to calculate the 3d location of the object based on known desired 2d viewport location?

                1. Hi Salman…

                  Sorry…there’s no true unproject capabilities yet.

                  Unproject gets messy fast because ultimately, one is dealing with individual mesh faces, all of which can be oriented in any way. And in keeping with the cocos2d/3d philosophy, we want to make sure we do something that’s easy and straightforward for developers to use.

                  I’ve added it to the development roadmap, tentatively as part of the 0.7 release (mid year).

                  In the meantime, if you have something like a floor that you want to move your object to, you can always overlay a series of transparent (don’t make them invisible, otherwise they won’t be detected) smaller rectangular meshes as tiles over your floor. Add the tile nodes as child nodes to the floor. You’ll then get notification of which tile has been touched, and you can move your object to that location.

                  …Bill

  5. Rasmus

    Great stuff! This is a huge step for cocos2d. Big thanks for the good work.

    Is it possible to do any kind of character animation at this point, knowing that rigging and skinning isn’t yet available? I know how to do it in blender, but i’m not sure how to go about dividing and exporting the animations in a way that would be controllable through code.

    Thanks

    1. Hi Ramus…

      Thanks for your encouraging comments.

      Unfortunately, we have not yet even begun to address bone rigging, so I can’t give you much help there…yet.

      It might help you to look at the way the CC3DemoMashUp example in the cococ3d distribution animates the robot arm, which is an assembly of CC3Nodes rigged together. It’s not true bone rigging, but it does illustrate how something like an arm can be managed in cococ3d. If you are able to get Blender to export your character models to COLLADA and converted to POD in a similar manner, it should work.

      I also suggest that you post this question as a new topic in the cocos3d forum, where you might find developers with more real-world bone rigging experience that myself.

      Thanks…

      …Bill

      1. Rasmus

        Hi Bill,

        Thanks for the quick reply. I’ll have a look at the example more in depth tomorrow. That should give me an idea.

        /Rasmus

  6. Raul

    Hi Bill. Congrats! Great guide.

    I would like to ask if it is possible to do this animation (http://www.box.net/shared/y1qeo8pn2u) with 3 individual models using cocos3d. The animation must start when the piece on the border is touched. The rotation could be either on the rows or columns and always initiated by the touch or click.

    Thanks in advance for your help.

    Raul.

    1. Raul

      Sorry, the correct link of the demo animation: http://www.box.net/shared/a96ih83b6u

    2. Hi Raul…

      Yes…it’s possible. The rotation is simply a matter of applying a CC3RotateTo action to the CC3Node that is the middle row (or whatever row).

      The real trick is to handle the touches. At present, cocos3d has no true automatic way to determine which object has been touched. That functionality will be coming in a future release.

      In the meantime, if you need to know that the middle row has been touched, you can map it yourself. One technique I can suggest is to attach a CC3Billboard, containing a 2D cocos2d CCNode to the 3D row, and visually size it to be the same size as the row. It will grow and shrink in tandem with the 3D node it is attached to. You can use the boundingBox of the 2D object as a way of determining whether the row has been touched.

      …Bill

      1. Raul

        Hi again Bill.

        Could an object be part of a cc3node at one moment and part of another one later? I mean, one object may need to be rotated with the entire row, but later, the same object may rotate with the column.

        Thanks in advance.

        Raul

        1. Hi Raul…

          Yes…you can use removeChild: and addChild: to move nodes around in your structural hierarchy. You can do this as part of the update: processing.

          At any one time, though, a node may be added to only one parent…because transformations are processed hierarchically.

          …Bill

          1. Raul

            Hi Again Bill.

            Please help! Maybe I’m a little confused with this apparently very simple task.

            I’ve created a new Cocos3d project and just change the pod file and get the node called “Monkey” from the new pod file. Just rotated a bit and it’s working just as expected.

            This is the changed code:

            CC3MeshNode* Monkey = (CC3MeshNode*)[self getNodeNamed: @”Monkey”];

            Monkey.rotation = cc3v(90.0, 0.0, 0.0);

            CCActionInterval* partialRot = [CC3RotateBy actionWithDuration: 1.0
            rotateBy: cc3v(0.0, 30.0, 0.0)];
            [Monkey runAction: [CCRepeatForever actionWithAction: partialRot]];

            Now I want to add a second “Monkey” as a child of the first, a little bit to the left to make it act as the satellite teapot do in the CC3DemoMashUp project, but I’m totally lost.

            Thanks in advance for your help

            Raul

            1. Hi Raul…

              Have a look at this post in the cocos3d forum.

              You might also think about using the forum for future questions of this sort…to get assistance from a larger community.

              Also…later this week, we will be releasing an update to cocos3d that greatly simplifies the ability to create copies of nodes. Keep an eye out for it!

              …Bill

  7. Kai

    Hi Bill,
    can you help me with a little problem?
    I have an 3d object an it rotates on the simulator, but how can I add a texture to this model? where i’ve to put the images etc?
    thanks for your help kai

    1. Hi Kai…

      The texture images go in the Resources folder of your application, as do any POD files that you are using.

      If you haven’t done so already, have a look at the CC3DemoMashUp example in the cocos3d distribution. It includes several textured components.

      …Bill

  8. Naimed

    Hello Bill, I have a little issue. I want to include a CCNode (a CCSprite actually) attached to a 3d figure, but i dont want the sprite to face the camera automatically. CC3Billboards have an automatic orientation towards the cam, and i want to disable this, or go somehow around.
    Thanks a lot for your help and congratulations for this awesome features!

    1. Naimed

      Hello again, never mind I realized that you can do this with populateCenteredRectangle and as texture using the CCSprite, but thanks anyway!

  9. […] can download the Cocos3D beta here: Cocos3D Beta You can find the cocos3D programming guide here: Cocos3D Programming Guide It looks like Cocos3D has a ways to go, but judging by the impressive start it appears to be in the […]

  10. […] You can find the cocos3D programming guide here: Cocos3D Programming Guide […]

  11. Syler Cider

    I’ve made a few games for the iPhone already, but they were all static (i.e. no moving images). I want to now start creating games with movement.

    Being new to games with movement, should I start out with cocos*2*d or jump right into cocos*3*d?

    1. Hi Syler…

      Well…that all depends on what you want to do!

      Full 3D games are very different than 2D games.

      3D games provide a much richer user experience. Think flight simulators or first-person shooters. But on smaller devices, 2D games can often be more playable. Think Angry Birds…or Run! (the latter is a cocos2d game).

      3D games are more complex to create, both in terms of content creation, and in terms of managing the objects…simply because you have to think in terms of 3 dimensions.

      If you’re brand new to dynamic games…start out with cocos2d. That will give you a taste of thinking and working in the dynamic world. Then move to cocos3d when you want to explore a richer user experience.

      …Bill

  12. Vincenzo

    Fantastic guide! 🙂
    I hope I’ll be able to do something with that..
    Any news about Xcode 4 templates?
    thanks

    Vincenzo

    P.S: I traslated this page in italian…I hope that isn’t a problem..:)

  13. ris

    Hi Sir,
    I am a new guy to 3d world, and cocos 3d is a great framework,i have a question that how can i render a image in the cocos 3d,does the cocos3d framework always need the pod file? (i just need a static background image).

    Thanks in advance.

    1. Hi ris…

      Have a look at family of populateAs... methods on CC3MeshNode. Plus the subclasses CC3PlaneNode and CC3BoxNode.

      You can find examples of how to use these in the demos CC3DemoMashUp and CC3Performance. The ground plane in CC3DemoMashUp is a static background rectangle like you are asking about.

      …Bill

      1. ris

        Hi Bill,

        Thanks a lot for your reply,i get it, i am a new guy to the 3d world,and i am plan to use cocos3d to build a 3d book application. But i find that i can not control the camera very well. Now i have no idea about this, Would you like to give me some idea about this? Is it easy to be done by cocos3d? If i can get some reply from,that will be a great help. Thanks in advance.

        Ris

        1. Hi ris…

          The best thing to do is to become familiar with the CC3DemoMashUp and CC3Performance demos. They include code examples of how to work with many of the features of cocos3d, including controlling the camera.

          In addition to the basic behaviour of these demos, you’ll also notice that there are a number of sections of code commented out in the demos. You can selectively uncomment these to see how they change the behaviour.

          …Bill

  14. ris

    Hi Bill,
    That is great help,i look into the CC3DemoMashUp,and build some mesh node like
    CC3MeshNode* floater = [CC3PlaneNode nodeWithName: kFloaterName];
    [floater populateAsCenteredRectangleWithSize: CGSizeMake(500.0, 500.0)
    withTexture: [CC3Texture textureFromFile: kFloaterTextureFile]
    invertTexture: NO];
    But i find i have two problems
    1.the image render on the stage is black,when i click it seems appear the original color,how can i get the right color?
    2.If i remove the Robot , it seems that the location and direction control do not work,how can i keep the camera function and remove the robot on the stage.

    It should be easy problem,but seems to be confuse to me. I hope i can get an answer from you. If it is not correct to post such problem here.Would you like to tell me where i can post the problem.Thanks again for your help.

    Thanks,
    Ris

    1. Hi ris…

      Sorry to see you’re having trouble.

      Please start posting your questions to the cocos3d forum. You’ll get answers much faster that way.

      Regarding the rendering issue, what is it that is rendering black? Is it the floating ring? Are you substituting your own texture file, or is it one of the textures in the demo?

      Regarding the camera and robot, have a look at this forum posting. It explains how to replace the camera when you remove the robot.

      …Bill

      1. ris

        Hi Bill,
        That’s great to see your answer,yes,i have add my own texture as plain node in the project,and it seems render a black color,when i set acts.color = ccWHITE; it appears,but not the real color of my texture, but when i rotate it,it seems get the right color,how can i disappear it correct as render the “ground ” plain node?
        Again,thanks for your help,bill.

        Thanks,
        Ris

  15. I have created project from template (using Xcode 4) and generated project has no target (“0 targets, missing base SDK”).
    I have no clue how to fix that – anyone had similar issue?

    cocos3d 0.5.4, cocos2d 1.0-rc

    cheers!

  16. Hmm… actually I forgot to install cocos2d template in Xcode. Now it works great.
    Thanks for the great job!

  17. Awesome ,is there any chance of having a top view game with a 2d physic engine like chipmonk or box2d settind the 3d positioning?

    1. Hi Gil…

      It depends on what you want to control. If you just want the 3D for a backdrop, you can control the 2D cocos2d sprites on the top layer with box2d or chipmunk.

      But those physics engines wont control the nodes in the 3D world.

      …Bill

      1. Do you have a sample code of it running with a Box2d physic engine? Do you think Is it simple to implement?
        I will try it, I think it might work good for a race game, I could add springs for curves letting the car rotate 5 degrees on it’s Z on the curves, it might give a nice felling.
        I’m thinking something like I did for http://www.formulanova.com but having a 3d Scene without road mountains, just a 2d physic engine top view.

        1. Hi Gil…

          I suggest you search the cocos3d forum for both cocos3d and box2d.

          Several of the contributors there have integrated the two quite successfully.

          …Bill

  18. Kareem Daker

    hello Bill,

    im using cocos3d 0.5.2, and im getting build warnings in xcode about having multiple position: getters and setters… one in cocos2d’s CALayer

    @property CGPoint position;

    and the other in CC3OpenGLES11Lighting:

    @property(nonatomic, retain) CC3OpenGLES11StateTrackerLightVector4* position;

    it is not creating any problems and everything is running fine but im just wondering what i need to change to remove the warning… or is this fixed in later versions of cocos3d?

    1. Hi Kareem…

      It’s extremely unlikely that a CC3OpenGLES11Lighting class could be getting mixed up with the CALayer class. The two classes are completely unrelated.

      Have a look at how your code is structured. If you still have problems, can you copy the exact error message and paste it here, please?

      …Bill

      1. Kareem Daker

        the warning is appearing on any line i use [lang] setPosition: [/lang] on subclasses of CCSprite or CCLayer (not related to cocos3d in anyway). the warning says: “Multiple methods named ‘position’ found”… and they direct me to the properties i mentioned earlier. note that the warning does not appear if i do [lang] mySpriteSub.position [/lang] but only if i do [lang] [mySpriteSub setPosition:aPosition] [/lang]…

        I did not start my project using cocos3d templates. It was an old cocos2d project and i simply added cocos3d source files to it. Also i am adding my only CC3Layer as a sub layer to a CClayer.

        1. Kareem Daker

          sorry false alarm… turns out i was calling setPosition: on CCNodes created as id objects… the warning went away with casting. sorry about that.

  19. Kareem Daker

    Hello again Bill,

    i am having a problem with the device orientation and cocos3d. When i started my project, i had my autorotation set to kGameAutorotationUIViewController from GameConfig.h… now i want to remove autorotation support and only view things in landscapeLeft… when i changed the cocos2d GAME_AUTOROTATION kGameAutorotationNone, everything was fine with cocos2d but all my 3d objects are now misplaced in Z. I tried playing around with several autorotation values from the RootViewController but nothing seems to work. any ideas?

    1. Hi Kareem…

      cocos3d does not use RootController. Instead, it uses CCNodeController, which is compatible with both cocos3d and cocos2d.

      Please see the AppDelegate class in any of the hello, world template, the CC3DemoMashUp demo, or the CC3Performance demo for examples of how to control device orientation with the CCNodeController.

      You can fix it to a particular orientation, or you can configure it to autorotate.

      …Bill

  20. Neogene

    Hi Bill,

    wonderful project (and really nice transparent integration witch cc2d), i’m facing a problem and i dunno if its my fault or something in the framework:

    i modified the default cc3d project: i created n CC3PlaneNode , each of them uses a texture, i place them on z axis using ground.location = cc3v(rect.origin.x, rect.origin.y, -990.0+(30*i)); where -990 is a nice distance from the camera and i is an incremental number (i=0…1…2…etc) so the distance from the camera decreases but i detected rotating the objects (with an action) that all of them are on the same plane! the z is not affecting them, the z are:

    -990
    -960
    -930 and so on…

    Note: the textures are transparent png.

    Have you any suggestion?

    CC3PlaneNode *ground = [CC3PlaneNode nodeWithName:[NSString stringWithFormat:@”n_%i”,i]];
    [ground populateAsCenteredRectangleWithSize: rect.size
    withTexture: [CC3Texture textureFromFile:[content objectForKey:@”filename”]]
    invertTexture: YES];

    ground.isOpaque = NO;
    ground.location = cc3v(rect.origin.x, rect.origin.y, -990.0+(30*i));
    ground.rotation = cc3v(-180.0, 180, -180);

    1. Hi Neogene…

      Please use the cocos3d forum for further questions. You’ll be able to make use of the community for help.

      In what direction are you rotating the planes? And where is your camera?

      If your camera is looking down the default negative Z-axis, and you are rotating all of the planes around the X or Y axis, they will indeed all appear inline at 90 degrees, because each is rotating along its own axis (eg- try holding out your hands with one covering the other with a bit of space between them, then rotate your wrists).

      If you are trying to rotate them all together and retain their spacing, you need to add them all to a parent node and rotate that parent node instead.

      Try modifying your code to create a CC3Node as a parent (call it say cardHolder), then add the planes to it at Z = i * 30. Add the cardHolder to the CC3World, and place it at Z = -990.

      When you now rotate the parent cardHolder node, you’ll see that it maintains the relative spacing of the planes it is holding.

      You can see something like this in the LandingCraft class of the CC3DemoMashUp demo, where many robot arms are added to a parent CC3Node.

      …Bill

  21. Neogene

    Thank you bill, i managed changing the to nil;

    I signal probably a bug:

    1) create a CC3PlaneNode using a transparent png:

    [head populateAsCenteredRectangleWithSize:headRect
    withTexture:[CC3Texture textureFromFile:@”first.png”] invertTexture:YES
    ];

    2) set opaque property to NO;

    3) change after a touch event or other events the texture using:

    [head populateAsCenteredRectangleWithSize:headRect
    withTexture:[CC3Texture textureFromFile:@”second.png”] invertTexture:YES
    ];

    The second time i change the texture it shows black in transparent areas, so i have to set the node to opaque=NO again to have the transparent texture again.

    1. Hi Neogene…

      The populateAs... methods are meant to be constructor methods, so they set a number of default property values.

      If you want to simply change the texture, do so via the texture property of CC3Material.

      …Bill

  22. Neogene

    first row: I managed changing to nil the drawingSequencer;

  23. George

    Nice work!
    I already stated using it and I have a problem:
    I have 3D object loaded (a thin tube) that’s supposed to be a wire between 2 points (loose, not stretched).
    I want to make it swing a bit left-right. How can I modify it to appear as it is swinging?

    Thank you very much!
    Excellent library!

    1. Hi George…

      Please submit your questions to the cocos3d forum to get answers from the cocos3d developer community.

      In your case, I guess you could make the two end points the zero-points in your mesh and then just rotate the node back and forth by a few degrees using the rotate property.

      …Bill

  24. Jp

    Thx! I learned a lot about 3d engines by reading this programing guide. It’s a long time I wish to make a step in the 3d world and I feel I could do it with your engine. Thx again.

  25. cocoachina

    how to show game center leadboard in cocos3d?
    and how to handle the leadboard orientation?

    1. Hi cocoachina…

      Please submit your questions to the cocos3d forum to get answers from the cocos3d developer community. Others there might have dealt with it already.

      …Bill

  26. cocoachina

    i have showed game center leadboard successfully,
    in AppDelegate.m add the line :
    window.rootViewController = viewController;

    but the leadboard won’t change orientation automaticlly while showing

  27. Great work with cocos3d. Been studying the samples.
    I’m still confused as to how one can create a mesh with code.
    Basically I want to make a rectangular mesh and split it into triangles and then have access to all the points in order to change their positions during the game thus altering the mesh.

    1. Hi Mihai…

      For simple examples of how to construct a mesh from vertices, have a look at the populateAs... methods of CC3MeshNode. For example, check out populateAsSolidBox:.

      Once you have constructed a mesh (either using a 3D editor, or programatically), you can manipulate the data on the vertices using accessor methods like setLocation:at:, setTexCoord2F:at:, etc. of the various CC3VertexArray subclasses that hold the mesh data.

      …Bill

  28. Mark

    Hi there, is it possible to use this software/coding to embed a 3d model viewer into an iphone app? I’m a novice developer looking for a plugin that will allow my users to call an ACTION that will open a small 3D/MD2 model so cached within the app and allow them to rotate zoom and leave model and return to main page. My iphone app knowledge is basic but modelling is good. Appreciate your time and advice. 🙂

    1. Hi Mark…

      Yes, cocos3d will do what you describe.

      You will need to convert your model to POD file format. See this article for more on that.

      …Bill

  29. Thanks Bill, I was able to make a cube programmatically. Is there a way to control the mesh resolution?

  30. Hi Mihai…

    If you’re referring to the number of triangles in your mesh, the factory methods for creating planes do allow you to define tessellation. For example, the populateAsRectangleWithSize:andPivot:andTessellation: method.

    Have a look at how that method is structured to develop your own mesh creation.

    Going further, you can scan the internet for code algorithms for creating basic shape meshes programmatically.

    Alternately, even for a simple cube or ball, you can use a 3D editor to create the mesh for you, in whatever level of mesh structure you want.

    …Bill

  31. Thank you for the quick response Bill. Back to your answer on my previous question, all these inner vertices should be accessible through the CC3VertexArray class, am I correct?
    Also, am I correct in assuming that a rectangle mesh has only one instance of CC3VertexArray?

    1. Hi Mihai…

      Please submit further questions to the cocos3d forum. Others can help answer your questions, and also benefit from seeing the collective answers.

      CC3VertexArray has several subclasses. Typically a mesh will have several arrays, one for vertex locations, another for normals, another for text coordinates…but only one of each type, unless you are using multi-texturing.

      The arrays can use interleaved data if you want.

      The underlying vertex data can be read and manipulated by accessor methods such as locationAt: and setLocationAt:. Be sure to familiarize yourself with the shouldAllowVertexBuffering and shouldReleaseRedundantData properties to help you retain the data in main memory so you can manipulate it.

      Again…have a look at the populateAs... methods to get an understanding of how they work together.

      …Bill

  32. James Allen

    Hi Bill, this looks great! This may have been asked before, so I apologize if it has – is there a way to loop through a 3d animation, writing each frame to a sprite-sheet? For instance, I want to make an isometric game, allowing for player customization, so using 3d parts and animations would be great, however for speed purposes I want to stick to animated sprite sheets for each character. Is this something that I can do with cocos3d? Thanks!

    1. Hi James…

      Nothing automatic. But there are solid render-to-texture features in cocos2d, and since cocos3d runs inside a cocos2d layer, so you may be able to easily render the 3D scene to a texture through cocos2d capabilities.

      …Bill

  33. James Allen

    That’s actually along the lines of what I was thinking Bill, thanks. I’ve been away on my honeymoon & haven’t yet had the chance to actually dig into cocos2d or 3d yet, but is there a way to set up a camera and your character and run through the 3d character’s animation without actually rendering to screen? I’m just assuming here, but I create the 3d character, set it up, but don’t addChild, right? Would I then have to manage the memory myself and dealoc it manually?

    1. Hi James…

      No…you should be able to just set everything up as you normally would, 3D models, cameras, lights, animation, etc. You can let cocos3d do all the memory management for you.

      Just don’t add the CC3Layer to the cocos2d director. Render it to texture instead. I’m not an expert on cocos2d rendering to texture…so I can’t give you much more advice than that. It looks to be fairly straightforward. And if you get stuck, check out the cocos2d forum.

      …Bill

  34. James Allen

    Yep, that’s the plan 🙂 Even if renderToTexture won’t work there’s more than one way of getting the bitmap data & outputting to a cached file. Thanks for your responses Bill, I’ll try to keep people posted on my progress over the next couple months on your cocos3d forums.

  35. James Allen

    I guess I couldn’t really do what I need without some sort of bones or BIP + skin support though – I know you mentioned it’s something you were working on for future iteration, do you know your proposed timeline for such a feature?

    Basically, and this is all theoretical, I’d need a way to export each armor & weapon for each character’s animation, then assemble the character based on current weapons, armor, & character’s customization, and then for each animation render to a spritesheet all of the frames of each animation. With each weapon change I’d have to re-render everything though, so I’m not sure if it would take too long. The other thought is to have every possible combination as single pngs, which can be assembled on the fly to 2d spritesheets. The problem with this is the size of the download would be huge I’d think, so that’s why I thought using iOS support for 3d and then baking on the fly would be best.

    Am I completely out of my mind??? 🙂

  36. Chris Myers

    Hey Bill,

    Great job on cocos3d. I’ve found it very useful and easy to use.
    I have found an issue with vertex colors that I suspect has gone overlooked due to lack of use.

    For some reason PVRFoundation is missing a few PVRT data types including ARGB and RGBA. I have a fix that works that I will post to the forum. It would be nice if these changes could get merged in to the release so I don’t have to insert it every time I upgrade.

    Also, I’ve been working on Bone + Skin support for meshes using glMatrixPaletteOES which is nearly integrated with cocos3d. It works, but the transformations are still incorrect, due to my lack of understanding of the way cocos3d handles the matrix stack. Unlike the vertex color issue, bone skinning has been designed as a plugin so I can work on it while you release changes.

    Chris

    1. Hi Chris…

      Thanks for working on your extensions.

      Please post the PVRT data types code to the forum, and I’d be happy to roll it into the next release.

      Also, when you get to a point that you’re happy with on the Bone Skinning, I’d be happy to have a look at it, and see if it would make sense to roll it into the main development (giving proper credit to you for your efforts).

      As you are working on that, if you have any questions about how the matrix transforms work in cocos3d, or if I can help point you in the right direction about anything, please contact me at support@brenwill.com.

      Thanks…

      …Bill

  37. Hi again Bill
    I’d like to make sure I understand if I am using the setlocation at method properly.
    Is the index created by traversing the mesh in the x direction first, then moving to the next row, etc?
    Thanks!

    1. Hi Mihai…

      The index of setLocation:at: is simply the index into the mesh vertex array, which is just one big long array of CC3Vectors.

      If you’ve created the mesh programmatically, the order of that array is whatever you set.

      If you’ve created the mesh using a 3D editor, then the order of that array is whatever order the 3D editor laid out for the mesh.

      It is not related to the X, Y & Z coordinate system, and is more typically aligned to the drawing order.

      …Bill

  38. But the indexing is automatically created by the method “populateAsRectangleWithSize:andPivot:andTessellation:”
    , so I was wondering if that follows x/y (e.g. first and second coordinates in the default cc3v argument list)

    See sketch here:
    http://img710.imageshack.us/img710/9422/2dcoords2index.jpg

    Thanks

    1. Hi Mihai…

      The best thing I can suggest is review the code in the method you mention to determine the order it lays out the vertices.

      If that order is not usable for you, you could consider writing a version of that method that lays out the vertices in a more useful order.

      …Bill

  39. akbar

    So, i installed cocos2d, created new cocos2d project, everything was ok. when i installed cocos3d the demo projects not run: CCDirector.h:32:9: fatal error: ‘kazmath/mat4.h’ file not found

    1. Hi akbar…

      Please post your questions to the cocos3d forum.

      The file kazmath/mat4h is not part of cocos3d.

      But in any case, have you run the install-cocos3d.sh script, as explained in the README file?

      …Bill

      1. akbar

        Of course.

      2. Marce

        Hi, I have the problem, here is how I install cocos3d. The problem is this, the .sh doesn’t copy or link kazmath folder inside cocos2d.

        sudo ./install-cocos3d.sh -u -f -2 /Users/me/Documents/Cocos2D/cocos2d-iphone-2.0
        Password:
        cocos3d installer

        Linking cocos2d libraries to workspace
        …linking cocos2d files
        …linking FontLabel files
        …linking CocosDenshion files
        …linking cocoslive files
        …linking cocoslive dependency files
        done!
        …creating Xcode 4 cocos3d template folder

        Installing Xcode 4 cocos3d iOS template
        —————————————————-

        …creating destination directory: /Users/marcelanievas/Library/Developer/Xcode/Templates/cocos3d/cocos3d Application.xctemplate
        …copying cocos3d Application template files
        …creating destination directory: /Users/marcelanievas/Library/Developer/Xcode/Templates/cocos3d/cocos3d Application.xctemplate/Resources
        …creating destination directory: /Users/marcelanievas/Library/Developer/Xcode/Templates/cocos3d/cocos3d-base.xctemplate
        …copying cocos3d-base template files
        …creating destination directory: /Users/marcelanievas/Library/Developer/Xcode/Templates/cocos3d/cocos3d-lib.xctemplate
        …copying cocos3d-lib template files
        …copying cocos3d files to cocos3d-lib template
        done!

      3. Marce

        Well, Instead of using cocos2d-iphone-2.0, I’ve used cocos2d-iphone-release-1.1-RC0 and It is working !!!! 🙂
        So the problem is with cocos2d 2.0

        Thanks !!!!

        1. Hi Marce…

          There’s a compatibility relationship between versions of cocos3d and cocos2d.

          cocos3d 0.x must be used with cocos2d 1.x.

          cocos3d 2.0 supports both cocos2d 2.x and cocos2d 1.x.

          ..Bill

  40. yilang

    can I do some Crash test on the cocos3d engine?

    1. Hi yilang…

      I’m not sure I understand your question.

      Do you mean “crash” as in debugging…or do you mean “crash” as in collision detection?

      If you mean collision detection, please post your questions to the cocos3d forum. And you can search that forum as well. There are a number of people who have been working on various types of collision detection.

      …Bill

  41. akbar

    It works! There was problem with versions.
    Thank you for answer.

  42. Can

    Hi all, Im implementing some 3D application for my research and I decided to use cocos3D for its large content. I tried to create a box using populateAsSolidBox

    [objc]
    CC3MeshNode* makeCube(float xSize, float ySize, float zSize,
    float originX, float originY, float originZ, BOOL wired)
    {
    CC3BoundingBox bounds = makeBounds(xSize, ySize, zSize, originX/2, originY, originZ);
    CC3MeshNode *cube = [[[CC3MeshNode alloc] init] autorelease];
    [cube populateAsSolidBox:bounds];
    if (wired)
    {
    [cube addChild:makeWire(bounds)];
    }
    cube.location=cc3v(originX,originY,originZ);
    return cube;
    }
    [/objc]

    But the cube is not drawn to the location specified. I am also drawing the boundingbox of the cube and it seems to be in the right location and the cube is drawn to some other location. Is there a problem with the vertices of the cube? may be this needs a fix? when ur not drawing to the origin there is a problem with the location for solidbox thing.

    Thanks in advance!!!

    1. Hi Akbar…

      Please ask you questions in the cocos3d forum. You’ll get better help there.

      There shouldn’t be a problem with mesh nodes. What is your implementation of your makeBounds() method? Keep in mind that CC3BoundingBox uses a minimum and maximum vertices, not an origin and size.

      …Bill

  43. Thanks Bill, I will lay out my mesh height by coordinate to see what goes where 🙂

  44. manish

    Hi,
    i want to run CCShakyTiles3D action in cc3world rather then cc3layer so how can i animate cc3node using CCShakyTiles3D action in cc3world?

    1. Hi Manish…

      If you want to shake the 3D world as a “tile”, then you can apply CCShakyTiles3D action to the CC3Layer, which is just a CCLayer.

      If you want the layer to stay stationary, and the 3D world to shake around within it, write a 3D version of CCShakyTiles3D, using it to move the location of the activeCamera around.

      You can get an understanding of how 3D versions of CCActions differ from 2D version (not by much really…each implementation is pretty simple), by reviewing the code for the subclasses of the CC3TransformBy class in the CC3ActionInterval.m file.

      …Bill

  45. Rajabi

    Hi Mr. Hollings
    Big thanks for your great work!

    I need some objects on the room with complete light but I have problem with world light.
    I’m using POD file for my resource objects. I inserted some lights on the world using Blender and when I render it, it shows me great sence. But in iPad I can’t see all objects!
    I read your demos carefully, but i can’t understand what is different between my code and yours.

    Thanks

    1. Hi Rajabi…

      Please post further questions to the cocos3d forum, where you’ll get better help.

      Try displaying your exported Collada file in Preview (by simply double-clicking on the DAE file), and the POD file in PVRShaman that comes with the PVR tools. That will let you know whether the lights are in the files.

      In cocos3d 0.6.1, you can turn on the LOGGING_REZLOAD=1 compiler build setting (its on by default in the 0.6.1 template and demos) which will log the details of your POD file as it is loading. That will also show whether the lights are in the POD file.

      Finally…you can easily recreate your lights programmatically in cocos3d. See the template or the CC3Performance demo, each of which programmatically place a light.

      …Bill

  46. Jody McAlister

    Besides the fact that this next statement would cover my own selfish need, I think a start to finish tutorial on creating a die and multiple dice with a 3d rolling of the cube(s) would increase the adoption rate of cocos3d. I’ve stopped several personal projects based solely on the fact without a user attractive dice rolling, I myself wouldn’t even want to use the games I was making.

    1. Hi Jody…

      Have you had a look at the rotating die cube in the CC3DemoMashUp demo (as of 0.6.1)?

      …Bill

  47. manish

    Hi Bill,
    i am new to cocos3d,can you please provide me guidance regarding to POD file.which software is used for create POD file and from where i can download software to create POD file.

  48. SandeepRC

    Hi Bill,
    I am working on AR with cocos3d and want cocos3d backround as transparent display. Please suggest something different because I had tried every code that makes the cocos3d background transparent.
    And I don’t want to use CCNodeController’s isOverlayingDeviceCamera property as NO.

    1. SandeepRC

      I don’t want to use CCNodeController’s isOverlayingDeviceCamera=YES.

      1. Hi Sandeep…

        Why can you not use the isOverlayingDeviceCamera property?

        If you don’t want to use that property directly, have a look at what it does in the source code.

        Primarily, you need to open an image picker controller, and set the glClearColor to transparent black {0, 0, 0, 0}.

        …Bill

  49. Guest

    hi guys!

    is there a way to get the api reference incorporated to the xcode cocumentation?

    regards

    1. The cocos3d API documentation is created using Doxygen.

      You can create your own local copy of the API documentation using the doxygen.config file in the Docs/API folder in the cocos3d distribution.

      You might be able to adjust the Doxygen configuration to output into an Xcode format. I’ve never tried.

      …Bill

  50. ElanII

    Someone can help me? I need an iPhone application that can load .ltd eulumdat files and can show a couple of ambient rendered for giving an idea of what light can do. I have the ltd files, thus can be multiplied till x16 for simulating the number of module on lamps … there’s someone that can help me?

    Best regards
    Sincerely

    Carlo

  51. Hi again Bill.
    I’m trying to have some rectangles that face the user.They show up when I am creating them as nodes (populate centered rectangle/ setting a color) and adding them to the world (of course, they don’t auto-orient themselves. sometimes my program crashes but that’s another issue)

    But adding them to CC3TargettingNodes and adding those to the world doesn’t work.
    I’m pretty sure I am doing the same routine as in demomashup

    Are there any limits to CC3TargettingNodes I should be aware of?

  52. sundialSoft

    Just an update on export from Mac Maya, there now is an exporter for Mac in the PVRGEOPOD download from Imagine so you can go directly from Maya on Mac to a .pod file for importing into Cocos3D.

    Cheers

    Ian
    SundialSoft

  53. Kotliarov

    Hi Bill. I’m having a little problem. I have a scene that supports node picking. When I run my scene, at the beginning, when I pick one or two nodes, Allocations instrument shows me a memory allocation peak, and the scene frezzes a little. What can I do to avoid this issue? Thanks in advance.

    1. Hi Kotliarov…

      Try experimenting with the CC3DemoMashUp.

      I expect that the stuttering is a result of the profiler collecting data. It does not seem to occur when the profiler is not running.

      There are occasional small jumps in memory, but nothing large, and most of the time they settle back down.

      Nothing seems tied to touches, except when touching the ground, which creates new teapot and explosions nodes, and does add a small amount of memory (for the node, not a new mesh).

      …Bill

  54. Kotliarov

    Hi bill, as you say the stuttering happens only once. I preallocate all textures before begin the scene, but this doesn’t fix the problem. Maybe there is some code I didn’t inspect yet. Thanks a lot for your time.

  55. Kotliarov

    Hello Bill. I have a new problem. I’ve been using CCMotionStreak for a few days, with the

    -(void) ccTouchMoved: (UITouch *)touch withEvent: (UIEvent *)event
    {
    CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
    [streak setPosition:touchLocation];
    }

    approach and I noted that first time it draws Ok, but from second time, the ribbon draws the first visible triangle of the strip inverted. Can you tell me if it could be a bug or I am doing something wrong? Thanks.

    1. Hi Kotliarov…

      I haven’t used `CCMotionStreak`, so I can’t really help you there.

      It seems very strange that a single triangle would be inverted. The mesh is simply submitted as is to the GL engine.

      Try submitting your question to the cocos3d forum.

      …Bill

  56. Kotliarov

    Thanks Bill.

  57. Alexy

    Hi Bill,
    first i want to thank you for this great job that you have done, its really amazing !
    i’m new to the 3D world but i think i’m doing just fine till now.
    i’m creating a CC3MeshNode from a POD file and i want to call [objc] movePivotToCenterOfGeometry [/objc] on it but it throws [objc] reason: ‘-[CC3PODNode movePivotToCenterOfGeometry]: unrecognized selector sent to instance [/objc]. can you provide me the best way to create a CC3MeshNode from a CC3PODNode ?

    1. Alexy

      I just changed the pivot in Blender and it worked. but is there a way to create a CC3MeshNode from a CC3PODNode ?

      1. Hi Alexy…

        It’s much better to search for answers and post questions to the cocos3d forum.

        In particular, this posting provides an answer and explanation to your question.

        …Bill

  58. Alex

    Hi guys,

    I am going to get straight to the point:
    I have a plane (x by y dimension) and I want to deform it using a specific formula: z = f(x,y) . Does the new version of Cocos3d support this ?
    Thanks in advance!

    1. Hi Alex…

      Yes, you can manipulate individual vertices using the setVertexLocation:at: family of methods.

      There are also related method for other vertex content such as normals, colors and texture coordinates.

      …Bill

  59. David

    Hi, all I want to do is go into the main class and display a line of text into the cocos3d environment.
    Such as “The path was long and curved around the hill” and place this line at say 20,30 xy coordinates.

    Thanks, David

  60. cabin

    Hi, Bill

    I’m beginner and stunned by a problem . When nodes(CC3PlaneNode) contains sub-nodes. I used in AR when rotate cc3camera nodes draw not correct.

    In link picture black pic is parent node(CC3PlaneNode) sub nodes are labels, userIcons.

    http://mng.hotpodcn.com/backend/AppFileMysqlDownload?id=52

    thanks!

  61. yorkdu

    Hi Bill,

    I want to create a plane with texture, and the texture png has some transparent part. However, the transparent part is render as black hole in my test. can you help me ? The code is just modified from demoMashUp:

    [lang]
    ground = [CC3PlaneNode nodeWithName: kGroundName];
    [ground populateAsCenteredTexturedRectangleWithSize: CGSizeMake(kPageWidth, kPageHeight)
    andTessellation: ccg(1, 1)];
    ground.texture = [CC3Texture textureFromFile: kPageTexture];
    [ground alignInvertedTextures];

    // To experiment with repeating textures, uncomment the following line
    // [ground repeatTexture: (ccTex2F){1.0, 3.0}];

    ground.material.specularColor = kCCC4FLightGray;
    ground.location = cc3v(0.0, 0.0, -kPageHeight);
    ground.rotation = cc3v(-90.0, 0.0, 0.0);
    ground.shouldCullBackFaces = NO; // Show the ground from below as well.
    ground.isTouchEnabled = YES; // Allow the ground to be selected by touch events.
    [ground retainVertexLocations]; // Retain location data in main memory, even when it
    [/lang]

    1. Hi yorkdu…

      It’s much better to search for answers and post questions to the cocos3d forum.

      In the CC3DemoMashUp demo app, uncomment the following line
      [objc]
      // [self addFloatingRing];
      [/objc]
      in the initializeWorld method of CC3DemoMashUpWorld.

      This will display a transparent floating ring. The addFloatingRing method demonstrates how it is created.

      …Bill

  62. Hi Bill,

    You are doing a great job! I tryed cocos3d once ago, but I´ve declined using couse it had no physic engine.

    Once ago I did a top view racing game using flash Papervision3D and box2d as physic engine, do you think it´s easy to use box2d and Cocos3d?

    I´m thinking on lauching SoccerVirtualCup 2 using a 3d engine, even if it has to do physics on 2d top view.

    Please let me know what you think.

    1. Hi Gil…

      There a several options for including physics into cocos3d.

      As of version 0.7.0, cocos3d now includes simple collision detection, allowing you to tell when a node is colliding with another node, or whether, and where, a ray (such as from a touch, or bullet track) intersects a node.

      Beyond that, there are a number of posts on the cocos3d forum from users who have successfully integrated either box2d or Bullet to cocos3d.

      Search the forum for references to cocos3d box2d or cocos3d bullet.

      …Bill

  63. […] 作者说明  ——  翻译 […]

  64. Priyanka

    [text]Hi Bill..[/text]
    [text]I am trying cocos3d for the first time.I have refered your tutorials for that.I have tried to implement cube and sphere and to rotate the same.It is working fine.
    But for pod files it is not working I am using blender 2.61 and collada 2.11 to create pod files [/text]

    [objc]
    rezNode = [CC3PODResourceNode nodeFromFile: @"trial.pod"];
    n = [rezNode getNodeNamed: @"trial"]; // This object is returning nil
    [n remove];
    n.isTouchEnabled = YES;
    [templates addObject: n];
    [/objc]

    [text]In NSLog rezNode is not nil, but n is nil.[/text]

    1. Hi Priyanka…

      In future, please ask questions in the cocos3d forum. Your questions will get answered by a larger user community, and others can benefit from the answers.

      If you are using the hello, world template application, at the end of your initializeScene method, you should see the line:

      LogCleanInfo(@”The structure of this scene is: %@”, [self structureDescription]);

      This line logs the structure of the nodes in your scene, including the names. From that log entry, make sure that the node you want actually exists in your POD, and that the name of the node is the same as the name you are using to retrieve that node. Also, make sure the logs do not contain any ERROR entries indicating that the POD file could not be loaded.

      …Bill

      1. Priyanka

        Hi Bill..

        Thanks for your response.
        Yes, From the next time I will surely ask questions on cocos3d forum..:)
        I tried what you suggested.
        code is crashing at this line:

        [objc][templates addObject: n];[/objc]

        I have logged rezNode description after this line,

        [objc]rezNode = [CC3PODResourceNode nodeFromFile: @"trial.pod"];
        NSLog(@"The structure of this scene is: %@",[rezNode structureDescription]);[/objc]

        Console is showing this:

        [objc]transformation in CCNode : YES
        2012-06-06 10:28:23.874 dieCubeDemo[392:cb03] -[CCConfiguration init] : cocos2d: compiled with Profiling Support: NO
        2012-06-06 10:28:23.904 dieCubeDemo[392:cb03] -[ES1Renderer resizeFromLayer:] : cocos2d: surface size: 480×320
        2012-06-06 10:28:24.024 dieCubeDemo[392:cb03] The structure of this scene is:
        CC3PODResourceNode trial.pod:1
        2012-06-06 10:28:24.030 dieCubeDemo[392:cb03] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[NSMutableArray insertObject:atIndex:]: attempt to insert nil object at 0’
        [/objc]

        1. Hi Priyanka…

          As you can see from the log line:

          [objc]CC3PODResourceNode trial.pod:1[/objc]

          there is nothing in your POD file. Compare that to the log from the hello, world template, or the CC3DemoMashUp.

          Your line:
          [objc]n = [rezNode getNodeNamed: @"trial"];[/objc]
          is therefore returning nil, which again, you can verify by logging, and that is causing the error when you try to add it to your templates array.

          …Bill

  65. David

    Could you post this user guide as a .pdf file?

  66. waca

    Hello,

    Great job !!!
    However I have a problem with a UITextField. When I change the orientation of the device all the nodes are moving accordingly (3D, sprites, CCbuttons…) except the UITextfield. On my other apps that only use cocos2d it works fine, it seems that the use of cocos3d changed something but I can not find what and how.
    Your help would be appreciated.

    Waca

    1. Hi Waca…

      In future, please ask questions in the cocos3d forum, where other users can answer your questions and benefit from the answers.

      If you want to have the UIKit perform the rotation so that UIKit components are rotated as well, you’ll need to make use of the RootController from cocos2d.

      cocos3d can be used with the cocos2d RootController. Have a look at the CC3Demo3DTiles demo app for an example of doing so.

      …Bill

  67. waca

    Many thanks for your help, and sorry for using the wrong site.

    Regards,

  68. Fabien Lydoire

    Hello,
    I just installed the Xcode template and it appears to delete the content of the folder where the project is created (delete, not put in Trash)!!
    I just loose all the content of my Desktop folder :'(
    I think it would be nice to fix this.

    Fabien

    1. Hi Fabien…

      Sorry for the delay in responding. I’ve been out of town.

      Typically the issue you describe arises when trying to use cocos3d with cocos2d 2.0.

      cocos3d requires cocos2d 1.x, and is not compatible with cocos2d 2.0.

      Please see the README file in the cocos3d distribution for more compatibility info.

      And when saving projects from the templates, be sure to avoid saving the project back to the template directory.

      …Bill

  69. Ruchita

    Hi Bill,
    I am new to 3D game development. When I started to learn cocos2d, tutorials helped me so much. But for cocos3d I haven’t found any. Can u suggest me.

    Thanks

    1. Hi Ruchita…

      We’re working on a documentation and tutorial web site, but it’s not ready yet.

      In the meantime, your best bet is to play with the CC3DemoMashUp demo app, and review the code in that app.

      The programming model of cocos3d is similar to cocos2d, in its use of hierarchical nodes, and CCActions.

      …Bill

  70. Ruchita

    Hi Bill,
    Thanks for response. Cocos3D is really very good. Now I am comfortable with this engine.
    I need your help to implement “Physics with cocos3D”.

    Thank you so much

    1. Hi Ruchita…

      cocos3d includes basic collision detection. Have a look at the teapot and brick wall in the CC3DemoMashUp demo app.

      If you’re looking for a complete physics engine, there are several initiatives that have integrated cocos3d with Bullet and Box2D. Search the cocos3d forum using keywords cocos3d and either bullet or box2D.

      …Bill

  71. […] 作者说明  ——  翻译 […]

  72. Yassine

    Hi,
    When I get the cocos3d zip, demos projects are missing cocos2d sources, is their any configuration to do ?

    Thanks,

  73. Yassine

    Sorry for the post, I just collecte those sources from different projects.

    Regards,

  74. a6965921

    CC3MeshNode* helloTxt = (CC3MeshNode*)[self getNodeNamed: @”Hello”];
    where i can get hello

    1. Please post questions to the cocos3d forum, where the community can help you.

      When you do, please clarify your question. I’m afraid that I don’t understand what you are asking.

      …Bill

  75. LC

    Hi Bill
    i create 2 CC3BoxNode instance in my CC3Scene instance. just like:

    CC3BoundingBox x;
    x.minimum = cc3v(-0.5,-0.5,-0.5);
    x.maximum = cc3v(0.5,0.5,0.5);
    CC3BoxNode *box1 = [CC3BoxNode nodeWithName:@”box1″];
    [box1 populateAsWireBox:x];
    box1.location = cc3v(0,2,0);
    [self addChild:box];
    CC3BoxNode *box2 = [CC3BoxNode nodeWithName:@”box2″];
    [box2 populateAsWireBox:x];
    box2.location = cc3v(0,-1,0);
    [self addChild:box2];

    and i want to know does they intersect. so i add this node in update: in my CC3Layer
    CC3MeshNode *box1 = (CC3MeshNode*)[self.cc3Scene getNodeNamed:@”box1″];
    CC3MeshNode *box2 = (CC3MeshNode*)[self.cc3Scene getNodeNamed:@”box2″];
    CC3NodeBoundingVolume *bv1 = [box defaultBoundingVolume];
    CC3NodeBoundingVolume *bv2 = [box2 defaultBoundingVolume];
    if ([bv1 doesIntersect:bv2]) {
    NSLog(@”intersect”);
    }
    [super update:dt];

    and i get “intersect” log every frame,but they are not intersect.
    then i move the box and i still get the “intersect”log.why?
    if i want to use the AABBbox to check intersect.what should i do?

    and i think maybe i find a bug or just my mistake?
    in my app.”addContentFromPODFile:withName:” method doesn’t change the name.i don’t know why.
    in template,
    [self addContentFromPODFile:@”hello-world.pod” withName:@”pod”];
    this method doesn’t change this node’s name,name still is “Hello”
    so i have to
    [self addContentFromPODFile:@”hello-world.pod”];
    CC3MeshNode *p = (CC3MeshNode*)[self getNodeName@”Hello”];
    p.name = @”newName”;
    to change the name.

    Thanks!

    1. In future, please post questions to the cocos3d forum, where the community can help you.

      Regarding your first question, one of the nice things about having open-source code is that you can look at the implementation of the framework. :^)

      Have a look at the implementation of defaultBoundingVolume. It creates and returns a bounding volume, but does not configure it for the mesh or the node, and it is not transformed as you move the node.

      What you want to use is the boundingVolume property of the node. It is populated automatically, and is automatically updated as the node moves around.

      Regarding your other question, have a look at the structural description of your nodes in the log. You’ll see that the addContentFromPODFile:withName: has loaded the POD into a CC3PODResourceNode, which is then dutifully renamed to @”pod”. The mesh node that is named @”Hello” is contained within this resource node (since the POD file may contain many other mesh nodes).

      To rename the @”Hello” mesh node, you should retrieve it by name as you have done, and give it a new name.

      …Bill

  76. CurtS

    When will Cocos2d v 2.x be supported?

    1. Hi Curt…

      Please check the cocos3d Development Roadmap for guidance on the delivery of upcoming features.

      Support for cocos2d 2.x will happen in conjunction with support for OpenGL ES 2.0, which is under development now, with a expected release by the end of March, 2013.

      …Bill

      1. Lee D

        Hi Bill, my first posting here as I’m a cocos3d noob (but a gnarled old iOS dev :). I was just looking into whether shaders are supported in cocos3d and I’m really happy to hear you’re planning this whole ES 2.0 / cocos2d 2.x thing… keep up the good work, and I look forward to the new releases!

        Lee

  77. Voppe

    Hi Bill,

    I’m learning how to use Cocos3D and like the relative simplicity a lot. Thanks for all the work you’re putting in!

    Currently I’m struggling to get an orientingWrapper working, using the teapot mesh example. It works for rotation (to change the pivot point of rotation), as described in the documentation, but I can’t get the wrapper to respond to translations by means of the ‘runAction’ method below. The ‘runAction’ method does work on the teapot itself, but not on the wrapper.
    What is wrong? Would most appreciate any suggestions.

    Regards,
    Voppe

    [objc]
    //VB Get the teapot

    CC3ModelSampleFactory *myFactory = [CC3ModelSampleFactory factory];
    CC3MeshNode *myMeshNode = [myFactory makeLogoTexturedTeapotNamed:@"myTeapot"];

    //Use an orientingWrapper to move the rotation point to the center of the pot and rotate 90 degrees
    CC3Node *myTeapotWrapper = [myMeshNode asOrientingWrapper];
    myMeshNode.location = CC3VectorMake(0.,-0.08,0.);
    myMeshNode.rotation = CC3VectorMake(0,90.,0.);

    [myTeapotWrapper addAxesDirectionMarkers];
    myTeapotWrapper.shouldDrawAllDescriptors = YES;
    myTeapotWrapper.shouldDrawAllWireframeBoxes = YES;

    // ‘self’ is the scene
    [self addChild:myTeapotWrapper];

    //Move the things around around
    CCActionInterval* moveX = [CC3MoveBy actionWithDuration:3. moveBy:cc3v(0.5, 0, 0 )];
    CCActionInterval* moveMinZ = [CC3MoveBy actionWithDuration:3. moveBy:cc3v(-0.5, 0, -3 )];
    CCActionInterval* moveMinX = [CC3MoveBy actionWithDuration:3. moveBy:cc3v(-0.5, 0., 3 )];
    CCActionInterval* moveZ = [CC3MoveBy actionWithDuration:3. moveBy:cc3v(0.5, 0., 0. )];
    CCActionInterval* moveActionSequence = [CCSequence actions:moveX, moveMinZ, moveMinX, moveZ, nil];

    //Following line does NOT work with wrapper (no movement), but works when used on the teapot (the child of the wrapper). WHY?
    [myTeapotWrapper runAction: [CCRepeatForever actionWithAction: moveActionSequence]];

    [/objc]

    1. Voppe

      Bill,

      I found out that by default the ‘isRunning’ property of the wrapper is ‘NO’. This would explain things, BUT… after setting this to YES and checking in the debugger that it indeed has the value ‘YES’, the wrapper (with the teapot in it) still does not move.
      A strange thing is that if I set the ‘isRunning’ property to ‘YES’ just before adding the wrapper to the scene and confirming in the debugger that the value is indeed ‘YES’, after the adding to the scene the value is suddenly ‘NO’ again. Moreover, when I set it to ‘YES’ again just before the ‘runAction’ method is used, the wrapper still does not move and the value is ‘NO’ again right after the runAction call.

      Looks as if the wrapper does not move because something is changing the ‘isRunning’ property .
      Any thoughts at all?

      Regards,
      Voppe

      1. Hi Voppe

        In future, please post questions to the cocos3d forum. You’ll get better support there.

        I’m not sure where you’re having difficulty. If I take the hello, world template project, and replace the line: [objc][self addContentFromPODFile: @"hello-world.pod"];[/objc] with exactly your code above, everything works as advertised. The teapot (and wrapper) moves around as expected from your code.

        …Bill

        1. Voppe

          Hi Bill,

          Thanks for your quick and very useful response.
          Sorry for posting here. I didn’t realize there was a forum as well, but will use this in future.

          I replicated what you did and indeed everything worked as expected. With this knowledge I will look into why I have problems in my program, but I am sure that I’ll get that sorted out now.

          Again, thanks a lot!

          Regards,
          Voppe

  78. Umit

    Hi Bill,

    I am familiar with cocos2d platform and just recently start playing around with cocos3d API. it is really exiting stuff! Thank you!!!

    So I am wondering if you have a sample tutorial somewhere on the internet that would show us step by step how to upload a 3d Image file (i.e replace the existing 3D Hello world with a 3D cube that comes as a default object in blender) ? I am not concerned about the importing complex 3D models into my cocos3d app. When I do it my app crash unexpectedly. I’d love to learn the right way to import 3D files into cocos 3D app. Any help is greatly appreciated.

    Thanks,

    Umit

    1. Hi Umit…

      Follow these instructions for exporting from Blender to the POD file format.

      Then start with the cocos3d Application Xcode template and load your own POD file instead of the hello, world file.

      Depending on how big your model is and where it is located, you can use the methods in the onOpen method in your custom CC3Scene to move the camera to the right position to view your scene.

      Remember to read the README files and run the install_cocos3d.sh installation script.

      …Bill

  79. Aaron

    Hi Bill,

    I would like to create many trajectory paths using key-frames, the path will be randomly selected and attached to an mesh object, i have the following question base on this usage:
    1) Looks like CC3Animation only support one key-frame am i correct? does this mean i will need to marge all my trajectory paths in a single key-frame?
    2) How can i assign key-frame to another mesh object? Basically the best method is to load all key-frame and attache to any mesh object of my choice, is it possible?

    Thanks..

    1. Hi Aaron…

      In future, please ask questions in the cocos3d forum where others can participate in the answers.

      1) cocos3d 2.0 supports multi-track animation, and you can blend between the tracks by setting weightings on each track. There are even several blending and cross-fading actions that you can apply. Have a look at the large family of animation methods on CC3Node and the animation actions in CC3Actions.h.

      2) Instances of CC3Animation can be shared between different nodes. You can assign the animation property of one node to another.

      …Bill

      1. Aaron

        Hi Bill,

        Many thanks… i didn’t notice Cocos3d forum was under cocos2d forum, i was actually looking for it within cocos3d web but unable to find it. I will post all future technical question in the forum. thanks again.

  80. infrid

    any developments on fbx loading? or if not; recommended way to get fbx (with animations) into pod format?

    1. Hi infrid…

      FBX loading is not currently planned. It is unlikely to be used for production loading because it is quite heavy, and poorly managed and documented (from an external loading perspective).

      The POD format supports animation. You can create multi-track animation using multiple PODs (you can even have a POD that just contains animation and no model by saving from CC3PODResource). You can also import animation in the Cal3D CAF format.

      Please see this article for instructions about exporting from Maya or 3DS to POD formats.

      …Bill

  81. karan

    Hi bill,
    I am on my way to create a board game using accelerometer. I cant add cc3scene as custom. When i try to create a new class, i can see only CCNODE class in cocos2d section. Cant see the cocos3d section at all !!! Why it is so ? Did i made any mistake in installation part ??

    1. Hi karan…

      Did you run the cocos3d installation script as described in the README?

      And how did you create your Xcode project? Did you use one of the cocos3d Application templates?

      …Bill

  82. karan

    Yes, i did. when i start new project i can find one template in cocos3d section , ie cocos3d Apllication template. I selected it and created some sample projects also. But the problem arises, when i add new file to my project.

  83. karan

    Hi bill, i got it. i simply re-installed cocos2d and cocos3d following the readme. Then i tried to add new objectiveC class file. I found all the 3d class types. Thanks Bill for your support

  84. Rodrigo Guerra

    Hi Bill,

    First of all, congratz on COCOS3D. I am using the framework and its really powerful.

    Let me ask you a question. I have a 2D game build on COCOS2D. This game has several diferent Scenes. I want a specific scene to be a 3D scene. That scene will be my main menu and I will be calling it periodically. All other scenes will be 2D.

    I have a GameManager class which is a singleton and all other scenes know about it. The GameManager class is invoked like [[GameManager sharedGameManager] runWithScene:{new scene}].

    How can I instantiate a new COCOS3D Scene (and Layer) from inside my GameManager Class?

    Thanks in advance.
    Rodrigo.

    PS. Sorry, I just realized I posted this same post on an unrelated thread. My bad.

    1. Hi Rodrigo…

      A 3D scene is a subclass of CC3Scene. It displays inside a CC3Layer, which is a 2D CCLayer that is specialized to work with the CC3Scene.

      As a 2D layer, you can display the CC3Layer the same way you by display any CCLayer. You can wrap it in a 2D CCScene, and use the CCDirector replaceScene: method to move between the 3D CC3Layer and your 2D CCLayers.

      …Bill

  85. Pu Shi

    Hi Bill,

    It seems cocos3d conflights with CCScrollView in cocos2d-iphone.

    When I add a CCScrollView and a 3d model into the same scene, the 3d model disappears.

    Is this a known problem?

    Pu

    1. Pu Shi

      And I found a hacky solution: adding an additional screen size CCScrollView to the scene after the 3D model is added.

      It seems somehow the newest CCScrollview in the scene clips 3D models on the screen.

  86. Ray

    Hi Bill.

    I am wondering:

    What if I want to look at objects on a scene simultaneously via 2 cameras from 2 individual aspects?

    Since all objects are rendered on the scene and each layer only has its self.scene active, how to make “view from multiple aspects simultaneously” happen ?

    Sincere thank!

    Best

    //btw did I succeed submit this question …?

    1. Hi Ray…

      In future, please ask questions in the official Cocos3D forum.

      It’s not officially supported, but all that is required is to assign your CC3Scene subclass instance to two separate CC3Layer subclass instances.

      And since you probably want a different viewpoint on the scene presented in each of those CC3Layers, you’ll need to add more than once camera to your CC3Scene, and toggle the activeCamera property before the CC3Scene drawSceneWithVisitor: method is invoked. One way to do this is to add the following method to each of your CC3Layer subclasses:

      -(void) drawSceneWithVisitor: (CC3NodeDrawingVisitor*) visitor {
      	CC3DemoMashUpScene* myScene = (MyScene*)self.cc3Scene;
      	myScene.activeCamera = myScene.cameraABC;
      	[super drawSceneWithVisitor: visitor];
      }
      

      where you’ve exposed the camera that you want for each view in a distinct property in the CC3Scene (in this case cameraABC).

      If you use this technique, you’ll need to expose the superclass drawSceneWithVisitor: method, by adding the following at the top of your each of your MyCC3Layer.m files:

      @interface CC3Layer (Protected)
      -(void) drawSceneWithVisitor: (CC3NodeDrawingVisitor*) visitor;
      @end
      

      If you need follow-up to this question, please re-ask this question in the Cocos3D forum

      …Bill

      1. Ray

        understood. Thank you.

        For another questions, I shall go to the cocos3d forum.

        Sincere thank.

      2. Ray

        I am not sure whether this code works. I shall try first

        -(void) drawSceneWithVisitor: (CC3NodeDrawingVisitor*) visitor {
        CC3DemoMashUpScene* myScene = (MyScene*)self.cc3Scene;
        myScene.activeCamera = myScene.cameraABC;
        [super drawSceneWithVisitor: visitor];
        }

        It seems that 2 different scene instance is assigner to 2 layers self.cc3Scene.

        I shall try first.

        If not solved, I shall re-ask it on the forum.

        Best

        1. Ray

          I tranfer to the forum now. plz ignore above reply.

          now It seems to work.

          Still some minor issues with my code exit to be fixed..