Jump to content
  • Advertisement

piecuch.p

Member
  • Content Count

    18
  • Joined

  • Last visited

Community Reputation

151 Neutral

About piecuch.p

  • Rank
    Member

Personal Information

Social

  • Github
    https://github.com/ppiecuch

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. piecuch.p

    New FreeType-based generator

    My work on UBFG is still continue, but I decided to go with some important changes: I gave up the original UBFG Qt-native font generator for FreeType-based (looks like nothing left of the original UBFG code - I might change the name of the application in the future as well). This seems to be more friendly to cross-platform and gives me better access to glyphs info (so. eg. I can export svg atlas). I have a plan to finish with the development until the end of the year.
  2. piecuch.p

    Ultimate Bitmap Font Generator 2

    Album for Ultimate Bitmap Font Generator 2
  3. piecuch.p

    TTFTriangulator demo

    I have updated demo for TTFTriangulator (simple C++ library designed to load a truetype font and triangulate its glyphs in real time) library to something working (I think). It is a little chaotic, but also very simple and generic, so easy to reuse (btw: it uses Qt for I/O and windows creation, but you can also use the code I modified and that is using GFLW). You can use my amalgamated (and dependency-free) version, available here: -rw-r--r-- 1 piecuchp staff 69K Jul 26 17:48 TTF.cpp -rwxr-xr-x 1 piecuchp staff 93K Jul 26 06:45 TTF.h -rw-r--r-- 1 piecuchp staff 217K Jul 26 06:50 TTF.o (it is also modified to use QFile for I/O so you can work with Qt's embedded resources) #include <QDebug> #include <QElapsedTimer> #include <QMouseEvent> #include <QPainter> #include <QWindow> #include <QOpenGLContext> #include <QOpenGLShaderProgram> #include <QOpenGLPaintDevice> #include <QOpenGLFunctions> #include <QApplication> #include "TTF.h" using namespace TTF; const char *fragCodeSimple = " \n\ varying vec3 tpos; \n\ float round(float val) \n\ { \n\ return sign(val)*floor(abs(val)+0.5); \n\ } \n\ void main() \n\ { \n\ float alpha = round((tpos.x*tpos.x-tpos.y)*tpos.z+0.5); \n\ gl_FragColor = alpha *vec4(1.0,1.0,1.0,1.0); \n\ } \n\ "; const char *fragCode =" \n\ varying vec3 tpos; \n\ void main() \n\ { \n\ float alpha = 1.0; \n\ if (tpos.z != 0.0) \n\ { \n\ vec2 p = tpos.xy; \n\ // Gradients \n\ vec2 px = dFdx(p); \n\ vec2 py = dFdy(p); \n\ // Chain rule \n\ float fx = ((2.0*p.x)*px.x-px.y); \n\ float fy = ((2.0*p.x)*py.x-py.y); \n\ // Signed distance \n\ float dist = fx*fx + fy*fy; \n\ float sd = (p.x*p.x - p.y)*tpos.z/sqrt(dist); \n\ // Linear alpha \n\ alpha = 0.5 - sd; \n\ if (alpha < 0.0) // Outside \n\ discard; \n\ } \n\ gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n\ } \n\ "; const char *vertCode = " \n\ attribute float t; \n\ attribute float c; \n\ attribute vec2 pos; \n\ varying vec3 tpos; \n\ void main(void) \n\ { \n\ tpos = vec3(t*0.5, max(t-1.0, 0.0), c); \n\ gl_Position = gl_ModelViewProjectionMatrix*vec4(pos, 0.0, 1.0);\n\ } \n\ "; double qtGetTime() { static QElapsedTimer timer; if (!timer.isValid()) timer.start(); return timer.elapsed() / 1000.; } class OpenGLWindow : public QWindow, public QOpenGLFunctions { Q_OBJECT typedef void (^RenderBlock)(); private: bool m_done, m_update_pending, m_auto_refresh; QOpenGLContext *m_context; QOpenGLShaderProgram m_shader; Font m_f; public: QPoint cursorPos; public: OpenGLWindow(QWindow *parent = 0) : QWindow(parent) , m_update_pending(false) , m_auto_refresh(true) , m_context(0) , m_f(":/fonts/VinMonoPro-Light.ttf") , m_done(false) { setSurfaceType(QWindow::OpenGLSurface); } ~OpenGLWindow() { } void setAutoRefresh(bool a) { m_auto_refresh = a; } void initialize() { qDebug() << "OpenGL infos with gl functions:"; qDebug() << "-------------------------------"; qDebug() << " Renderer:" << (const char*)glGetString(GL_RENDERER); qDebug() << " Vendor:" << (const char*)glGetString(GL_VENDOR); qDebug() << " OpenGL Version:" << (const char*)glGetString(GL_VERSION); qDebug() << " GLSL Version:" << (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); m_shader.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); m_shader.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCode); m_shader.link(); } void update() { renderLater(); } void render() { glViewport(0, 0, width()*devicePixelRatio(), height()*devicePixelRatio()); glClearColor(0.8, 0.8, 0.8, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1, 1, -1, 1, -10, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); m_shader.bind(); float scale = 0.1 + 0.2*fabs(cos(qtGetTime()/2.0)); glScalef(scale, scale, 1); glTranslatef(-3.6, 0, 0); renderMsg(m_f, "KomSoft"); m_shader.release(); } void mousePressEvent(QMouseEvent *event) { cursorPos = QPoint(event->x(), event->y()); Qt::KeyboardModifiers modifiers = event->modifiers(); if (event->buttons() & Qt::LeftButton) { } } void mouseReleaseEvent(QMouseEvent *event) { cursorPos = QPoint(event->x(), event->y()); Qt::KeyboardModifiers modifiers = event->modifiers(); if (event->button() == Qt::LeftButton) { } } void mouseMoveEvent(QMouseEvent *event) { cursorPos = QPoint(event->x(), event->y()); } void keyPressEvent(QKeyEvent* event) { switch(event->key()) { case Qt::Key_Escape: quit(); break; default: event->ignore(); break; } } void quit() { m_done = true; } bool done() { return m_done; } protected: void closeEvent(QCloseEvent *event) { quit(); } bool event(QEvent *event) { switch (event->type()) { case QEvent::UpdateRequest: m_update_pending = false; renderNow(); return true; default: return QWindow::event(event); } } void exposeEvent(QExposeEvent *event) { Q_UNUSED(event); if (isExposed()) renderNow(); } public slots: void renderLater() { if (!m_update_pending) { m_update_pending = true; QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); } } void renderNow() { if (!isExposed()) return; bool needsInitialize = false; if (!m_context) { m_context = new QOpenGLContext(this); m_context->setFormat(requestedFormat()); m_context->create(); needsInitialize = true; } m_context->makeCurrent(this); if (needsInitialize) { initializeOpenGLFunctions(); initialize(); } render(); m_context->swapBuffers(this); if (m_auto_refresh) renderLater(); } private: void renderMsg(const Font &f, const char *msg); }; void OpenGLWindow::renderMsg(const Font &f, const char *msg) { TTF::FontMetrics font_metrics = f.GetFontMetrics(); // will tell you about the font // Triangulator2DI, Triangulator2DII, Triangulator2DLinearI, Triangulator2DLinearII TTF::Triangulator2DI triangulator; for (int i = 0; i < strlen(msg); i++) { CodePoint cp(msg[i]); f.TriangulateGlyph(cp, triangulator); if (i > 0) { TTFCore::vec2t kerning = f.GetKerning(CodePoint(msg[i-1]), cp); glTranslatef(0.9*kerning.x*0.001, kerning.y*0.001, 0); } struct vertex_t { vec2f pos; signed char texCoord; // 0 = (0,0), 1 = (0.5,0), 2 = (1,1) signed char coef; // -1 = CW edge, 0 = inner segment, +1 = CCW segment }; QVector<vertex_t> verts; for (auto tri : triangulator) { TTF::vec2t v0 = triangulator[tri.i0]; TTF::vec2t v1 = triangulator[tri.i1]; TTF::vec2t v2 = triangulator[tri.i2]; // store in a buffer, or do something with it from here... up to you really verts.push_back((vertex_t){{0.001f*v0.x, 0.001f*v0.y}, 0, static_cast<signed char>(tri.coef)}); verts.push_back((vertex_t){{0.001f*v1.x, 0.001f*v1.y}, 1, static_cast<signed char>(tri.coef)}); verts.push_back((vertex_t){{0.001f*v2.x, 0.001f*v2.y}, 2, static_cast<signed char>(tri.coef)}); } if (verts.size()) { GLint loc = m_shader.attributeLocation("t"); glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 1, GL_BYTE, GL_FALSE, sizeof(vertex_t), &verts[0].texCoord); loc = m_shader.attributeLocation("c"); glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 1, GL_BYTE, GL_FALSE, sizeof(vertex_t), &verts[0].coef); loc = m_shader.attributeLocation("pos"); glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), &verts[0].pos); glDrawArrays(GL_TRIANGLES, 0, verts.size()); } #if 0 printf("%c: %d verts\n", msg[i], verts.size()); for (int j = 0; j < verts.size(); j++) { const vertex_t &mv = verts[j]; printf("%c %d %d, %d: (%f, %f), %d, %d\n", msg[i], j, j/3, j%3, mv.pos.x, mv.pos.y, mv.texCoord, mv.coef); } #endif } } int main(int argc, char *argv[]) { QSurfaceFormat surface_format = QSurfaceFormat::defaultFormat(); surface_format.setAlphaBufferSize( 8 ); surface_format.setDepthBufferSize( 24 ); // surface_format.setRedBufferSize( 8 ); // surface_format.setBlueBufferSize( 8 ); // surface_format.setGreenBufferSize( 8 ); // surface_format.setOption( QSurfaceFormat::DebugContext ); // surface_format.setProfile( QSurfaceFormat::NoProfile ); // surface_format.setRenderableType( QSurfaceFormat::OpenGLES ); // surface_format.setSamples( 4 ); // surface_format.setStencilBufferSize( 8 ); // surface_format.setSwapBehavior( QSurfaceFormat::DefaultSwapBehavior ); // surface_format.setSwapInterval( 1 ); // surface_format.setVersion( 2, 0 ); QSurfaceFormat::setDefaultFormat( surface_format ); QApplication app(argc, argv); OpenGLWindow w; w.resize(800, 600); w.show(); return app.exec(); } #include "demo.moc"
  4. piecuch.p

    liboggvorbis as a single-file

    liboggvorbis combined into one file - might be usefull if you want to simpifie dependencies of your project. Get it here. -rw-r--r-- 1 piecuchp staff 2.0M Apr 26 17:55 oggvorbis.c -rw-r--r-- 1 piecuchp staff 134K Apr 26 17:55 oggvorbis.h -rw-r--r-- 1 piecuchp staff 3.1M Apr 26 17:55 oggvorbis.o Combining script is quite complex and not well commented (also I might make some changes into source code that I don't recall right now) but maybe someone find it usefull: #!/bin/bash src_c="\ \ lib/codebook.h lib/mdct.h lib/envelope.h lib/smallft.h lib/codec_internal.h lib/lookup.h lib/lookup_data.h lib/lpc.h lib/lsp.h lib/masking.h lib/misc.h lib/os.h lib/registry.h lib/scales.h lib/window.h\ lib/books/floor/floor_books.h lib/books/coupled/res_books_stereo.h lib/books/uncoupled/res_books_uncoupled.h lib/books/coupled/res_books_51.h\ lib/analysis.c lib/bitrate.c lib/block.c lib/codebook.c lib/envelope.c lib/floor0.c lib/floor1.c lib/info.c lib/lookup.c lib/lpc.c lib/lsp.c lib/mapping0.c lib/mdct.c lib/psy.c lib/registry.c lib/res0.c lib/sharedbook.c lib/smallft.c lib/synthesis.c lib/vorbisenc.c lib/vorbisfile.c lib/window.c\ " src_h="\ include/ogg/config_types.h include/ogg/os_types.h include/ogg/ogg.h\ lib/ogg/bitwise.c lib/ogg/framing.c\ include/vorbis/codec.h include/vorbis/vorbisenc.h include/vorbis/vorbisfile.h\ " mkdir -p lib-portable files=0 C="lib-portable/oggvorbis.c" H="lib-portable/oggvorbis.h" echo "/** $0: `date`*/" > "$C" echo "" >> "$C" echo "_#include \"oggvorbis.h\"" >> "$C" echo "" >> "$C" echo "#define _BUILD_SINGLE_SOURCE" >> "$C" echo "#ifdef __cplusplus" >> "$C" echo "# define restrict __restrict__" >> "$C" echo "#endif" >> "$C" echo "" >> "$C" echo "/** $0: `date`*/" > "$H" echo "" >> "$H" line_offset=3 for c in $src_c; do if [ -e "$c" ]; then echo "/** $0: $c*/" >> "$C" echo "" >> "$C" #line=`cat "$C"|wc -l` echo "#line $line_offset \"$c\"" >> "$C" cat $c \ | sed "s/\([^_]\)ilog/\1ilog${cnt}/g" \ | sed "s/FLOOR1_fromdB_LOOKUP/FLOOR1_fromdB_LOOKUP${cnt}/g" \ | sed "s/bitreverse/bitreverse${cnt}/g" \ >> "$C" echo "" >> "$C" ((cnt++)) echo -n "." else # use '' for space echo "" >> "$C" echo "${c//\'\'/ }" >> "$C" echo "" >> "$C" echo -n "_" fi done for h in $src_h; do if [ -e "$h" ]; then echo "/** $0: $h*/" >> "$H" echo "" >> "$H" echo "#line $line_offset \"$h\"" >> "$H" cat $h >> "$H" echo "" >> "$H" ((cnt++)) echo -n "." else # use '' for space echo "" >> "$H" echo "${h//\'\'/ }" >> "$H" echo "" >> "$H" echo -n "_" fi done for i in lib/modes/*.h; do inl=`basename "$i"` sed -i "" -e "/#include \"modes\/$inl\"/r $i" -e "/#include \"modes\/$inl\"/d" "$C" echo -n "@" done echo "" sed -i "" -e "/^#\(.*\)include \".*\.h\".*$/d" "$H" sed -i "" -e "/^#\(.*\)include \<ogg\/.*\.h\>.*$/d" "$H" "$C" sed -i "" -e "/#include_inline \"psy.h\"/r lib/psy.h" -e "/#include_inline \"psy.h\"/d" "$C" sed -i "" -e "/#include_inline \"bitrate.h\"/r lib/bitrate.h" -e "/#include_inline \"bitrate.h\"/d" "$C" sed -i "" -e "/#include_inline \"highlevel.h\"/r lib/highlevel.h" -e "/#include_inline \"highlevel.h\"/d" "$C" sed -i "" -e "/#include_inline \"backends.h\"/r lib/backends.h" -e "/#include_inline \"backends.h\"/d" "$C" sed -i "" -e "/#include_inline \"asm_arm.h\"/r tremor/asm_arm.h" -e "/#include_inline \"asm_arm.h\"/d" "$C" sed -i "" -e "/# include \"collect.c\"/r theora/lib/collect.c" -e "/# include \"collect.c\"/d" "$C" sed -i "" -e "/^#\(.*\)include \".*\.h\".*$/d" "$C" sed -i "" -e "/^#\(.*\)include \<theora\/.*\.h\>.*$/d" "$C" sed -i "" -e "s/^_#/#/" "$C" echo "** Done (with $cnt files)"
  5. piecuch.p

    QLMesh 2.0

    QLMesh is small but useful QuickLook plugin showing a preview of various well-known 3D model formats. All formats provided by the Open Asset Import Library (http://http://assimp.sourceforge.net) are supported: 3d, 3ds, ac, ac3d, acc, ase, ask, assbin, b3d, blend, bvh, cob, csm, dae, dxf, enff, fbx, gltf, gltf2, hmp, ifc, ifczip, irr, irrmesh, lwo, lws, lxo, md2, md3, md5anim, md5camera, md5mesh, mdc, mdl, mesh, mesh.xml, mot, ms3d, ndo, nff, obj, off, ogex, pk3, ply, prj, q3o, q3s, raw, scn, smd, stl, ter, uc, vta, x, xgl, xml, zgl. I use this tool in my daily work, so I have added also support for some frequent file formats I work with: compressed textures (dds, etc/pkm and pvr (including multi-image support for mipmaps), Adobe Photoshop brushes (abr) and bitmapped font (BDF files). Current version (1.1) is using Mesa for offline rendering, but somehow I not happy with this solution. The new build (2.0) is using OSX built-in support for COLLADA/ASE format - this much more convenience in daily use. See my blog at http://pawelp.ath.cx/
  6. piecuch.p

    QLMesh with support for LDraw models

    I am preparing a new version of QLMesh with LDraw models support. Except the size of the models library I had to embed into the executable, the conversion process is quite fast event for large models, as you see on attached pictures. Nice thing is, that I was able to integrate it nicely with Open Asset Library, so the final result is quite consistent.
  7. piecuch.p

    Compressing LDraw database

    One of the main goal for QLMesh was to add some new formats I have been working with quite often, like Photoshop files of bdf fonts. For 3D it is LDraw formats and DAZ Studio models. LDraw is one of my favourite. I am currently working on extending Assimp to support .ldr and .mpd files. One of the major challenge is actually not drawing but embedding library definitions into the plugin. Original library it is about 250MB (compressed to ~40MB). That's quite large for Quicklook plugin. I started to work on some heavy compression/optimalization and current result is: -rw-r--r-- 1 piecuchp staff 40M May 12 17:18 parts.db -rw-r--r-- 1 piecuchp staff 2.2M May 12 17:18 parts.db.gz That's much better. 2MB can be easily embedded into plugin, eg. using assembler module like this: bits 64 section .rodata global _ldrawlib global _ldrawlib_end global _ldrawlib_size _ldrawlib: incbin "parts.db.gz" _ldrawlib_end: _ldrawlib_size: dd $-_ldrawlib and later build with e.g. nasm: /opt/local/bin/nasm -fmacho64 ldraw_lib.asm -o ldraw_lib.o PS1 Sometimes less is more. Working on reading gzip stream, I had to remove one of the compression optimisation. The uncompressed file is slightly bigger, but compressed one much smaller: -rw-r--r-- 1 piecuchp staff 41M Jun 17 12:03 parts.db -rw-r--r-- 1 piecuchp staff 1.5M Jun 17 12:03 parts.db.gz PS2 Sadly, this is not the end of the story I had to increase the precision of the float numbers in the database (it is now 17 bits - sign:8bit:8bit) - it increased the size but also significantly affected the compression ratio: -rw-r--r-- 1 piecuchp staff 67M Jul 11 08:55 parts.db -rw-r--r-- 1 piecuchp staff 41M Jul 11 08:55 parts.db.gz Seems like I am gonna have to live with such database for a while.
  8. piecuch.p

    UBFG2

    Bitmap font generator inspired by UBFG and BMfont applications with multiply features: multiply fonts in one atlas plenty customisations options font preview (w. OpenGL) font styling with externals editors (Photoshop/Gimp) multi-texture fonts full debug of glyphs borders and padding; glyphs rotation external font files (ttf/otf) glyph outlines signed distance field fonts, including multi-channel generator multisampling multi-channel export template-based exporter (w. Google CTemplate) Work in progress with a lot of details still to be implemented, but usable at the moment. Fonts can be generated, tested and exported.
  9. piecuch.p

    QLMesh 2.1 released

    I have prepared another update to QLMesh: ver. 2.1 add performance improvements (plugin is better handling big bitmaps), major update of Open Asset Library and support for new format: Photoshop Patterns (PAT) files - both RGB and CMYK formats are supported. New version is also build against OSX SDK 10.13, since I have finally updated my MacBook to Sierra. (http://pawelp.ath.cx/)(http://komsoft.ath.cx/)(https://itunes.apple.com/us/app/qlmesh/id1037909675)
  10. piecuch.p

    QLMesh 2.0 and Asset Import Library

    For QLMesh (and some other projects), I am running my own fork of Asset Import Library. The difference: it is amalgamated build - all sources are merged into one file (including dependencies). Since Assimp recently switched to miniz, I have replaced remaining references to zlib with miniz - so zlib is not required too. drwxr-xr-x 85 piecuchp staff 2890 Jan 17 23:34 assimp -rw-r--r-- 1 piecuchp staff 4921627 Jan 17 23:34 assimp.cpp -rw-r--r-- 1 piecuchp staff 2893785 Jan 17 23:34 private\assimp.h Everything you need to buid the assimp is: g++ -c -std=c++11 code-portable/assimp.cpp or just add assimp.cpp to your project/IDE (you can find code-portable directory in my repo. One disclaimer: I have only tested this amalgamation under OSX with QLMesh). Main reason for this amalgamation is that it makes compilation/recompilation on different platforms with different configurations rather easier. Side-effect is that single-file assimp.cpp compiles really fast (like 10x faster on my MacBook than original project files). (http://pawelp.ath.cx/)(http://komsoft.ath.cx/)(https://itunes.apple.com/us/app/qlmesh/id1037909675)
  11. piecuch.p

    QLMesh 2.0 release

    I am quite happy I finally had time to release a new version of QLMesh. With multitude of 3d files on my disk, having such a quick tool is always nice welcome. But also relaying on built-in OSX 3d generator (for .obj and .collada) made the whole code simpler and cleaner - previous version had a lot of code that suppose to work only in non-sandboxed environment (like texture support in 3d view). But after AppStore release most of this code was not in use. Now what would be good to have is finally support for Daz3D models and formats and my long-lasting missing feature: LDraw format support. (http://pawelp.ath.cx/)(http://komsoft.ath.cx/)
  12. piecuch.p

    QLMesh 2.0

    Album for QLMesh 2.0
  13. Apple has just accepted my application on AppStore: QLMesh. It is a QuickLook plugin for displaying a preview of many 3d formats, base on Open Assets Import Library. All 3d formats are supported plus some 2d compressed textures. [attachment=31149:qlmesh1.png]   Mipmaps are displayed with multi-page view - quite handy and useful feature - also because you can browse within mipmaps directly in finder. [attachment=31150:mipmaps.png] CGContextRef kcontext = QLPreviewRequestCreatePDFContext(preview, NULL, NULL, properties); ... CGImageRef cimage = ...; // Fill 3/4 of the rect const float enlarge = 1.0 + 0.48*i*i; CGRect canvasRect = CGRectMake((image[0].width - w*enlarge)/2, (image[0].height - h*enlarge)/2, w*enlarge, h*enlarge); CGContextBeginPage(kcontext, &pageRect); CGContextDrawImage(kcontext, canvasRect, cimage); CGContextEndPage(kcontext); Part of the QLMesh is control application for quicklook plugin. [attachment=31151:qlmesh5.png] Usually that would not be anything special, however for MacStore applications this is a very different story. MacStore applications are all sanboxed. There are ways to communicate and share data between such applications, eg. using App groups, but quicklook plugins do not support that feature. After struggling for some time with this problem I came out with this simple solution:  1. register additional file type/extension managed by your plugin - dedicated for passing settings to the plugin 2. when you want to pass some settings to the plugin - save settings in a file with  a special extension and request  a quicklook thumbnail for that file 3. you plugin will be executed with settings file - you can now configure your plugin   That's easy. Now hardest part: how to send some data (eg. current configuration) from plugin to Control application. Solution: encode data in thumbnail image and send it back from plugin.   Some coding - function for decoding CGDictionary to CGImage: CGImageRef _decodeDictToCGImage(CFDictionaryRef dictref, const int thsize) { NSDictionary *dict = (__bridge NSDictionary *)dictref; // Get a color space CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); NSData *decodedData = [NSKeyedArchiver archivedDataWithRootObject:dict]; const long decodedDataSize = decodedData.length; NSMutableData *paddedData = [NSMutableData dataWithBytes:&decodedDataSize length:sizeof(long)]; [paddedData appendData:decodedData]; int sz = thsize; // min. thumbnail size if (decodedData.length < sz*sz*3) [paddedData increaseLengthBy:sz*sz*3-decodedData.length]; else { sz = ceil(sqrtf(decodedData.length/3)); [paddedData increaseLengthBy:sz*sz*3-decodedData.length]; } const char* rgb = [paddedData bytes]; char* rgba = (char*)malloc(sz*sz*4); for(int i=0; i < sz*sz; ++i) { rgba[4*i] = rgb[3*i]; rgba[4*i+1] = rgb[3*i+1]; rgba[4*i+2] = rgb[3*i+2]; rgba[4*i+3] = 0xff; } // Assuming the decoded data is only pixel data CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgba, sz*sz*4, NULL); // Given size_t width, height which you should already have somehow CGImageRef image = CGImageCreate( sz, sz, /* bpc */ 8, /* bpp */ 32, /* pitch */ sz*4, colorSpace, kCGBitmapByteOrderDefault|kCGImageAlphaNone, dataProvider, /* decode array */ NULL, /* interpolate? */ FALSE, kCGRenderingIntentDefault /* adjust intent according to use */ ); if (image == nil) NSLog(@"Failed to create image from %@.", decodedData); #if 0 NSData *data = (id)CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(image))); NSLog(@"output image: %zux%zu %zu, %zu, %@ %lu", CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerPixel(image), CGImageGetBitsPerComponent(image), data, [(id)data length]); #endif // Release things the image took ownership of. CGDataProviderRelease(dataProvider); CGColorSpaceRelease(colorSpace); if (rgba) free(rgba); return image; } What's next:   1. Rendering is done using off-screen Mesa extension (this is static build). Currently it is software rasterizer (swsoft) but next version should use llvmpipe engine.   2. I am working on may optimisations - mostly related to speeding-up file loading. Current Xcode QL generator for OBJ models seems to be much faster in many cases.   3. Texture access in sandboxed environment - tricky but some workarounds could be found.     Best regards  
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!