<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Luanatic with features &#187; C/C++</title>
	<atom:link href="http://www.pplux.com/category/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pplux.com</link>
	<description>PpluX &#039;s blog</description>
	<lastBuildDate>Mon, 11 May 2009 08:21:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>The Safe bool idiom.</title>
		<link>http://www.pplux.com/2009/02/18/the-safe-bool-idiom/</link>
		<comments>http://www.pplux.com/2009/02/18/the-safe-bool-idiom/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 10:25:34 +0000</pubDate>
		<dc:creator>PpluX</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[English]]></category>

		<guid isPermaLink="false">http://www.pplux.com/?p=220</guid>
		<description><![CDATA[This is something I came across reviewing the headers of OSG, it&#8217;s called the &#8220;safe bool idiom&#8221; and arises when we try to overload the bool operator of a class to make it part of boolean expressions&#8230; Of course this is wrong, let me spoil you a correct version of what should look like a [...]]]></description>
			<content:encoded><![CDATA[<p>This is something I came across reviewing the headers of <a href="http://www.openscenegraph.org">OSG</a>, it&#8217;s called the &#8220;<a href="http://www.artima.com/cppsource/safebool.html">safe bool idiom</a>&#8221; and arises when we try to overload the bool operator of a class to make it part of boolean expressions&#8230; Of course this is wrong, let me spoil you a correct version of what should look like a class using the  <em><a href="http://www.artima.com/cppsource/safebool.html">safe bool idiom</a></em></p>
<pre name="code" class="c++">
  class Testable {
    bool ok_;
    typedef void (Testable::*bool_type)() const;
    void this_type_does_not_support_comparisons() const {}
  public:
    explicit Testable(bool b=true):ok_(b) {}

    operator bool_type() const {
      return ok_==true ?
        &#038;Testable::this_type_does_not_support_comparisons : 0;
    }
  };
</pre>
<blockquote><p>
Simple, eh? Let&#8217;s examine what&#8217;s going on here. First, we typedef bool_type to be a pointer to a const member function of Testable, taking zero arguments and returning void. This is our magic type that allows for testing in Boolean contexts, without taking part in overloading contexts. Next, we define a conversion function to bool_type, just as we did with bool and void* earlier. Finally, we return &#8220;true&#8221; using a pointer to a member function (this_type_does_not_support_comparisons), which fits the bool_type, and a null value for &#8220;false&#8221;. It&#8217;s now possible to safely test instances of Testable in Boolean contexts. The strange name does have a purpose; read on to find out what it is!</p></blockquote>
<p>Yeah, simple! the way I like it. XD</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pplux.com/2009/02/18/the-safe-bool-idiom/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>lua API, introducción</title>
		<link>http://www.pplux.com/2008/04/16/lua-api-introduccion/</link>
		<comments>http://www.pplux.com/2008/04/16/lua-api-introduccion/#comments</comments>
		<pubDate>Wed, 16 Apr 2008 09:19:38 +0000</pubDate>
		<dc:creator>PpluX</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.pplux.com/2008/04/16/lua-api-introduccion/</guid>
		<description><![CDATA[Haciendo honor al nombre del blog, y aprovechando que recientemente me han comentado que el API de lua es un poco rara, vamos a hincarle el diente directamente al problema. Este post es sólo para programadores, no trata del léxico/sintaxis de lua, sólo de una parte muy particular del API, concretamente, la que más problema [...]]]></description>
			<content:encoded><![CDATA[<p>Haciendo honor al nombre del blog, y aprovechando que recientemente me han comentado que el API de lua es un poco rara, vamos a hincarle el diente directamente al problema. Este post es sólo para programadores, no trata del léxico/sintaxis de lua, sólo de una parte muy particular del API, concretamente, la que más problema da al programador que se está iniciando en esto de lua.</p>
<p>Veamos en primer lugar que es eso de un <strong>lua_State*</strong>, es fácil crearlo (luaL_newstate), y destruirlo (lua_close) y representa un estado completo de lua. A efectos prácticos es como si con cada lua_State fuera una máquina virtual independiente, por lo que podemos tener tantos como queramos (uno por thread, uno por efecto, uno por agente, etc, etc&#8230;).</p>
<div class="alignCenter"><img src="/files/lua101_lua_State.png" alt="state basics" /></div>
<p><span id="more-163"></span><br />
En la imagen vemos que un estado de lua ofrece básicamente  un <strong>stack</strong>(pila) para trabajar con el estado. Esto es lo más complicado de entender del API, pero una vez se ve en el contexto, es una forma super eficiente de trabajar. No voy a explicar hoy qué razón se oculta tras la pila, asumamos que es así y que hay que aprender a usarla.</p>
<p>También está representado en la imagen los tipos básicos de lua: strings, números, booleanos, funciones, tablas&#8230; y poco más. La estructura clave aquí es la tabla que es el único contenedor que tiene lua y se trata de un map de pares clave-valor. La clave puede ser cualquier tipo de lua y el valor, por supuesto, también.</p>
<p>Las funciones en lua también son tipos de primer orden, esto quiere decir que las funciones son un valor más que se puede copiar, asignar, devolver como resultado de otra función, etc. Como hemos dicho antes, las tablas incluso pueden usar funciones como claves, nada lo impide.</p>
<p>La linea de puntos de la imagen que separa el stack de la tabla global es para resaltar que no accedemos directamente a la tabla de valores globales. Para poder manejar la tabla de valores globales, u otra tabla, usaremos operaciones que apilarán o consumirán valores del stack. En resumidas cuentas <strong>siempre trabajamos con el stack</strong></p>
<div class="alignCenter"><img src="/files/lua101_stack.png" alt="stak" /></div>
<p>El stack se accede por índice, en lua los índices numéricos empiezan siempre en 1, en contraposición con lo típico en C/C++ de empezar todo en 0. También hay razones tras este acto de maldad, pero como somos programadores serios y profesionales, esto no es más que un detalle, y nos da igual.</p>
<p>Los índices pueden ser positivos, o negativos. Si son positivos contamos desde la base del stack y si son negativos desde el <em>top</em> del stack. Para saber el top actual, usamos lua_gettop(L). La mayor parte de las funciones, por no decir todas ellas, utilizan los valores cercanos al top&#8230; y lo divertido de esto, si has cursado alguna asignatura de compiladores, es que se parece mucho a la forma de trabajar en ensamblador para llamar a funciones <img src='http://www.pplux.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Bueno, para ilustrar todo lo anterior, y explicar con detalle un ejemplo del manual, vamos a ver paso a paso la ejecución del código equivalente a esta expresión de lua:</p>
<p><code><br />
a = f("how", t.x, 14)<br />
</code></p>
<p>según el manual se traduce en las siguientes instrucciones del API de lua:</p>
<p><code><br />
     lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* function to be called */<br />
     lua_pushstring(L, "how");                        /* 1st argument */<br />
     lua_getfield(L, LUA_GLOBALSINDEX, "t");   /* table to be indexed */<br />
     lua_getfield(L, -1, "x");        /* push result of t.x (2nd arg) */<br />
     lua_remove(L, -2);                  /* remove 't' from the stack */<br />
     lua_pushinteger(L, 14);                          /* 3rd argument */<br />
     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */<br />
     lua_setfield(L, LUA_GLOBALSINDEX, "a");        /* set global 'a' */<br />
</code></p>
<p>Las instrucciones del API del <a href="http://www.lua.org/manual/5.1/manual.html">manual</a> van acompañadas de una etiqueta de la forma  [<strong>-o</strong>, <strong>+p</strong>, x] :</p>
<ul>
<li> <strong>-o</strong>: número de elementos que consume del stack (pops from the stack) </li>
<li> <strong>+p</strong>: número de elementos que apila en el stack</li>
<li> x: tipos de errores que pueden saltar&#8230; esto es para otro día (así que como si no estuviera)</li>
</ul>
<p>Es fácil deducirlo pero las funciones de lua pueden devolver varios elementos, y por supuesto, consumir otros tantos. Las etiquetas vienen bien para saber de un vistazo de qué forma van a operar con el stack.</p>
<p>Volviendo al ejemplo anterior, supongamos que ahora mismo el stack está vacío, y veamos paso a paso cada una de las instrucciones. </p>
<div class="alignCenter"><img src="/files/lua101_a.png" alt="step_1" /></div>
<blockquote class="go"><p>
void <a href="http://www.lua.org/manual/5.1/manual.html#lua_getfield">lua_getfield</a> (lua_State *L, int index, const char *k) [-0, +1, e]
</p></blockquote>
<p>Por la etiqueta sabemos que esta función no va a consumir nada del stack y siempre va a hacer push de un elemento. Esta función concretamente busca el elemento <em>key</em> de la tabla que está en el índice <em>index</em> y lo devuelve en el stack. Si el elemento no existe hará un push de &#8220;nil&#8221; que es otro tipo de datos, usado para indicar, precisamente, la ausencia de tipo de datos <img src='http://www.pplux.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>LUA_GLOBALSINDEX es un pseudo-índice, en el stack no hay ninguna posición que permita acceder a la tabla de valores globales, así que hay una serie de pseudo-índices para acceder a ciertas tablas especiales (como la de los valores globales en concreto). Puedes imaginar ese índice de la forma que más te apetezca, a efectos prácticos es equivalente a poner un 1,2,&#8230; -1,-128, etc&#8230; en unos pasos veremos un getfield sobre una tabla en el stack para compensar. </p>
<div class="alignCenter"><img src="/files/lua101_b.png" alt="step_2" /></div>
<blockquote class="go"><p>
void <a href="http://www.lua.org/manual/5.1/manual.html#lua_pushstring">lua_pushstring</a> (lua_State *L, const char *s) [-0, +1, m]</p></blockquote>
<p>Lua tiene unas cuantas funciones para meter y sacar elementos del stack, esta es una de tantas, y sirve para apilar un string. [Nota mental: <em>hablar de los strings de lua en otro post...</em>]</p>
<div class="alignCenter"><img src="/files/lua101_c.png" alt="step_3" /></div>
<p>Otro acceso a la tabla global, en este caso tras el <em>key</em> &#8220;t&#8221; se esconde una tabla, por lo que se apila una tabla. Lo he dibujado con otro color como alarde de creatividad, pero no es más que otro valor [booleano, string, funcion, tabla, numero....] metido en la tabla. </p>
<div class="alignCenter"><img src="/files/lua101_d.png" alt="step_4" /></div>
<p>Esta es más interesante, aunque la función es conocida. Se trata de un getfield de un elemento en la propia tabla, por lo que usamos un índice numérico para indicar de qué tabla queremos buscar la clave. Como el índice es <strong>-1</strong>, estamos haciendo referencia al top actual del stack, donde <em>voilà</em> está justo la tabla que acabábamos de apilar. </p>
<blockquote class="exclamation"><p><strong><em>¿Podíamos haber usado 3 cómo índice para acceder a la tabla?</em></strong><br />
sí, &#8230; pero mejor no te acostumbres. El &#8220;3&#8243; depende de todas las acciones que hayamos hecho antes, mientras que el -1 depende sólo de las últimas acciones sobre la pila. Así que&#8230; en general, es mejor usar índices negativos para este tipo de acciones puntuales.</p>
<p>En este caso queremos acceder al elemento &#8220;t.x&#8221; para hacer ejecutar &#8220;a = f(&#8220;how&#8221;, t.x, 14)&#8221;, si por ejemplo fuese &#8220;a = f(1,2,3,&#8221;how&#8221;, t.x, 14) ya no podríamos usar el índice 3 (usaríamos 6, al haber 3 elementos más en la pila), pero sí que podríamos seguir usando el -1.
</p></blockquote>
<div class="alignCenter"><img src="/files/lua101_e.png" alt="step_5" /></div>
<blockquote class="go"><p>void <a href="http://www.lua.org/manual/5.1/manual.html#lua_remove">lua_remove</a> (lua_State *L, int index);         [-1, +0, -]</p></blockquote>
<p>Esta función, si miras la etiqueta, elimina un elemento del stack y no añade nada. Hay poco que explicar aquí, nos cargamos lo que esté en la posición apuntada por <em>index</em>. Al margen de la función, hemos conseguido obtener el elemento &#8220;t.x&#8221; para la llamada &#8220;a = f(&#8220;how&#8221;,<strong>t.x</strong>,14)&#8221; (bieeeen!)</p>
<div class="alignCenter"><img src="/files/lua101_f.png" alt="step_6" /></div>
<blockquote class="go"><p>
void <a href="http://www.lua.org/manual/5.1/manual.html#lua_pushinteger">lua_pushinteger</a> (lua_State *L, lua_Integer n)         [-0, +1, m]</p></blockquote>
<p>&#8230; No hace falta dar detalles, ¿no? otro &#8220;lua_pushxxxx&#8221;</p>
<div class="alignCenter"><img src="/files/lua101_g.png" alt="step_7" /></div>
<blockquote class="go"><p>
void <a href="http://www.lua.org/manual/5.1/manual.html#lua_call ">lua_call</a> (lua_State *L, int nargs, int nresults);          [-(nargs + 1), +nresults, e]
</p></blockquote>
<p>Ahora vamos a realizar una &#8220;llamada a función&#8221; (un <em>call</em>) de <em>nargs</em> argumentos de entrada y esperando obtener <em>nresults</em> elementos de salida. Si miráis la etiqueta de la función pone que se consumen del stack nargs+1 elementos: n argumentos + 1 función. </p>
<p>El órden es el que podéis ver en el stack, primero la función apilada, después cada argumento en orden y llamamos a lua_call. Con esto ejecutamos la función tal y como se ve en la figura.</p>
<p>No sabemos el tipo del resultado devuelto, pero por la forma de llamar a call sabemos que siempre tendremos un elemento en la pila. Aquí lua realiza un proceso de ajuste: si la función devolvió 600 elementos, al poner nosotros lua_call(&#8230;, 1);  se queda con el primero y descarta los otros 599, si la función no devolvía nada (0 elementos) y nosotros queríamos 1, rellenará el espacio con nil&#8217;s , finalmente si queremos que la función devuelva todos los elementos que quiera, en vez de poner un numero en <em>nresults</em>, usamos la constante LUA_MULTRET ( y con ello se evita el proceso de ajuste ).</p>
<div class="alignCenter"><img src="/files/lua101_h.png" alt="step_8" /></div>
<blockquote class="go"><p>
void <a href="http://www.lua.org/manual/5.1/manual.html#lua_setfield">lua_setfield</a> (lua_State *L,  int index, const char *k);          [-1, +0, e]
</p></blockquote>
<p>Para acabar, asignamos el resultado de la operación a la variable global &#8220;a&#8221;, usando lua_setfield (análogo a lua_getfield). La etiqueta nos dice que va a consumir un elemento y que no va a apilar nada. Con esto tenemos ejecutada toda la secuencia de &#8221; a = f(&#8220;how&#8221;, t.x, 14)&#8221;.</p>
<p>Nota:el call lo hicimos con lua_call(&#8230;,1) precisamente porque la intención era guardar el resultado en <strong>una</strong> variable ( gracias al ajuste nos da igual lo que haya devuelto la función ).</p>
<p>
Y hasta aquí el primer tutorial sobre el API de lua&#8230; para las dudas y aclaraciones, ahí tenéis los comentarios <img src='http://www.pplux.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.pplux.com/2008/04/16/lua-api-introduccion/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>disléxicos del mundo unisors!!!</title>
		<link>http://www.pplux.com/2008/04/13/dislexicos-del-mundo-unisors/</link>
		<comments>http://www.pplux.com/2008/04/13/dislexicos-del-mundo-unisors/#comments</comments>
		<pubDate>Sun, 13 Apr 2008 17:49:06 +0000</pubDate>
		<dc:creator>PpluX</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[humor]]></category>
		<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://www.pplux.com/2008/04/13/dislexicos-del-mundo-unisors/</guid>
		<description><![CDATA[Después del primer mandamiento, viene el de &#8220;evitarás la disléxia&#8221;: #ifndef __RESOURCE__ #define __RESORUCE__ ... #endif Sabía cual era el fallo, sabía que era un define mal puesto, sabía incluso en qué fichero estaba dando problemas&#8230; y aun así no veía el problema XD]]></description>
			<content:encoded><![CDATA[<p>Después del <a href="http://soledadpenades.com/2008/04/08/mental-note-about-ifndefs/">primer mandamiento</a>, viene el de &#8220;evitarás la disléxia&#8221;:</p>
<blockquote class="exclamation">
<pre>
#ifndef __RESOURCE__
#define __RESORUCE__
...
#endif
</pre>
</blockquote>
<p>Sabía cual era el fallo, sabía que era un define mal puesto, sabía incluso en qué fichero estaba dando problemas&#8230; y aun así no veía el problema XD</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pplux.com/2008/04/13/dislexicos-del-mundo-unisors/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Seminarios de la Breakpoint&#8217;08</title>
		<link>http://www.pplux.com/2008/04/11/seminarios-de-la-breakpoint08/</link>
		<comments>http://www.pplux.com/2008/04/11/seminarios-de-la-breakpoint08/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 10:31:30 +0000</pubDate>
		<dc:creator>PpluX</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[DemoScene]]></category>
		<category><![CDATA[Gráficos]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.pplux.com/2008/04/11/seminarios-de-la-breakpoint08/</guid>
		<description><![CDATA[Las Breakpoint&#8217;s siempre dejan demos espectaculares pero, personalmente, lo que más me fascina de la party son la calidad de algunos de sus seminarios. Se molestan en organizarlos, grabarlos y dejarlos online para disfrute de todo el mundo. A mi me han gustado especialmente, sin ningún orden específico: Multi-threading made easier through Open-Source Threading Building [...]]]></description>
			<content:encoded><![CDATA[<p>Las <a href="http://breakpoint.untergrund.net/">Breakpoint&#8217;s</a> siempre dejan <a href="http://www.pouet.net/party.php?which=450&#038;when=2008">demos</a> espectaculares pero, personalmente, lo que más me fascina de la party son la calidad de algunos de sus <a href="http://breakpoint.untergrund.net/seminars.php">seminarios</a>. Se molestan en organizarlos, grabarlos y dejarlos <a href="http://breakpoint.untergrund.net/seminars.php">online</a> para disfrute de todo el mundo.</p>
<p>A mi me han gustado especialmente, sin ningún orden específico:<br />
<span id="more-159"></span><br />
<a href="http://breakpoint.untergrund.net/download.php?dir=2008/seminars/&#038;file=BP08_Seminar_Aaron_Coday.mp4"><strong>Multi-threading made easier through Open-Source Threading Building Blocks</strong></a></p>
<div class="alignCenter"><img src="/files/BP08-tbb.png" alt="BreakPoint'08 TBB" /></div>
<blockquote><p>Task stealing: cuando un core real se queda sin tareas &#8220;roba&#8221; a otro una tarea para maximizar el <a href="http://es.wikipedia.org/wiki/Throughput">throughput</a> </p></blockquote>
<p>Después de hacer una extensa introducción sobre paralelismo, paralelismo sobre datos, paralelismo funcional, etc&#8230; muy orientado a videojuegos (bien!) nos presenta <a href="http://threadingbuildingblocks.org/">Threading Building Blocks</a>(TBB), una librería brutal, open-source y multiplataforma,  de la mano de intel. </p>
<p>La parte novedosa de usar TBB es que está orientado a tareas (task patterns), no a programar threads (hilos) como tal. Programar tareas hace que, teóricamente, el diseño escale automáticamente según el número de cores que tenga nuestro procesador. TBB es para C++, y está hecho para C++, por lo que usa plantillas para definir concurrent-containers (hash, queue, vector, ..), algoritmos paralelos (sort, for, while, reduce, &#8230;), tiene también un patrón &#8220;pipeline&#8221; para poder encadenar tareas, scalable-memory-allocators (para evitar sincronizaciones entre tareas al reservar memoria), etc.</p>
<p>Otra razón para usar tareas es que es fácil debuggear, ya que por diseño, puedes limitar todo a un single thread y depurar, una vez todo funciona puedes lanzarlo en multithread con casi todas las garantías de que va a funcionar.</p>
<p>En general TBB está <strong>muy</strong> bien montado. No se si se nota las ganas que tengo de usarlo <img src='http://www.pplux.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://breakpoint.untergrund.net/download.php?dir=2008/seminars/&#038;file=BP08_Seminar_Bonzaj.mp4"><br />
<strong>To hardcode or not &#8211; considerations about an ultimate demotool</strong></a></p>
<div class="alignCenter"><img src="/files/BP08-plastic.png" alt="BreakPoint'08 Plastic" /></div>
<blockquote><p> Motor de render picoEngine, integrado dentro de Maya como plugin. Escena de la última demo de <a href="http://www.plastic-demo.org/">plastic</a>: <a href="http://www.pouet.net/prod.php?which=50170">Linger in Shadows</a>  </p></blockquote>
<p>¿ hardcodear demos ó demotools ? Evolución de <a href="http://www.plastic-demo.org/">plastic</a> desde sus primeras demos hardcodeadas a los plugins y editores que ahora usan para diseñar demos. Por lo visto tienen su motor de render  (picoEngine) integrado como un plugin del editor que usen (Maya en este caso), y un editor de escenas para ajustar timelines, velocidad, etc. </p>
<p>Definitivamente para plastic el enfoque está muy cerca del artista, aunque reconocen que cierta funcionalidad es más cómoda de implementar en código que diseñarla con un editor.</p>
<p><a href="http://breakpoint.untergrund.net/download.php?dir=2008/seminars/&#038;file=BP08_Seminar_Navis.mp4"><br />
<strong>Tonite let&#8217;s all make demo in Bingen</strong></a></p>
<div class="alignCenter"><img src="/files/BP08-asd.png" alt="BreakPoint'08 ASD" /></div>
<blockquote><p> La demo cuenta una historia, tiene un flujo y los efectos de transición, no son tales, si no que se integran en ese flujo conectando una escena con la siguiente, suavemente. </p></blockquote>
<p>Vemos la otra cara de la moneda, para <a href="http://www.asd.gr/">ASD</a> lo principal es el código como herramienta y defienden que muchos de los efectos y transiciones no se podrían hacer con comodidad en un demoeditor. Por otro lado, como con plastic, no todo es blanco o negro.</p>
<p>Empieza con las razones por las que no hacemos demos ( me ha gustado eso de : &#8220;19% estamos intimidados por Farbrausch&#8221; ) y cómo las hacen en ASD. Básicamente: librería sencillita en C++, soporte básico para manejo de shaders y texturas, sin engine para animaciones, sistemas de partículas adecuados, scripting para los eventos y funciones de cámara imaginativas.</p>
<p>Desmitifican el &#8220;hacer una hardcoded demo es más difícil&#8221; y explican paso a paso como organizan sus demos. Detallan cómo organizan las escenas, efectos y las transiciones (aunque las transiciones de ASD son para dar de comer aparte).</p>
<p>Del motor de partículas destacan que es una pérdida de tiempo el típico bucle de actualización de partícula por frame, ya que en el 95% de los casos, las partículas se comportan de forma determinista por lo que se puede calcular su path previamente.</p>
<p>También es interesante cómo ajustan los detalles de las escenas, utilizando rands, y semillas asociadas a eventos de teclado y ratón para encontrar algún estado que quede bien en la demo (mola!!!).</p>
<p>Las cámaras tienen solo un par de movimientos, elípticos y lineales, interpolados con <a href="http://en.wikipedia.org/wiki/Sigmoid_function">s-curves</a>, simple y controlable.</p>
<p>El resto es filosofía de diseño, muy, muy interesante.</p>
<p><a href="http://breakpoint.untergrund.net/download.php?dir=2008/seminars/&#038;file=BP08_Seminar_Yury_Uralsky_Smoke.mp4"><strong>When there&#8217;s smoke there&#8217;s fire</strong></a></p>
<div class="alignCenter"><img src="/files/BP08-nvidia.png" alt="BreakPoint'08 Nvidia" /></div>
<blockquote><p> ¡¡ Ruido, y más ruido !!  </p></blockquote>
<p>Una presentación de nvidia muy asequible para el público en general sobre generación procedural y cálculo en la GPU. Explica con muchísimo detalle <a href=" http://en.wikipedia.org/wiki/Perlin_noise">perlin noise</a> para modelado de partículas, al margen del uso que hagan la explicación por si sola ya merece la pena.</p>
<p>Después continúa con la evolución del perlin noise hacia el <a href="http://en.wikipedia.org/wiki/Simplex_noise">Simplex noise</a> y cómo usarlo, acabando con notas sobre el sampleado del ruido para conseguir los mejores resultados.</p>
<p>La segunda parte de la charla trata sobre cómo renderizar humo. Empieza por la composición del humo en la escena (esta es la parte fácil y similar con la primera parte de la charla). Después comenta cómo calcular la simulación de fluidos en la GPU y añade cómo  detectar las colisiones con geometría de la escena (pasándola a un volumen).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pplux.com/2008/04/11/seminarios-de-la-breakpoint08/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cómo detectar herencia de clases en C++ ( en tiempo de compilación )</title>
		<link>http://www.pplux.com/2007/10/05/como-detectar-herencia-de-clases-en-c-en-tiempo-de-compilacion/</link>
		<comments>http://www.pplux.com/2007/10/05/como-detectar-herencia-de-clases-en-c-en-tiempo-de-compilacion/#comments</comments>
		<pubDate>Fri, 05 Oct 2007 17:20:14 +0000</pubDate>
		<dc:creator>PpluX</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[recetas]]></category>

		<guid isPermaLink="false">http://www.pplux.com/2007/10/05/como-detectar-herencia-de-clases-en-c-en-tiempo-de-compilacion/</guid>
		<description><![CDATA[Como todo programador de C++ sabe, no existe función alguna para comprobar en tiempo de compilación si una clase A hereda de otra B. En tiempo de ejecución podemos usar dynamic_cast, pero con mucho cuidado: dynamic_cast permite saber si un puntero de una clase base es en realidad de una clase hija, esto ya presupone [...]]]></description>
			<content:encoded><![CDATA[<p>Como todo programador de C++ sabe, no existe función alguna para comprobar en <strong>tiempo de compilación</strong> si una clase A hereda de otra B.   En <strong>tiempo de ejecución</strong> podemos usar <span class="green">dynamic_cast</span>, pero con mucho cuidado:</p>
<ol>
<li><span>dynamic_cast permite saber si un puntero de una clase base es en realidad de una clase hija, esto ya presupone que las dos clases a comparar están &#8220;emparentadas&#8221;. De no ser así, el compilador nos soltará un warning (en el mejor de los casos) diciendo que la conversión <strong>nunca</strong> tendrá éxito.</span></li>
<li><span>dado que dynamic_cast está pensado para usarse en el caso anterior, la clase a convertir tiene que ser <strong>obligatoriamente</strong> polimórfica.</span></li>
<li><span>dynamic_cast es&#8230; lento, y requiere soporte de RTTI.</span></li>
</ol>
<p>Escribiendo plantillas nos podemos encontrar que necesitamos saber si una clase hereda de otra, por ejemplo, para especializar la plantilla con un código optimizado. En esta circunstancia sólo nos sirve de verdad si somos capaces de tomar la decisión en tiempo de compilación, y dado que C++ no ofrece nada para ello <a href="http://erdani.org/book/main.html">Alexandrescu</a> nos revela este truco. </p>
<h3>¿ Se puede saber si una instancia de tipo A se puede convertir (automáticamente) en otra de tipo B ?</h3>
<blockquote class="go" ><p>Cuando los tipos A y B son clases estamos hablando de si la clase A hereda de B, pero el truco funciona igual de bien para cualquier par tipos, por ejemplo, para saber si un <span class="green">int</span> se puede convertir a <span class="green">float</span> o mejor si una clase A tiene conversión definida a otra B (<a href="http://www.cplusplus.com/doc/tutorial/typecasting.html">explicit conversion</a>).</p></blockquote>
<p>La respuesta es <strong>¡sí!</strong>, y todo se lo debemos curiosamente a <span class="green">sizeof</span>. </p>
<blockquote><p><span class="green">sizeof</span> es realmente potente, se puede aplicar a cualquier expresión, sin importar lo compleja que esta sea, sizeof devolverá el tamaño de esta sin llegar a evaluar la expresión en tiempo de compilación. Esto significa que sizeof  tiene presente la sobrecarga, la especialización de plantillas, reglas de conversión &#8230; <strong>absolutamente todo</strong> lo que pueda aparecer en una expresión de C++ . En realidad, sizeof es capaz de deducir el tipo de una expresión; desechando la expresión pero devolviendo su tamaño.<span class="block small grey">Alexandrescu</span></p></blockquote>
<p>Evaluar el valor de una expresión implica hacerlo en tiempo de ejecución, pero evaluar el tamaño del tipo devuelto por una expresión es algo que se debe realizar en <strong>tiempo de compilación</strong>. Lo que Alexandrescu nos viene a decir es que sizeof es precisamente capaz de esto, y al hacerlo desecha el valor de la expresión y &#8220;calcula&#8221; solamente el tamaño del tipo devuelto. </p>
<p>El truco consiste en tener un par de funciones de test sobrecargadas, una que acepta el tipo objetivo (B) y otra que acepte cualquier otra cosa. Cada función devuelve un tipo de tamaño diferente,  al intentar llamar a la función test con el tipo A si existe la conversión de A a B se utilizará una función y si no, la otra. Tranquilos que los detalles siguen a continuación.</p>
<p>Primero creamos dos clases de tamaños diferentes, Alexandrescu nos recomienda algo como:<br />
<code><br />
<span class="blue">// Esta, por definición, ocupa 1 byte </span><br />
typedef char S_True;<br />
<span class="blue"> // Esta no se sabe cuanto ocupa, pero seguro que > 1 </span><br />
class S_False { char dummy[2]; }<br />
</code></p>
<p>Ahora necesitamos un par de funciones sobrecargadas, una que acepte B y devuelva S_True:<br />
<code><br />
S_True Test(B);<br />
</code></p>
<p>Y otra para &#8220;todo lo demás&#8221;, y que tenga menos prioridad. De esta forma si el objeto de tipo A no se puede convertir de ningúna forma a B se utilice esta función. Para ello utilizamos la construcción de <a href="http://en.wikipedia.org/wiki/Stdarg.h#.3Cvarargs.h.3E">varargs</a> que por definición siempre será el último recurso a utilizar.</p>
<p><code><br />
S_False Test(...);<br />
</code></p>
<p>Ahora ya podemos averiguar si el tipo A se puede transformar en B, sin más que comparar el tamaño de evaluar la llamada de Test:<br />
<code><br />
const bool <span class="green">existe_conversion</span> = sizeof( Test(A()) ) == sizeof(S_True) ;<br />
</code></p>
<p>Y ya está!! ya tenemos una constante booleana que nos indica si la conversión es posible en tiempo de compilación&#8230; pero ¿cómo funciona? Recordemos lo que hemos venido comentando:</p>
<blockquote class="exclamation"><p> <span class="green">sizeof</span> sólo evalúa el <strong>tamaño</strong> de una expresión sin necesidad de realizar llamadas reales, esto permite que no haga falta implementar nada en absoluto, nunca se van a llamar a ninguna función Test, ni al constructor de A(), ni nada&#8230; sizeof evalúa la expresión para ver qué <strong class="red" >tamaño</strong> tendrá el <strong class="red">tipo del resultado</strong>.</p></blockquote>
<p>Un pequeño problema es que la expresión &#8220;A()&#8221; tiene que ser válida lo que supone que el constructor por defecto debe existir en el tipo A. Como esto no tiene por qué ser cierto, vamos a darle un pequeño giro de tuerca.</p>
<p><code><br />
A CrearInstancia();<br />
const bool <span class="green">existe_conversion</span> = sizeof( Test(CrearInstancia()) ) == sizeof(S_True) ;<br />
</code></p>
<p>La función CrearInstancia no hay que implementarla, nuevamente sizeof sólo la usa para saber que el parámetro de vuelvo es de tipo A, de esta forma evitamos tener que usar el constructor de A.</p>
<p>Con todo esto, ya tenemos para hacernos un template que nos diga si una clase es convertible a otra.<br />
<code><br />
template &lt;class A, class B&gt;<br />
class Conversion<br />
{<br />
    typedef char S_True;<br />
    class S_False { char dummy[2]; }<br />
    static A CrearInstancia();<br />
    static S_True  Test(B);<br />
    static S_False Test(...);<br />
public:<br />
    enum {<br />
        existe = ( sizeof(Test(CrearInstancia())) == sizeof(S_True) )<br />
    };<br />
};<br />
</code></p>
<p>Como ejemplo&#8230;<br />
<code><br />
#include &lt;iostream&gt;<br />
#include &lt;vector&gt;<br />
int main() {<br />
    std::cout<br />
        &lt;&lt; Conversion&lt;double,int&gt;::existe &lt;&lt; ' '<br />
        &lt;&lt; Conversion&lt;char, char*&gt;::existe &lt;&lt; ' '<br />
        &lt;&lt; Conversion&lt;size_t ,vector&lt;int&gt; &gt;::existe &lt;&lt; ' '<br />
}<br />
</code><br />
Y el resultado &#8217;1 0 0&#8242; &#8230;  Finalmente para detectar la herencia de clases (como decíamos en el tíutlo del post) lo que debemos es usar punteros constantes a los tipos:<br />
<code><br />
Conversion&lt;const clase1*, const clase2*&gt;::existe<br />
</code></p>
<blockquote class="go" ><p>
¡¡¡ Todo esto gracias a <a href="http://erdani.org/book/main.html">Alexandrescu</a> y al power of <span class="green">sizeof</span> !!!
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.pplux.com/2007/10/05/como-detectar-herencia-de-clases-en-c-en-tiempo-de-compilacion/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Cargar texturas con ImageMagick</title>
		<link>http://www.pplux.com/2007/02/07/cargar-texturas-con-imagemagick/</link>
		<comments>http://www.pplux.com/2007/02/07/cargar-texturas-con-imagemagick/#comments</comments>
		<pubDate>Wed, 07 Feb 2007 12:12:49 +0000</pubDate>
		<dc:creator>PpluX</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[recetas]]></category>

		<guid isPermaLink="false">http://www.pplux.com/2007/02/07/cargar-texturas-con-imagemagick/</guid>
		<description><![CDATA[Cargar texturas en OpenGL implica leer una textura, crear un objeto de textura y subir los texels a la gráfica. Los dos últimos pasos, el de crear y subir la información, no son complicados o por lo menos siempre se hacen igual, pero leer una imagen de disco suele ser un quebradero de cabeza si [...]]]></description>
			<content:encoded><![CDATA[<p>Cargar texturas en OpenGL implica leer una textura, crear un objeto de textura y subir los <a href="http://en.wikipedia.org/wiki/Texel_%28graphics%29">texels</a> a la gráfica. Los dos últimos pasos, el de crear y subir la información, no son complicados o por lo menos siempre se hacen igual, pero leer una imagen de disco suele ser un quebradero de cabeza si pretendemos hacerlo a mano. Claro está, no me refiero a leer de disco a secas, me refiero a leer imágenes con formato ya sea jpg, png, svg, etc.</p>
<p>Típicamente en el mundillo de los gráficos desde tiempos inmemoriales se ha venido usando un set de librerías conocido por <a href="http://openil.sourceforge.net/">DevIL</a> ( que inicialmente se llamaba OpenIL  aunque por problemas con SGI cambiaron el nombre). Esta librería es además de práctica muy sencilla de utilizar y entona muy bien con openGL por estar basada en una máquina de estados y estar separada en varios niveles de abstracción IL, ILU, ILUT (como GL, GLU, y GLUT). </p>
<p>Pero si queremos usar algo más potente de DevIL podemos usar <a href="http://www.imagemagick.org/script/index.php">ImageMagick</a>. Con ImageMagick ganaremos no sólo un cargador, además ganamos un editor, compositor y conversor de imágenes con la ventaja de que ImageMagick probablemente ya viene instalada en las ubuntu/debian/*nix normales ( y si no viene, sólo hay que enseñar a usar <a href="http://www.imagemagick.org/script/convert.php">convert</a> o cualquiera de las <a href="http://www.imagemagick.org/script/command-line-tools.php">command-line-tools</a> de ImageMagick ).</p>
<p>Veamos un breve, rapidísimo tutorial de cómo cargar una imagen con Imagemagick. Vamos a usar la interfaz &#8220;C&#8221; de magick-wand, también existe una para C++ (así como para python, perl, php,&#8230;) pero implicaría tener que añadir una dependencia extra&#8230; y la verdad es que Magick-Wand es suficientemente fácil de usar por sí misma. </p>
<p><code><br />
<font color="#ff40ff">#include </font><font color="#ff6060">&lt;wand/magick_wand.h&gt;</font><br />
<font color="#00ff00">int</font> main(...) {<br />
    MagickWandGenesis();<br />
    MagickWand *wand = NewMagickWand();<br />
    <font color="#8080ff">// ...</font><br />
    wand = DestroyMagickWand(wand);<br />
    MagickWandTerminus();<br />
}<br />
</code></p>
<p>Las llamadas MagickWandGenesis y MagickWandTerminus inicializan y finalizan la librería, una vez hecho con NewMagickWand y DestroyMagickWand podemos crear y liberar varitas (mágicas) para trabajar con imágenes, transformalas, etc&#8230; Lo siguiente consiste en cargar la imagen de un fichero o un <a href="http://en.wikipedia.org/wiki/Binary_large_object">BLOB</a> de memoria:</p>
<p><code><br />
        <font color="#8080ff">// opcion 1: leer de fichero dado un path</font><br />
        MagickBooleanType status = MagickReadImage ( wand, path );<br />
        <font color="#8080ff">// opcion 2: leer de un puntero a memoria (data) de tamaño conocido (size)</font><br />
        MagickBooleanType status = MagickReadImageBlob( wand, data, size );<br />
        <font color="#ffff00">if</font> ( status != MagickFalse )<br />
        {<br />
        }<br />
</code></p>
<p>Las dos llamadas de MagickReadImage[Blob] hacen lo mismo, leen una imagen y además lo hacen identificando el tipo de imagen que es. Esto lo digo concretamente por la versión &#8220;blob&#8221;, no hay que decirle si es un png, jpg, ppm, svg&#8230; Imagemagick lo identificará por la cabecera del fichero, si usáis vuestro propio cargador de ficheros no tenéis más que leer el fichero entero sin preocuparos del tipo de fichero y MagickReadImageBlob intentará leerlo.<br />
También existe la versión MagickReadImageFile que recibe un descriptor de fichero tipo FILE*<br />
<b>nota:</b> en vuestro caso particular sólo hay que usar una de las dos opciones, claro está <img src='http://www.pplux.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>El resultado es un booleano, si todo a ido bien sólo queda recuperar esa información y subirlo a la textura. En este caso vamos a tener en cuenta si la imagen tiene alfa o no (para ImageMagick es ver si tiene opacidad):</p>
<p><code><br />
        <font color="#00ff00">unsigned</font> <font color="#00ff00">long</font> width = MagickGetImageWidth( wand );<br />
        <font color="#00ff00">unsigned</font> <font color="#00ff00">long</font> height = MagickGetImageHeight( wand );<br />
        <font color="#00ff00">unsigned</font> <font color="#00ff00">char</font> *data = <font color="#ff6060">0</font>;<br />
        MagickFlipImage( wand );<br />
        <font color="#8080ff">// reservamos para una textura y la activamos</font><br />
        glGenTextures(<font color="#ff6060">1</font>, &amp;texture);<br />
        glBindTexture(GL_TEXTURE_2D, texture);<br />
        <font color="#ffff00">if</font> ( MagickGetImageChannelDepth(wand, OpacityChannel) &gt; <font color="#ff6060">1</font> )<br />
        {<br />
            <font color="#8080ff">// con alfa</font><br />
            data = <font color="#ffff00">new</font> <font color="#00ff00">unsigned</font> <font color="#00ff00">char</font>[width*height*<font color="#ff6060">4</font>];<br />
            MagickGetImagePixels(wand, <font color="#ff6060">0</font>,<font color="#ff6060">0</font>, width, height, <font color="#ff6060">&quot;RGBA&quot;</font>, CharPixel, data);<br />
            glTexImage2D(GL_TEXTURE_2D, <font color="#ff6060">0</font>, GL_RGBA, width, height, <font color="#ff6060">0</font>, GL_RGBA, GL_UNSIGNED_BYTE, data);<br />
        }<br />
        <font color="#ffff00">else</font><br />
        {<br />
            <font color="#8080ff">// sin alfa</font><br />
            data = <font color="#ffff00">new</font> <font color="#00ff00">unsigned</font> <font color="#00ff00">char</font>[width*height*<font color="#ff6060">3</font>];<br />
            MagickGetImagePixels(wand, <font color="#ff6060">0</font>,<font color="#ff6060">0</font>, width, height, <font color="#ff6060">&quot;RGB&quot;</font>, CharPixel, data);<br />
            glTexImage2D(GL_TEXTURE_2D, <font color="#ff6060">0</font>, GL_RGB, width, height, <font color="#ff6060">0</font>, GL_RGB, GL_UNSIGNED_BYTE, data);<br />
        }<br />
        <font color="#ffff00">delete</font>[] data;<br />
</code></p>
<p>Este ya es un buen cacho, primero obtenemos ancho y alto de la imagen, hacemos un flip de la imagen (ya que en OpenGL las imágenes empiezan abajo a la izquierda &#8211; <a href="http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/">pitfall 12</a>) y reservamos una textura de OpenGL. Después preguntamos a la varita si la imagen tiene alfa, en realidad le preguntamos si la profundidad del canal de opacidad es mayor que 1, si es así reservamos espacio para guardarnos la información de la imagen en formato RGBA y lo subimos a la textura. Si no tiene alfa pues lo mismo pero en formato RGB. Y como somos muy limpios, al final un delete[] para liberar la memoria temporal donde guardamos la imagen.</p>
<p>Y finalmente el ejemplo más o menos completo del tema&#8230; Para compilarlo en linux no hay que olvidar que tenemos un <em>mágico</em> <code> `Wand-config --cppflags --cflags --ldflags --libs`</code> para ayudarnos.</p>
<p><code><br />
<font color="#ff40ff">#include </font><font color="#ff6060">&lt;GL/gl.h&gt;</font><br />
<font color="#ff40ff">#include</font><font color="#ff6060">&lt;wand/magick_wand.h&gt;</font><br />
<font color="#00ff00">int</font> main(...) {<br />
    <font color="#8080ff">// inicializamos openGL o lo que haga falta...</font><br />
    GLuint texture = <font color="#ff6060">0</font>; <font color="#8080ff">// nuestra textura</font><br />
    MagickWandGenesis();<br />
    MagickWand *wand = NewMagickWand();<br />
    <font color="#8080ff">// opcion 1: leer de fichero dado un path</font><br />
    MagickBooleanType status = MagickReadImage ( wand, path );<br />
    <font color="#8080ff">// opcion 2: leer de un puntero a memoria (data) de tamaño conocido (size)</font><br />
    MagickBooleanType status = MagickReadImageBlob( wand, data, size );<br />
    <font color="#ffff00">if</font> ( status != MagickFalse )<br />
    {<br />
        <font color="#00ff00">unsigned</font> <font color="#00ff00">long</font> width = MagickGetImageWidth( wand );<br />
        <font color="#00ff00">unsigned</font> <font color="#00ff00">long</font> height = MagickGetImageHeight( wand );<br />
        <font color="#00ff00">unsigned</font> <font color="#00ff00">char</font> *data = <font color="#ff6060">0</font>;<br />
        MagickFlipImage( wand );<br />
        <font color="#8080ff">// reservamos para una textura y la activamos</font><br />
        glGenTextures(<font color="#ff6060">1</font>, &amp;texture);<br />
        glBindTexture(GL_TEXTURE_2D, texture);<br />
        <font color="#ffff00">if</font> ( MagickGetImageChannelDepth(wand, OpacityChannel) &gt; <font color="#ff6060">1</font> )<br />
        {<br />
            <font color="#8080ff">// con alfa</font><br />
            data = <font color="#ffff00">new</font> <font color="#00ff00">unsigned</font> <font color="#00ff00">char</font>[width*height*<font color="#ff6060">4</font>];<br />
            MagickGetImagePixels(wand, <font color="#ff6060">0</font>,<font color="#ff6060">0</font>, width, height, <font color="#ff6060">&quot;RGBA&quot;</font>, CharPixel, data);<br />
            glTexImage2D(GL_TEXTURE_2D, <font color="#ff6060">0</font>, GL_RGBA, width, height, <font color="#ff6060">0</font>, GL_RGBA, GL_UNSIGNED_BYTE, data);<br />
        }<br />
        <font color="#ffff00">else</font><br />
        {<br />
            <font color="#8080ff">// sin alfa</font><br />
            data = <font color="#ffff00">new</font> <font color="#00ff00">unsigned</font> <font color="#00ff00">char</font>[width*height*<font color="#ff6060">3</font>];<br />
            MagickGetImagePixels(wand, <font color="#ff6060">0</font>,<font color="#ff6060">0</font>, width, height, <font color="#ff6060">&quot;RGB&quot;</font>, CharPixel, data);<br />
            glTexImage2D(GL_TEXTURE_2D, <font color="#ff6060">0</font>, GL_RGB, width, height, <font color="#ff6060">0</font>, GL_RGB, GL_UNSIGNED_BYTE, data);<br />
        }<br />
        <font color="#ffff00">delete</font>[] data;<br />
    }<br />
    wand = DestroyMagickWand(wand);<br />
    MagickWandTerminus();<br />
}<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.pplux.com/2007/02/07/cargar-texturas-con-imagemagick/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Depurando con CGDB</title>
		<link>http://www.pplux.com/2006/11/30/depurando-con-cgdb/</link>
		<comments>http://www.pplux.com/2006/11/30/depurando-con-cgdb/#comments</comments>
		<pubDate>Thu, 30 Nov 2006 14:55:45 +0000</pubDate>
		<dc:creator>PpluX</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.pplux.com/2006/11/30/depurando-con-cgdb/</guid>
		<description><![CDATA[Depurar con gdb no es realmente complicado, al principio uno se siente tentado de usar printf&#8217;s(C)/std::couts(C++) como método de depuración, pero no!, invertir tiempo en aprender a usar mínimamente gdb es más práctico, más eficiente y además ahorra mucho tiempo. Hay mil manuales sobre gdb, aquí os propongo dos que he encontrado buscando a bote [...]]]></description>
			<content:encoded><![CDATA[<p>Depurar con <a href="http://www.gnu.org/software/gdb/">gdb</a> no es realmente complicado, al principio uno se siente tentado de usar printf&#8217;s(C)/std::couts(C++) como método de depuración, pero <strong>no!</strong>, invertir tiempo en aprender a usar mínimamente gdb es más práctico, más eficiente y además ahorra mucho tiempo. Hay mil manuales sobre gdb, aquí os propongo dos que he encontrado buscando a bote pronto, <a href="http://refcards.com/refcards/gdb/gdb-refcard-letter.pdf">gdb-quickreference</a> y esta <a href="http://heather.cs.ucdavis.edu/~matloff/UnixAndC/CLanguage/Debug.html">guía</a>, aunque la <a href="http://sources.redhat.com/gdb/current/onlinedocs/gdb_toc.html">documentación oficial</a> es genial. </p>
<p>En cualquier caso, ya de puestos, y suponiendo que os habéis mirado algo de gdb, buscando interfaces gráficas para el gdb encontré este que me ha gustado especialmente, <a href="http://cgdb.sourceforge.net/">cgdb</a>. Es básicamente un gdb, en ncurses, pero con una ventana para ver el código con resaltado de sintaxis y la posibilidad de abrir el tty de la aplicación en otra subventana (para no mezclar la entrada/salida del programa con la linea de comandos del depurador). </p>
<p>Si ya sabes gdb, esto solamente será azúcar para tu debug <img src='http://www.pplux.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.pplux.com/2006/11/30/depurando-con-cgdb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Glee con soporte para OpenGL 2.1</title>
		<link>http://www.pplux.com/2006/11/18/glee-con-soporte-para-opengl-21/</link>
		<comments>http://www.pplux.com/2006/11/18/glee-con-soporte-para-opengl-21/#comments</comments>
		<pubDate>Sat, 18 Nov 2006 09:16:32 +0000</pubDate>
		<dc:creator>PpluX</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.pplux.com/2006/11/18/glee-con-soporte-para-opengl-21/</guid>
		<description><![CDATA[Glee es una pequeña librería multiplataforma + cabecera (gl.h) que permite programar siempre con la última versión de la especificación de OpenGL, en este caso la versión 2.1. Glee cargará por ti dinámicamente aquellas extensiones que soporte tu tarjeta, sólo hay que tener en cuenta que aunque estés progrmando contra el API de OpenGL 2.1, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://elf-stone.com/glee.php">Glee</a> es una pequeña librería multiplataforma + cabecera (gl.h) que permite programar siempre con la última versión de la especificación de OpenGL, en este caso la versión 2.1. </p>
<p>Glee cargará por ti dinámicamente aquellas extensiones que soporte tu tarjeta, sólo hay que tener en cuenta que aunque estés progrmando contra el API de OpenGL 2.1, es posible que tu tarjeta <b>NO</b> soporte ciertas llamadas, o ciertos formatos&#8230; las comprobaciones de las <em>capabilities</em> de la tarjeta se tienen que seguir haciendo ( en tiempo de ejecución ).</p>
<p>En resumen, el que prueba esta librería no vuelve a complicarse la vida con las <a href="http://www.opengl.org/resources/features/OGLextensions/">extesiones de OpenGL</a>.</p>
<p>Desde: <a href="http://www.opengl.org/news/permalink/glee_opengl_extension_library_adds_support_for_opengl_21_and_geforce_8_open/">OpenGL.org</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.pplux.com/2006/11/18/glee-con-soporte-para-opengl-21/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

