tag:blogger.com,1999:blog-48785149375538111652024-02-18T19:12:15.539-08:00Weird ScienceTech with wings and shiny things and...HCI Research, Interaction Prototypes, Creative Coding, and other such madness.Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.comBlogger40125tag:blogger.com,1999:blog-4878514937553811165.post-50183829918042340372015-05-03T14:03:00.001-07:002015-05-03T14:03:16.063-07:00...Hostile, Agile<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnBnXCe9Dyr5X_cBNMEUAVrjUZlDjTIGRR9b_o0yN4LHDjz09KGeJRrirtXv7xsKWfny5Xgwj-gUvuZiHua8-I_wsY1-EXwF4WLe-2DAxE54PTSGWp4SQsNh8BiGcAlr5cO-E7r_lLHdM/s800/vrmobile.png"/>
</center>
</div>
<br/>
<div>
<h3><b>TL;DR:</b> Once again, Carmack was right. Go Mobile, Young Man, Go Mobile.</h3>
</div>
<br/>
<div>
Holy Jeebus, that’s right! I have a design and prototyping blog too, no, no, just kidding, I didn’t forget about it, in fact, I have so much stub content written that’s just waiting to be finished and published that you’d think...whatever one thinks about the aforementioned situation? More book reviews in the works, some mindset stuff as well, just need to get out from under May (Mai? insert joke about hot asian women and reverse cowgirl?) and content will start flowing again.
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv35F5OlX4uXp5QDv5rSiV8DwbwZM3qzk0L3VdG80BxMkKVBizw0b-UYaArpWmf3CILQlZaPvPnV8oqpF1p3TL5NKtpDZLJz-VfmhtSiu3qAeeWRzwIqKFI8iWGOQZoXF6IcADk3Jy2lo/s800/mai_s.png"/><br/>
<b>Mmm...Mai. More great work at <a href="http://pop-lee.deviantart.com/">http://pop-lee.deviantart.com/</a></b>
</center>
</div>
<br/>
<div>
To that, I’ve been in Android development land for the last couple weeks, working on...oh, of course it’s something I can’t talk about yet, you should all know that by now, but if I pull it off, it’ll be pretty cool. I can say that it may end up being a stage demo for <a target="_blank" href="https://events.google.com/io2015/">Google I/O</a>, and while my specific part of it won’t be that cool in and of itself, the total package I think’ll be pretty sweet and I actually hope it’s something that people pick up on. Like most of the tech I'm working with, I don't know how consumer friendly it is, but I think in the right hands it'll be inspirational, and could definitely pave the way for consumer uptake. Hopefully I haven't just violated my work NDA...
</div>
<br/>
<div>
Anyway, after two or three weeks of learning Android basics, Android Studio, and OpenGL ES, I’ve finally got a build running on a device, my trusty Tango tablet, well, actually more like my poor, neglected Tango tablet that I haven’t done anything with yet, but I digress...Yeah, it was a bit of a long process, but that’s how I learn new languages and platforms, more on that later. It’s a little thing, but I'm actually really excited by the simple prospect of having an OpenGL ES app fully deployed to a platform, Android, well, "mobile" development has certainly become more of an interest in the last few weeks. If you’ve been thinking about developing for Android and ESPECIALLY developing OpenGL ES based stuff...DO IT!! The world needs more resources and more folks actively banging on this stuff for things other than games, so <b>Join Me In My Quest!!</b>
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKVgnN8_sZDFyoLrXKZ3DVfvXkLDXUsnmCVzmW_qIdaCPoInr2n5bHCHrPthfRTSowX32gjVBzzdVc3-la_-sIgC0rKqY3pLYnb_PDtkgAI9nV0XIVF8HZePGVCB6dmzVMYAHcYrUlJ5g/s800/javaquest.png"/><br/>
<b>The Fellowship of the...AVD?</b>
</center>
</div>
<br/>
<div>
Seriously, it's a bit of a wild west, there aren't a ton of resources available for learning OpenGL ES on Android, and god help you if you're trying to learn the Android build chain AND OpenGL ES at the same time. The currently existing resources, well, they're a bit spotty on effectiveness, at least in my opinion, but again, once Mai is done with me, I'll try and put together my findings, hopefully they'll be useful to someone, and I encourage more folks to do the same. I'm sorta tempted to do an ES 3 tutorial series similar to what I did with my <a target="_blanl" href="https://github.com/SethGibson/CiOpenGL-Tutorial">Cinder::gl Tutorials</a>, but ES 3.0 is close enough to stock OpenGL that you could just learn OGL 3.2/3 and then brush up on the Android (or whatever your platform of choice's) buildchain. Hmm...maybe a "Learning OpenGL ES with Android Studio"? ...and I haven't even touched on Tango/Tegra stuff, which is a whole kraken unto itself...
</div>
<br/>
<div>
Why my sudden love, or at least technolust, for mobile development? Well, I know some folks are certainly given to agree with the below image and are probably thinking “Android, but that’s just for silly little apps, and none of the hardware platforms have the power/perf metrics to do anything REALLY cool,” well...I disagree with this, or at least, I disagree based on what I see when I look three to five years down the road, what with the likes of the Tegra X1 and beyond, ES 3, Vulkan, and whatever the Tango evolves into, all these things add up to a platform just ready to be taken forward into the future. If you have a modern android device with a decent mobile GPU, you should check out the <a target="_blank" href="https://play.google.com/store/apps/details?id=jp.co.siliconstudio.YEBISDemo&hl=en">Yebis 2 OpenGL ES 3.0 Demo on Google Play</a>, which is from whence the shiny part of the below image cometh (cameth?). Sure, the kicker is having an OpenGL ES 3.0 capable mGPU, and I know, I know, a demo is not a full app and doesn't have the same power/perf profile (don't you be tellin' my nu'n 'bout demos, BOY!), etc, etc, but if we should all know anything about hardware, it's that it doesn't stagnate, and I don't see that trend slowing down.
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc5P72ANm4Mxyq46XCA1Jl3bwBkbrEkEhrK1PgG1BJzkf9l3IzXar0YuGltAW6bWEeAJqOHKwmmxth-fIZRzcYXnGtWXrWmBLtOcaKZ7xh-i0MJyi21eaNG0z1erhgHrBwS27zFjHdnDE/s800/androidogl.png"/><br/>
<b>True Story, Bro.</b>
</center>
</div>
<br/>
<div>
So I’m excited now, mobile has come to mean something completely different to me in the last couple of weeks, mobile isn’t just phones and tablets, it’s Oculus, it’s Vive, it’s HoloLens, it’s most certainly things like GearVR and Wearality, but it’s also the intersection of all those things and current mobile devices and paradigms. Gotta say, at first I thought Carmack was a little crazy, but no, I think I get where he’s coming from and I’m on board for it. My big issue with VR and HMDs up till now has been the idea of people just sitting alone in dark rooms with displays wrapped around their heads, and I think that's definitely an acceptable use scenario, but I didn't want it to be the only one. Given the new perspective that I think we can all take on "mobile", I don't think it will be.
</div>
<br/>
<div>
Alright, back to it. Nothing earth-shattering or groundbreaking here for sure, just some thoughts. I just got back from //build, and I'm definitely excited about Windows 10 and Universal Windows Platform too, so I'm not just a late-to-the-party Android sycophant, well, based on what I've said, I may actually be early to some party, so I think I'm alright. The mobile future is certainly shaping up to be...interesting times. Here's to it, and hopefully my next post will have some actual useful stuff (curse you, Mai! But keep doing what you're doing...). I'll leave with a bit of shiny just so this post isn't totally useless, a short vid of my aforementioned first build, gotta love that early 90s demoscene aesthetic! Cheers!
</div>
<br/>
<blockquote class="instagram-media" data-instgrm-version="4" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:8px;"> <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:50% 0; text-align:center; width:100%;"> <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAGFBMVEUiIiI9PT0eHh4gIB4hIBkcHBwcHBwcHBydr+JQAAAACHRSTlMABA4YHyQsM5jtaMwAAADfSURBVDjL7ZVBEgMhCAQBAf//42xcNbpAqakcM0ftUmFAAIBE81IqBJdS3lS6zs3bIpB9WED3YYXFPmHRfT8sgyrCP1x8uEUxLMzNWElFOYCV6mHWWwMzdPEKHlhLw7NWJqkHc4uIZphavDzA2JPzUDsBZziNae2S6owH8xPmX8G7zzgKEOPUoYHvGz1TBCxMkd3kwNVbU0gKHkx+iZILf77IofhrY1nYFnB/lQPb79drWOyJVa/DAvg9B/rLB4cC+Nqgdz/TvBbBnr6GBReqn/nRmDgaQEej7WhonozjF+Y2I/fZou/qAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;"></div></div><p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;"><a href="https://instagram.com/p/2On1KKvkEM/" style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none;" target="_top">A video posted by Seth Gibson (@djtomservo)</a> on <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2015-05-03T17:39:43+00:00">May 3, 2015 at 10:39am PDT</time></p></div></blockquote>
<script async defer src="//platform.instagram.com/en_US/embeds.js"></script>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-55220813781610332922015-03-23T10:48:00.000-07:002015-03-23T10:48:01.502-07:00Book Review: Learning C++ by Creating Games with UE4<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjcLutQ654AIGhNyXRjKZuQxIN0JiJxwV9GkCyMFepiWTrtYK530IXLcKbbDwMKAgkO5BfvFlhagPH-EjoBsgaJyE6WUlwBgpw6PnovlAMsVKWxqplp3_GnljgF0i3SsYuNQRn_oCNxH0/s400/lcppue4_cover.jpg"/><br/>
<b><a target="_blank" href="https://www.packtpub.com/game-development/learning-c-creating-games-ue4">Buy from Publisher</a> | <a target="_blank" href="http://www.amazon.com/Learning-C-creating-games-UE4/dp/1784396575/">Buy from Amazon</a></b>
</center>
</div>
<br/>
<div>
The past week I’ve pretty much jumped into UE4 programming feet first with my boots on, and I gotta say it’s been pretty fun. As I mentioned on <a target="_blank" href="http://twitter.com/djTomServo">twitter</a>, good on Epic for providing a great UX for developers, so often people tend to think UX only applies to non-code content creators and end users, but as a someone who spends most of his time writing code, having a smooth flow from IDE to Build is awesome, especially given the fact that with something like UE4, it’s not just as simple as hitting the build button and clicking “Start Debugging” (although, with UE4 it actually is, which is a monumental feat). Props to <a target="_blank" href="http://twitter.com/CeliaHodent">Celia Hodent</a> and the rest of the Epic UX crew, next time you guys are in the bay area, drinks on me.
</div>
<br/>
<div>
I have to say it hasn’t been lack of wanting that’s kept me out of UE4 up ‘till now, I was excited as anyone to get started last year, it’s been more due to a lack of available resources coupled with lack of available learning time. Seems the universe is doing that thing where it gently nudges me in a direction again though, and as I’ve had some projects come up at work recently that are less research and more production (and also require a high degree of shiny), combined with the aforementioned availability of resources, it seems like the perfect time to dive in. Sadly, I can’t give any specifics on what I’m working on just yet, but let’s just say...Good Hunting.
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiujghK-TWxsrsvIIHbTmW7Yx0f9zitirmuh0yAUmEC2OCP51Y5t8pketu_eS-aIxike9LSgr4DCh0TNmi2YlOndQ2GkD17cy8LuAxUJPQzZ7fE8cU3RUlZlsrQAE3gkVG5GCtECz_zIf0/s800/ue4shiny.png" width="500px"/><br/>
<b>...and UE4 is definitely good at shiny. <a target="_blank" href="https://www.youtube.com/watch?v=gpkhZzE8GPo">(Atlantis by Allegorithmic)</a></b>
</center>
</div>
<br/>
<div>
To set some context for my review - In my search for learning resources, there were some specific “filter settings” I applied:
<ol>
<li>Having prior C++ knowledge, I didn’t want something that focused too much on the basics of C++. Ideally, I’d like a “UE4 Programming for C++ Programmers” type of thing.
<li>I didn’t want something that focused too much on Blueprints other than how to implement custom Blueprints. I’ve seen quite a few tutorials that promise to teach UE4 programming but only touch on C++ just enough to get you into Blueprints, then all the actual heavy lifting is done in Blueprints, even thought it could be done in C++. I need to be “close to the metal,” as the kids say.
<li>I also didn’t want something that only focused on implementing gameplay features. I know that’s a tall order since it’s a game engine (and hey, I was a tech artist for 10 years, I know tools development and the like isn’t sexy), but ideally I’d also like to learn how to implement lower order functionality, say Blueprints for utility functions or how to wrap external libraries for use in UE4.
</ol>
Of course, since I’ve only been able to find this one book on UE4 C++ Programming, this criteria may be moot, although I just got wind of <a target="_blank" href="http://www.crcpress.com/product/isbn/9781498706247">another text coming out end of next month</a>, and though I’m not totally sanguine on paying college textbook prices anymore, I'll definitely be giving it the once over as well. Getting back on topic though, how does <u>Learning C++ by Creating Games with UE4</u> stack up to my scrutiny?
</div>
<br/>
<div>
Given my first criterion, I can’t comment on the first seven chapters, but even if I could, I probably wouldn’t. One of my personal beliefs (validated through experience, mind you), is that using a tool like UE4 to teach a programming language isn’t the best approach, there are just too many other topics to contend with. Definitely not a knock on UE4, I mean, if I were going to teach someone C#, I wouldn’t use something like Unity either (for reasons I may detail in another blog post).
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQzGR1VVme6aHb0z5wlBYIzpswoQ28hnQVDAClA_J3q6SuqI4O546pYiZsN5Tsaq5mKnaPnlqYZhM6qg0mh21w2qom0x2tbupbNnzWiJOJg8LfEv8Zf64KI7G3OZX5gmysU6yT0gyKr2A/s800/unityui.png"/><br/>
<b>...pretty, but all that shiny can be distractive and not quite conducive to learning to code</b>
</center>
</div>
<br/>
<div>
So how about actually teaching UE4 programming? Well, I have to say it does a pretty good job of that, but until the next revision comes out, I definitely recommend having google and the <a target="_blank" href="https://docs.unrealengine.com/">Official Unreal Engine docs</a> on hand. Already much of the code in the book relies on deprecated functions and paradigms, which can cause a bit of confusion on initial read and also results in build errors. No knock on the book or UE4, it should certainly be expected that the APIs are going to change, and I would advise any other author and publisher to consider any UE4 text a living document and make sure to stay on top of errata and keep the code updated. That aside, the programming projects start from a good place and progress very well. Additionally, the author provides short learning projects for the reader to implement on their own which build on the currently presented topic. Personally, I spent about 4 hours going through some of those learning projects and exploring other features, so you can definitely use these as jumping off points for other exploration. And yes, there is some Blueprint work, but only so much as necessary to get the code accessible from the editor and to teach basic workflow, so you’ll definitely be self-sufficient after working through this text.
</div>
<br/>
<div>
Sadly, the book does focus purely on implementing gameplay features, but as I stated earlier, I can’t knock the author or publisher too much for that. I have to imagine that the majority of readers who come to this text will be more interested in creating gameplay features as opposed to plug-ins or other tools, but as the APIs tend to follow common patterns and conventions, branching out into other sorts of UE4 programming tasks shouldn’t be too hard from this foundation (hopefully once the plug-in framework crystallizes a bit!).
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUhw_BpnZwcPecCqslyxGkVLMjlNyph6yjKLmas896If3nEN71OXp4QusmmP3g3CAP3yHCSTcCAcvPFEt58C5nqIya7O3FkUDBO0AIpQjBLok-cJKNRUfKUmHxp9EsgmGivjwSxu3P1H0/s800/ueleap.png"/><br/>
<b>...and there's plenty of <a target="_blank" href="https://github.com/getnamo/leap-ue4">plugin source</a> available, so you're in good...err, hands.</b>
</center>
</div>
<br/>
<div>
Hopefully you can gather that my overall impression of this text is positive, but there are a few things I found a bit off, though none of them are showstoppers, at least not for an experienced C++ developer. The in-line code snippets tend to gloss over a few points, things like declaring things public vs private, including headers where necessary, and other little things that, again, for an experienced C++ developer won’t provide any roadblocks, but if you're just learning C++ and have some of the first time jitters (which is to be expected!), these oversights may cause some frustrations. I think there was also a bit of a missed opportunity with <i>Chapter 9: Templates and Commonly Used Containers</i>. This chapter touches on array types and gives a comparison to STL types, which is valuable, but reads a bit out of place. In my opinion, this discussion would’ve been better in the first section on basic C++, which would have allowed for this chapter to provide some more UE4 specific projects and code samples showing how to work with the T* container types. Just a small thought, again, not a total showstopper.
</div>
<br/>
<div>
I guess what I’ll say is that if you’re an experienced C++ developer and you want something light that you can just work through in a weekend or so and feel comfortable in UE4, this is a great choice. Between this and the official documentation, you’ll find yourself in a good position to strike out into your own projects, whatever they be. Based on the review criteria and my own perspective as outlined earlier, I don’t know if I would recommend this to someone who was wanting to learn C++ and UE4, but like I said, I wouldn’t recommend someone learn C++ through a large content creation framework anyway. My impression based on skimming through the first seven chapters is that it teaches you enough to be comfortable working in UE4, but I don’t know that it’s going to make you a competent C++ programmer, granted that's something that only really comes from practice, but having a good solid foundation is also key. To its credit, this book will definitely give you a good foundation in modern programming basics, but C++ is a vast topic that requires some specific discussions. I would recommend instead something along the lines of the tutorials found at <a target="_blank" href="http://www.cprogramming.com/tutorial/c++-tutorial.html">Cprogramming.com</a>, <a target="_blank" href="http://www.learncpp.com/">LearnCPP.com</a>, and/or <a target="_blank" href="http://www.cplusplus.com/doc/tutorial/">CPlusPlus.com</a>. I don’t say these things out of elitism or snobbery, it's just that since UE4 now gives you access to the <a target="_blank" href="https://github.com/EpicGames/UnrealEngine">FULL engine source</a>, I think it’s really worth learning C++ properly so you can take advantage of that fact. Who knows, you too may find yourself with an opportunity to push the engine outside of its original sandbox, why not be ready to rise to the occasion?
</div>
<br/>
<div>
<center>
<b>Overall, 7 out of 10</b>
</center>
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-60637660178271128312014-06-21T12:07:00.001-07:002014-06-21T12:07:45.501-07:00Getting Started With Kinect.v2 and Cinder, pt. 1: Cinder-Kinect2<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjueTKGZEmfaV6lTyE6JUTD55KZMs4s80jcCvxhfIUsVQvXPciZ1Noupuzdo_37j8krCJFcCF1t9LKZFTD2xDKj7IDE1BR1w_vlxMf4m2oYx8l06JNw7mP8tTtfILBt3FmhDJ0_JhkmzVQ/s800/cckinect.png" width="400px" /><br/>
<b>...Gentlefolks, start your frameworks.</b>
</center>
<br/>
<div>
So, I'm somewhat ashamed to admit this, but I've actually had my <a target="_blank" href="http://www.microsoft.com/en-us/kinectforwindows/">Kinect v2</a> devkit for about a month-and-a-half now and haven't really done much with it other than run some of the demos, browse the sample code, and in general be amazed at the technology. Thank god for <a target="_blank" href="http://eyeofestival.com">eyeo festival</a> and time off for a week to just create and be inspired, as it allowed me to really get hands on with the hardware and some of the solutions available for Cinder. Let's take a look, then, shall we? In this first installment, we'll go over Cinder-Kinect2, which is a wrapper around the core SDK, developed by <a target="_blank" href="http://bantherewind.com">Stephen Schieberl</a> of Wieden-Kennedy and of course, Cinder, fame.
</div>
<br/>
<div>
<hr/>
<i>DISCLAIMER: This is preliminary software and/or hardware and APIs are preliminary and subject to change</i>
<hr/>
</div>
<br/>
<div>
Let me preface this by saying I'm not presenting anything show-stopping here, this isn't even Cinder Kinect 101 (it's more like 90), chances are most users probably know this stuff already, but at least it's here for some amount of posterity, and I will be updating this as the APIs mature (which I guess should be any week now?).
</div>
<br/>
<div>
Ok, that all said, here we go, for real. Cinder-Kinect2 is the simpler of the two solutions, granted, they're both simple, Cinder-Kinect2 just requires less to get started. How simple? Well, assuming you have the K4W DPP SDK installed...<br/>
<br/>
<div class="cpp-box">
<b>-></b> Clone or fork <a target="_blank" href="https://github.com/heisters/Cinder-Kinect2">Ian Smith-Heisters' fork of Cinder-Kinect2</a>, as it includes some fixes to account for changes in the 1404 Developer Preview SDK.<br/>
<br/>
<b>-></b> "Install" it as you would any ordinary Cinder block, i.e. clone your chosen repo into your <cinder_root>\blocks folder.<br/>
<br/>
<b>-></b> Pop open a sample, make whatever changes you need, if any, to the Project Properties.<br/>
<br/>
<b>-></b> Build and Run. ??? Profit!<br/>
</div>
<br/>
As of this writing, the main fork of Cinder-Kinect2 doesn't take the 1404 changes into account. If you're interested in fixing it yourself, really you just need to make some minor changes involving the commenting out or removal to references to KinectStatus, as it's been deprecated, replacement pending, but the good Mr. Heisters has also added a few other features that make his branch worth taking a look at.
</div>
<br/>
<div>
The interface itself is as simple, if not simpler, than the installation process. Here's a sample image and a snippet of the code that produced it, cribbed from the BasicApp and BodyApp sample:
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0VTJ-u9AnZsXRUEraYg48GtDXjEGiuBgDoZLznR3DM9z-Q68VIJEWJYtkNkolZ4Tf2P4xEj53NDW1dRh4_gOrJkVt708K1YSv6rm8dY3PYvMG1f559DjE0_5fJYD2zm7KIY1F0pZSXeA/s400/k2tutorial.png" width="550px" />
</center>
</div>
<br/>
<div class="cpp-box">
<span class="code-key">void</span> <span class="code-type">K2TutorialApp</span>::update()<br/>
{<br/>
<span class="code-key">if</span>(mKinect->getFrame().getTimeStamp()>mFrame.getTimeStamp())<br/>
{<br/>
mFrame = mKinect->getFrame();<br/>
<span class="code-key">if</span>(mFrame.getColor())<br/>
{<br/>
mRgbTexture = gl::<span class="code-type">Texture</span>(mFrame.getColor());<br/>
<span class="code-key">auto</span> cBodies = mFrame.getBodies();<br/>
<span class="code-key">if</span>(cBodies.size()><span class="code-num">0</span>)<br/>
mJoints = cBodies.at(<span class="code-num">0</span>).getJointMap();<br/>
}<br/>
}<br/>
}<br/>
<br/>
<span class="code-key">void</span> <span class="code-type">K2TutorialApp</span>::draw()<br/>
{<br/>
gl::clear(Color(0, 0, 0));<br/>
<span class="code-key">if</span>(mFrame.getColor())<br/>
{<br/>
mRgbTex = gl::<span class="code-type">Texture</span>::create(mFrame.getColor());<br/>
gl::draw(mRgbTex,<br/>
<span class="code-type">Rectf</span>(<span class="code-type">Vec2f</span>::zero(), getWindowSize()));<br/>
<br/>
<span class="code-key">auto</span> cJoints = mBody.getJointMap();<br/>
<span class="code-key">if</span>(cJoints.size()>0)<br/>
{<br/>
gl::pushMatrices();<br/>
gl::scale(<span class="code-type">Vec2f</span>(getWindowSize()) / <span class="code-type">Vec2f</span>(mRgbTex->getSize()));<br/>
<span class="code-key">for</span>(<span class="code-key">auto</span> cCjoint : cJoints)<br/>
{<br/>
<span class="code-type">Vec2f</span> cp = <span class="code-type">Kinect2</span>::mapBodyCoordToColor(<br/>
cCjoint.second.getPosition(),<br/>
mKinect->getCoordinateMapper());<br/>
gl::drawSolidCircle(cp,10);<br/>
}<br/>
gl::popMatrices();<br/>
}<br/>
}<br/>
}<br/>
</div>
<br/>
<div>
<h2>Resources</h2>
<ul>
<li>Cinder Home - <a target="_blank" href="http://libcinder.org">http://libcinder.org</a></li>
<li>Cinder on github - <a target="_blank" href="https://github.com/cinder/Cinder">https://github.com/cinder/Cinder</a></li>
<li>Ian Smith-Heister's Cinder-Kinect2 fork - <a target="_blank" href="https://github.com/heisters/Cinder-Kinect2">https://github.com/heisters/Cinder-Kinect2</a></li>
<li>Stephen Schieberl's Cinder-Kinect2 fork - <a target="_blank" href="https://github.com/wieden-kennedy/Cinder-Kinect2">https://github.com/wieden-kennedy/Cinder-Kinect2</a></li>
<li>K2TutorialApp Source - <a target="_blank" href="https://github.com/SethGibson/K2Tutorial">https://github.com/SethGibson/K2Tutorial</a></li>
</ul>
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-19153489699967873912014-04-15T23:01:00.002-07:002014-04-15T23:01:28.490-07:00A video is worth 30,000 words per second?<div>
<center>
<iframe src="//player.vimeo.com/video/91813979" width="500" height="273" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe> <p><a href="http://vimeo.com/91813979">Point Clouds and FBOs</a> from <a href="http://vimeo.com/user11168439">Seth Gibson</a> on <a href="https://vimeo.com">Vimeo</a>.</p>
</center>
</div>
<br/>
<div> Just popping in to say that if you haven't checked out my Vimeo channel recently...err...there's not much new stuff there, but there's more fun stuff coming (along with new blog posts that I've promised people and myself). I'm considering doing some Cinder video tutorials if I ever find some free time, not sure about what, maybe covering Kinect, the Intel depth cameras, that sort of thing...not sure really, we'll see. But anyway, yeah, bookmark my channel, show your friends, loved ones, your inner circle, all that. If nothing else, it's good for a tiny bit of inspiration...maybe.
</div>
<br>
<div>
<center>
<h2>>>> <a target="_blank" href="https://vimeo.com/user11168439">Me on Vimeo</a> <<<</h2>
</center>
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-48126207062934197862014-03-21T13:48:00.001-07:002014-03-21T13:48:02.460-07:00Cinder-Assimp, VS2012, and Cinder 0.8.5<div>
If you're in a hurry, absolutely need to get Cinder-Assimp functional, and don't have time to read my drivel...TOO BAD! I kid, I kid, here's all you need to know:
<ul>
<li>Download the pre-built Assimp 3.0 libs from Eric Renaud-Houde's <a target="_blank" href="https://github.com/num3ric/Cinder-Skinning">Cinder-Skinning block</a> and stick them in Cinder-Assimp's lib/msw folder
<li>Pop open AssimpLoader.cpp and change line 460-ish from cam.setFovHorizontal to cam.setFov
<li>Shake your head sadly at the fact that I'm so desperate for attention that I took a two step process and turned it into the yarn below, which you may optionally read. Yep, I'm definitely management material.(Optional)
</ul>
</div>
<br/>
<div>
More often than not, when we need to deal with 3d content here in Lab land, we tend to use Unity as our framework of choice, though with dropping of the <a target="_blank" href="http://www.youtube.com/watch?v=cS6q1H23njM">thermonuclear bomb that is UE4</a> on reality this week, that may be changing. The problem, as you can imagine, is that sometimes we don't really need something as extensive as Unity, but we end up using it anyway because we don't have options, which leads to some really interesting design decisions sometimes. Recently, we had a project that really only required a minimal amount of 3d content management, so little so that it would've been nice to be able to keep the whole project in Cinder, but since our content was skinned and animated, Cinder's built in <a target="_blank" href="http://libcinder.org/docs/dev/classcinder_1_1_obj_loader.html">OBJLoader</a> obviously wouldn't suffice. So we were stuck in a situation where really we needed the absolute most minimal subset of Unity's functionality, but because it was our only option, it required quite a bit of one-off development to turn Unity into something like a useable component. Well, gee Seth, why didn't you just use <a target="_blank" href="https://github.com/gaborpapp/Cinder-Assimp">Cinder-Assimp</a>? Great question...
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxp9FdXMjP3exMMLlwz73pfgLw5XfLS69lV-weHwWT6rFhzyM_a_xnTylI2XzgqY_88_lpOTiSvn1dCMjRYKoTWkwqYlgeMFq_Pw7lasYReyPNzIkFwjXumCB_nyvSE3oOouXTD-S0Sx0/s800/bigbrain.png" height="200" width="500" /><br/>
<b>...check out the big brain on the Cinder forums.</b>
</center>
</div>
<br/>
<div>
Cinder 0.8.5 is an interesting beast, there seem to be quite a few interface changes from previous versions, that, if the dev docs are to be believed, may be re-appearing in 0.8.6. This was probably the thing that kept us from designing with Cinder-Assimp in mind originally, the fact that we couldn't really get it to work. Thankfully, we had some time to revisit the project and wrap it up, so I made it a priority to figure out Cinder-Assimp. If you're a Cinder user, you're probably familiar with <a target="_blank" href="https://vimeo.com/gabor">Gabor Papp's</a> work, if not, well, it's good, and if he says it worked, then at some point it did, so I figured it was more an error on my part than the block's part. Turns out I was right.
</div>
<br/>
<div>
First, all credit where it's due, it was actually <a target="_blank" href="http://num3ric.com/">Eric Renaud-Houde's</a> excellent <a target="_blank" href="https://github.com/num3ric/Cinder-Skinning">Cinder-Skinning</a> block that solved the major problem, that of getting compatible libraries. Sure, I could've just built Assimp myself against VS 2012, which also would have solved that problem, but hey, I'm lazy and am more than happy to let other people do work for me, although I'll probably be running a build of it myself going forward just to make sure I have it. As much as I'm excited about <a target="_blank" href="https://www.unrealengine.com/">UE4</a>, I'm definitely not abandoning Cinder...ever. I like to think of UE4 (or whatever game engine I use) as the infantry and Cinder as Spetsnaz. Anyway, if you grab the pre-built Assimp libraries linked on Eric's repo for Cinder-Skinning, you can link the Cinder-Assimp samples against that. But wait, there's probably one more error you might run up against...
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTMv_xP_QqXDJOpfnIkFqU70oVpFp3qYLw4XW4mw1ThnxZtQH2_ogMPZEAjEm8KEMC0Lazrcux3JusDKQIY3KyYOYWNb4SFrKl45T-Cd-X5McD9v39Jjn8MY47FmObUVTpeVJ-Q_vdcZY/s400/Polar-Bear-hiding-face.jpg" height="386" width="400" /><br/>
<b>...i know, i know, it's always one more thing.</b>
</center>
</div>
<br/>
<div> This..."fix", as I alluded to earlier, gives me a bit of pause, but hey, if you need to get work done, you need to get work done. But first, consider this:
<ul>
<li><a target="_blank" href="https://github.com/cinder/Cinder/blob/master/include/cinder/Camera.h">Camera.h master</a>
<li><a target="_blank" href="https://github.com/cinder/Cinder/blob/dev/include/cinder/Camera.h">Camera.h dev</a>
</ul>
As you can see, the missing setFovHorizontal() will be (is) returning (here-ish), so my actual advice is to man up and work out of the dev branch and build your own version of Assimp, which you'll probably want to do anyway since Cinder is also moving to boost 155, so why not just build everything against the same boost? But again, if that's not an option, you can just patch AssimpLoader.cpp to use the setFov() method vs setFovHorizontal() for now. So to recap (stop me if you've heard this one before):
<ul>
<li>Download the pre-built Assimp 3.0 libs from Eric Renaud-Houde's <a target="_blank" href="https://github.com/num3ric/Cinder-Skinning">Cinder-Skinning block</a> and stick them in Cinder-Assimp's lib/msw folder
<li>Pop open AssimpLoader.cpp and change line 460-ish from cam.setFovHorizontal to cam.setFov
</ul>
<br/> Now to finish up some prototypes so I can go to a Systema seminar this weekend and not sleep at the office. Hopefully I'll carve out some time to play with UE4 as well, although, I had an interesting conversation with <a target="_blank" href="http://www.bantherewind.com">Stephen Schieberl</a>, also of Cinder fame, at eyeo festival last year where he alluded to the idea that Team Cinder's been looking at game engines and thinking about how to bring some of those ideas, especially on the content creation side, into Cinder land, so...maybe UE4 is just a passing fancy too. The future is exciting, my friends, go make something.
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWqP4L0lKX9DR0Z6IAZl84nJz7cNpAuQf_MQWpS6onD1vUTqOPw3t_H-nyxWjDXJWcs2jC42MIeVj7WNDTo7Cw5IVwJ1FsPihV_655SEhTGfZhugpQEGZRX6X1oEpJ4CCbqVZhlGIfVOg/s800/ue4lab.png" height="250" width="500" /><br/>
<b>...in the future, all UIs will be MADE OF CASCADE PARTICLES!!!</b>
</center>
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-26542019191361130832014-03-09T13:36:00.001-07:002014-03-09T14:33:14.358-07:00The Human Triangulation Experiment, Stage 1<div>
Recently, us lucky saps in the Perceptual Computing Lab have been fortunate enough to be doing some prototypes for different external groups, and I've actually been lucky enough to work with one of my favorite groups, [REDACTED]! Needless to say, I'm super excited, and one of the first projects I'm working on involves using depth data and object/user segmentation data to interact with virtual/digital content, much like the ever popular kinect/box2d experiments you've probably seen floating around...
</div>
<br/>
<div>
<center>
<iframe width="420" height="315" src="//www.youtube.com/embed/BPWKx3KAvTI" frameborder="0" allowfullscreen></iframe><br/>
<b>Check out more of Stephen's stuff on <a target="_blank" href="https://github.com/BanTheRewind">github</a> or on his <a target="_blank" href="http://bantherewind.com/">website</a>.</b>
</center>
</div>
<br/>
<div>
Depth buffer, OpenCV, cinder::Triangulator, and Box2D, seemed pretty straightforward, I mean let's be honest, that's creative coding 101, right? That's what I thought, but as usual, the devil's in the details, and after some (not terribly extensive) searching and a little bit more coding I had...eh, well...nothing. My code <i>looked</i> correct, but no meshes were drawn that day, and even in a cursory inspection of my TriMesh2ds, there was nary a vertex to be seen. Here's what I tried originally (this is sketch code, so yeah, the pattern is a little sloppy):
</div>
<br/>
<div class="cpp-box">
<span class="code-cmnt">//cv contours are in mContours, mMeshes is vector<TriMesh2d></span><br/>
<span class="code-key">for</span>(<span class="code-key">auto</span> vit=mContours.begin();vit!=mCountours.end();++vit)<br/>
{<br/>
<span class="code-type">Shape2d</span> cShape;<br/>
<span class="code-type">vector</span><cv::<span class="code-type">Point</span>> contour = *vit;<br/>
auto pit=contour.begin();<br/>
cShape.moveTo(pit->x,pit->y); ++pit;<br/>
<span class="code-key">for</span>(<span class="code-cmnt">/* nothing to see here */</span>;pit!=contour.end();++pit)<br/>
{<br/>
cShape.lineTo(pit->x, pit->y);<br/>
cShape.moveTo(pit->x, pit->y);<br/>
}<br/>
cShape.close;<br/>
<span class="code-type">Triangulator</span> tris(cShape);<br/>
mMeshes.push_back(tris.calcMesh());<br/>
}
</div>
<br/>
<div>
Right, so at this point, it should be a simple exercise in gl::draw()ing the contents of mMeshes, yeah? Sadly, this method yields <i>no trimesh for you!</i>, and as I mentioned above, even a quick call to getNumVertices() revealed that there were, in fact, <i>no vertices for you!</i>, either. The docs on Triangulator lead me to believe that you can just call the constructor with a Shape2d and you should be good to go, and a quick test reveals that constructing a Triangulator with other objects does in fact yield all the verts you could ever want, so methinks maybe it's an issue with the Shape2d implementation, or perhaps I'm building my Shape2d wrong. I rule the latter out, though (well, not decisively), since Triangulator has the concept of invalid inputs, e.g. if you don't close() your Shape2d, the constructor throws, so...what to do, what to do? To the SampleCave!
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNYEVCqUE5Hn7yHd_Ni8FRmBMs6AbBpbCjdEJ1tGAVyZiBoQg6Ydon8eB360v9Upm4ua4iEpf0g_k7tbJMOoPKm0GyFvCE2g_3wIlEdI5I9TtRfhK8n4mLuNyjj852SGe_62ya_n6NAh4/s800/soupnazi.png" height="200" width="290" /><br/>
<b>TRIANGULATE AGAIN, ONE YEAR! NEXT!</b>
</center>
</div>
<br/>
<div>
<a target="_blank" href="http://bost.ocks.org/mike/">Mike Bostock</a>, he of <a target="_blank" href="http://d3js.org">d3.js</a> fame gave a great talk at <a target="_blank" href="http://eyeofestival.com">eyeo festival</a> last year on the importance of good examples (<a target="_blank" href="https://vimeo.com/69448223">Watch it on Vimeo</a>), and you know, it's so true. It's sorta like documentation, we employ technical writers for that sorta thing, I feel like we should at least give some folks a solid contract to put together good sample code for whatever we're foisting onto the world, rather than relegating samples to free time and interns (no offense to either free time or interns). Now Cinder has amazing sample code, so a quick google search for TriMesh2d popped up the <a target="_blank" href="https://github.com/cinder/Cinder/tree/master/samples/PolygonBoolean">PolygonBoolean sample</a>, which was basically doing what I wanted, i.e. constructing and drawing a TriMesh2d from a Shape2d...kinda. I trust the good folks at Team Cinder to not ship sample code that doesn't work, so a quick build 'n' run later and I had a solution. I was sooooo close...
</div>
<br/>
<div class="cpp-box">
<span class="code-cmnt">//cv contours are in mContours, mMeshes is vector<TriMesh2d></span><br/>
<span class="code-key">for</span>(<span class="code-key">auto</span> vit=mContours.begin();vit!=mCountours.end();++vit)<br/>
{<br/>
<span class="code-type">PolyLine2f</span> cShape;<br/>
<span class="code-type">vector</span><cv::<span class="code-type">Point</span>> contour = *vit;<br/>
<span class="code-key">for</span>(auto pit=contour.begin();pit!=contour.end();++pit)<br/>
{<br/>
cShape.push_back(fromOcv(*pit));<br/>
}<br/>
<span class="code-type">Triangulator</span> tris(cShape);<br/>
mMeshes.push_back(tris.calcMesh());<br/>
}
</div>
<br/>
<div>
The results? Well, see for yourself:
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD4HOyLpkqSBh8EcmTcpwMR4l1H9FlbQC4XsVBMF03dwTWiATBVPJmjn5biWG4KLrIScCf4wEE5PlZXSTfa4OhYW8EGuw1N4Asfz8HFYefm56-JTUGfZuDbYe7uZEYopu8eSOQ0j7x6oI/s800/metrie.png" width="500px" /><br/>
<b>My tribute to Harold Ramis, may you never end up in one of your own traps, sir.</b>
</center>
</div>
<br/>
<div>
Next steps are to maybe run some reduction/smoothing on the contours, although I suppose it doesn't matter terribly for this prototype, and get it into Box2D, all of which I'll cover in Stage 2, including a quick 'n' dirty Cinder-based Box2D debug draw class. This is awesome, it's total Tron stuff, bringing the real into the digital and all that sort of sorcery. Once I get the Box2D stuff implemented, I'll stick a project up on github, until then, if you have specific questions, <a href="mailto:seth.gibson1@gmail.com">Tag The Inbox</a> or leave a comment below, you are always welcome to try my Shogun Style...for reference, here's the complete update() and draw():
</div>
<br/>
<div class="cpp-box">
<span class="code-cmnt">//Using Cinder-OpenCV and Intel Perceptual Computing SDK 2013</span><br/>
<span class="code-key">void</span> <span class="code-type">segcvtestApp</span>::update()<br/>
{<br/>
mContours.clear();<br/>
mMeshes.clear();<br/>
<span class="code-key">if</span>(mPXC.AcquireFrame(<span class="code-key">true</span>))<br/>
{<br/>
<span class="code-type">PXCImage</span> *rgbImg = mPXC.QueryImage(<span class="code-type">PXCImage</span>::<span class="code-num">IMAGE_TYPE_COLOR</span>);<br/>
<span class="code-type">PXCImage</span> *segImg = mPXC.QuerySegmentationImage();<br/>
<span class="code-type">PXCImage</span>::<span class="code-type">ImageData</span> rgbData, segData;<br/>
<span class="code-key">if</span>(rgbImg->AcquireAccess(<span class="code-type">PXCImage</span>::<span class="code-num">ACCESS_READ</span>, &rgbData)>=<span class="code-num">PXC_STATUS_NO_ERROR</span>)<br/>
{<br/>
mRGB=gl::<span class="code-type">Texture</span>(rgbData.planes[<span class="code-num">0</span>],<span class="code-res">GL_BGR</span>,<span class="code-num">640</span>,<span class="code-num">480</span>);<br/>
rgbImg->ReleaseAccess(&rgbData);<br/>
}<br/>
<span class="code-key">if</span>(segImg->AcquireAccess(<span class="code-type">PXCImage</span>::<span class="code-num">ACCESS_READ</span>, &segData)>=<span class="code-num">PXC_STATUS_NO_ERROR</span>)<br/>
{<br/>
mSeg=gl::<span class="code-type">Texture</span>(segData.planes[<span class="code-num">0</span>],<span class="code-res">GL_LUMINANCE</span>,<span class="code-num">320</span>,<span class="code-num">240</span>);<br/>
segImg->ReleaseAccess(&segData);<br/>
}<br/>
<br/>
mSrcSurf = <span class="code-type">Surface</span>(mSeg);<br/>
ip::resize(mSrcSurf, &mDstSurf);<br/>
mPXC.ReleaseFrame();<br/>
}<br/>
<br/>
cv::<span class="code-type">Mat</span> surfMat(toOcv(mDstSurf.getChannelRed()));<br/>
cv::findContours(surfMat, mContours, <span class="code-num">CV_RETR_LIST</span>, <span class="code-num">CV_CHAIN_APPROX_SIMPLE</span>);<br/>
<br/>
<span class="code-key">for</span>(<span class="code-key">auto</span> vit=mContours.begin();vit!=mContours.end();++vit)<br/>
{<br/>
<span class="code-type">PolyLine2f</span> cLine;<br/>
<span class="code-type">vector</span><cv::<span class="code-type">Point</span>> contour = *vit;<br/>
<br/>
<span class="code-key">for</span>(<span class="code-key">auto</span> pit=contour.begin();pit!=contour.end();++pit)<br/>
{<br/>
cLine.push_back(fromOcv(*pit));<br/>
}<br/>
<br/>
<span class="code-type">Triangulator</span> tris(cLine);<br/>
mMeshes.push_back(tris.calcMesh());<br/>
}<br/>
}<br/>
<br/>
<span class="code-key">void</span> <span class="code-type">segcvtestApp</span>::draw()<br/>
{<br/>
<span class="code-cmnt">// draw camera feed</span><br/>
gl::clear(<span class="code-type">Color</span>( <span class="code-num">0</span>, <span class="code-num">0</span>, <span class="code-num">0</span> ) );<br/>
gl::color(<span class="code-type">Color</span>::white());<br/>
gl::draw(mRGB, <span class="code-type">Vec2f</span>::zero());<br/>
<br/>
<span class="code-cmnt">//draw meshes</span><br/>
gl::enableWireframe();<br/>
gl::color(<span class="code-type">Color</span>(<span class="code-num">0</span>,<span class="code-num">1</span>,<span class="code-num">0</span>));<br/>
<span class="code-key">for</span>(<span class="code-key">auto</span> mit=mMeshes.begin();mit!=mMeshes.end();++mit)<br/>
{<br/>
gl::draw(*mit);<br/>
}<br/>
gl::disableWireframe();<br/>
}<br/>
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-8966627409279448562013-06-09T11:50:00.002-07:002013-06-09T13:00:39.162-07:00EyeO Recap[0]<div>
My brain is COMPLETELY full. I mean, honestly I don't even know where to begin, there were so many great presentations, and so many awesome conversations about random cool things, and so many good ideas tossed around, and...I took a bunch of notes on individual sessions, which I'll toss up on the google drive at some point, maybe in about an hour when I go sit down for lunch (aside, MSP is one of the most connected airports I've ever been in. Seriously SFO and SJC, step up), and once some of the noise dies down I'll put up my actual thoughts. I'd started some posts about each day, but eventually it just got to the point where I couldn't digest things fast enough to come up with coherent thoughts on a nightly basis. Granted, there were open bars involved too, but i didn't really stay out that late, something I plan to remedy next year.
</div>
<br/>
<center>
<a href="http://www.billatkinson.com"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiV1ogeoIuYDgxXLc2hcgTlTqvOPT4e_5XV3obXMXyVm_B_JEiozTuM2vOQaxKjUaXnaufXDHNJKtI97qnebMOjJ2tZgEPi9FRc0uoPxOY7tuGe8otBfP9LhjTUx6guA5AENrWPL_abcp4/s400/BillAtWork_1.jpg" height="269" width="400" /></a><br/><span style="font-weight:bold;font-size:12px">This guy is a genius, listening to him talk, you can totally see how he would build something like Hypercard. Photo by <a href="http://charlescramer.com">Charlie Cramer</a></span>
</center>
<br/>
<div>
If I had to pull out one takeaway right now, Bill Atkinson (of <a href="http://hypercard.org">Hypercard</a> fame) said it best. Learning to code is cool, but take a different approach. There's the approach that says "I want to learn how to code", and there's the approach that says "I want to do something cool, and I'll need to learn how to code to make it happen", or alternately expressed, forget about how you want to do something and focus more on what you want to do and why you want to do it. That's not to say that tools, frameworks, languages, etc don't matter, but I've always held that application is the best way to learn something, learning through doing, learning through projects, that sort of thing. So often, I hear people say, well, why would I need to learn to code or, ok, I know some basics, but what do I do next? Answer that problem first, and learning to code becomes easy. Learn the things you need to learn for this project, then build off of them for the next project (or shoot off in a different direction and learn new things, either way is a great approach).  But don't get so caught up in learning how to code or learning every particular of a language, framework, paradigm, or process that you forget to make something beautiful. As I ranted to a co-worker a little while back "There is no perfect tool or SDK/API. Unity, UDK, Max, Maya, Cinder, ofx, processing, Windows, Mac OS, they ALL suck." But I'm going to append that with they all make beautiful things. So quit whining and make cool shit.
</div>
<br/>
<div>
My other takeaway is that <a href="http://www.memo.tv">Memo Akten</a> is in fact a machine, but his talk was probably the most personally inspiring. More on that later, but suffice it to say, I used to think I was crazy until I heard his talk.
</div>
<br/>
<div>
EyeO this year definitely struck me as more about experience than technology. I think this is both good and bad. Good because experience is really what matters at the end of the day, bad because so many people now are talking about experience, moreso than the people building experience. It would be really sad to see EyeO become a glorified UX/HCI conference, and I really hope they keep to the trend of only recruiting speakers who have actually MADE stuff. I don't see that trend changing, and I really hope EyeO continues to feel the way it did this year. Sometimes it takes a long journey fraught with setbacks, delays, time spent wandering the wilderness, time spent off the trail for a bit, or time looking at the map trying to remember where it was you were going in the first place, before you reach home. I'm not there yet, but after EyeO this year, I feel like I'm passing the last few mile markers. GDC had been home of sorts for too many years, really looking forward to this new place. It feels real.
</div>
Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-53053497304955320312013-06-06T01:03:00.000-07:002013-06-06T01:03:53.523-07:00EyeO Festival, Day 0<div>
I'm not even going to try and quote Zach Lieberman's excellent keynote, it'll be up on Vimeo anyway. I can't do it justice, but he really did say some things that lit a fire under me, especially when he called out people who spend their time building corporate demos for tradeshows and posited that CEOs shouldn't be the ones onstage telling the world what the future's going to be. It's true, and I urge everyone, especially any of my colleagues in Perceptual Computing to keep an eye on Vimeo for when it's released (or just my facebook, since I'll be posting and reposting it probably a few times an hour).
</div>
<br/>
<div>
Watching the Ignite talks at EyeO tonight, I realized a few things:<br/>
<ul>
<li>I'm total weak-sauce for not submitting an Ignite talk, since I wouldn't have been the only first time speaker.
<li>I haven't really given a talk on anything I REALLY care about since I spoke at Ringling.
<li>If I want to do an Ignite talk next year, I need to start prepping now. Holy jeebus those speakers were GOOD.
</ul>
In fact, the last sorta public speech I gave, I was doing the exact opposite of that, i.e. I was being made to champion a cause I absolutely didn't believe in and tell a story that...wasn't really a story. Seeing all those folks just KILL IT during the Ignite presentations really reminded me of what I love about public speaking, and that's telling stories I care about that give me an opportunity to connect with my listeners and inspire them. I need the opportunity to do that again because, "Without Change, Something Sleeps Inside Us and Seldom Wakens."
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTy3bf_2ud1zhd6oVPISiQgxA6onUX6VaFKkISjXsOAQcZk9iRaNgJC6WMcvZqR5xO6Kiq5gXmjw4A292F20L0tAVccSBL2fCMfzvUXin0SuiwHLyrTZ8wM4PHMMp5Ngn_e7CsyMhbt3s/s800/Crysknife.jpg" width="400px" /><br/><b>I feel like I've been sleepwalking for the last month at least</b>
</center>
<br/>
<div>
But enough positing! There was actual content today, so let's talk about interesting things instead of listening to me spew opinion. The first of two workshops today was a great intro to <a href="http://d3js.org">D3</a> from <a href="http://alignedleft.com/tutorials/d3/">Scott Murray</a>. I'd been looking at d3 earlier this year and getting to play around with it reminded me of why I liked d3 in the first place and why I wouldn't mind doing a bit more javascript work. I don't know if it's proper to say I want to do more javascript work, I think it's more that there are certain libraries that let me do certain things that just happen to be javascript, so really what I want to do is more work with said libraries and if that means a particular language, I guess that's it. I mean, if it were about a particular language/toolkit's available libraries, by that logic I'd be much more of an ofx fan than a Cinder fan, yeah? I'm really excited about the idea of using d3 and Three together, hadn't really thought much about that but the idea popped up today. Could be fun.
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyigQeWtU0kHr2BqIGUaGF9uqngn9KIEOEo14loJ9gXbv54i-nX-L49twdYBnVt1sKf78xwzgEZGCMJv8P6WMMQhBtdD0L6MQig6m6OGd0ilXSlhTR-4D03PpiQ8jTlKe-G9LNpULtUzM/s400/D3.jpg" height="270" width="400" /><br/>
<b>It's kinda nuts how easy it is to make these in d3, even with animation and interactivity</b>
</center>
<br/>
<div>
The second workshop was an applied math tutorial from the man himself, <a href="http://memo.tv">Memo Akten</a>. This course just reinforced to me how we really need to rethink the way we teach math in this country. It also confirmed my suspicion that Memo is a machine. Seriously, the way he talks about numbers and math, you can just tell he processes all that stuff differently than normal humans do, like...he SEES in linear algebra and trig. I'm totally jealous, hopefully it'll come with practice. The two things that I feel made this class work were a) the fact that the information was presented in such a way that concepts either built on top of each other or were otherwise shown in relation to each other and b) PRACTICAL EXAMPLES! Honestly, I've always been comfortable-ish with Trig, but seeing some practical examples, like projector-to-camera mapping, for example, really just locked it in. I put some notes online, they're probably only useful to me, but you're welcome to take a peek anyway: <a href="https://docs.google.com/document/d/1_JTL1xOvluQhWzfZ4z01E_P6JB-uajEYLLUmtRxw8hc/edit?usp=sharing">EyeO 2013 Applied Math Notes</a>
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwfRxOGi1ASbTxyVlpqQ0w241a6SSO0wMYYZvnOY3Zcv78uHLDtXikSpDgqDl9ao2MmCG1v5JVPV83RfI-LktEvIoUfgTrqztjyX-dZER_OuKPAlMDMW4vd_VWRXJFvh1t0owXf7518xE/s800/matrices.gif" width="400px" /><br/><b>...they're useful and make sense!</b>
</center>
<br/>
<div>
Day 0 wrapped up with Zach Lieberman's amazing keynote and an incredible round of Ignite talks. I really can't do them justice, so keep checking Vimeo for them, they're all worth watching. Onto Day 1 for talks and hack-a-thons!
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-27743053763002669662013-06-04T19:06:00.001-07:002013-06-04T19:14:42.862-07:00Eye-O Festival, Day -1<div>
I came to a really interesting realization this morning over some incredibly hot coffee (plus, Dunn Bros coffee on 15th? Yes, just, yes) that this may be the first time I've gone to a conference where I'm actually NOT interested in networking. I mean, don't get me wrong, it'd be great to get my name out into the space a little, but I'd rather do it through real work. Putting a few samples on github doesn't really count as compelling work, no matter how extensive the development might be (for the record, it's not much at this point).<br/>
<br/>
In all honesty, my interest lies in mapping the space, and again, not for a networking standpoint, I'm very interested just to see who's doing what in general, mainly because I think all this stuff is really cool (oddly enough, what brought me to intel). I think if I had meant to network really hard, I would've tried a bit harder to make sure I brought business cards, so maybe my brain just knows things that I don't. Yeah so, really excited to get a look at what people are working on, and just spend a few days writing code. Workshops start tomorrow, first up D3 with Scott Murray, followed by Applied Math with the man himself, Memo Akten. Mind preparing to be...expanded at least, probably blown.
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhW391hCUKWm5mbLs39rCSsoyrQNYuYQPIQocVFR0eKpUrxS8yhGyiPdt34QEb4Mpmx9dLLw3AKtrJqb8lBgxQLIMzjYcFI-54kxu0y75OTiQG_6SXuOt2pjmYVqVrhKQO-SojESCxTYPc/s400/fostars.jpg" height="225" width="400" /><br/>
<b>My God, It's Full Of Code...</b>
</center>
<br/>
<div>
So, here's a subject I don't talk about a whole lot, but it's definitely something I think about, for one reason or other. This particular thought thread stems from my reading of this article: <a href="http://www.wired.com/beyond_the_beyond/2013/06/intel-capital-creates-hundred-million-dollar-perceptual-computing-fund/">Intel Capital creates hundred million dollar Perceptual Computing fund</a>. Now, aside from this reinforcing my belief that it's time for me to go independent, a few things caught my eye. First, there was the opening statement:<br/>
<br/>
<i>"That’s a lot of money, tech-art fans."</i><br/>
<br/>
Second, the term "Tech Art" appeared in the Categories list for this article. So of course I had to click on it and see what other articles fell under that category. Quite an interesting list, one of them being an article highlighting the release of <a href="http://processing.org">processing 2</a>. Being here at Eye-O festival, now somewhat surrounded by people who make art by writing code, really makes me ponder that term "Tech Art" and what a "Tech Artist" really is. I'm probably not very qualified to speak on what the future of "Tech Art" as a game development discipline is, but ultimately, I'm not really sure there's such a thing as a Tech Artist in games anymore. Well that's not true, but I definitely think they're becoming fewer and further between.<br/>
<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOccF1MDKt0sbLpPb4r-yZ3dr9Cx76KbhZJidQYGhOZXlXU5gICGF_lvqTDMtl0rD98EG-E11icFULIyve6lzW83zYLnF1pu411sByLSPcZ8x0OQg1G8kzNo1rNT7kKkM8GUsQnlqpMNw/s800/codeart.png" height="130" width="400" /><br/>
<b>When code meets art (or at least my feeble attempt)...</b>
</center>
<br/>
You see, somewhere back up the line, Tech Artists became much more specialized, almost to the point where I'm not sure the title "Tech Artist" was really applicable anymore. All of a sudden we had riggers, technical animators, dcc tools developers, shader programmers, even physics artist, but to me, a proper Tech Artist was all of these things. I wrote my first auto-rigging tool in 2002, and I wrote my first Cg (proper Cg, not CgFX) shader not much later, and you know, back then that was the job. When that "normal mapping" thing started to be whispered in games circles (a lot longer ago than most of you kids think), I was one of the first people to write a normal map extractor from Maya and a Mental Ray shader to test it. Yep.  And again, that was just the job? A Tech Artist was rigger, dcc tools programmer, shader writer, fx artist, jack of many different languages, and sometimes even modeler and renderer. I feel like nowadays, that original diversity and spirit of exploration that defined tech art once is gone, and now the extent of it is finding new ways to solve the same old problem inside whatever tech art sandbox you've chosen.  Sheesh...borrow someone else's solution and use all that free time to learn something NEW, trust me, your pipeline isn't that complex, and your toolchain requirements aren't that special. Your production process is not a unique delicate flower, for shame.<br/>
<br/>
I can't really say if the current trend of specialization is going to continue, I imagine it will and people will make the argument that the increasing complexity of AAA game content will require it, but you know, I went from PS2 and low spec PC all the way to the dusk of the 360 and PS3, and I think I chose to work faster and smarter, rather then continue to add complexity to my chosen sandbox (or job security, whichever you want to call it). I think it's that approach to Tech Art that continues to serve me well in the world of RED, and just to get a little sentimental, it warms my heart to see that original spirit of Tech Art continuing to live on as Creative Coding.
</div>
<br/>
<div>
<center>
<iframe src="http://player.vimeo.com/video/51533137?color=55c4e4" width="500" height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe> <p><a href="http://vimeo.com/51533137">Eyeo2012 - Andrew Bell</a> from <a href="http://vimeo.com/eyeofestival">Eyeo Festival</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
</center>
</div>
<br/>
<div>
Andrew Bell said it best at Eye-O last year, TDs (and of course, TAs) are Creative Coders for games and film. I think this was much more true back in the day (FUCK ME I'M OLD), and I'd like to see Tech Artist return to that original spirit of exploration and diversity, rather than continuing to play "how many ways can i make up to solve the same maya problems everyone else has already solved?". That said, tomorrow is Eye-O! Time to shut my mouth, open my eyes, and engage my brain. This should be awesome.
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-44005220061551754572013-06-03T22:37:00.001-07:002013-06-03T22:37:46.774-07:00Eye-O Festival, Day -2<div>
I think I've aged about 20 years in the last month or so because I feel like I've just gotten super preachy, which is somewhat annoying, though probably less to me and more to the people to whom I've been preaching. I don't know, I feel like all these thoughts, observations, and opinions have sorta been brewing over the last while and I've decided I need to start recording more of my internal monologues, not that they're any good, but it gives me some talking points if in the future I ever end up talking to anyone who's listening. So that said, you can probably guess this isn't going to be a very technical post, but hey, I'm at Eye-O! Trust me, there will be tons of technical musings coming...Plus, I'm going to use a lot of marketing/businessey terms, for which I am also truly sorry...don't hate me, my friends (or do, i suppose).
</div>
<br/>
<div>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZhL-hewWPXd7Aiw9XGPncxDKlWugfTDBKy7KCT7vJjsV2Qqu5hBhDpJOtFPm_W1ld2fdmN4vZY04wlDzohJjQsvTaf8FOlzkl0FugTcweiC9HnuOY0bVLnKcPG50oSMAkGigd1Te5Vxs/s800/cheapfastgood.png" height="295" width="293" /><br/>
<b>We deliver all three, yo...</b>
</center>
</div>
<br/>
<div>
You get to that point sometimes where you've had a bunch of related conversations with different people and it all adds up to one conversation, or at least, it would be more efficient and probably effective to just have the whole conversation rather than have bits and pieces with different people. It's definitely been that kind of week/month/year/etc. I've been thinking, talking, trying to practice, etc what being a rapid experience developer, interaction prototyper, interactivist, whatever you want to call it, etc, and I don't think I've quite succeeded yet. Most of that is probably due to the fact that I've spent more time being an evangelist, educator, excel jockey, etc, otherwise not really an experience developer. That said, the one really useful skill I took from my time in the games industry was learning to observe and analyze process, learning what was and wasn't important, and I gotta say I got pretty good at it. So that said, here are my own thoughts on being a Rapid Experience Developer...(I'm probably 100% wrong).
</div>
<br/>
<div>
I think a big part of this thought thread started quite a while ago (well, as the internet goes anyway) when a friend of mine was pitching a hardware device to me and I kept interrupting and asking what the experience was. When developing experiences, especially for mainstream consumption, it all starts with the approach. I've noticed that here in tech-land it's all too easy for us to fall back to things like features and implementation details, or presentation and visual details, you know, the things we're good at, but let's be honest, only the pundits, marketers, and people who need techno-babble to sound intelligent care about individual features, and of those people, an even smaller slice care about anything lower level than that, algorithms and optimization details, for instance. Now don't get me wrong, I'm a developer/geek (seriously, don't let the powerlifting and MMA fool you, that's just my security blanket) at heart, I can go on about that stuff all day and then a few more, but in the right company at the right time. So mastering the art of the pitch? Crucial to rapid experience developers (henceforth, RED).
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkGJZKHdUv9qsfShKCYuKhQ3Sq3ph3y9Iim0XCvVc1G5bMWL7k3JycxHFJ_j-PwvdwPuo__ijr8EGaLe4sv-Ea6OqvZyoAUFQVdoVD1d093_Aq-iQfw4Nfprf-JlOYxVsZ9AIlMCJLk3E/s800/square_peg_in_round_hole_2.jpeg" width="400px" /><br/>
<b>Everything in its place...</b>
</center>
<br/>
<div>
First off, there's the overall mindset that comes with delivering a successful pitch. When we realize that we only have a very set amount of time to make people "get it", we really start to focus in on what our overall messaging has to be, so it goes with RED. Our experience has to communicate its essence to either an uninformed user, or even worse, a user who thinks they're informed, both of which are uphill battles. Nowadays, most people have...what I'll call a latent knowledge of experiences, that is, we're so inundated with interactive technology that we know what we DON'T like. If you've ever been in a production job, you know how annoying it is to work with creative leads who pull that stuff (oh, I'll know it when I see it), and while it's acceptable to not put up with that garbage in that situation (I mean really, that's just unprofessional), we can't really hold our target audience to that same standard, so the onus is really on us to...not really know what they want end-to-end, but at least put something in front of them that gets them in. We don't need to sell someone a product, but we do need to make sure it stays with them (no easy feat given today's short attention spans. I blame internet.)
</div>
<br/>
<div style="float:right;padding:10px">
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAwQ9krEEOKeOIJjKn7jeWE6nXj21vnwhFAXxOO8ug8ea5jBte_2akkLjqwBs3E1ogzbrIYb5UXh8kgZBon26WbpmzkmGw1zy_FLURfrRF-GCS4M3JxdPuyCnps06LjjUlQGQPsCvO2WU/s800/red.png" width="100px" />
</div>
<div>
Another crucial element of the pitch process is that it puts us into the role of storytellers, and as any good storyteller knows, we have to be able to connect with our audience. A big part of that is being able to put ourselves into the mindset of said audience. You know, in that way, RED is a lot like being an artist, in that the best artists are those who can see through their audience's eyes and know what they'll be looking for/at. Ok, I know that's a little hippy/new-agey, but I think it's a valid idea, and ultimately, I think it's the closest we're going to get to getting any sort of an indicator as to what our audiences are going to want from our experience (see, again, the onus is on US). Additionally, telling the experience as a story is a great tool for how to structure the experience overall. What's the introduction, i.e. what's that hook that's going to get the user engaged initially? Next, what's the "meat" of the experience, that is, the body of the story? What is it that's going to keep the user around for a bit? Lastly, how do we resolve the experience and give the user some impetus to at the very least stay tuned to see what's in store for either the next iteration or the next story we choose to tell? That's quite a bit to think about, and when we consider we may only have a few weeks to put all this together, well...are we starting to think a little differently about how we approach development?
</div>
<br/>
<div>
The last thing I'll touch on here about the pitch process is that it teaches us really quickly that we CANNOT fall in love with our pitch, our product, and most especially, our process. The same goes for an experience, especially when it comes to RED. Now, I realize that strikes a bit counter to what I'd previously said about RED being like art, but make no mistake, while we borrow tenets and process from art, we are NOT making art. At best, we're creating a beautiful corpse, and at worse, we're creating a trinket or a bauble to fill some space. Hopefully not too much of the latter, but it will happen, and when that order comes down, crap it out, flush it down the pipe, and get back to what matters. When we start developing an experience, we've got all these great ideas about all the features we want to include, an all the cool things we're going to write into it, and all the great infrastructure we're going to build, but you know what? The minute that stuff starts throwing up walls, trash it and move through. Coding style? Screw it. Properly modeled and textured meshes? Save that noise for polycount. Here's the question we should be asking ourselves at every step: If this experience were being demoed for 60 seconds (which is probably longer than it will be demoed in actuality), would it totally suffer if I didn't implement this feature that's had me stuck implementing for the last week? If I were to just fake it, would anyone care? Answer is probably not, unless it's some sort of interaction model we're trying to work through. Now, I know at this point someone wants to make the argument that "Presentation Counts! Visuals Matter!". That may be true, but I wonder what a little company called Rovio thinks about that, and the same goes for technical details. You probably get my point, but if you don't let me summarize by paraphrasing Einstein, "visuals, presentation, and code should be as aesthetically pleasing and functional as they need to be, but no more." Focus on what matters, forget what doesn't, and who cares if you're embarrassed to show someone your code or source files at the end? Chances are, no one's even going to ask, so...check it in and call it good.
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTMv_xP_QqXDJOpfnIkFqU70oVpFp3qYLw4XW4mw1ThnxZtQH2_ogMPZEAjEm8KEMC0Lazrcux3JusDKQIY3KyYOYWNb4SFrKl45T-Cd-X5McD9v39Jjn8MY47FmObUVTpeVJ-Q_vdcZY/s400/Polar-Bear-hiding-face.jpg" height="386" width="400" /><br/>
<b>Seriously, just put it in a private repo, i don't wanna know, it's cool</b>
</center>
<br/>
<div>
I think i'll leave this with one of my favorite creative coding projects, Red Paper Heart's Golden Clock. I like this for so many reasons (Cinder represent!!), but the main reason I like it is because it was developed by four people in 10 days. And this wasn't a prototype, mind you, this was a mission critical application, in front of hundreds of people, with different degrees of interactivity that had to run the duration of a party with it being the backdrop for the evening's main event! If this can be done in ten days by four people (albeit four kick ass developers and artists), imagine what one really capable RED could do in a month...There's your brass ring.
</div>
<br/>
<center>
<iframe src="http://player.vimeo.com/video/35320241?color=ff9933" width="500" height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe> <p><a href="http://vimeo.com/35320241">A Golden Clock</a> from <a href="http://vimeo.com/redpaperheart">Red Paper Heart</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
</center>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-62621679417942522482013-03-31T13:19:00.001-07:002013-04-01T17:00:42.513-07:00[TUTORIAL] Visualizing Depth in Unity, part 2<div>
The joys of having a laptop capable of development, I'm seriously in love with my Ultrabook. This isn't just me shilling for the company, I'm totally sold on this thing. Apple did right by forcing people to figure out how to build smaller, lighter laptops that still pack serious development punch. For reference, I'm currently working off of a <a target="_blank" href="http://www.gigabyte.com/products/product-page.aspx?pid=4209#kf">Gigabyte U2442</a>, would be nice to get something that has a Core i7 CPU, but this one's a Core i5 at 3.1 with a mobile Geforce 6xx, so I'm happy with it. Made it easy for me to bang out this second depth sample from the comfort of a...actually I think it was a bar as opposed to a coffee shop...<br/>
<br/>
<center>
<img src="http://cdn.slashgear.com/wp-content/uploads/2012/03/U2442_5.jpg" width="500px"><br/>
<b>The Technolust, i sorta haz it...</b>
</center>
</div>
<br/>
<div>
I mentioned in my last post I'd been messing around with some other methods for visualizing depth from the Creative Camera, I took a few moments after GDC to decompress and finish this one up, it sorta builds off the last sample. Instead of visualizing a texture, I'm using the depth to set attributes on some particles to get that point cloudy effect that everyone seems to know and love. This one's a bit more complex, mainly because I added a few parameters to tweak the visualization, but if you've got some Unity under your belt, none of this will be that tricky, and in fact, you'll probably see pretty quickly how setting particle data is very similar to setting pixel data. I should also note that the technique presented here could apply to any sort of 3d camera, pretty much if you can get an array of depth values from your input device, you can make this work. So here's what we're trying to accomplish when all's said and coded:<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT8EpoGOc5ngtnqlmGP_Up2DJRxhti-Eb3zmfgTklE9kI8PQrc4Y8CK50Lz34_L-BtFjgI3uPtGmFWBA5FrAXpFAszpBYfGU8eNbG_sXxHMLj9CjZCN86aLWBIof0AiRnmi_f7Y3g42ak/s800/pdepth.png" width="500px" />
</center>
</div>
<br/>
<div>
Since this is a Unity project, we'll need to set up a scene first. All that's required for this is a particle system, which you can create from the GameObject menu (GameObject > Create Other > Particle System). Set the particle system's transforms (translate and rotate) to 0,0,0 and uncheck all the options except for Renderer. Next, set the Main Camera's transform to 160,120,-240, and our scene is ready to go. That all in place, we can get to coding. We'll only need a single behavior for this test, which we'll put on the particle system. I called mine PDepth, but you'll call it Delicious (or whatever else suits your fancy)! First, let's set up our particle grid and visualization controls:<br/>
</div>
<br/>
<div class="code-box">
//We'll use these to control our particle system<br/>
public float MaxPointSize;<br/>
public int XRes, YRes;<br/>
<br/>
private ParticleSystem.Particle[] points;<br/>
private int mXStep, mYStep;<br/>
</div>
<br/>
<div>
<ul>
<li><b>MaxPointSize:</b> This controls the size of our particles</li>
<li><b>XRes, YRes:</b> These control the number of particles in our grid</li>
<li><b>points:</b> This container holds our individual particle objects</li>
<li><b>mXStep, mYStep:</b> These control the spacing between particles (this is calculated, not set manually)</li>
</ul>
<br/>
With those in place, we can populate our particle grid and get some stuff on screen. Here's what our initial Start() and Update() methods should look like:<br/>
</div>
<br/>
<div class="code-box">
void Start()<br/>
{<br/>
points = new ParticleSystem.Particle[XRes*YRes];<br/>
mXStep = 320/XRes;<br/>
mYStep = 240/YRes;<br/>
<br/>
int pid=0;<br/>
for(int y=0;y<240;y+=mYStep)<br/>
{<br/>
for(int x=0;x<320;x+=mXStep)<br/>
{<br/>
points[pid].position = new Vector3(x,y,0);<br/>
points[pid].color = Color.white;<br/>
points[pid].size = MaxPointSize;<br/>
++pid;<br/>
}<br/>
}<br/>
}<br/>
<br/>
void Update()<br/>
{<br/>
particleSystem.SetParticles(points, points.Length);<br/>
}<br/>
</div>
<br/>
<div>
If you're wondering where the values 320 and 240 came from, we're making some assumptions about the size of our depth map to set the initial bounds. Once we add in the actual depth query, we'll fix that and not have to rely on hardcodes. Otherwise, if all went according to plan, we should have a pretty grid of white particles. Be sure to set some values for XRes, YRes, and MaxPointSize in the Inspector! For this example, I've used the following settings:
<ul>
<li><b>XRes:</b> 160</li>
<li><b>YRes:</b> 120</li>
<li><b>MaxPointSize:</b> 5</li>
</ul>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzhNG8eEcgHHcaOddYVv-HZ_L9IQaOTeIGuUKMZKaYho_QSwnA1cxFiRGAwClUkCuWfnZuhZGufXwb4cdBbgEteaK2wB4zSn0NLSLb_YmGTzh1oxSfJSIy1Xhl0C6y0J8XIoNgNu9Tgsk/s800/pgrid.png" width="500px"/>
</center>
</div>
<div>
As I mentioned earlier, this procedure actually isn't too much different from the previous sample, in that we're building a block of data from the depth map then loading it into a container object, just in this case we're using an array of ParticleSystem.Particle objects instead of a Color array, and we're calling SetParticles() instead of SetPixels(). That in mind, you've probably already started figuring out how to integrate the code and concepts from the previous tutorial into this project, so let's go ahead and plow forward. First, well need to add a few more members to our behaviour:<br/>
</div>
<br/>
<div class="code-box">
public float MaxPointSize;<br/>
public int XRes, YRes;<br/>
<span class="key-term">public float MaxSceneDepth, MaxWorldDepth;</span><br/>
<br/>
<span class="key-term">private PXCUPipeline mSession;</span><br/>
<span class="key-term">private short[] mDepthBuffer;</span><br/>
<span class="key-term">private int[] mDepthSize;</span><br/>
private ParticleSystem.Particle[] points;<br/>
private int mXStep, mYStep;<br/>
</div>
<br/>
<div>
<ul>
<li><b>MaxSceneDepth:</b> The maximum Z-amount for particle positions</li>
<li><b>MaxWorldDepth:</b> The maximum distance from the camera to search for depth points</li>
<li><b>mDepthBuffer:</b> Intermediate container for depth values from the camera</li>
<li><b>mDepthSize:</b> Depth map dimensions queried from the camera. We'll replace our hardcoded 320,240 with this</li>
</ul>
</div>
<br/>
<div>
The only major additions we need to make to our Start() method involve spinning up the camera and using some of that information to properly set up our particle system. Our new Start() looks like this:<br/>
</div>
<br/>
<div class="code-box">
void Start()<br/>
{<br/>
<div class="key-term">
mDepthSize = new int[2];<br/>
mSession = new PXCUPipeline();<br/>
mSession.Init(PXCUPipeline.Mode.DEPTH_QVGA);<br/>
mSession.QueryDepthMapSize(mDepthSize);<br/>
mDepthBuffer = new short[mDepthSize[0]*mDepthSize[1]];<br/>
</div>
<br/>
points = new ParticleSystem.Particle[XRes*YRes];<br/>
mXStep = <span class="key-term">mDepthSize[0]</span>/XRes;<br/>
mYStep = <span class="key-term">mDepthSize[1]</span>/YRes;<br/>
<br/>
int pid=0;<br/>
for(int y=0;y<<span class="key-term">mDepthSize[1]</span>;y+=mYStep)<br/>
{<br/>
for(int x=0;x<<span class="key-term">mDepthSize[0]</span>;x+=mXStep)<br/>
{<br/>
points[pid].position = new Vector3(x,y,0);<br/>
points[pid].color = Color.white;<br/>
points[pid].size = MaxPointSize;<br/>
++pid;<br/>
}<br/>
}<br/>
}<br/>
</div>
<br/>
<div>
The bulk of the changes are going to be in the Update() method. The big difference between working with a particle cloud and a texture as in the previous example is that we need to know the x and y positions for each particle, thus the nested loops as opposed to a single loop for pixel data. This makes the code a bit more verbose, but not a ton more difficult to grok, so let's take a stab at building a new Update() method:</br>
</div>
<br/>
<div class="code-box">
void Update()<br/>
{<br/>
<div class="key-term">
if(mSession.AcquireFrame(false))<br/>
{<br/>
mSession.QueryDepthMap(mDepthBuffer);<br/>
int pid=0;<br/>
for(int dy=0;dy<mDepthSize[1];dy+=mYStep)<br/>
{<br/>
for(int dx=0;dx<mDepthSize[0];dx+=mXStep)<br/>
{<br/>
int didx = dy*mDepthSize[0]+dx;<br/>
<br/>
if((int)mDepthBuffer[didx]>=32000)<br/>
{<br/>
points[pid].position = new Vector3(dx,mDepthSize[1]-dy,0);<br/>
points[pid].size = 0.1f;<br/>
}<br/>
else<br/>
{<br/>
points[pid].position = new Vector3(dx, mDepthSize[1]-dy, lmap((float)mDepthBuffer[didx],0,MaxWorldDepth,0,MaxSceneDepth));<br/>
float cv = 1.0f-lmap((float)mDepthBuffer[didx],0,MaxWorldDepth,0.15f,1.0f);<br/>
points[pid].color = new Color(cv, cv, 0.15f);<br/>
points[pid].size = MaxPointSize;<br/>
}<br/>
++pid;<br/>
}<br/>
}<br/>
mSession.ReleaseFrame();<br/>
}</div><br/>
particleSystem.SetParticles(points, points.Length);<br/>
}
</div>
<br/>
<div>
So like I said, a bit more verbose, but hopefully not terribly difficult to understand. A few things to be aware of:<br/>
<br/>
<div class="code-box">
int didx = dy*mDepthSize[0]+dx;<br/>
</div>
<br/>
We use the variable didx as an index into the depth buffer. The reason we do this is because our particles don't correspond 1:1 to values in the depth buffer, so we use each particle's x and y position to do the depth buffer lookup. In the next example, we'll take a look at how we can actually have a 1:1 depth buffer to particle setup using generic types.<br/>
<br/>
<div class="code-box">
if((int)mDepthBuffer[didx]>=32000)<br/>
{<br/>
...<br/>
}<br/>
else<br/>
{<br/>
...<br/>
}<br/>
</div>
<br/>
Here, the reason we test against a depth value of 32000 is because this is what the Perceptual Computing SDK uses as the error term. So if the SDK can't resolve a depth value for a given pixel, it sends back 32000 or more. In this case, if we find an error term, we make the particle really small, but in the next example, we'll look at how we can skip that particle altogether if we have an error value. Finally, remember we need to implement some sort of range remapping function, I call mine lmap as a homage to Cinder's remap, but you can call it whatever, again, it's basically just:<br/>
<br/>
<div class="code-box">
float lmap(float v, float mn0, float mx0, float mn1, float mx1)<br/>
{<br/>
return mn1+(v-mn0)*(mx1-mn1)/(mx0-mn0);<br/>
}<br/>
</div>
</div>
<br/>
<div>
So that's that, in the next sample, we'll look at some different ways to map the depth buffer to a particle cloud and use the PerC SDK's UV mapping feature to add some color from the RGB stream to the particles. Until then, <a href="mailto:seth.gibson1@gmail.com">email me</a>, <a target="_blank" href="http://twitter.com/djTomServo">follow me on Twitter</a>, <a target="_blank" href="https://www.facebook.com/djTomServo">find me on facebook</a>, or otherwise feel free to <a target="_blank" href="http://about.me/djTomServo">stalk me socially however you prefer</a>. Cheers!<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiehrEyqWZpTyypc1ZeaEnYF023C2pqK_sAGrFm6tadSfInq2Tx3aSbRda8OokHtbTiTJ_QFtD1ZpZpaHTebNaRp9LVEf2osHDAe0rMK0aM-aNHqw22-jET7hyUeUX-4o-rbbILHtn6eBQ/s800/pcloudfinal.png" width="500px" /><br/>
<b>What can i say, i love OpenNI...</b>
</center>
</div>
Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-67863628015246596372013-03-27T11:12:00.000-07:002013-03-31T10:50:58.813-07:00[TUTORIAL] Depth maps and Ultrabooks<div>
Went to a really great hack-a-thon this past weekend at the <a target="_blank" href="http://hackerlab.org">Sacramento Hacker Lab</a> to help coach some folks through working with the Perceptual Computing SDK and got to see some really cool work being done, everything from a next-generation theremin to a telepresence bot, all powered by the <a target="_blank" href="http://intel.com/software/perceptual">Creative 3D Camera and Perceptual Computing SDK</a>. Does me good to actually get out into the community and see people just dive right in and start building stuff. Compound that with the GDC Dev Day that personally I think went amazingly well (standing room only at one point!) and it's been a good GDC for Perceptual Computing so far. But now comes the really hard part, which is that PerC needs to not become a victim of its own success. As the technology gets into more hands, now it becomes about not burning through goodwill by breaking features, being uncommunicative, or not keeping up with the ecosystem. But I digress...<br/>
</div>
<br/>
<div>
Wanted to share a little Unity tip I got asked about a few times during the hack-a-thon, and that's how to visualize the depth map. The SDK ships with a sample for visualizing the label map, and visualizing the color map is a fairly trivial change, but visualizing the depth map requires a little bit of doing. It's actually pretty trivial from a working standpoint, so let's take a look at what's required.<br/>
<br/>
To get a depth map into a usable Texture2D, the basic flow is:<br/>
<ul>
<li>Grab the depth buffer into a short array</li>
<li>Walk the array of depth values and and remap them into 0-1 range</li>
<li>Store the remapped value in a Color array</li>
<li>Load the Color array into a Texture2D</li>
</ul>
If that seems really simple, fear not, it actually is, so let's take a look at some code and see how we accomplish this. Here's a really simple Unity behavior that populates the texture object from the depth map. I'll leave assigning the texture as an exercise to the readers:<br/>
</div>
<br/>
<div class="code-box">
using UnityEngine;<br/>
using System.Collections;<br/>
<br/>
public class Test : MonoBehaviour<br/>
{<br/>
private PXCUPipeline mSession;<br/>
private int[] mDepthSize;<br/>
private short[] mDepthBuffer;<br/>
private int mSize;<br/>
<br/>
private Texture2D mDepthMap;<br/>
private Color[] mDepthPixels;<br/>
<br/>
void Start()<br/>
{<br/>
mDepthSize = new int[2];<br/>
mSession = new PXCUPipeline();<br/>
mSession.Init(PXCUPipeline.Mode.DEPTH_QVGA);<br/>
mSession.QueryDepthMapSize(mDepthSize);<br/>
mSize = mDepthSize[0]*mDepthSize[1];<br/>
<br/>
mDepthMap = new Texture2D(mDepthSize[0], mDepthSize[1], TextureFormat.ARGB32, false);<br/>
mDepthBuffer = new short[mSize];<br/>
mDepthPixels = new Color[mSize];<br/>
for(int i=0;i<mSize;++i)<br/>
{<br/>
mDepthPixels[i] = Color.black;<br/>
}<br/>
}<br/>
<br/>
void Update()<br/>
{<br/>
if(mSession.AcquireFrame(false))<br/>
{<br/>
mSession.QueryDepthMap(mDepthBuffer);<br/>
for(int i=0;i<mSize;++i)<br/>
{<br/>
float v = 1.0f-lmap((float)mDepthBuffer[i],0,1800.f,0,1.f);<br/>
mDepthPixels[i] = new Color(v,v,v);<br/>
mDepthMap.SetPixels(mDepthPixels);<br/>
mDepthMap.Apply();<br/>
}<br/>
mSession.ReleaseFrame();<br/>
}<br/>
}<br/>
<br/>
float lmap(float val, float min0, float max0, float min1, float max1)<br/>
{<br/>
return min1 + (val-min0)*(max1-min1)/(max0-min0);<br/>
}<br/>
}
</div>
<br/>
<div>
So like i said, fairly simple, albeit verbose technique, but should be fairly easy to wrap it up into a simple function for quick future use. This same technique can also be used to visualize the IR map with some very minor tweaks. I've actually been doing alot of stupid depth map tricks the last few days. I'm at GDC all this week so I'm not sure how much dev time I'll get to be able to polish a few more of these up but maybe the weekend'll afford me some cycles if i'm not in full on crash out recovery mode...
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-79871623972990444902013-03-01T14:46:00.000-08:002013-03-01T14:54:57.678-08:00Milestone presents! 5000 pageviews for me just ranting is pretty cool, so have some surprise processing code! I won't tell you what it does, basically it came out of a Unity UI experiment Annie's been working on and my desire to learn how processing's PVector interface really works. Found some interesting quirks, tho having more to do with 2d and 3d and PVector being a 3d construct vs PVector's implementation, i'm going to say (since Shiffman's a genius and probably knows what he's doing).  Anyway...have fun (and send Annie a hey if you end up using this code for something)! If it's any hint, i call this "Spider Silk"...(poetic, no?)<br/>
<br/>
<pre>
float thresh = 0.5;
//world vectors
PVector v_ctr_w = new PVector(0,0);
PVector v_0_w = new PVector(0,0);
PVector v_1_w = new PVector(0,0);
//image vectors
PVector v_ctr_i = new PVector(0,0);
PVector v_0_i = new PVector(0,0);
PVector v_1_i = new PVector(0,0);
void setup()
{
size(500,500,P2D);
stroke(128);
}
void draw()
{
background(0);
v_ctr_i.set(map(v_ctr_w.x,-1,1,0,width),map(v_ctr_w.y,-1,1,0,height),0);
v_0_i.set(mouseX,mouseY,0);
v_0_w.set(map(v_0_i.x,0,width,-1,1),map(v_0_i.y,0,height,-1,1),0);
line(v_ctr_i.x,v_ctr_i.y,v_0_i.x,v_0_i.y);
ellipse(v_ctr_i.x,v_ctr_i.y,50,50);
fill(0);
ellipse(v_0_i.x,v_0_i.y,30,30);
fill(255);
if(v_0_w.mag()<thresh)
v_1_w.set(v_0_w.x,v_0_w.y,0);
else
v_1_w = PVector.mult(v_0_w,thresh/v_0_w.mag());
v_1_i.set(map(v_1_w.x,-1,1,0,width),map(v_1_w.y,-1,1,0,height),0);
ellipse(v_1_i.x,v_1_i.y,15,15);
}
void mousePressed()
{
thresh = v_0_w.mag();
}
</pre>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com1tag:blogger.com,1999:blog-4878514937553811165.post-37299334745517865122013-02-24T20:25:00.002-08:002013-02-24T20:27:17.585-08:00A little time to breathe... First time in a while i've felt like i had a Sunday morning, not sure why that is, but it's nice to have a little room to do some random. Thought I'd just take a moment and touch on some of the things I've been working on, mainly to gloat about all the cool shit I'm doing. No, no that's not true, honestly professional life has taken a tiny bit of a turn in that I'm pretty much heading fully down the management track now and am relegating myself to weekend code warrior. This is all totally by choice, mind you, because if I've come to realize anything in the last year it's that i REALLY love software arting, like, in a bad, unnatural way. No, that's also not true, at least the last part. After 10+ years, I think i'm just burned out on industrial strength development for money in general, just because there are specific things I like doing with code, and I'm probably not going to get to do those things unless I start my own company (prospective employers and recruiters, take not). I think I've also gotten to the point in my career where I feel like I've amassed enough knowledge and experience to be a pretty good teacher, which in a weird way has brought me back around to management.<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIwjGkBBxfwsJjKo25HZD-GY-lLQ3c8bbOry4_r3FlKKqqpla8dNAw6MbU08O73rmk_3Tk3gK7jzacQ9Emo8pRvBLQm7780yI1aN6r_J6_A_TB_huEzkWucXmtmpEORtSb__8p8G_UzpE/s400/waitpimp.jpg" height="244" width="400" /><br/>
<b>Hear me out, seriously...</b>
</center>
<br/>
To me, management done properly is very much about facilitating, mentoring, and sheltering the team, which, if you think about it, parallels teaching a bit (actually, when I think about it, it also parallels parenting a bit, maybe I'm just getting to that age where I'm wanting to have kids...no, no, that's a terrifying thought). No, I've always liked the idea of teaching, for which I blame my family. There are quite a few good teachers/educators, in fact, now that I think about it, EVERYONE on my mom's side of the family are teachers. It's not so much the power and ego trip of having the authority or getting attention and letting the world know how smart i am, i just like it when knowledge is shared. In my old age, i'm getting less and less ok with the idea of making money off of ideas. Sure, you have to start with an idea, but nowadays especially, too many people get so far with the idea and don't take it through. I put code on github on a fairly regular basis, code that some people consider potential ip, but man, it's just not. It's just knowledge waiting to be re-applied. Something we all need to keep in mind, methinks.<br/>
<br/>
<span style="font-weight:bold;font-size:1.2em">Coding For Creative Non-Coders</span><br/>
So i've gotten a few questions about Coding For Creative Non-Coders (which is weird that people were actually even paying attention to that) and the short is, it's not dead (just dreaming). I've had the opportunity to present the curriculum in a few different live venues, which means I'm focusing on cleaning it up and getting it presentable to a live audience. Means it'll be a while before it's actually published here, but it also means that by the time it gets here there'll be a ton more content and it'll all flow together a bit more. One of the issues that bothered me about the curriculum initially was that it didn't really go anywhere, it sorta stopped at putting random things on screen with processing. The new, refocused curriculum deals with visualizing social networking data, so we'll go from not knowing much about coding at all to being able to scrape web services for data and displaying said data. Cool eh? So if you were watching, waiting, wondering, i apologize for taking it dark like that, but rest assured, it'll be worth it, methinks. If you're in the bay area, keep watching the <a target="_blank" href="http://gaffta.org">GAFFTA</a> website for more details on the class, and feel free to pop in!<br/>
<br/>
<center>
<img src="http://farm9.staticflickr.com/8356/8319119348_b4ee384654.jpg" width="500" height="166" alt="teaser">
</center>
<br/>
<span style="font-weight:bold;font-size:1.2em">Cindering and Other Creative Coding</span><br/>
Dunno if anyone found my Cinder rantings at all useful (probably not), but if you did, fear not, more of those are on the way as well. I'm pretty much deep into development at this point, churning on content for GDC, workshops, and a new SDK release, which means when i'm not managering, i'm coding pretty fiercely, and haven't taken the time to stop and do proper writeups like i should. Hopefully the code will be self-documenting enough, though I do plan on releasing some sort of documentation for certain projects (Cinder block, ofx addon, Unity samples, etc). Basically, useful code is on the way, so fear not. If all goes according to plan, everything should line up with the SDKs Gold Release, which is...well, soon.<br/>
<br/>
<span style="font-weight:bold;font-size:1.2em">Thinking, Thinking</span><br/>
About pretty much everything. As i type this, i have a window open with a linkedin message to a google recruiter in a somewhat unfinished state. I don't really want to work for google, in fact, after Intel i really don't want to work for anyone but me anymore on smaller, project based contracts. It was actually my initial contact with google that got me thinking about that because they didn't really have a job for me, it was more that they think they like my skillset, or at least what they can tell of it from paper. So it's probably the case of they just want to bring on engineering resources, then assign them to projects, or even more, the oft-romanticized work on whatever project interests you, made popular by such groups as Valve (wonder how that worked for the crew they just laid off...). I notice alot of people think that sort of environment is fairly attractive, but if i've learned anything about my work habits, it's that i REALLY like projects.<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqSqQensKiOAIZVbnh2hPsrDcbrMWrKmSNTexCRHY1BuHqzpzSme3fm5B8bGMpjusX70WyAI1iPgUZmXgjZwOIUpdzSdtWeUeNzgTR9gcGsu4XDNAZY_xn1lWxR7bPV_p-yzIRpMTSKgo/s800/horizon.png" height="211" width="500" />
<br/>
<b>...always looking towards some horizon, i suppose...</b>
</center>
<br/>
Ultimately, I'd rather be hired because someone saw my body of work and thougth that was attractive, rather than a few lines under the "Skills" heading on a website. I'm actually considering removing specific languages from my LinkedIn profile and just adding frameworks, SDKs, APIs, environments, etc. I imagine that would blow some recruiter's mind pretty hard, but the flipside is i would probably get approached by people who really wanted to work with me on things I was really interested in working on. Might be an interesting experiment.<br/>
<br/>
Experiment...that's another incredibly relevant descriptor. I think my whole time at Intel is going to be a series of experiments, from proving some ideas I have about project management to going from tech artist to UX Developer/Project Manager. It's daunting but exciting at the same time, I think my limited experience managing Tech Artists is probably going to be a big help when it comes to managing the crew i'm working with right now. I say i'd never go back to game development, but who knows? If my ideas turn out to be correct, might be fun to do some indie development. Dunno tho, i think any game i made wouldn't do too well because after Intel, i don't think i could adhere to the established input modalities that games seem to be comfortable with. Ah well, UX Development Manager it is, I suppose. For now.Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-54994216981878067542013-01-30T12:13:00.001-08:002013-01-30T12:22:29.644-08:00[CODE] simple bullet physics debug draw for Cinder<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiISr3s8cSfzn4UZVfgmORSynVHT3uYxUdvQPGS2C9SUZ6-FIiGMSxGZ-30yYxuLa-C6StHfqIndoNKyCrdxkE5qqEhqUow-X4ucjY2EgvgM_dmS48w-8yD-_9rX8uzBMk3r9OCnUPVUpI/s800/bullinder.png" height="170" width="340" />
</center>
<br/>
<div>
Not horribly hard to figure out but if you feel like saving yourself some code time or just looking for a quick jumping off point, here you go. You can also grab the whole <a target="_blank" href="https://github.com/SethGibson/BulletTest">project from github</a>. If this looks like a straight port of bullet's GLDebugDrawer, it pretty much is.<br/>
</div>
<br/>
<div>.h</div>
<div class="cpp-box">
<span class="code-pp">#include</span> <span class="code-str">"cinder/app/AppBasic.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"cinder/gl/gl.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"cinder/Text.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"btBulletDynamicsCommon.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"LinearMath/btIDebugDraw.h"</span><br/>
<br/>
<span class="code-res">using namespace</span> ci;<br/>
<span class="code-res">using namespace</span> ci::app;<br/>
<span class="code-res">using namespace</span> std;<br/>
<br/>
<span class="code-type">class</span> CibtDebugDraw : <span class="code-type">public</span> btIDebugDraw<br/>
{<br/>
<span class="code-type">int</span> m_debugMode;<br/>
public:<br/>
CibtDebugDraw();<br/>
<span class="code-type">virtual</span> ~CibtDebugDraw();<br/>
<span class="code-type">virtual void</span> drawLine(<span class="code-type">const btVector3&</span> from, <span class="code-type">const btVector3&</span> to, <span class="code-type">const btVector3&</span> fromColor, <span class="code-type">const btVector3&</span> toColor);<br/>
<span class="code-type">virtual void</span> drawLine(<span class="code-type">const btVector3&</span> from, <span class="code-type">const btVector3&</span> to, <span class="code-type">const btVector3&</span> color);<br/>
<span class="code-type">virtual void</span> drawSphere(<span class="code-type">const btVector3&</span> p, <span class="code-type">btScalar</span> radius, <span class="code-type">const btVector3&</span> color);<br/>
<span class="code-type">virtual void</span> drawBox(<span class="code-type">const btVector3&</span> bbMin, <span class="code-type">const btVector3&</span> bbMax, <span class="code-type">const btVector3&</span> color);<br/>
<span class="code-type">virtual void</span> drawContactPoint(<span class="code-type">const btVector3&</span> PointOnB, <span class="code-type">const btVector3&</span> normalOnB, <span class="code-type">btScalar</span> distance, <span class="code-type">int</span> lifeTime, <span class="code-type">const btVector3&</span> color);<br/>
<span class="code-type">virtual void</span> reportErrorWarning(<span class="code-type">const char*</span> warningString);<br/>
<span class="code-type">virtual void</span> draw3dText(<span class="code-type">const btVector3&</span> location, <span class="code-type">const char*</span> textString);<br/>
<span class="code-type">virtual void</span> setDebugMode(<span class="code-type">int</span> debugMode);<br/>
<span class="code-type">virtual int</span> getDebugMode() <span class="code-type">const</span>;<br/>
};<br/>
</div>
<br/>
<div>.cpp</div>
<div class="cpp-box">
CibtDebugDraw::CibtDebugDraw() : m_debugMode(<span class="code-num">0</span>)<br/>
{<br/>
}<br/>
<br/>
CibtDebugDraw::~CibtDebugDraw()<br/>
{<br/>
}<br/>
<br/>
<span class="code-type">void</span> CibtDebugDraw::drawLine(<span class="code-type">const btVector3&</span> from, <span class="code-type">const btVector3&</span> to, <span class="code-type">const btVector3&</span> fromColor, <span class="code-type">const btVector3&</span> toColor)<br/>
{<br/>
gl::begin(<span class="code-num">GL_LINES</span>);<br/>
gl::color(<span class="code-type">Color</span>(fromColor.getX(), fromColor.getY(),<br/> fromColor.getZ()));<br/>
gl::vertex(from.getX(),from.getY(),from.getZ());<br/>
gl::color(<span class="code-type">Color</span>(toColor.getX(), toColor.getY(), toColor.getZ()));<br/>
gl::vertex(to.getX(),to.getY(),to.getZ());<br/>
gl::end();<br/>
}<br/>
<br/>
<span class="code-type">void</span> CibtDebugDraw::drawLine(<span class="code-type">const btVector3&</span> from, <span class="code-type">const btVector3&</span> to, <span class="code-type">const btVector3&</span> color)<br/>
{<br/>
drawLine(from,to,color,color);<br/>
}<br/>
<br/>
<span class="code-type">void</span> CibtDebugDraw::drawSphere(<span class="code-type">const btVector3&</span> p, <span class="code-type">btScalar</span> radius, <span class="code-type">const btVector3&</span> color)<br/>
{<br/>
gl::color(<span class="code-type">Color</span>(color.getX(), color.getY(), color.getZ()));<br/>
gl::drawSphere(<span class="code-type">Vec3f</span>(p.getX(),p.getY(),p.getZ()), radius);<br/>
}<br/>
<br/>
<span class="code-type">void</span> CibtDebugDraw::drawBox(<span class="code-type">const btVector3&</span> bbMin, <span class="code-type">const btVector3&</span> bbMax, <span class="code-type">const btVector3&</span> color)<br/>
{<br/>
gl::color(<span class="code-type">Color</span>(color.getX(), color.getY(), color.getZ()));<br/>
gl::drawStrokedCube(<span class="code-type">AxisAlignedBox3f</span>(<br/>
<span class="code-type">Vec3f</span>(bbMin.getX(),bbMin.getY(),bbMin.getZ()),<br/>
<span class="code-type">Vec3f</span>(bbMax.getX(),bbMax.getY(),bbMax.getZ())));<br/>
}<br/>
<br/>
<span class="code-type">void</span> CibtDebugDraw::drawContactPoint(<span class="code-type">const btVector3&</span> PointOnB, <span class="code-type">const btVector3&</span> normalOnB, <span class="code-type">btScalar</span> distance, <span class="code-type">int</span> lifeTime, <span class="code-type">const btVector3&</span> color)<br/>
{<br/>
<span class="code-type">Vec3f</span> from(PointOnB.getX(), PointOnB.getY(), PointOnB.getZ());<br/>
<span class="code-type">Vec3f</span> to(normalOnB.getX(), normalOnB.getY(), normalOnB.getZ());<br/>
to = from+to*1;<br/>
<br/>
gl::color(<span class="code-type">Color</span>(color.getX(),color.getY(),color.getZ()));<br/>
gl::begin(<span class="code-num">GL_LINES</span>);<br/>
gl::vertex(from);<br/>
gl::vertex(to);<br/>
gl::end();<br/>
}<br/>
<br/>
<span class="code-type">void</span> CibtDebugDraw::reportErrorWarning(<span class="code-type">const char*</span> warningString)<br/>
{<br/>
console() << warningString << std::endl;<br/>
}<br/>
<br/>
<span class="code-type">void</span> CibtDebugDraw::draw3dText(<span class="code-type">const btVector3&</span> location, <span class="code-type">const char*</span> textString)<br/>
{<br/>
<span class="code-type">TextLayout</span> textDraw;<br/>
textDraw.clear(<span class="code-type">ColorA</span>(<span class="code-num">0</span>,<span class="code-num">0</span>,<span class="code-num">0</span>,<span class="code-num">0</span>));<br/>
textDraw.setColor(<span class="code-type">Color</span>(<span class="code-num">1</span>,<span class="code-num">1</span>,<span class="code-num">1</span>));<br/>
textDraw.setFont(<span class="code-type">Font</span>(<span class="code-str">"Arial"</span>, <span class="code-num">16</span>));<br/>
textDraw.addCenteredLine(textString);<br/>
gl::draw(<span class="code-type">gl::Texture</span>(textDraw.render()),<br/>
<span class="code-type">Vec2f</span>(location.getX(),location.getY()));<br/>
}<br/>
<br/>
<span class="code-type">void</span> CibtDebugDraw::setDebugMode(<span class="code-type">int</span> debugMode)<br/>
{<br/>
m_debugMode = debugMode;<br/>
}<br/>
<br/>
<span class="code-type">int</span> CibtDebugDraw::getDebugMode() <span class="code-type">const</span><br/>
{<br/>
return m_debugMode;<br/>
}<br/>
</div>
<br/>
<div>Here's a quick shot of the debug drawer in action with a single body:</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNGd36fbN5XgZVIvA_3g6CWXiKbhrbZpr_MazwziUJICoar6eXOqFmx191yWce9Q_nQ1y5si6hgQm-OCNwWhZtbIZz6WqjG1OdKRQ0li3sj8ukSPPElelntLZizHxMpu_8Uh4sIBWE_hM/s400/bullettest.png" height="316" width="400" />
</center>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-47528940324648332532013-01-27T15:27:00.002-08:002013-01-27T20:19:31.395-08:00[TUTORIAL] Getting tweets into Cinder<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK2pb4cvBU8QL64GSp4SupdGMSVNTz9QQMj9qFV2qi1yn3DczMyo56GzMD3Hzztp_eNuvNXP1BFwzzKII0-Q4c3b_eRERqjGrLpKj2kmQxBhSlUPtvshwUZu-3c2drv6EuSv_P3ct4Nsc/s800/twinder.png" height="170" width="340" />
</center>
<br/>
<div>
Hmm...the notion of "getting something into Cinder" may be a bit of a misnomer, but then, you are pulling data into a framework/environment, so maybe it is. Ah well, point being we're moving on from the <a target="_blank" href="http://protomatic.blogspot.com/2013/01/building-twitcurl-in-visual-studio-2010.html">previous installment</a> wherein we walked through the steps required to build the twitcurl library so we could tweet in C++. Now we need to actually use the darn thing, yeah? So let's get to...err...Tweendering? (Cindweeting? Cindereeting? Sure, ok). I'm assuming we all know how to use Tinderbox to setup a Cinder project, if not, just hit up <span class="matrix-code"><your cinder root>\tools\TinderBox.exe</span>, it's pretty self-explanatory after that. Here we gooo...<br/>
<br/>
<b>1.a)</b> Once we've got an initial project tree, let's move some files and folders around to make setting up dependencies a bit simpler. Starting from <span class="matrix-code"><your cinder project root></span>, let's make our project tree look something like this (completely optional):
</div>
<br>
<div class="info-box matrix-code">
assets/<br/>
include/<br/>
<span style="font-weight:normal"> twitcurl.h</span><br/>
<span style="font-weight:normal"> oauthlib.h</span><br/>
curl/<br/>
<span style="font-weight:normal"> (all the curl headers)</span><br/>
lib/ <span style="font-weight:normal;color:white"><-- add this folder manually</span><br/>
<span style="font-weight:normal"> libcurl.lib</span><br/>
<span style="font-weight:normal"> twitcurl.lib</span><br/>
resources/<br/>
src/<br/>
vc10/<br/>
<span style="font-weight:normal"> afont.ttf</span><br/>
</div>
<br/>
<div>
Given this tree, setting up the rest of the dependencies for the project should be pretty straightforward. I should point out that putting the font file directly into the vc10 folder is a bit of a hack and not at all the proper way to set up a Cinder resource, but for now I just want to get something functional. Much respect to the Cinder team for their solution to cross-platform resource management though, I'll probably cover that once we start getting into building the final project. Feel free to do some independent study, though, and check out the documentation on <a target="_blank" href="http://libcinder.org/docs/v0.8.4/_cinder_resources.html">Assets & Resources in Cinder</a> (and send me a pull request if you do!).
<br/>
<br/>
<b>1.b)</b> So...let's code (and test out the new style sheet I wrote for syntax-highlighting)! If you're interested in taking a peek at what the finished result might look like, check out the <a target="_blank" href="http://scotland.proximity.on.ca/dxr/tmp/processing-mobile/examples/twitter/blprnt-twitter-demo.html">web version of Jer Thorp's tutorial</a>, and if you're reading this Jer, no disrespect, I'm totally not meaning to steal your work for profit or some nefarious purpose, it's just a great, simple example that's super straightforward and easy to understand. Had to get that off my chest, all credit where it's due. If you haven't checked out the <a target="blank" href="http://blog.blprnt.com/blog/blprnt/updated-quick-tutorial-processing-twitter">original tutorial</a>, it goes (a little something) like this:<br/>
<br/>
<div class="info-box">
<b>1)</b> Do a twitter search for some term, we'll use "perceptualcomputing"<br/>
<b>2)</b> Split all the tweets up into individual words<br/>
<b>3)</b> Draw a word on screen every so often at a random location<br/>
<b>4)</b> Fade out a bit, rinse, repeat steps 3 and 4<br/>
</div>
<br/>
<b>1.c)</b> Easy-<a target="_blank" href="http://mrfeinberg.com/peasycam/">peasy</a>! 'Right, so first we need to get some credentials from twitter so we can access the API. Not a hard process, just login to <a target="_blank" href="http://dev.twitter.com">Twitter Developers</a>, go to <span class="matrix-code">My Applications</span> by hovering over your account icon on the upper-right, then click the <span class="matrix-code">Create a new application</span> button, also on the upper-right. Fill out all the info, then we'll need to grab a few values once the application page has been created. The <span class="matrix-code">Consumer Key</span> and <span class="matrix-code">Consumer Secret</span> at the top of the page are the first two values we'll need, then we'll scroll down to the bottom of the page, click the <span class="matrix-code">Create Access Token</span> button, and grab the <span class="matrix-code">Access Token</span> and <span class="matrix-code">Access Token Secret</span> values. For now we'll just stick these in a text file somewhere for future reference.<br/>
<br/>
<b>1.d)</b> Finally the moment we've all been waiting for, getting down with cpp (yeah you know m...ok, ok that's enough of that). As with most C++ projects, we'll start with some includes and using directives:
</div>
<br/>
<div class="cpp-box">
<span class="code-pp">#include</span> <span class="code-str"><iostream></span><br/>
<span class="code-pp">#include</span> <span class="code-str">"cinder/app/AppBasic.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"cinder/gl/gl.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"cinder/gl/TextureFont.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"cinder/Rand.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"cinder/Utilities.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"json/json.h"</span><br/>
<span class="code-pp">#include</span> <span class="code-str">"twitcurl.h"</span><br/>
<br/>
<span class="code-res">using namespace</span> ci;<br/>
<span class="code-res">using namespace</span> ci::app;<br/>
<span class="code-res">using namespace</span> std;<br/>
</div>
<br/>
<div>
Outside of the normal Cinder includes, we'll be using <span class="matrix-code">Rand</span> and <span class="matrix-code">TextureFont</span> to draw our list of tweet words on screen, and we'll be using <span class="matrix-code">Utilities</span>, <span class="matrix-code">twitcurl</span>, and <span class="matrix-code">json</span> to fetch, parse, and set up our twitter content for drawing.<br/>
<br/>
<b>1.e)</b> Let's set up our app class next, should be no surprises here:
</div>
<br/>
<div class="cpp-box">
<span class="code-type">class</span> TwitCurlTestApp : <span class="code-type">public</span> AppBasic<br/>
{<br/>
<span class="code-type">public:</span><br/>
<span class="code-cmnt">//Optional for setting app size</span><br/>
<span class="code-type">void</span> prepareSettings(<span class="code-type">Settings*</span> settings);<br/>
<br/>
<span class="code-type">void</span> setup();<br/>
<span class="code-type">void</span> update();<br/>
<span class="code-type">void</span> draw();<br/>
<br/>
<span class="code-cmnt">//We'll parse our twitter content into these</span><br/>
<span class="code-type">vector<string></span> temp;<br/>
<span class="code-type">vector<string></span> words;<br/>
<br/>
<span class="code-cmnt">//For drawing our text</span><br/>
<span class="code-type">gl::TextureFont::DrawOptions</span> fontOpts;<br/>
<span class="code-type">gl::TextureFontRef</span> font;<br/>
<br/>
<span class="code-cmnt">//One of dad's pet names for us</span><br/>
<span class="code-type">twitCurl</span> twit;<br/>
};<br/>
</div>
<br/>
<div>
Ok, so I may have lied just a tiny bit. If you're coming from the <a target="_blank" href="http://processing.org">processing</a> or <a target="_blank" href="http://openframeworks.cc">openFrameworks</a> lands, notice we need to do a little bit of setup before drawing text, but it's nothing daunting. We'll see this a bit with Cinder as we get into more projects, there's a little more setup and it does require a little bit more C++ knowledge to grok completely, but it's nothing that should throw anyone with even just a little scripting experience. That said, a little bit of <a target="_blank" href="http://www.cprogramming.com/tutorial/c++-tutorial.html">C++ learnings</a> can never hurt.
</div>
<br/>
<div>
<b>1.f)</b> Time to implement functions! If we're choosing to implement a <span class="matrix-code">prepareSettings()</span> method, let's go ahead and clear that first. For this tutorial, I'm going with a resolution of <span class="matrix-code">1280x720</span>, so:
<br/>
<br/>
<div class="cpp-box">
<span class="code-type">void</span> TwitCurlTestApp::prepareSettings(<span class="code-type">Settings*</span> settings)<br/>
{<br/>
settings->setWindowSize(<span class="code-num">1280</span>, <span class="code-num">720</span>);<br/>
}<br/>
</div>
</div>
<br/>
<div>
<b>1.g)</b> Onward! Let's populate our <span class="matrix-code">setup()</span> method now. The first thing we'll want to do is setup our canvas and drawing resources, which means loading our font and setting some GL settings so our effect looks cool-ish:<br/>
<br/>
<div class="cpp-box">
gl::clear(<span class="code-type">Color</span>(<span class="code-num">0</span>, <span class="code-num">0</span>, <span class="code-num">0</span>));<br/>
gl::enableAlphaBlending(<span class="code-num">false</span>);<br/>
font = <span class="code-type">gl::TextureFont::</span>create(<span class="code-type">Font</span>(loadFile(<span class="code-str">"acmesa.TTF"</span>), <span class="code-num">16</span>));<br/>
</div>
<br/>
<b>1.h)</b> Now it's time to warm up the core, or I guess you could we could call it setting up our twitCurl object, so let's get out those Consumer and Access tokens and do something with them:<br/>
<br/>
<div class="cpp-box">
<span class="code-cmnt">//Optional, i'm locked behind a corporate firewall, send help!</span><br/>
twit.setProxyServerIp(<span class="code-type">std::string</span>(<span class="code-str">"ip.ip.ip.ip"</span>));<br/>
twit.setProxyServerPort(<span class="code-type">std::string</span>(<span class="code-str">"port"</span>));<br/>
<br/>
<span class="code-cmnt">//Obviously we'll replace these strings</span><br/>
twit.getOAuth().setConsumerKey(<span class="code-type">std::string</span>(<span class="code-str">"Consumer Key"</span>));<br/>
twit.getOAuth().setConsumerSecret(<span class="code-type">std::string</span>(<span class="code-str">"Consumer Secret"</span>));<br/>
twit.getOAuth().setOAuthTokenKey(<span class="code-type">std::string</span>(<span class="code-str">"Token Key"</span>));<br/>
twit.getOAuth().setOAuthTokenSecret(<span class="code-type">std::string</span>(<span class="code-str">"Token Secret"</span>));<br/>
<br/>
<span class="code-cmnt">//We like Json, he's a cool guy, but we could've used XML too, FYI.</span><br/>
twit.setTwitterApiType(<span class="code-type">twitCurlTypes::</span>eTwitCurlApiFormatJson);<br/>
</div>
</div>
<br/>
<div>
Hopefully this all makes sense and goes over without a hitch. Never a bad idea to scroll through everything and look for the telltale red squiggles, or if you're lazy like me, just hit the build button and wait for errors.<br/>
<br/>
<hr/>
<br/>
Since we're only going to be polling twitter once in this demo, we'll do all of our twitter queries in the <span class="matrix-code">setup()</span> method as well. Let's take a look at the main block of code first, then we'll go through the major points:<br/>
<br/>
<div class="cpp-box">
<span class="code-res">if</span>(twit.accountVerifyCredGet())<br/>
{<br/>
twit.getLastWebResponse(resp);<br/>
console() << resp << std::endl;<br/>
<span class="code-res">if</span>(twit.search(<span class="code-type">string</span>(<span class="code-str">"perceptualcomputing"</span>)))<br/>
{<br/>
twit.getLastWebResponse(resp);<br/>
<br/>
<span class="code-type">Json::Value</span> root;<br/>
<span class="code-type">Json::Reader</span> json;<br/>
<span class="code-type">bool</span> parsed = json.parse(resp, root, <span class="code-num">false</span>);<br/>
<br/>
<span class="code-res">if</span>(!parsed)<br/>
{<br/>
console() << json.getFormattedErrorMessages() << endl;<br/>
}<br/>
<span class="code-res">else</span><br/>
{<br/>
<span class="code-type">const Json::Value</span> results = root[<span class="code-str">"results"</span>];<br/>
<span class="code-res">for</span>(<span class="code-type">int</span> i=<span class="code-num">0</span>;i<results.size();++i)<br/>
{<br/>
temp.clear();<br/>
<span class="code-type">const string</span> content = results[i][<span class="code-str">"text"</span>].asString();<br/>
temp = split(content, <span class="code-str">' '</span>);<br/>
words.insert(words.end(), temp.begin(), temp.end());<br/>
}<br/>
}<br/>
}<br/>
}<br/>
<span class="code-res">else</span><br/>
{<br/>
twit.getLastCurlError(resp);<br/>
console() << resp << endl;<br/>
}<br/>
</div>
</div>
<br/>
<div>
This code should read pretty straightforward, there are really just a few ideas we need to be comfortable with to make sense of things:<br/>
<br/>
<div class="info-box">
<b>1)</b> Both <span class="matrix-code">Jsoncpp</span> and <span class="matrix-code">twitcurl</span> follow a similar paradigm (which pops up in a lot of places, truth be told) wherein we get a <span class="matrix-code">bool</span> value back depending on the success or failure of the call.<br/>
<br/>
<b>2)</b> The pattern for using <span class="matrix-code">twitcurl</span> is a) make a twitter api call b) if successful, <span class="matrix-code">.getLastWebResponse()</span>, if not <span class="matrix-code">.getLastCurlError()</span>.<br/>
<br/>
<b>3)</b> There are a few different constructors for <span class="matrix-code">Json::Value</span>, but for our purposes the default is sufficient.<br/>
<br/>
<b>4)</b> Json members can be accessed with the <span class="matrix-code">.get()</span> method or via the <span class="matrix-code">[] operator</span>, es.g. <span class="matrix-code">jsonvalue.get("member",default)</span>, <span class="matrix-code">jsonvalue["member"]</span>. I'm just using the <span class="matrix-code">[] operator</span>, but either one seems to work.
</div>
</div>
<br/>
<div>
That all in mind, let's walk through that last block a chunk at a time.<br/>
<br/>
<b>2.a)</b> First, we need to make sure we can successfully connect to the twitter API, and here we see the twitcurl pattern in action. <span class="matrix-code">.accountVerifyCredGet()</span> "logs us in" and verifies our consumer and access keys, then returns some info about our account. If all went according to plan (unlike the <a target="_blank" href="http://youtu.be/g9ZVWMPuZ2c?t=46s">latest reincarnation</a>), we should see the string representation of our jsonified twitter account info in the debug console:<br/>
<br/>
<div class="cpp-box">
<span class="code-res">if</span>(twit.accountVerifyCredGet())<br/>
{<br/>
twit.getLastWebResponse(resp);<br/>
console() << resp << endl;<br/>
</div>
<br/>
<span class="matrix-code">console()</span> returns a reference to an output stream, provided for cross-platform friendliness. Just think of it as Cinder's cout.<br/>
<br/>
<b>2.b)</b> Now the fun stuff, let's get some usable data from twitter. We'll do a quick twitter search, then get a json object from the result, provided everything goes well (from here on out, let's just assume that happens, if something goes horribly awry, <a href="mailto:seth.gibson1@gmail.com">email me</a> and we'll work it out):<br/>
<br/>
<div class="cpp-box">
<span class="code-res">if</span>(twit.search(<span class="code-type">string</span>(<span class="code-str">"perceptualcomputing"</span>)))<br/>
{<br/>
twit.getLastWebResponse(resp);<br/>
<br/>
<span class="code-type">Json::Value</span> root;<br/>
<span class="code-type">Json::Reader</span> json;<br/>
<span class="code-type">bool</span> parsed = json.parse(resp, root, <span class="code-num">false</span>);<br/>
<br/>
<span class="code-res">if</span>(!parsed)<br/>
{<br/>
console() << json.getFormattedErrorMessages() << endl;<br/>
}<br/>
</div>
<br/>
Hopefully nothing too hairy here, there's that twitcurl pattern again. We do our search with our term of choice (note this could be a hashtag or an @name too), catch the result into a string, then call our json reader's <span class="matrix-code">parse()</span> method. The <span class="matrix-code">false</span> argument for <span class="matrix-code">parse()</span> just tells our reader to toss any comments it comes across while parsing the source string. In this case, since we know what keys we're looking for, it's probably not a big deal, but if we were ever in a situation where we were going to have to query all the members to find something specific, having less noise might be a good thing.<br/>
<br/>
<b>2.c)</b> Ok, since for the duration of this tutorial we're living in a perfect world, everything went according to plan, there were no oauth or parsing errors, and now we have a nice, pretty json egg ready to be cracked open and scrambled. Let's get our tweets, split them up, and stash them in our string vector, then we'll be ready to make some art.<br/>
<br/>
<div class="cpp-box">
<span class="code-res">else</span><br/>
{<br/>
<span class="code-type">const Json::Value</span> results = root[<span class="code-str">"results"</span>];<br/>
<span class="code-res">for</span>(<span class="code-type">int</span> i=<span class="code-num">0</span>;i<results.size();++i)<br/>
{<br/>
temp.clear();<br/>
<span class="code-type">const string</span> content = results[i][<span class="code-str">"text"</span>].asString();<br/>
temp = split(content, <span class="code-str">' '</span>);<br/>
words.insert(words.end(), temp.begin(), temp.end());<br/>
}<br/>
}<br/>
}<br/>
}<br/>
</div>
<br/>
Again, nothing crazy here, in fact I'm sorta starting to feel bad for making people read this since i'm not doing any crazy 3d, shadery, lighting, particle, meshy awesomeness, it's just simple parsing operations...Ah well, the sexy bullshit (as the good Josh Nimoy <a target="_blank" href="https://vimeo.com/41151944">calls it</a>) is coming, I promise. One of the things to be aware of here is that <span class="matrix-code">Json::Value</span> is really good about parsing data into the proper types for us. As I mentioned earlier, the docs present a few different constructors, but we're not using any of those here. Querying the <span class="matrix-code">"results"</span> key (which contains all of our search results) gives us back a list we can iterate through in fairly simple order. So all we do is parse that, then for every element in our array, we get its <span class="matrix-code">"text"</span> key, which contains the actual body of a tweet. Lastly, we take that text and use Cinder's built-in string splitter, which should be quite familiar to you if you've ever split a string in a different language.<br/>
</div>
<br/>
<hr/>
<br/>
<div>
Looks like all we have left is to make some stuff happen on-screen, so same as we did with the <span class="matrix-code">setup()</span> method, let's take a glance at the code first, then we'll break it down, although if you're already familiar with Cinder, there probably won't be anything new here...<br/>
<br/>
<div class="cpp-box">
<span class="code-type">void</span> TwitCurlTestApp::draw()<br/>
{<br/>
gl::color(<span class="code-num">0</span>, <span class="code-num">0</span>, <span class="code-num">0</span>, <span class="code-num">0.015f</span>);<br/>
gl::drawSolidRect(<span class="code-type">Rectf</span>(<span class="code-num">0</span>, <span class="code-num">0</span>, getWindowWidth(), getWindowHeight()));<br/>
<br/>
<span class="code-type">int</span> numFrames = getElapsedFrames();<br/>
<span class="code-res">if</span>(numFrames%<span class="code-num">15</span>==0)<br/>
{<br/>
<span class="code-res">if</span>(words.size()><span class="code-num">0</span>)<br/>
{<br/>
<span class="code-type">int</span> i = numFrames%words.size();<br/>
<br/>
gl::color(<span class="code-num">1</span>, <span class="code-num">1</span>, <span class="code-num">1</span>, Rand::randFloat(<span class="code-num">0.25f</span>, <span class="code-num">0.75f</span>));<br/>
fontOpts.scale(randFloat(<span class="code-num">0.3f</span>, <span class="code-num">3.0f</span>));<br/>
font->drawString(words[i],<br/>
<span class="code-type">Vec2f</span>(Rand::randFloat(getWindowWidth()),<br/>
Rand::randFloat(getWindowHeight())),<br/>
fontOpts );<br/>
}<br/>
}<br/>
}<br/>
</div>
</div>
<br/>
<div>
<b>3.a)</b> No messing around, let's get right to it. If you've ever done anything in processing, you're probably familiar with the technique we're implementing with these two lines of code to fade the foreground a bit between frames, i.e. set the fill color to black with some amount of transparency and draw a rectangle the size of the screen.<br/>
<br>
<div class="cpp-box">
gl::color(<span class="code-num">0</span>, <span class="code-num">0</span>, <span class="code-num">0</span>, <span class="code-num">0.015f</span>);<br/>
gl::drawSolidRect(<span class="code-type">Rectf</span>(<span class="code-num">0</span>, <span class="code-num">0</span>, getWindowWidth(), getWindowHeight()));<br/>
</div>
<br/>
<b>3.b)</b> The last step then, is to draw some words to the screen. We'll grab a new word every 15 frames, set the fill color to white (also with some amount of transparency), scale the font by a random amount, and draw the word to a random location in the window. <br/>
<br/>
<div class="cpp-box">
<span class="code-type">int</span> numFrames = getElapsedFrames();<br/>
<span class="code-res">if</span>(numFrames%<span class="code-num">15</span>==0)<br/>
{<br/>
<span class="code-res">if</span>(words.size()><span class="code-num">0</span>)<br/>
{<br/>
<span class="code-type">int</span> i = numFrames%words.size();<br/>
<br/>
gl::color(<span class="code-num">1</span>, <span class="code-num">1</span>, <span class="code-num">1</span>, Rand::randFloat(<span class="code-num">0.25f</span>, <span class="code-num">0.75f</span>));<br/>
fontOpts.scale(Rand::randFloat(<span class="code-num">0.3f</span>, <span class="code-num">3.0f</span>));<br/>
font->drawString(words[i],<br/>
<span class="code-type">Vec2f</span>(Rand::randFloat(getWindowWidth()),<br/>
Rand::randFloat(getWindowHeight())),<br/>
fontOpts );<br/>
}<br/>
}<br/>
}<br/>
</div>
<br/>
At this point, we should be able to build/run the project and hopefully see something similar to this:
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieP5zhkGPIE-751w_40t86_-4hgp4Xix4_LidP6CvXbgPOA-MoDuhmeLkxSY5moDxShNmhS5-IvyXN4FdsUWrfAkLmgbMEtNJD47iTuY5uSaNErVFhXXyP9T5ToiomZ2qrnN_BX-gxNZc/s400/tcapp.png" height="263" width="400" />
</center>
<br/>
<div>
If something has gone horribly awry, send me an <a href="mailto:seth.gibson1@gmail.com">e-mail</a> or hit me up on <a target="_blank" href="http://github.com/SethGibson">github</a>. I've put the <a target="_blank" href="https://github.com/SethGibson/TwitCurlTest">project up on github</a> as well, but be advised you may have to change some of the project settings to reflect your own build environment. For the scope of my project, I've got quite a bit more twitter to learn, including how to manage tweets, maybe how to deal with the streaming API, and a few other things, but that's all down the road. Next up:
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiISr3s8cSfzn4UZVfgmORSynVHT3uYxUdvQPGS2C9SUZ6-FIiGMSxGZ-30yYxuLa-C6StHfqIndoNKyCrdxkE5qqEhqUow-X4ucjY2EgvgM_dmS48w-8yD-_9rX8uzBMk3r9OCnUPVUpI/s800/bullinder.png" height="170" width="340" />
</center>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-49937913462268981382013-01-16T10:55:00.001-08:002013-01-22T16:13:08.971-08:00building twitcurl in visual studio 2010<div style="
color:rgb(0,255,0);
font-size:x-small">
<b>UPDATE 20130122.1330:</b> Verified this build chain does let you query twitter from Cinder, that being the goal. Yeah, yeah, i should've tested that too;P I don't have a really fun tutorial yet, just printing to the app::console(), but yeah, it works, so go forth and...uhh...twinderifiy?
</div>
<hr/>
<div> If you're wondering where the next round of C4CNC is, fear not, the manuscript is actually done and waiting to get some design and formatting love. I wasn't kidding when I said this is probably a bad time to embark on a project that required some time and attention, but I'm committed to delivering on that. Just got back from a great weekend of <a href="http://www.gaffta.org/2012/08/20/openframeworks-c-for-processing-coders/">openFrameworkshops</a> with <a href="http://www.syedrezaali.com/">Reza Ali</a> and <a href="http://jtnimoy.net/">Josh Nimoy</a> at <a href="http://gaffta.org">GAFFTA</a>, so i'm...not charged, but definitely refreshed and ready to keep cranking on creative coding related work, and especially C++ work. I've really been dragging my feet on C++, but this year we're doing it live. Seriously, my brain is so full of things i want to explore, prototype, visualize, maaaan...
<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPWGf_OJI9e9xiVLSmR7rOClgdSV8dGqjBSaZqApfR7Ax7L7Nx_sgueofG6WSQxLSr1ikE5spE5UgFsp2N4tkXtMJbRZdbHVX_pmrc3EfFDxQgCKqnXJjiW1ztr-Rev-2-5VFyHsXYHLk/s400/trippinburt.jpg" height="277" width="400" />
</center>
<br/>
To that end, it's time to get cracking on an installation for <a href="http://www.gdconf.com">GDC</a>, my favorite time of year. Hopefully since I'm getting started sooner on this than I did for my ill-fated CES installation attempts, this one will go all the way. We've decided to do a twitter visualizer, and since I've decided that this year I'd like to do much more work in C++, I'm going with <a href="http://libcinder.org">Cinder (of course)</a>.</div>
<br/>
<div>
The first bump-in-the-road I came across is the lack of any official C++ support for twitter, but there are a few different <a href="https://dev.twitter.com/docs/twitter-libraries">twitter c++ libraries</a> that have been written by various external parties. I've settled on <a href="http://code.google.com/p/twitcurl/">twitcurl</a> because it seems like the lightest, most straightforward version. The current download doesn't support Visual Studio 2010 though, which means the whole dependency chain needs to be rebuilt. It's not a terribly hard process, but there aren't a ton of good directions on the website, and in fact I got more out of the directions for building and using libcurl. I'm going to try and present a condensed version here, mainly for my own reference if I have to do this again, but also for anyone else trying to get up and running with C++/twitter in short order.
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrTq6XX-amPmeQABIB8gkMiNX9ikVM4-0vSQq4dQ8PY0-43o7GDBZsH1mPitpEELtSnrBgZPE0SjtS7elw29kAjvMlkd9FQsh6iUJeNvCsLFXwp1CJ-dqC9xOt7sXsd5Ivcl1mqYYtIe4/s800/3py8hf.jpg" height="240" width="370" /></center>
<br />
<div>
I'm going to assume you've got some experience setting up Visual Studio projects, so I'm not going to go too deep into the specifics of that. First up, we need to grab the source distros:
<br />
<br/>
<div class="info-box">
<span class="key-term"><b>openssl</b></span> - <a href="http://www.openssl.org/source/openssl-1.0.1c.tar.gz">Download</a> (1.0.1c is latest as of this writing)<br/>
<span class="key-term"><b>libssh2</b></span> - <a href="http://www.libssh2.org/download/libssh2-1.4.3.tar.gz">Download</a> (1.4.3 is latest as of this writing)<br/>
<span class="key-term"><b>libcURL</b></span> - <a href="http://curl.haxx.se/download/curl-7.28.1.zip">Download</a> (7.28.1 is latest as of this writing)<br/>
<span class="key-term"><b>twitcurl</b></span> - <a href="http://code.google.com/p/twitcurl/source/checkout">Checkout SVN</a>
</div>
</div>
<br/>
<div>
Now before we get down to business, I'm going to recommend a little bit of housekeeping. These projects are all rather noisy, i.e. there are a lot of folders, a lot of files, solutions, workspaces, and support files for different IDEs, and...well you get the idea. This may be 101 for some folks, but it's worth jotting down. I've set my folder structure up so, feel free to adopt this or something similar (or ignore completely):
</div>
<br/>
<div class="info-box">
<blockquote style="font-family: Courier, monospace;color:rgb(0,255,0)">
<b>CPP/</b><br />
<b>libs/</b><br />
<b>src/</b><br />
curl-7.28.1/<br />
libssh2-1.4.3/<br />
libtwitcurl/<br />
openssl-1.0.1c/<br />
<b>build/</b><br />
<b>libcurl/</b><br />
include/<br />
lib/<br />
Debug/<br />
Release/<br />
<b>libssh2/</b><br />
include/<br />
lib/<br />
Debug/<br />
Release/<br />
<b>libtwitcurl/</b><br />
include/<br />
curl/<br />
lib/<br />
Debug/<br />
Release/<br />
<b>openssl/</b><br />
</blockquote>
</div>
<br/>
<div>
Again, this is really just a suggestion based on how i store all my libraries on my machine, it's just for convenience. That all in place, let's get to building some dependencies.
</div>
<br/>
<div class="info-box">
All the directions are taken from the following document, which I HIGHLY recommend reading. There are some really important points here that make all the difference between odd linker errors and not.<br/>
<center>
<div style="font-size:large">
<b><a href="curl.haxx.se/libcurl/c/Using-libcurl-with-SSH-support-in-Visual-Studio-2010.pdf">Using libcurl With SSH Support in Visual Studio 2010</a></b><br/>
</div>
</center>
</div>
<br/>
<div>
<h2>openssl</h2>
<br/>
<b>1)</b> Install Perl. I used <a href="http://www.activestate.com/activeperl">ActivePerl</a>, but any distribution should be sufficient, really you just need it to run some build configuration scripts. The doc also recommends using NASM, but I haven't seen any disadvantage of not using it. That said, I can't really comment, because I haven't seen the advantages of using it either.
<br/>
<br/>
<b>2)</b> Open a Visual Studio command line and switch over to your openssl source root directory. You may need to add perl to your path, which you can do by issuing the command:<br/>
<br/>
<div class="info-box">
<span style="font-family:Courier, serif;font-size:medium;font-weight:bold;color:rgb(0,255,0)">path=%PATH%;<your perl executable folder></span>
</div>
<br/>
<b>3)</b> Now we can configure and kick off our build. Issue the following commands (there'll be a pause in between as the scripts run):<br/>
<br/>
<div class="info-box">
<div style="font-family:Courier, monospace;font-size:small;font-weight:bold;color:rgb(0,255,0)">
perl Configure VC-WIN32 --prefix=<your openssl build path's root><br/>
ms\do_ms<br/>
nmake -f ms\nt.mak<br/>
nmake -f ms\nt.mak test<br/>
nmake -f ms\nt.mak install<br/>
</div>
</div>
<br/>
<span style="font-family:Courier, monospace;font-size:small;font-weight:bold;color:rgb(0,255,0)"><your openssl build path's root></span> should be just that, the root folder of your desired openssl build <span class="key-term"><b>with forward slashes</b></span>. In fact, if you jump back up and look at how I've laid out my folder, you'll see I have no folders under my openssl folder by design. This is because the openssl build process creates include, lib, and a few other folders for you. Also, pay close attention to the output of the <span class="matrix-code">test</span> step, you shouldn't see any errors, but if you do, retrace your steps and try the build again.<br/>
<br/>
From here on out, it's all in Visual Studio, so let's get the rest of our libraries built. So long, command line environment!
</div>
<br/>
<div>
<h2>libssh2</h2>
<br/>
<b>1)</b> Open the Visual Studio project, located at <span style="font-family:Courier, serif;font-size:small;font-weight:bold;color:rgb(0,255,0)"><your libssh2 source root>\win32\libssh2.dsp</span> and take the project through the Visual Studio 2010 conversion process.
<br/>
<br/>
<b>2)</b> Now we need to configure the <span class="matrix-code">LIB Debug</span> build configuration. We need to add openssl as a dependency, so first, add the path to the openssl include folder to the <span class="matrix-code">C/C++ > General > Additional Include Directories</span>.
<br/>
<br/>
<b>3)</b> We also need to set the <span class="matrix-code">C/C++ > Code Generation > Runtime Library</span> option to <span class="matrix-code">Multi-threaded Debug (MTd)</span>. This is easily the most important step in the whole process, every other project will need to have this set, or you'll get some weird linker errors.
<br/>
<br/>
<b>4)</b> Next, we need to add the openssl libraries to our linker dependencies. Add <span class="matrix-code">libeay32.lib</span> and <span class="matrix-code">ssleay32.lib</span> to the <span class="matrix-code">Librarian > General > Additional Dependencies</span> field; Be sure to also add <span class="matrix-code"><your openssl build root>\lib</span> to the <span class="matrix-code">Librarian > General > Additional Library Directories</span> field.
<br/>
<br/>
<b>5)</b> The last bit of configuration is to set the <span class="matrix-code">Librarian > General > Output File</span> field to wherever you'd like the final lib file to end up. In my case, the value is <span class="matrix-code">lib\build\libssh2\lib\Debug\libssh2.lib</span>. Be sure to configure the <span class="matrix-code">LIB Release</span> configuration as well. The steps are all the same, save the output file settings.
<br/>
<br/>
<b>6)</b> Build the project and ignore the <span class="matrix-code">LNK4221</span> warnings, they won't affect anything here.
<br/>
<br/>
Whew! Halfway done, now comes the main event, libcurl. Twitcurl and any projects you build with twitcurl depend on this, so let's plow through and get tweeting from C++ (and Cinder (or ofx, or whatever your C++ framework of choice be)).
<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil7gErC8TP16goR98xIOs4GcOrPJEHuC6y6CVRnXE17pu8kl15j_g17v7f0rNNOWAJQBiV4ioFpNW5cjBd6b_siRoioQgDiCh97LJRCcMRsekhxFnN9qNorPYjCTZsXZGNmSz5czghiLg/s800/troncomeat.gif" height="215" width="500" /><br/>
<span class="matrix-code">bro::comeAt(&me);</span>
</center>
</div>
<br/>
<div>
<h2>libcurl</h2>
<br/>
<b>1)</b> For libcurl, we need to setup libssh2 as a dependency, so open the Visual Studio project <span class="matrix-code"><your curl source root>\lib\libcurl.vcproj</span> and add the include path, the library, and the library path for your libssh2 build to the appropriate fields.
<br/>
<br/>
<b>2)</b> Remember to also set the <span class="matrix-code">C/C++ > Code Generation > Runtime Library</span> to <span class="matrix-code">Multi-Threaded Debug (MTd)</span> and stay odd linker error free!
<br/>
<br/>
<b>3)</b> libcurl requires a few preprocessor definitions. To set these up, open the <span class="matrix-code">C/C++ > Preprocessor > Preprocessor Definitions</span> window and copy-paste the following block below the existing definitions:
<br/>
<br/>
<div class="info-box matrix-code">
CURL_STATICLIB<br/>
USE_LIBSSH2<br/>
CURL_DISABLE_LDAP<br/>
HAVE_LIBSSH2<br/>
HAVE_LIBSSH2_H<br/>
LIBSSH2_WIN32<br/>
LIBSSH2_LIBRARY<br/>
</div>
<br/>
<b>4)</b> If you've setup a custom folder structure, remember also to set your output file settings to wherever you'd like libcurl to sit after it gets built.
<br/>
<br/>
<b>5)</b> Hit build and you should be good to go. All that's left now is to build twitcurl and you'll (we'll, i'll) be tweeting in style, because C++ never goes out of style. Weird style fads and convoluted paradigms might, but that's a whole other conversation.
</div>
<br/>
<div>
<h2>twitcurl</h2>
<br/>
The twitcurl project page and wiki are a little odd and convoluted, so I would say those may not the best places to go for information on the project. Probably a good idea to just checkout the source and make like Kenobi talking to storm troopers talking to Kenobi...(yo, dawg)
<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl3EUiHF9Dpau43rAulLlWjSaj9xXLrdttHXXivoJyrh66d4kaT0H2HqXyWdfPckDIbXS9PHksotobfXGiIse7dryOb5zg-HjH_muznJuGr8EaOqZ6OxjvCQldk4zrjxwyOjiYvlDHyAU/s800/movealong.jpg" height="300" width="359" />
</center>
<br/>
<b>1)</b> We'll need to do a little more housekeeping, this time with the twitcurl source. In the <span class="matrix-code"><your twitcurl source root>\libtwitcurl</span> folder, you'll see two subfolders, <span class="matrix-code">curl</span> and <span class="matrix-code">lib</span>. These folders contain the libcurl dependencies for twitcurl, but as we mentioned earlier, these are out of date. At this point, we can take a few different approaches. The end goal is to replace the existing libcurl dependencies with the ones we built previously, so we can replace the contents of the curl and lib folders with the contents from our libcurl build, or we can ignore these and change the project configurations. I chose to change the project configurations so I wouldn't have duplicates floating around. Ultimately, we're going to need to change some configuration settings anyway, so I'm not sure there's much value in keeping the old dependencies around.
<br/>
<br/>
<b>2)</b> Once we've got a plan of action (keep,delete,etc), let's pop open <span class="matrix-code">libtwitcurl/twitcurl.sln</span> in Visual Studio and replace all the references to curl with the paths to our previously built libcurl. We need to update a few fields with the relevant info:<br/>
<br/>
<div class="info-box">
<span class="matrix-code">C/C++ > General > Additional Include Directories</span><br/>
<span class="matrix-code">Librarian > General > Additional Dependencies</span><br/>
<span class="matrix-code">Librarian > General > Additional Library Directories</span><br/>
<span class="matrix-code">Librarian > General > Output File</span> (optional)<br/>
<span class="matrix-code">Librarian > General > Additional Dependencies</span> (also add ws2_32.lib to this field)
</div>
<br/>
<b>3)</b> Next, let's not forget to set the <span class="matrix-code">C/C++ > Code Generation > Runtime Library</span> to...Yep, <span class="matrix-code">Multi-threaded Debug (MTd)</span>.
<br/>
<br/>
<b>4)</b> Lastly, let's add <span class="matrix-code">CURL_STATICLIB</span> to <span class="matrix-code">C/C++ > Preprocessor > Preprocessor Definitions</span> and build the project. If everything's setup correctly and all your previous builds of the dependency chain succeeded, congrats! You now have everything you need to send tweets in C++. Take a moment and be awesome (or <a href="http://www.passiveaggressivenotes.com/2009/06/22/soyfckers-anonymous/">keep being awesome</a> if you already are)!
<br/>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrzFkHGBhk54DMlo7JZV5CXq7IrI4qPK6yjPY64qQrXwcvTYFv-AwCPA7e1wDVHJ7uw6G5_i1o2jXoE4eVRAoJ_TgFujVlT8ZbVU69CZTn1G3ts_Ut_atoKUEFOlySJ84FBMjfhGuaL8s/s800/sjawesome.jpg" height="300" width="400" />
</center>
</div>
<br/>
<div> So now it's pretty much just using twitcurl in a project. Building the included twitterClient is pretty simple, we just need to:
<br/>
<br/>
<b>1)</b> Add our builds of <span class="matrix-code">libtwitcurl</span> and <span class="matrix-code">libcurl</span> as dependencies<br/>
<b>2)</b> Add <span class="matrix-code">ws2_32.lib</span> as a dependency<br/>
<b>3)</b> Add the <span class="matrix-code">CURL_STATICLIB</span> Preprocessor Definition<br/>
<b>4)</b> Set the <span class="matrix-code">C/C++ > Code Generation > Runtime Library</span> option to...whaaaat?<br/>
<b>5)</b> Build that muthah (out). We'll need to change some of the URLs in the project, but otherwise it should be a straight ahead process.
<br/>
<br/>
Step one down, and trust me when I say this is monumental. If I learned anything from this process it's <b>RTFM!!!</b> <b>TWICE!!!!</b> I had the hardest time getting things to build because I glossed over a step here and there and didn't read all the little details about what settings needed to be which specifically. But that's all behind us now, so next we need to get tweeting from Cinder. For the next segment, I'll probably recreate <a href="http://blog.blprnt.com/blog/blprnt/updated-quick-tutorial-processing-twitter">Jer Thorp's twitter and processing tutorial</a> in Cinder just to get up and running. Stay Tuned!
</div>
<br/>
<center>
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK2pb4cvBU8QL64GSp4SupdGMSVNTz9QQMj9qFV2qi1yn3DczMyo56GzMD3Hzztp_eNuvNXP1BFwzzKII0-Q4c3b_eRERqjGrLpKj2kmQxBhSlUPtvshwUZu-3c2drv6EuSv_P3ct4Nsc/s800/twinder.png" height="170" width="340" /></center>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-73037460756362268572012-12-29T17:40:00.001-08:002012-12-31T15:15:27.778-08:00C4CNC101 - Section 1: Intro To Functions<div style="font-style:italic;font-size:85%;color:rgb(176,0,0)">
<span style="font-weight:bold;color:rgb(255,0,0)">DISCLAIMER:</span><br/>
<span style="font-weight:bold;color:rgb(255,0,0)">(1)</span> If you are already familiar with functions, variables, types, otherwise coding basics, C4CNC101 is not for you. I'd recommend taking a look at something like <a target="_blank" href="http://natureofcode.com">The Nature Of Code</a> if you're interested in getting up and running with processing.<br/>
<span style="font-weight:bold;color:rgb(255,0,0)">(2)</span> A familiarity with digital art in general, including coordinate systems, pixels, etc will be extremely helpful. If you've ever used Photoshop, Illustrator, or any other digital art program, 2d or 3d, you should be good to go.<br/>
<span style="font-weight:bold;color:rgb(255,0,0)">(3)</span> If you're a programmer, you'll probably find tons of inconsistencies or things i'm glossing over. My goal here is not to teach programming, it's more to get people who want to get into using code as a tool to create or augment the creation of art up and running, enough to give them the foundation knowledge to research deeper if they so choose. I've done alot of thinking about this and I believe the information as I've presented it is true in spirit and in the scope of processing.
</div>
<br/>
<img style="display:block;margin:auto" src="http://farm9.staticflickr.com/8358/8319288474_92c8e96ec1.jpg" width="560" height="50" alt="header">
<br/>
<div>
Ok, so hopefully by now you've <a target="_blank" href="http://processing.org/download/">downloaded</a> and installed processing, signed up for an <a target="_blank" href="http://openprocessing.org">OpenProcessing</a> account, and joined the <a target="_blank" href="http://www.openprocessing.org/classroom/2325">C4CNC Classroom</a> on OpenProcessing. The first step is really the only requirement, but i do recommend at least peeking around OpenProcessing to get an idea of what's possible. I'll warn you in advance that if you're just starting out, it can be pretty easy to get overwhelmed by the breadth and depth of content therein, but fear not! Hopefully by the time we're through these first five lessons, you'll know enough to read through some of the sketches and even build your own sketches based off of them. As I mentioned in the <a target="_blank" href="http://protomatic.blogspot.com/2012/12/c4cnc-road-ahead.html">last post</a>, if you come across any sketches or effects you'd like to remix, breakdown, or dive into deeper, <a href="mailto:seth.gibson1@gmail.com">let me know</a> and I'll work something out for a future set of tutorials. Alright, so let's begin!<br/>
<br/>
First, let's conceptualize a computer program as nothing more than a set of commands or instructions that processes information and produces results based on the specifics of the information and the commands. While that's a bit of an oversimplification, on some level this holds true for any program, from the small visualization sketches we'll be writing here, all the way up to full on operating systems like Windows or Linux. We call these instructions <span class="key-term">functions</span> and we call the information <span class="key-term">data</span>. So let's write our first program. Open processing and type the following function:
</div>
<br/>
<div id="step-1-0" class="code-box">
<span class="function-name">ellipse</span>(50, 50, 50, 50);
</div>
<br/>
<div>
Once that's in place, press the <span class="key-term">Run</span> button (it looks like a 'Play' button) in the upper left hand corner. Alternately, you can check out the sketch on OpenProcessing(<a target="_blank" href="http://www.openprocessing.org/sketch/83440">1-1: Basic Functions</a>), although I highly recommend you follow along by typing the code yourself to get the most out of these lessons. Either way, you should see something like the following:
</div>
<br />
<center>
<img src="http://farm9.staticflickr.com/8203/8270977675_1989aed687_m.jpg" width="134" height="153" alt="Step1_0"></center>
<br />
<div class="info-box">
<span style="font-weight:bold;color:rgb(0,128,255);">CODERSPEAK:</span> When we issue a command in a program, we say we are <span class="key-term">calling the function</span> or <span class="key-term">making a function call</span>, and when we provide data to a function, we say we are <span class="key-term">passing an argument (or arguments)</span>. So when we issue a command and give it some information, we are <span class="key-term">calling a function with arguments</span>.
</div>
<br />
<div>
This may not look like much, but it's actually a valid processing sketch, so congrats. In some languages, Python for example, a single function like this could also comprise a valid and complete program, so not bad for a first step! Sure, it's not very exciting and doesn't do much, but we'll get there.<br/>
<br/>
Now, let's take a moment and break down our function call. For our intents and purposes, every function call will be a <span class="key-term">name</span> followed by a set of <span class="key-term">parentheses</span>. If we're passing <span class="key-term">arguments</span> to the function, they'll be <span class="key-term">between the parentheses</span>, separated by commas. And finally, we end our function call with a <span class="key-term">semicolon</span>, so processing knows to move on to the next function. Thus, the skeleton for any function call is:
</div>
<br />
<div class="code-box">
<span class="function-name">functionName</span>(argument1, argument2, argument3, etc);
</div>
<br />
<div>
Recall that we started out by defining a program as a set of commands(<span class="key-term">functions</span>) that processes information(<span class="key-term">data</span>) to produce a result. <span class="key-term">Arguments</span> are how we provide the data to a function. In cases where we're passing multiple arguments, each argument is used by the function to perform a specific task along the way to producing the final result. So in the case of our first sketch here, as the programmer we're telling processing to:
</div>
<br/>
<div class="code-box">
Draw an <span class="function-name">ellipse</span> with a position of <span class="key-term">50</span> pixels along the x-axis and <span class="key-term">50</span> pixels along the y-axis, and a size of <span class="key-term">50</span> pixels along the x-axis and <span class="key-term">50</span> pixels along the y-axis.
</div>
<br/>
<div>
Most, if not all, publicly available coding tools and environments have references that describe (some in more detail than others) what each argument does. For example, take a look at the <a target="_blank" href="http://processing.org/reference/ellipse_.html">reference page for the ellipse() function</a>, which not only details the arguments, but also provides some useful tips on calling <span class="function-name">ellipse</span>().
</div>
<br/>
<div>
Alright, so let's practice a bit by adding a few more functions. Add another function before the <span class="function-name">ellipse</span>() call, so your sketch contains the following function calls. Note that we're changing some of the arguments to the <span class="function-name">ellipse</span>() call, and you should feel free to change any of the arguments to any of the functions. Experimentation is a key to learning!
</div>
<br />
<div id="step1-2" class="code-box">
<span class="function-name">size</span>(400, 400);<br />
<span class="function-name">ellipse</span>(200, 200, 50, 50);
</div>
<div>
<a target="_blank" href="http://www.openprocessing.org/sketch/83443">1-2: More Functions</a>
</div>
<br/>
<div>
As you can probably tell from the result, the <span class="function-name">size</span>() function sets the size in pixels of our sketch's window. Even though both functions take a different number of arguments and produce markedly different results, you can see that they both follow the same skeleton we outlined above, i.e.:
</div>
<br />
<div class="code-box">
<span class="function-name">functionName</span>(argument1, argument2, argument3, etc);
</div>
<br />
<div>
Before we get a little more advanced, let's add a few more basic processing functions, again for practice, and also to see how we can affect what we're drawing on-screen so we can start getting an idea of the kind of drawing functionality that processing makes available to our sketches. We're going to add three more function calls in-between our <span class="function-name">size</span>() call and our <span class="function-name">ellipse</span>() call: <span class="function-name">background</span>(), <span class="function-name">stroke</span>(), and <span class="function-name">fill</span>(). Type these functions in as presented below:
</div>
<br />
<div id="step1-3" class="code-box">
<span class="function-name">size</span>(400, 400);<br />
<span class="function-name">background</span>(0, 0, 0);<br />
<span class="function-name">stroke</span>(255, 255, 255);<br />
<span class="function-name">fill</span>(0, 128, 255);<br />
<span class="function-name">ellipse</span>(200, 200, 100, 100);
</div>
<div>
<a target="_blank" href="http://www.openprocessing.org/sketch/83444">1-3: Drawing</a>
</div>
<br/>
<div>
As the saying goes, the more things change, the more things stay the same. As we add functions, we see the results compound and the output become more complex, but in the end, all functions are called in the same manner using the same syntax. Feeling comfortable typing in functions? Then give the following exercises a try and see what you come up with. Questions? Please post them in the comments!
</div>
<br />
<img style="display:block;margin:auto" src="http://farm9.staticflickr.com/8353/8319307910_9bb4bb7c43_z.jpg" width="560" height="75" alt="footer">
<br/>
<div class="exer-box">
<span style="font-weight:bold;color:rgb(255,0,255);">
EXERCISE 1:</span> Draw 5 different ellipses with different radii and in different locations. Be sure to check out the <a target="_blank" href="http://www.processing.org/reference/ellipse_.html">Processing Language Reference for ellipse()</a> for more details on how the ellipse() function works. Try changing some of the arguments to the other functions as well!<br/><a target="_blank" href="http://www.openprocessing.org/sketch/83446">Exercise 1-1</a>
</div>
<br />
<div class="exer-box">
<span style="font-weight:bold;color:rgb(255,0,255);">
EXERCISE 2:</span> Take a look at the Language Reference for <a href="http://processing.org/reference/background_.html" target="_blank">background()</a>, <a href="http://processing.org/reference/stroke_.html" target="_blank">stroke()</a>, and <a href="http://processing.org/reference/fill_.html" target="_blank">fill()</a>. Now, take the previous exercise and change the stroke and fill color for each ellipse. While you're at it, change the background color to something a bit friendlier than black, it's getting a bit gloomy in here...<br/><a href="http://www.openprocessing.org/sketch/83447">Exercise 1-2</a></div>
<br>
<div id="cs-02" class="info-box">
<span class="cs-header">CODERSPEAK:</span> You might be wondering how processing knows what to do when we call any of the functions presented here. Well, most, if not all programming languages and environments come with a set of pre-existing functions and data that we use to build up our programs initially, which you'll often hear referred to as <span class="key-term">built-ins</span> or <span class="key-term">library functions</span>. When writing programs, you'll use a combination of both built-in functions and data, as well as functions and data you define yourself. We'll discuss this process in the next couple lessons.
</div>
<br/>
<hr/>
<br/>
<div>
<b>REVIEW AND REFERENCE</b><br/>
<a target="_blank" href="http://processing.org">processing Homepage</a><br/>
<a target="_blank" href="http://processing.org/reference/">processing Language Reference</a><br/>
<a target="_blank" href="http://processing.org/reference/background_.html">background() API Reference</a><br/>
<a target="_blank" href="http://processing.org/reference/ellipse_.html">ellipse() API Reference</a><br/>
<a target="_blank" href="http://processing.org/reference/fill_.html">fill() API Reference</a><br/>
<a target="_blank" href="http://processing.org/reference/size_.html">size() API Reference</a><br/>
<a target="_blank" href="http://processing.org/reference/stroke_.html">stroke() API Reference</a><br/>
</div>
<br/>
<hr/>
<br/>
<div>
<b>PREVIOUS ARTICLES</b><br/>
<a target="_blank" href="http://protomatic.blogspot.com/2012/12/coding-for-creative-non-coders.html">Foreword</a><br/>
<a target="_blank" href="http://protomatic.blogspot.com/2012/12/c4cnc-road-ahead.html">Project Preview</a>
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-13458932374028329072012-12-28T10:29:00.000-08:002012-12-28T10:33:22.363-08:00C4CNC: The Road Ahead...<div>
If you've already stopped over to the <a href="http://www.openprocessing.org/classroom/2325">OpenProcessing Classroom</a>, you'll notice there's not a ton of really exciting stuff there (yet). The idea is that we're going to ramp into more advanced sketches from simple concepts, so we'll start slow-ish to get folks comfortable with both the ideas and just the act of typing code, then we'll start to speed up as we build the actual project. That all said, I figured I'd toss up a quick preview of where we're going to end up by the end of C4CNC 201.
</div>
<br />
<div style="text-align: center;">
<img alt="Step1_0" height="153" src="http://farm9.staticflickr.com/8203/8270977675_1989aed687_m.jpg" width="134" />
<br/>
We'll start here...
</div>
<br/>
<div style="text-align: center;">
<img alt="teaser" height="166" src="http://farm9.staticflickr.com/8356/8319119348_b4ee384654.jpg" style="display: block; margin: auto;" width="500" />
...and end up here.<br/><a href="http://hack-the-gibson.net/p5/C4CNC/">Watch the sketch in action</a>
</div>
<br/>
<div>
If in your travels through <a href="http://openprocessing.org">OpenProcessing</a> (or elsewhere) you see one or more effects you're interested in learning about, <a href="mailto:seth.gibson1@gmail.com">let me know</a>! Given my limited creativity, I'm always looking for new project inspiration for tutorials, would be fun to piece together a tutorial from a few different effects/sketches. I guess I could just do that myself, but i'm curious as to the nature of other people's aesthetic sense...in a non-creepy way. Anyway, back to work, I should have the first lesson up later today.
</div>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-63863258235306599732012-12-27T23:04:00.000-08:002012-12-27T23:04:17.064-08:00Coding For Creative Non-Coders<div>
I'm going to stop short of saying I've become a bad programmer over the last year, but I will definitely say I've written alot of bad code. Well, alright, that's actually not true on two counts:
</div>
<ul>
<li>It hasn't been bad code, just poorly, well, no, lazily architected code.</li>
<li>I didn't really become a bad programmer, i just maintained my level of already not good programmering.</li>
</ul>
<hr/>
<br/>
<img style="display:block;margin:auto;" src="http://farm9.staticflickr.com/8501/8316395819_e4c7d67c5b.jpg" width="500" height="126" alt="records_top">
<br/>
<div>
That said, it's been really interesting making the transition from tools...eh...programmer to software prototyper/artist. It's gotten me thinking quite a bit about what elements of coding are important to me as an artist and more than that, how I would present the idea of programming to someone who was interested in software art, or creative coding as it were. I've often ranted about how the reason more people don't get into programming is not because the act itself is hard, but more because of how it's taught. That's the problem I know I had with learning C++ especially, all the books start out with variables, then move onto simple functions, then eventually get to the meat of the language, but by then I'm just bored. One could argue that people need to be introduced to the concepts slowly, which I agree with, but I think it's the order of the presentation and the way we connect concepts to each other that's up for review. For example, when I'm in my (somewhat questionable) artist mind, I'm a very visual learner, I like to see things happen. So when I have to read chapters that drone endlessly on about simple variables, of course I get bored. In the same vein, I like building things. I feel like if programming were presented in the context of building something, rather than a set of disjointed programs/code listings that just focus on single concepts, it would be easier for people to make the connection from theory to application.
</div>
<br />
<center>
<img src="http://farm9.staticflickr.com/8497/8316350621_d74341e233.jpg" width="500" height="125" alt="sineart_banner">
</center>
<br/>
<div>
So where am I going with this? Well, me being the arrogant know-it-all that I am, I think I've come up with a good way to teach, not programming in full perse, but enough to get someone started down the path of creative coding. Even though I'm convinced the world doesn't need another set of "Learn to code using processing" tutorials, I feel like I need to write this line of thinking down because it may just be useful. Or I may be crazy. Or...crazy useful, right, right? Anyway, if you're interested in following along, I'd recommend a few things before diving in:
</div>
<ul>
<li><a href="http://processing.org/download/">Download Processing.</a> I'll be using Processing 2 for this tutorial series, so the most recent version (2 beta 7 as of this writing) on the website should suffice. </li>
<li>Make an account on <a href="http://openprocessing.org">OpenProcessing</a> and sign up at the <a href="http://www.openprocessing.org/classroom/2325">Coding For Creative Non-Coders 101 Classroom</a>. <a href="mailto:seth.gibson1@gmail.com">Send me an email</a> when you do and you'll get free OpenProcessing Plus+ membership.</li>
</ul>
<div>
I'll admit i'm picking a rather lame time to kick this off, as I'm up to my nasal hairs in CES demos, but my goal is to have the first five sections done by mid-February. Stay tuned and I'll see you in the first lesson!
</div>
<br/>
<img style="display:block;margin:auto" src="http://farm9.staticflickr.com/8491/8317450118_55967b111a.jpg" width="500" height="126" alt="records_btm">Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-69677538310950482732012-08-30T15:54:00.000-07:002012-08-30T18:53:11.839-07:00the perfect engine Every time i type "blogger.com" into my address bar i'm reminded of a rant penned by a game writer a while back railing against the idea of being called a "journalist" because he was, in fact, a blogger, and as such didn't need to be bound by the tenets of that horribly oppressive, creativity-killing force called "journalistic integrity". This got me thinking about a conversation I was having a little while ago with a colleague about the death of Triple-A game development and consoles as we know them today. I wondered at the time if that would give rise to a new form of game journalism where game writers aren't afraid to put together well thought out and well written articles that reflect the notion of an older readership, as opposed to the current race for they eyes, hearts, and minds of 13 year old boys. Oh well, one can dream.<br />
<br />
<center>
<a href="http://www.unity3d.com/"><img src="http://download.unity3d.com/media/images/elements/backgrounds/shuriken.jpg" width="500px" /></a>
<br />
<b>Shuriken Particles</b>
</center>
<br />
This idea of games and misguided representation, self or otherwise, has been quite a topic of thought for me recently, especially where the term "interaction" is concerned. Don't get me wrong, I love lying in bed playing xbox games on the ceiling (projectors, so awesome) or sitting at my PC playing whatever F2P MMO has my attention for the next month, but i've started to re-classify this sort of activity as something other than "interaction". I mean sure, in the loosest sense of the word it is an interactive activity, but when I think of myself as an interactive developer/artist/performer, this is not what i classify as "interaction" or "interactivity". I'll concede that games are a subset of a broader interactive media and entertainment classifier, but games do get most of the spotlight and are driving alot of the technology in that space.<br />
<br />
<center>
<a href="http://libcinder.org/"><img src="http://libcinder.org/media/images/gallery/relentless_sm.jpg" width="500px" /></a><br />
<b>Relentless, The REV</b>
</center>
<br />
Therein lies a problem. We can look at things like the Wii and the Kinect and talk about how they redefined interaction, which sure, they did, but this kind of merging the physical and digital world through different interaction paradigms is based on much older work (watch Underkoffler's TED talk for the details) that most of the public is probably unaware of, or at least, has relegated to the realm of science fiction, or more recently to games and academia. So of course, big technology hasn't had a huge incentive to make sweeping changes in how we interact with technology, but then i suppose that could be chalked up as "good business". Unrelated, I would argue that "good business" is why the country is in such a sorry state, but that's for a different blog post by someone who isn't me. <br />
<br />
<center>
<a href="http://www.unity3d.com/"><img src="http://unity3d.com/unity/editor/i_shuriken/splatter.jpg" width="500px" /></a><br /><b>More Shuriken Particles</b>
</center>
<br />
So this presents some really funny irony, at least from my perspective. While alot of advanced interaction is being developed for and because of games, that idea of "good business" means that middleware vendors aren't necessarily rushing out to build functionality to support this sort of thing into their products, because how do you sell depth camera support to an industry and consumer base who have written depth cameras off as motion control gimmicks? Funny, this is the same ideology championed by a man who thought one of the killer features of his game was that you could pick up your own shit, but whatever. I'm not here to skewer said vendors for not including this sort of support, but it does bring up an interesting idea, that of "graphics engines" vs "interaction engines". It's been a running debate, the idea of Unity vs UDK vs ofx vs Cinder vs whatever, so it's alot to think about. The distinction was solidified best to me in a post on the Cinder forums on the same topic. Someone wrote "Life is easy if you stick to loading models (animated or not) into the scene graph, setting up transitions triggers, using basic particle emitters...", whereas "Cinder is made in a way that it's easy to import foreign technologies." That pretty clearly outlines/sums up the difference between graphics and interaction engines in my experience. Being able to just have webcam access as a ready made call, or an easy path to adding an external SDK for some non-native hardware is key to quickly prototyping and building advanced interaction. While alot of game engines do have facilities for this, it's not always quick and easy, but I don't feel like this is the way it has to be. I've always felt that one of the things that's really helped me think in terms of interaction design is having been around games for so long, so it seems logical that there would/could/should be some sort of convergence. Not that there isn't already, search Vimeo and you'll find games made with Cinder and ofx sitting alongside interactive installations made with Unity. I think if it were easier to build either type of experience on either platform, we'd truly have convergence between the idea of games and advanced interactivity/interaction.<br />
<br />
<center>
<a href="http://libcinder.org/"><img src="http://libcinder.org/media/images/gallery/addition_subtraction_sm.jpg" width="500px" /></a><br />
<b>Addition Subtraction</b>
</center>
<br />
Ultimately, I'm not saying Unity/UDK need gesture recognition or anything like that, just an easier way to get it into the engine. Keep the .NET integration current, get rid of UnrealScript, etc, don't predicate everything on the idea of mouse and keyboard events, or at least give me an easier way to hook into them, that sort of thing. No reason for game engines to stay in the dark ages of interaction and interaction engines to stay in the dark ages of rendering.<br />
<br />
Just some thoughts, nothing really meaningful here, i just hadn't blogged in a while and felt like writing some words. For the record, I'm using both Unity and Cinder. I've been playing with some new Unity stuff recently that's got me super excited, i'll be able to talk about that pretty soon here...<br />
<br />
<center>
<a href="http://libcinder.org/"><img src="http://libcinder.org/media/images/gallery/cymaptic_ripple_sm.jpg" width="500px" /></a><br />
<b>Cymatic Ferrofluid</b>
</center>
Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-73515772710196055842012-07-11T21:39:00.000-07:002012-07-11T21:46:25.721-07:00we maed a v1d w1th f!shez 1n it!!1 So i've been following this whole OUYA thing somewhat closely, and as much as I feel like I don't know enough about their business plan to kickstart the project, I feel like i'm actually a pretty fair representation of the target audience. I think about how i use my Xbox nowadays and yeah, it's pretty much just to play XBLA games. That makes the OUYA at 99USD, pretty much an impulse buy for me, so i'm supposing if there's enough content, it would make sense as a gaming solution. Here's the problem, i don't play XBLA games that often. I either play a PC game because i'm on my PC working and i need a break after a few hours or I play games on a mobile device because i'm out and i'm bored waiting on something for a bit. In that vein, i thought it might be cool to have a mobile android box with an HDMI out to run processing sketches on, if only i didn't have to plug it in. Really that's probably not a huge issue though. If the hardware ends up being as open as they say, might be moddable to this end. But then i suppose the question remains why i still just wouldn't use an android tablet...I know, i know, don't kick if you don't believe, but hey, it's internet, i'm allowed to have opinions.<br />
<br />
<center>
<img src="http://uncrate.com/p/2012/07/ouya-xl.jpg" width="500" /><br />
<b><i>...Mobile p5 engine..?</i></b>
</center>
<br />
...But let's be honest, you're not here to listen to me rain on internet's parade, so let's get onto the meat of it. As the title sorta tries to allude to, we built a sort of installation! Or at least, we got something to an early workable stage. Sometime last week, <a href="https://twitter.com/_chrisrojas_" target="_blank">Chris</a> had the idea that we should motion track <a href="https://twitter.com/anniecatdev" target="_blank">Annie's</a> betta and use the resulting data to drive a flocking simulation. To keep the footprint small, we decided to use a webcam based solution. I spent a few hours working on a basic frame differencing solution using some code from <a href="http://processing.org">processing.org</a> to tweak the overall performance and output and came up with this:<br/>
<br />
<center>
<iframe allowfullscreen="" frameborder="0" height="375" mozallowfullscreen="" src="http://player.vimeo.com/video/45281760" webkitallowfullscreen="" width="500"></iframe></center>
<br />
I did put a version up on my <a href="http://github.com/SethGibson/DiffTest">github</a>, it's not quite as usable as I want it to be (a bit more dependencies than i'd like), but in a revision or two it'll be where i'd like it to be. Meantime, it's definitely usable enough to do your own simple tracking based sketches, so have at! If you're interested in putting your own motion tracker together, check these out:<br />
<br />
<a href="http://processing.org/learning/library/framedifferencing.html" target="_blank">Frame Differencing by Golan Levin</a><br />
<a href="http://gsvideo.sourceforge.net/examples/Capture/FrameDifferencing/FrameDifferencing.pde" target="_blank">Frame Differencing with GSVideo</a><br />
<br />
We got all the code merged and tweaked to an initial state last night, and here's the result so far, fish courtesy of our buddy <a href="http://www.ermaldreshaj.com/?p=342" target="_blank">Ermal's Fishcam</a>:<br />
<br />
<center>
<iframe allowfullscreen="" frameborder="0" height="278" mozallowfullscreen="" src="http://player.vimeo.com/video/45586946" webkitallowfullscreen="" width="500"></iframe><br/><b><i><a href="http://vimeo.com/45586946">Live Fish Flocking</a> from <a href="http://vimeo.com/interhacktive">Chris Rojas</a> on <a href="http://vimeo.com/">Vimeo</a></i></b>.<br />
</center>
<br />
Next up, live tracking Annie's fish per the original spec. Annie had some interesting ideas about how we might be able to enhance with some projection or some kind of external display to liven the overall display up. Version 2.0 incoming! Created with <a href="http://processing.org/" target="_blank">processing</a>, <a href="http://toxiclibs.org/" target="_blank">toxiclibs</a>, and <a href="http://gsvideo.sourceforge.net/" target="_blank">GSVideo</a>.Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com2tag:blogger.com,1999:blog-4878514937553811165.post-84387405066421748322012-07-03T22:15:00.000-07:002012-07-03T22:49:48.805-07:00in difference... ...we may find the answers we seek. Or at least a cool way to do motion-ish tracking. <br />
<br />
This makes the second time this week i've been researching something just for the hell of it and suddenly find a use for it a day later, altho I guess the rounding algorithm stuff did have an actual purpose. Oddly enough, the project i want to use it for was waiting for me to figure out some version of this little snippet. Originally I was thinking i was going to have to do it as a full on hand-tracking/skeletal tracking thing, but if I can figure out some smoothing, I think this'll work pretty nicely on its own. We're putting together a mini-installation at work, details of which I'll not spoil for you here, but should be fun...<br />
<br />
I started wondering about frame differencing after repeated visits to <a href="http://testwebcam.com/">testwebcam.com</a> (yes, it's SFW). Simple effect, but it looks really cool. Also a great way to approximate motion on a webcam stream. The initial implementation didn't take me too long, now I just have to implement some optical flow or maybe even just a cheap trailing-3 tap, who knows? Of course, you're welcome to solve that problem yourself if you wanna copy-paste this into your own copy of <a href="http://www.processing.org/" target="_blank">processing</a> and hit Ctrl-R...seriously, your copy of p5 looks a little lonely and unloved, you should do something with it...I did some tests with lerping and vector/distancing, but i think i'm going to need a real filter...<br />
<br />
<center>
<img alt="faketracker" height="375" src="http://farm8.staticflickr.com/7248/7499008522_40dc3758ec.jpg" width="500" /><br /><b>
This is totally not a photoshop, run the sketch if you don't believe me...
</b></center><center><br /></center>
One of these days I need to start seriously optimizing some (all) of these sketches and my <a href="http://openframeworks.cc/" target="_blank">ofx</a> projects. It's ok to suck out loud for now, but truth be told, I think i'm actually a better programmer than that. I mean, not that I'm a good programmer, i'm just decent enough not to make silly un-optimization mistakes. Eh, this one'll optimize itself out anyway me thinks, i imagine the filtering isn't going to be cheap...I also really need to start taking video...<br />
<pre>
//PREPARE YOURSELF FOR THE COMING OF 2.0
//GET GSVIDEOOOOkay it's actually not going to be
//that big of a transition.
import codeanticode.gsvideo.*;
PImage lastFrame;
GSCapture vStream;
int diff;
int thresh = 32;
ArrayList<PVector> dVals = new ArrayList();
PVector p_m;
PVector lastP;
void setup()
{
p_m = new PVector(0,0);
lastP = new PVector(0,0);
size(640, 480, P2D);
frameRate(30);
lastFrame = createImage(width,height,RGB);
vStream = new GSCapture(this, width, height);
vStream.start();
background(0);
}
void draw()
{
diff = 0;
loadPixels();
dVals.clear();
if(vStream.available())
{
vStream.read();
vStream.loadPixels();
lastFrame.loadPixels();
for (int x=0;x<width;x++)
{
for (int y=0;y<height;y++)
{
int i = y*width+x;
color c = vStream.pixels[i];
color l = lastFrame.pixels[i];
int c_r = int(red(c));
int c_g = int(green(c));
int c_b = int(blue(c));
int l_r = int(red(l));
int l_g = int(green(l));
int l_b = int(blue(l));
int d_r = max(0,(c_r-l_r)-thresh);
int d_g = max(0,(c_g-l_g)-thresh);
int d_b = max(0,(c_b-l_b)-thresh);
int d_s = d_r+d_g+d_b;
diff += d_s;
if(d_s>0)
{
dVals.add(new PVector(x,y));
}
pixels[i] = vStream.pixels[i];
lastFrame.pixels[i] = c;
}
}
}
updatePixels();
if(diff>0)
{
p_m = avgArrayList(dVals);
fill(255,255,255);
ellipse(p_m.x,p_m.y,40,40);
}
lastP = p_m;
}
PVector avgArrayList(ArrayList<PVector> arr)
{
float sumx=0;
float sumy=0;
for(int i=0;i<arr.size();i++)
{
PVector c = (PVector)arr.get(i);
sumx+=c.x;
sumy+=c.y;
}
return new PVector(sumx/arr.size(),sumy/arr.size());
}
void keyPressed()
{
if(key=='q')
{
thresh+=1;
if(thresh>128)
thresh=128;
}
if(key=='a')
{
thresh-=1;
if(thresh<8)
thresh=8;
}
}
void stop()
{
vStream.stop();
vStream.dispose();
}
</pre>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0tag:blogger.com,1999:blog-4878514937553811165.post-72075532067546089412012-07-03T02:04:00.000-07:002012-07-03T02:08:35.523-07:00grabbing hands ...grab all the video frames they can. Or maybe they don't...<br />
<br />
It's funny, i've always been a graphics-ish programmer. I don't mean hardcore rendering programmer or any of that madness, but i've always been motivated to code by graphics. Back in high school, the first thing I dove into while learning C was the BGI, mainly so I could learn how to code graphics for demos (never mind that everyone was writing demos in assembly, which i was also learning so i could...yeah, write graphics routines). I can only imagine where I'd be nowadays if I'd had things like openframeworks to tinker with. Of course, we did have GLUT back in my day, which i did spend a fair amount of time mucking about with. Cool how somethings just stand the test of time.<br />
<br />
Taking the plunge into video capture with openframeworks tonight, whipped up another quick, bitcrushesque-type vis. Took some cues from some of the processing vidcap samples i've been doing, some ideas just keep working:<br />
<br />
<br />
<center>
<img alt="ofVidTest" height="375" src="http://farm9.staticflickr.com/8147/7493122702_04e5e2acb4.jpg" width="500" />
</center><center><b><i>Should you lose your disc, you will be subject to immediate de-resolution...</i></b></center><br />
<div>
<br /></div>
...And of course, here're some codes:<br />
<pre>/* testApp.h */
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
ofVideoGrabber grabber;
unsigned char* gPixels;
ofImage img;
};
/* testApp.cpp */
#include "testApp.h"
void testApp::setup()
{
grabber = ofVideoGrabber();
grabber.setVerbose(true);
grabber.initGrabber(640,480,true);
ofEnableAlphaBlending();
}
void testApp::update()
{
grabber.update();
}
void testApp::draw()
{
ofBackground(0,0,0);
gPixels = grabber.getPixels();
for(int x=0;x<64;x++)
{
int xStep = x*10;
for(int y=0;y<48;y++)
{
int yStep = y*10;
int i = (yStep)*640*3+xStep*3;
ofSetColor(gPixels[i],gPixels[i+1],gPixels[i+2],128);
ofRectMode(OF_RECTMODE_CENTER);
ofNoFill();
ofRect(xStep,yStep,10,10);
ofSetColor(gPixels[i],gPixels[i+1],gPixels[i+2],255);
ofFill();
ofCircle(xStep,yStep,3);
}
}
}
</pre>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com2tag:blogger.com,1999:blog-4878514937553811165.post-58777289222116911882012-06-26T12:11:00.000-07:002012-06-26T12:13:30.168-07:00post reality filter You know, for as much as i love music, i never really considered myself much of a music snob, or at least, not a genre snob anyway. The whole idea of having to create millions of sub-genres in some feeble attempt to differentiate yourself from the next guy other than just having cool music always boggled my mind. Even worse, the music critics and journos who would always be coming up with new genres just to, i dunno, safeguard their idea of what a particular genre was or some such nonsense...For as much as i rail on game journalists, it's probably true of most media journalists. The genre qualifier "post" always bothered me the most, what you can't think of a new genre name, so you just take the laziest path? "Oh, this is what comes AFTER <genre>", in which case it might just be arrogance, i.e. really, wow, you think your music is that much different that you alone are going to define what comes next? Wow alright then...<br />
<br />
Anyway, here's a fun little video experiment i knocked together in processing yesterday. You can copy and paste the code below into a sketch and run it, should be that simple. Ohhh yes, you'll also need <a href="http://gsvideo.sourceforge.net/" target="_blank">GSVideo</a>, as I'm not using processing 1.5's native video. After reading a few pages on what was required to get it working based on software that may or may not really exist anymore and also reading <a href="http://wiki.processing.org/w/Changes#The_Big_Stuff" target="_blank">somewhere</a> that p2 was going to move to <a href="http://gsvideo.sourceforge.net/" target="_blank">GSVideo</a> anyway, figured i might as well take the plunge. It's a pretty friendly library overall...on the subject of laziness, gotta admit i probably could've captured a video of this, but didn't. That's probably ok though, you should really run this yourself and see the effect, maybe play around with it a bit, see what you come up with...<br />
<br />
<br />
<center>
<img alt="vidcap_02" height="375" src="http://farm8.staticflickr.com/7276/7449565198_29829ccd34.jpg" width="500" />
</center><center><b>Hello from videoland...</b></center>
<br />
<pre>import codeanticode.gsvideo.*;
PVector gridStep = new PVector(16,8);
int gridX;
int gridY;
GSCapture vStream;
void setup()
{
size(640, 480, P2D);
frameRate(30);
gridX = int(width / gridStep.x);
gridY = int(height / gridStep.y);
vStream = new GSCapture(this, width, height);
vStream.start();
background(0);
noStroke();
}
void draw()
{
if(vStream.available())
{
vStream.read();
vStream.loadPixels();
//Thanks, RoHS
fill(0,0,0,8);
rectMode(CORNER);
rect(0,0,width,height);
for (int i = 0; i < gridX; i++)
{
for (int j = 0; j < gridY; j++)
{
int x = i*int(gridStep.x);
int y = j*int(gridStep.y);
int loc = (vStream.width - x - 1) + y*vStream.width;
color col = color(red(vStream.pixels[loc]),green(vStream.pixels[loc]), blue(vStream.pixels[loc]), 32);
float vradius = brightness(col)*0.1;
fill(col);
if(vradius<12.8)
{
ellipseMode(CENTER);
ellipse(x, y, vradius,vradius);
}
else
{
rectMode(CENTER);
rect(x,y,vradius,vradius);
}
}
}
}
}
</pre>Anonymoushttp://www.blogger.com/profile/16909294074810837780noreply@blogger.com0