Saturday, 15 January 2011

DIY Pseudo "iMac"

This was the situation : I have an laptop (HP-DV5000) with 5 years which still works pretty well apart from the broken LCD, which was due it had already been at Breakpoint, Inercia, Euskal and almost all the college period in my backpack. So the LCD started to show some weird vertical coloured lines which would require a new LCD, which is almost the price of a new laptop...
After i started my current job, which is purely macintosh based, i noticed the iMac where actually an interesting concept to keep all the cables inside the computer. So i though maybe i can do something similar to my old laptop !

The basic idea was to mount the laptop behind an LCD monitor, my monitor (Sony SDM-S93) had a sliding plate behind which helped to mount the metal holder bars. After that I only needed some sort of electronic connection to power up the laptop, since the power button would be hidden under the lid. 

The electronic circuit consists in a relay which is activated when we press the front power/iddle button in the monitor, the relay acts as the power switch of the laptop. I could have connected directly the two switches, but that wouldn't be very safe and healthy for both the devices. The circuit steals 12V from the monitor PSU, which is always available whatever the current state(idle or on). On idle state the available current is very low, because the PSU switching circuit is working at a very small duty cycle to use less mains power, so the laptop switching circuit must be power efficient.

Monitor PSU and control circuit plus my circuit in the breadboard The compact version of the laptop switching circuit

After building the circuit I only needed to add some cables to the laptop which would intercept the power button signal, using my trusty Dremel i drilled a path through the plastic and used the hole of one screw to pass the cables. The cables end with a male conector to help mount and unmount the laptop from the suport, or even still use the laptop .. as a laptop :)

Drilled path to pass the cables
The end result isn't a iMac, but still, I managed to recycle old hardware to create a new "computer" which manages to accomplish all my current needs (Blender, development, office and minecraft :P). It was still has some issues due to idle/on/off state of monitor, when it's on iddle mode and we press the power button, it powers up the laptop and powers down the monitor (iddle->off), but pressing it again it powers up the monitor without powering down the laptop. I could easily fix this by intercepting also the monitor power switch and with some extra logic, but for now it's enough ! 

Back view Front view

Sunday, 26 December 2010

Blender Armatures and Exporting


One of the things i have spent many time trying to understand is the Blender animation data for the armatures. Since the quaternions and translation vectors have their own special space, which depends on the bone orientation and roll vector as shown in how armatures work, it isn't always easy to translate the animations to other formats like collada, fbx, bvh or to export the data for real-time applications.

The first thing to take in consideration is the matrix theoretical layout used to describe armature chain, like OpenGL, Blender uses the translation vector in a column, which may create some confusion. One typical example of this issue is the OpenGL (2) and DirectX (1) shaders, at machine level, they are done in the same way (see the gluProject source from Mesa), but from the programmers high level, the syntax is quite the opposite for the following cases :
out.pos = mul(float4(in.vertex,1.0), WorldViewProj ) (1)
gl_Position = WorldViewProj  * vec4(vertex, 1.0) (2)


Keeping this in mind we rewrite the blender armature expression the way i like (3).
b.matrix = IK(b) * Constrains(b) * actions(b) * bonemat(b) * head(b) * tail(b-1) * b.parent.matrix (3)

Ignoring the IK and Constrains we have something similar to what i use for my armatures (4), but still, the action data (quaternions and translations) are affected by the bonemat matrix, which disables the direct use of the animation data from blender.
bone.matrix = Scale(bone.scale) * Rotate(bone.quaternion) * Translate(bone.head+bone.translation) *Translate(bone.parent.tail-bone.parent.head)*bone.parent.matrix (4)


To fix this issue, i found this expression to be the solution to export Blender animation data for my applications and the bXporter API (5).

matArmatureSpace = b.matrix['ARMATURESPACE']
matInvArmatureSpace = Matrix(matArmatureSpace).invert()

rotFixed = (matInvArmatureSpace.rotationPart()* graphQuaternion.toMatrix()*
matArmatureSpace.rotationPart()).toQuat()

posFixed = (matInvArmatureSpace*
TranslationMatrix(graphPosition)*
matArmatureSpace.rotationPart()).translationPart() (5)

This peculiar transformation applies the transformation of the bone rest pose in armature space to the current action data, this way we get the bone animated in armature space, then by applying the inverse bone rest pose matrix, we get the the rotation and translation relative to bone space and independent of the bonemat matrix, enabling the use of the expression (4).

Currently i have even fixed the issue with the animation beziers with another solution which doesn't use Cardano solver like in Blender or ILM ones, which consists in recalculate the bezier coefficients, but that will be another blogpost :)

Thursday, 11 November 2010

Event Report - FIBDA 2010

This year event was dedicated to the 100th birthday of the portuguese republic, with many works related to the satire of portuguese people and the events during the implantation of the republic. It also exhibited some comics with almost 100 years, pretty well conserved!

This year there wasn't an official cosplay event, because there weren't enough conditions to support the event, but still some contestants still appeared. It had some awesome installations with comics and sculptures of some artists but in general it was a bit weaker in relation to last year. The japanese section was a bit short for my taste, but had a huge scroll exposed over the walls with a colab work of many artists. It also featured a video installation with an animation of ancient japanese drawings.

The courageous ones who still came to the event

1/2 of the wall scroll
GUNMM Mangas Collection, 18 books 
I also bought the full collection of the GUNMM manga which I wasn't expecting to find and it was well worth the price, it's an specular cyberpunk story from the 90's, although it's a bit gore'ish :P

Wednesday, 13 October 2010

XNA 4.0 - Binary Model Loader

So i was trying to avoid the standard xna pipeline classes to start porting some features of my "graphic engine" to XNA. The first thing i wanted was to render a model with my custom file format, the C# and the XNA API stood well to the task, allowing me to read a buffers of bytes from filestream and copying it to vertex and index buffer.
 public class CustomModel  
 {  
      int m_Vertices;  
      int m_Triangles;  
   
      byte[] m_VerticeData;  
      byte[] m_TrianglesData;  
   
      GraphicsDevice m_GraphicsDevice;  
      VertexBuffer m_VertexBuffer;  
      IndexBuffer m_IndexBuffer;  
   
      public CustomModel()  
      {  
           m_Vertices = 0;  
           m_Triangles = 0;  
      }  
   
      public void Render()  
      {  
           m_GraphicsDevice.SetVertexBuffer(m_VertexBuffer);  
           m_GraphicsDevice.Indices = m_IndexBuffer;  
           m_GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, m_Vertices, 0, m_Triangles);  
   
           m_GraphicsDevice.SetVertexBuffer(null);  
           m_GraphicsDevice.Indices = null;  
      }  
   
      public void Load(GraphicsDevice graphics, ContentManager manager, string filename)  
      {  
           m_GraphicsDevice = graphics;  
   
           String StageIndexPath = manager.RootDirectory + "\\" + filename;  
   
           StreamReader st = new StreamReader(StageIndexPath);  
           BinaryReader bin = new BinaryReader(st.BaseStream);  
   
           m_Vertices = bin.ReadInt32();  
           m_Triangles = bin.ReadInt32();  
   
           m_VerticeData = new byte[m_Vertices * 32];  
           m_TrianglesData = new byte[m_Triangles * 12];  
   
           bin.Read(m_VerticeData, 0, m_Vertices * 32);  
           bin.Read(m_TrianglesData, 0, m_Triangles * 12);  
   
           bin.Close();  
           st.Close();  
   
           VertexDeclaration vdx = new VertexDeclaration(  
                new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),  
                new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),  
                new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)  
           );  
   
           m_VertexBuffer = new VertexBuffer(m_GraphicsDevice, vdx, m_Vertices, BufferUsage.None);  
           m_IndexBuffer = new IndexBuffer(m_GraphicsDevice, IndexElementSize.ThirtyTwoBits, 3 * m_Triangles, BufferUsage.None);  
   
           m_VertexBuffer.SetData<byte>(m_VerticeData);  
           m_IndexBuffer.SetData<byte>(m_TrianglesData);  
      }  
 }  

Sunday, 10 October 2010

Event Report - Euskal 2010

Awesome place to sleep, if you still like concrete floor.

Yet again after one year of abstention the portuguese crew was back to Bilbao and Euskal, as usual our driver was Evil and is mighty mitsubishi, but this time we used a GPS to get there, although the roads in the frontier messed the GPS a bit :), we arrived at 23pm local hours after leaving Porto at 10:30am.

As usual the place was full gamers and scene spirit kept being replaced by stupid videos on youtube at the big screen, which was the biggest mistake, if I wanted to see video on youtube I could stayed in home and didn't needed to waste 300€ on trips and food :(

This year we learned how to waste less money on food, we bought microwave food on the local supermarket and we heated it at the local party microwaves, 2.5€ per meal, a great deal!

The sleeping space was ... the same, the showers were ... the same. But the big issue was the first night, I tried to slept under the hall lights and it didn't work very well since I didn't even had a tent.

During the party i bought an external hard drive with esata port with a good price tag, but the first impressions weren't the best, since the hard drive blew up in my face, which was interesting :), but the guys at the shop gave me a new kit and everything was fine. It's a 1-Tera Byte HD were i store my projects that I need a faster access, since the USB drives are awfully slow.

The demoparty was meh, no demoshow during the event, the competitions didn't went well to evil and me, only xernobyl managed win something and still he had to share the price with someone, because in Euskal it's pretty common the entry's classification being tied(like the ASD and XPSV demos, seriously wtf ?)

My 3D art entry didn't got any prize, I admit it still needed some improvements, but I didn't agree with the second and third place, oh well ...

The party is becoming less and less interesting for sceners, although the prizes are interesting, it can't be the unique reason to attend to the party, for me it's was the final Euskal, if the opportunity appears in the near future, I will go to Main DemoParty.

At least it was good to see the spanish sceners, Ham, Stage7 and the guys markan and pope with their awesome laser demo, props for putting napalmcore in the greetings :)

In the last day me and jae went out to take photos in Bilbau, the city is amazing place, saldy we didn't had time to visit the Guggenheim.