How to implement the btIDebugDraw interface of Bullet in OpenGL 4.0 - opengl-3

Bullet has an implementation of the btIDebugDraw interface in older OpenGL which is used to draw the physics world for debugging. The interface is like this :
class GLDebugDrawer : public btIDebugDraw
{
int m_debugMode;
public:
GLDebugDrawer();
virtual ~GLDebugDrawer();
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor);
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color);
virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color);
virtual void drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha);
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color);
virtual void reportErrorWarning(const char* warningString);
virtual void draw3dText(const btVector3& location,const char* textString);
virtual void setDebugMode(int debugMode);
virtual int getDebugMode() const { return m_debugMode;}
};
The OpenGL 1.1 implementation works in immediate mode sending vertices down to the GPU at every function call. eg. here is drawLine()
void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor)
{
glBegin(GL_LINES);
glColor3f(fromColor.getX(), fromColor.getY(), fromColor.getZ());
glVertex3d(from.getX(), from.getY(), from.getZ());
glColor3f(toColor.getX(), toColor.getY(), toColor.getZ());
glVertex3d(to.getX(), to.getY(), to.getZ());
glEnd();
}
To convert this into OpenGL 4.0, I am thinking of using a Vertex Array Object defined as a member of this class, say mVAO and the VBOs will also be members. I will setup the VAO in the ctor of GLDebugDrawer and then generate and send vertices to the VBO as well as render it within drawLine()
drawLine()
{
// Update buffers
// Bind and render the buffer
}
But since I ll be sending vertices everytime drawLine() gets called, it seems I am not using the power of VAO but instead simulating immediate mode rather badly!
What would be a better way to implement a line drawing function in this interface whose vertices can change in every call ?
I want to use this code in my android app later to check my physics, so I am rewriting the interface in OpenGL 4.0 which I assume will be easier to convert to openGLES 2.0 .
I was thinking of recording the vertices in a vector at every drawLine() call and then updating the VBO after all of Bullet's calls to the btIDebugDraw functions are complete. Then I would not need to send pairs of vertices intermittently to the GPU as Bullet calls the btIDebugDraw functions.
I have got some information here about managing vertex data so far :
http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html

Do not immediately draw on drawLine(). :)
Instead push the Vertices/Colors into a buffer in Host/RAM.
After the call to dynamicsWorld->debugDrawWorld(), you know that your DebugDrawer got all the lines for the frame, so you can do:
update the VBOs once
glDraw ...
clear the Host Buffer

Related

Is it possible to get class name when implementing malloc_logger function in iOS?

From here, we know if malloc_logger global function is defined, it will be called whenever there is a malloc or free operation. I want to use it to record memory allocations in my app like this:
typedef void(malloc_logger_t)(uint32_t type,
uintptr_t arg1,
uintptr_t arg2,
uintptr_t arg3,
uintptr_t result,
uint32_t num_hot_frames_to_skip);
extern malloc_logger_t *malloc_logger;
void my_malloc_stack_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t result, uint32_t num_hot_frames_to_skip);
malloc_logger = my_malloc_stack_logger;
void my_malloc_stack_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t result, uint32_t num_hot_frames_to_skip)
{
// do my work
}
In my_malloc_stack_logger, I can directly get the allocated size and address. But how about object types? I want to record the class name if it is an NSObject instance. Is it possible to get this information?
After playing around with the hook, it looks like what you want to achieve is not quite possible.
First problem here is that if you try to read a class name from within this function (by calling any of object_getClassName, class_getName
or NSStringFromClass), this action on its own tends to trigger new allocations. That apparently happens because some Cocoa classes load lazily. I noticed however that when requesting all classes with objc_getClassList it makes a lot of preliminary allocations that helps to avoid them later on. So my idea is to cache all class names before subscribing to the allocations hook and refer to the cached values when needed. For the storage I used Apple's CFMutableDictionary:
CFMutableDictionaryRef objc_class_records;
void refresh_objc_class_list(void) {
pthread_mutex_lock(&objc_class_records_mutex);
if (objc_class_records) {
CFRelease(objc_class_records);
}
objc_class_records = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
// The buffer needs to accomodate at least 26665 instances
static const unsigned buffer_length = 100000;
Class registered_classes[buffer_length];
objc_getClassList(registered_classes, buffer_length);
for (unsigned i = 0; i < buffer_length; ++i) {
if (!registered_classes[i]) {
break;
}
const Class class = registered_classes[i];
const CFStringRef class_name = CFStringCreateWithCString(kCFAllocatorDefault, class_getName(class), kCFStringEncodingUTF8);
CFDictionarySetValue(objc_class_records, class, class_name);
CFRelease(class_name);
}
}
Be advised that you don't want to have it called when the malloc logger is enabled (especially from within the hook itself).
Now you need to obtain a Class instance from the Objective-C objects. Depending on the type of allocation, the pointer argument goes to fifth or third parameter:
void my_malloc_logger(uint32_t type, uintptr_t param0, uintptr_t param1, uintptr_t param2,
uintptr_t param3, uint32_t frames_to_skip) {
void *ptr = NULL;
unsigned size = 0;
switch (type) {
case MALLOC_OP_MALLOC:
case MALLOC_OP_CALLOC:
ptr = (void *)param3;
size = (unsigned)param1;
break;
case MALLOC_OP_REALLOC:
ptr = (void *)param3;
size = (unsigned)param2;
break;
case MALLOC_OP_FREE:
ptr = (void *)param1;
break;
}
id objc_ptr = (id)ptr;
Class objc_class = object_getClass(objc_ptr);
if (!objc_class) {
return;
}
const CFStringRef class_name;
const bool found = CFDictionaryGetValueIfPresent(objc_class_records, objc_class, (const void **)&class_name);
if (found) {
const static unsigned name_max_length = 256;
char c_class_name[name_max_length];
if (CFStringGetCString(class_name, c_class_name, name_max_length, kCFStringEncodingUTF8)) {
const char *alloc_name = alloc_type_name(type);
nomalloc_printf_sync("%7s: Pointer: %p; Size: %u; Obj-C class: \"%s\"\n", alloc_name, objc_ptr, size, c_class_name);
}
}
}
And now why it won't work as expected:
object_getClass is not able to tell whether a pointer is an object of Cococa classes at the time of allocation (it will find the class, however, when the object is already allocated, e.g. before deallocation). Thus, the following code:
[NSObject new];
Will produce output similar to this:
CALLOC: Pointer: 0x600000600080; Size: 16
FREE: Pointer: 0x600000600080; Size: 0; Obj-C class: "NSObject"
Most of the standard Cocoa classes are in fact so-called Class Clusters and under the hood the actual allocation happens for an instance of a private class (which is not always recognisable by its public interface), thus this information is incomplete and sometimes misleading.
There are also many other factors which need to be taken into account (which i didn't cover here because it's beyond the question asked): the way you output data to standard output should not cause allocation by itself; the logging needs synchronisation since allocation happens a lot from any number of threads; if you want to enable/disable recording the Objective-C classes (or update the cache occasionally) access to the storage also needs to be synchronised.
Having that said if you are satisfied with what can be done with it, feel free to refer to the repository I made where this approach is already implemented in a form of a static library.

store a lambda that captures this

Using C++ 17, I'm looking for a way to store a lambda that captures the this pointer, without using std::function<>. The reason to not using std::function<> is that I need the guaranty that no dynamic memory allocations are used. The purpose of this, is to be able to define some asynchronous program flow. Example:
class foo {
public:
void start() {
timer(1ms, [this](){
set_pin(1,2);
timer(1ms, [this](){
set_pin(2,1);
}
}
}
private:
template < class Timeout, class Callback >
void timer( Timeout to, Callback&& cb ) {
cb_ = cb;
// setup timer and call cb_ one timeout reached
...
}
??? cb_;
};
Edit: Maybe it's not really clear: std::function<void()> would do the job, but I need / like to have the guaranty, that no dynamic allocations happens as the project is in the embedded field. In practice std::function<void()> seems to not require dynamic memory allocation, if the lambda just captures this. I guess this is due to some small object optimizations, but I would like to not rely on that.
You can write your own function_lite to store the lambda, then you can use static_assert to check the size and alignment requirements are satisfied:
#include <cstddef>
#include <new>
#include <type_traits>
class function_lite {
static constexpr unsigned buffer_size = 16;
using trampoline_type = void (function_lite::*)() const;
trampoline_type trampoline;
trampoline_type cleanup;
alignas(std::max_align_t) char buffer[buffer_size];
template <typename T>
void trampoline_func() const {
auto const obj =
std::launder(static_cast<const T*>(static_cast<const void*>(buffer)));
(*obj)();
}
template <typename T>
void cleanup_func() const {
auto const obj =
std::launder(static_cast<const T*>(static_cast<const void*>(buffer)));
obj->~T();
}
public:
template <typename T>
function_lite(T t)
: trampoline(&function_lite::trampoline_func<T>),
cleanup(&function_lite::cleanup_func<T>) {
static_assert(sizeof(T) <= buffer_size);
static_assert(alignof(T) <= alignof(std::max_align_t));
new (static_cast<void*>(buffer)) T(t);
}
~function_lite() { (this->*cleanup)(); }
function_lite(function_lite const&) = delete;
function_lite& operator=(function_lite const&) = delete;
void operator()() const { (this->*trampoline)(); }
};
int main() {
int x = 0;
function_lite f([x] {});
}
Note: this is not copyable; to add copy or move semantics you will need to add new members like trampoline and cleanup which can properly copy the stored object.
There is no drop in replacement in the language or the standard library.
Every lambda is a unique type in the typesystem. Technically you may have a lambda as a member, but then its type is fixed. You may not assign other lambdas to it.
If you really want to have an owning function wrapper like std::function, you need to write your own. Actually you want a std::function with a big enough small-buffer-optimization buffer.
Another approach would be to omit the this capture and pass it to the function when doing the call. So you have a captureless lambda, which is convertible to a function pointer which you can easily store. I would take this route and adapter complexer ways if really nessessary.
it would look like this (i trimmed down the code a bit):
class foo
{
public:
void start()
{
timer(1, [](foo* instance)
{
instance->set_pin(1,2);
});
}
private:
template < class Timeout, class Callback >
void timer( Timeout to, Callback&& cb )
{
cb_ = cb;
cb_(this); // call the callback like this
}
void set_pin(int, int)
{
std::cout << "pin set\n";
}
void(*cb_)(foo*);
};

Send id<MTLTexture> from ios to unity

I'm writing a plugin for unity, and I need to send a texture from ios to unity.
There is a UnitySendMessage function which takes char* as a parameter, but I didn't find a way to convert id<MTLTexture> to char*.
How can I send id<MTLTexture> from ios and receive it in unity?
My current code :
//ios side ...
id<MTLTexture> _texture = CVMetalTextureGetTexture(texture);
UnitySendMessage(CALLBACK_OBJECT, CALLBACK_TEXTURE_READY,_texture);//error
//...
//unity side
private void OnTextureReady(string texture_str)
{
IntPtr texture = new IntPtr(Int32.Parse(texture_str));
int width = 256;
int height = 256;
rawImage.texture = Texture2D.CreateExternalTexture(width, height,
TextureFormat.ARGB32, false, false, texture);
}
iOS plugin documentation says that you can only pass strings using UnitySendMessage.
The workaround would be to create a mapping from string to texture objects in Objective-C side, pass the string key via UnitySendMessage and then retrieve the texture object using a custom DllImport function.
Declare you map:
// class field
{
NSMutableDictionary<NSString *, id<MTLTexture>> _textures;
}
// in constructor
_textures = [NSMutableDictionary new];
// in function code
NSString *textureName = #"cookies";
_textures[textureName] = texture; // save MTLTexture for later
UnitySendMessage(CALLBACK_OBJECT, CALLBACK_TEXTURE_READY, textureName);
On the C# side CreateExternalTexture requires a pointer to a texture object of type IntPtr. To obtain it you can declare a DllImport function that takes a texture name and returns IntPtr:
[DllImport("__Internal")]
static extern IntPtr GetMetalTexturePointerByName(string textureName);
and implement it on the iOS side like so:
return plugin->_textures[textureName];
Not sure if it works though in terms of what CreateExternalTexture expects.
See also this post, a guy is doing something similar (but reverse):
Convert uintptr_t to id<MTLTexture>

Is it possible to access OpenGL ES from RoboVM without using LibGDX?

Is it possible to access OpenGL ES on iOS from RoboVM without using LibGDX? If so, are there any useful references?
The only thing I can find is this super-simple demo from over 2 years ago: http://robovm.com/ios-opengles-in-java-on-robovm/
But it doesn't provide any functions besides glClearColor and glClear.
The Apple GLKit framework seems to be implemented, though. I just can't find all the actual glWhatever(...) functions...
Yes, it is possible. You need two things for this: 1. Access to the OpenGL ES functions (like glClear(...), etc.) and 2. a UIView in your app that can draw the GL image.
Turns out the second point is very easy. You can either use a GLKView (requires iOS 5.0) or a CAEAGLLayer (requires iOS 2.0) if you're feeling nostalgic. For both, there are tons of tutorials online on how to use them in Objective-C, which can readily be translated to RoboVM. So, I won't spend too much time on this point here.
Access to the OpenGL ES functions is a little more difficult, as RoboVM doesn't ship with the definitions file out of the box. So, we'll have to build our own using Bro. Turns out, once you wrap your head around how Bro handles C-strings, variable pointers, IntBuffers and such (which is actually quite beautiful!), it's really pretty straight forward. The super-simple demo I linked to in the original question is the right starting point.
In the interest of brevity, let me post here just a very abridged version of the file I wrote to illustrate the way the different data types can be handled:
import java.nio.Buffer;
import java.nio.IntBuffer;
import org.robovm.rt.bro.Bro;
import org.robovm.rt.bro.Struct;
import org.robovm.rt.bro.annotation.Bridge;
import org.robovm.rt.bro.annotation.Library;
import org.robovm.rt.bro.ptr.BytePtr;
import org.robovm.rt.bro.ptr.BytePtr.BytePtrPtr;
import org.robovm.rt.bro.ptr.IntPtr;
#Library("OpenGLES")
public class GLES20 {
public static final int GL_DEPTH_BUFFER_BIT = 0x00000100;
public static final int GL_STENCIL_BUFFER_BIT = 0x00000400;
public static final int GL_COLOR_BUFFER_BIT = 0x00004000;
public static final int GL_FALSE = 0;
public static final int GL_TRUE = 1;
private static final int MAX_INFO_LOG_LENGTH = 10*1024;
private static final ThreadLocal<IntPtr> SINGLE_VALUE =
new ThreadLocal<IntPtr>() {
#Override
protected IntPtr initialValue() {
return Struct.allocate(IntPtr.class, 1);
}
};
private static final ThreadLocal<BytePtr> INFO_LOG =
new ThreadLocal<BytePtr>() {
#Override
protected BytePtr initialValue() {
return Struct.allocate(BytePtr.class, MAX_INFO_LOG_LENGTH);
}
};
static {
Bro.bind(GLES20.class);
}
#Bridge
public static native void glClearColor(float red, float green, float blue, float alpha);
#Bridge
public static native void glClear(int mask);
#Bridge
public static native void glGetIntegerv(int pname, IntPtr params);
// DO NOT CALL THE NEXT METHOD WITH A pname THAT RETURNS MORE THAN ONE VALUE!!!
public static int glGetIntegerv(int pname) {
IntPtr params = SINGLE_VALUE.get();
glGetIntegerv(pname, params);
return params.get();
}
#Bridge
private static native int glGetUniformLocation(int program, BytePtr name);
public static int glGetUniformLocation(int program, String name) {
return glGetUniformLocation(program, BytePtr.toBytePtrAsciiZ(name));
}
#Bridge
public static native int glGenFramebuffers(int n, IntPtr framebuffers);
public static int glGenFramebuffer() {
IntPtr framebuffers = SINGLE_VALUE.get();
glGenFramebuffers(1, framebuffers);
return framebuffers.get();
}
#Bridge
private static native void glShaderSource(int shader, int count, BytePtrPtr string, IntPtr length);
public static void glShaderSource(int shader, String code) {
glShaderSource(shader, 1, new BytePtrPtr().set(BytePtr.toBytePtrAsciiZ(code)), null);
}
#Bridge
private static native void glGetShaderInfoLog(int shader, int maxLength, IntPtr length, BytePtr infoLog);
public static String glGetShaderInfoLog(int shader) {
BytePtr infoLog = INFO_LOG.get();
glGetShaderInfoLog(shader, MAX_INFO_LOG_LENGTH, null, infoLog);
return infoLog.toStringAsciiZ();
}
#Bridge
public static native void glGetShaderPrecisionFormat(int shaderType, int precisionType, IntBuffer range, IntBuffer precision);
#Bridge
public static native void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, IntBuffer data);
#Bridge
private static native void glVertexAttribPointer(int index, int size, int type, int normalized, int stride, Buffer pointer);
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, Buffer pointer) {
glVertexAttribPointer(index, size, type, normalized ? GL_TRUE : GL_FALSE, stride, pointer);
}
}
Note how most methods are exposed via just trivial #Bridge-annotated native definitions, but for some it's convenient to define a wrapper method in Java that converts a String to a *char or unpacks a result from an IntPtr for example.
I didn't post my whole library file, since it is still very incomplete and it'll just make it harder to find the examples of how different parameter types are handled.
To save yourself some work, you can copy the GL constant definitions from libGDX's GL20.java. And the OpenGL ES docs are a great reference for the calling signature of the methods (the data types GLenum and GLbitfield correspond to a Java int).
You can then call the gl-methods statically by prepending GLES20. (just like on Android), e.g.:
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Turns out Bro is so smart that you don't even need to include the <framework>OpenGLES</framework> tag in robovm.xml any more, like you would with libGDX.
And - What do you know? - my app starts about 3 times as quickly as it did when it was still using libGDX. And it fixed another issue I had (see LibGDX displays black screen while app is paused but still visible (e.g. during in-app purchase password dialog) on iOS). "Yay!" for getting rid of unnecessary baggage.
The one thing that makes life a little annoying is that if you mess up the call signature of a method or the memory allocation, your app will simply crash with a very unhelpful "Terminated due to signal 11" message in the IDE-console that contains no information about where the app died.

Updating code in old book to Xcode5

Totally new to iOS development. I have a book published in 2010 called iPhone 3d Programming. There is a file explained on page 23 that will not compile in XCode5. Can somebody tell me what I am doing wrong or how to update this code to make it compile?
I"m getting errors like:
Expected ';' at end of declaration list
Unknown type name 'virtual'
IRendereringEngine.hpp
#ifndef HelloArrow_IRenderingEngine_hpp
#define HelloArrow_IRenderingEngine_hpp
// Physical orientation of a handheld device, equivalent to UIDeviceOrientation
enum DeviceOrientation {
DeviceOrientationUnknown,
DeviceOrientationPortrait,
DeviceOrientationPortraitUpsideDown,
DeviceOrientationLandscapeLeft,
DeviceOrientationLandscapeRight,
DeviceOrientationFaceUp,
DeviceOrientationFaceDown
};
// Creates an instance of the renderer and setus up various OpenGL state
struct IRenderingEngine* CreateRenderer1();
// Interface to the OpenGL ES renderer, consumed by GLView
struct IRenderingEngine {
virtual void Initialize (int width, int height) = 0;
virtual void Render() const = 0;
virtual void UpdateAnimation(float timeStep) = 0;
virtual void OnRotate(DeviceOrientation newOrientation) = 0;
virtual ~IRenderingEngine();
};
#endif

Resources