All Blog Entries

All blog entries, ordered from most recent. Entry count: 1198.

Warning! Some information on this page is older than 6 years now. I keep it for reference, but it probably doesn't reflect my current knowledge and beliefs.

Pages: > 1 ... 33 34 35 36 37 ... 150 >

# Global Game Jam Starts Tomorrow

Thu
24
Jan 2013

Tomorrow Global Game Jam 2013 starts - annual, 48-hour, worldwide event about game development. Just like last year, big Polish cities will also host this event (Warsaw, Poznań, Gdańsk, Łódź, Kraków), but this time the local edition in my city - Gdańsk - is organized as 3City Global Game Jam 2013 (Facebook page) by playsoft company. I will go there despite I have no team and no idea what technology to use. I will just see what happens :)

Comments | #competitions #events #ggj Share

# SBX - Scale-Bias Transform

Wed
23
Jan 2013

A class of 2D or 3D point and vector transformations called affine transformations (that is - linear transformation plus translation) can be conveniently represented by matrix. But sometimes we don't need possibility of input x to influence output y or vice versa. For example, that's the case when we want to convert coordinates of mouse cursor from pixels, like we take it from WinAPI (where X goes right from 0 to e.g. 1280 and Y goes down from 0 to e.g. 720) to post-projective 3D space (where X goes right from -1.0 to +1.0 and Y goes up from -1.0 on the bottom to +1.0 on the top). Then every component can be transformed independently using linear transform, like this:

Parameters are: scale.xy, bias.xy.
Given input point i.xy, output point o.xy is:

o.x = i.x * scale.x + bias.x
o.y = i.y * scale.y + bias.y

This seems trivial, but what if we wanted to encapsulate such transformation in a new data structure and define operations on it, like we do on matrices? Let's call it SBX - Scale-Bias Transform. I propose following structure:

struct ScaleBiasXform
{
    static const ScaleBiasXform IDENTITY;
    vec2 Scale;
    vec2 Bias;
};

And following functions:

void Construct(ScaleBiasXform& out,
    const vec2& input1, const vec2& output1,
    const vec2& input2, const vec2& output2);
void Scaling(ScaleBiasXform& out, float scale);
void Scaling(ScaleBiasXform& out, const vec2& scale);
void Translation(ScaleBiasXform& out, const vec2& vec);
void Inverse(ScaleBiasXform& out, const ScaleBiasXform& sbx);
void Combine(ScaleBiasXform& out, const ScaleBiasXform& sbx1, const ScaleBiasXform& sbx2);
void TransformPoint(vec2& out, const vec2& point, const ScaleBiasXform& sbx);
void UntransformPoint(vec2& out, const vec2& point, const ScaleBiasXform& sbx);
void TransformVector(vec2& out, const vec2& vec, const ScaleBiasXform& sbx);
void UntransformVector(vec2& out, const vec2& vec, const ScaleBiasXform& sbx);

Full source code with additional comments and function bodies is here: ScaleBiasTransform.hpp, ScaleBiasTransform.cpp. Some additional notes:

Comments | #math Share

# Mesh of Box

Mon
21
Jan 2013

Too many times I had to come up with triangle mesh of a box to hardcode it in my program, written just from memory or with help of a sheet of paper. It's easy to make a mistake and have a box with one face missing or something like that. So in case me or somebody in the future will need it, here it is. Parameters:

Box spanning from (-1, -1, -1) to (+1, +1, +1). Contains 3D positions and normals. Topology is triangle strip, using strip-cut index. Backface culling can be used, front faces are clockwise (using Direct3D coordinate system).

// H file

struct SVertex {
    vec3 Position;
    vec3 Normal;
};

const size_t BOX_VERTEX_COUNT = 6 * 4;
const size_t BOX_INDEX_COUNT  = 6 * 5;
extern const SVertex BOX_VERTICES[];
extern const uint16_t BOX_INDICES[];

// CPP file

const SVertex BOX_VERTICES[] = {
    // -X
    { vec3(-1.f, -1.f,  1.f), vec3(-1.f,  0.f,  0.f) },
    { vec3(-1.f,  1.f,  1.f), vec3(-1.f,  0.f,  0.f) },
    { vec3(-1.f, -1.f, -1.f), vec3(-1.f,  0.f,  0.f) },
    { vec3(-1.f,  1.f, -1.f), vec3(-1.f,  0.f,  0.f) },
    // -Z
    { vec3(-1.f, -1.f, -1.f), vec3( 0.f,  0.f, -1.f) },
    { vec3(-1.f,  1.f, -1.f), vec3( 0.f,  0.f, -1.f) },
    { vec3( 1.f, -1.f, -1.f), vec3( 0.f,  0.f, -1.f) },
    { vec3( 1.f,  1.f, -1.f), vec3( 0.f,  0.f, -1.f) },
    // +X
    { vec3( 1.f, -1.f, -1.f), vec3( 1.f,  0.f,  0.f) },
    { vec3( 1.f,  1.f, -1.f), vec3( 1.f,  0.f,  0.f) },
    { vec3( 1.f, -1.f,  1.f), vec3( 1.f,  0.f,  0.f) },
    { vec3( 1.f,  1.f,  1.f), vec3( 1.f,  0.f,  0.f) },
    // +Z
    { vec3( 1.f, -1.f,  1.f), vec3( 0.f,  0.f,  1.f) },
    { vec3( 1.f,  1.f,  1.f), vec3( 0.f,  0.f,  1.f) },
    { vec3(-1.f, -1.f,  1.f), vec3( 0.f,  0.f,  1.f) },
    { vec3(-1.f,  1.f,  1.f), vec3( 0.f,  0.f,  1.f) },
    // -Y
    { vec3(-1.f, -1.f,  1.f), vec3( 0.f, -1.f,  0.f) },
    { vec3(-1.f, -1.f, -1.f), vec3( 0.f, -1.f,  0.f) },
    { vec3( 1.f, -1.f,  1.f), vec3( 0.f, -1.f,  0.f) },
    { vec3( 1.f, -1.f, -1.f), vec3( 0.f, -1.f,  0.f) },
    // +Y
    { vec3(-1.f,  1.f, -1.f), vec3( 0.f,  1.f,  0.f) },
    { vec3(-1.f,  1.f,  1.f), vec3( 0.f,  1.f,  0.f) },
    { vec3( 1.f,  1.f, -1.f), vec3( 0.f,  1.f,  0.f) },
    { vec3( 1.f,  1.f,  1.f), vec3( 0.f,  1.f,  0.f) },
};

const uint16_t BOX_INDICES[] = {
     0,  1,  2,  3, 0xFFFF, // -X
     4,  5,  6,  7, 0xFFFF, // -Z
     8,  9, 10, 11, 0xFFFF, // +X
    12, 13, 14, 15, 0xFFFF, // +Z
    16, 17, 18, 19, 0xFFFF, // -Y
    20, 21, 22, 23, 0xFFFF, // +Y
};

Comments | #rendering Share

# How to Flip Triangles in Triangle Mesh

Sat
19
Jan 2013

Given triangle mesh, as we use it in real-time rendering of 3D graphics, we say that each triangle have two sides, depending on whether its vertices are oriented clockwise or counterclockwise from particular point of view. In Direct3D, by default, triangles oriented clockwise are considered front-facing and they are visible, while triangles oriented counterclockwise are invisible because they are discarded by the API feature called backface culling.

When we have backface culling enabled and we convert mesh between coordinate systems, we sometimes need to "flip triangles". When vertices of each triangle are separate, an algorithm for this is easy. We just need to swap first with third vertex of each triangle (or any other two vertices). So we can start implementing the flipping method like this:

class CMesh
{
    ...
    D3D11_PRIMITIVE_TOPOLOGY m_Topology;
    bool m_HasIndices;
    std::vector<SVertex> m_Vertices;
    std::vector<uint32_t> m_Indices;
};

void CMesh::FlipTriangles()
{
    if(m_Topology == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
    {
        if(m_HasIndices)
            FlipTriangleListInArray<uint32_t>(m_Indices);
        else
            FlipTriangleListInArray<SVertex>(m_Vertices);
    }
    ...
}

Where the function template for flipping triangles in a vector is:

template<typename T>
void CMesh::FlipTriangleListInArray(std::vector<T>& values)
{
    for(size_t i = 0, count = values.size(); i < count - 2; i += 3)
        std::swap(values[i], values[i + 2]);
}

Simple reversing all elements in the vector with std::reverse would also do the job. But things get complicated when we consider triangle strip topology. (I assume here that you know how graphics API-s generate orientation of triangles in a triangle strip.) Reversing vertices works, but only when number of vertices in the strip is odd. When it's even, triangles stay oriented in the same way.

I asked question about this on forum.warsztat.gd (in Polish). User albiero proposed following solution: just duplicate first vertex. It will generate additional degenerate (invisible) triangle, but thanks to this all following triangles will be flipped. It seems to work!

I also wanted to handle strip-cut index (a special value -1 which starts new triangle strip), so the rest of my fully-featured algorithm for triangle flipping is:

    ...
    else if(m_Topology == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP)
    {
        if(m_HasIndices)
        {
            size_t begIndex = 0;
            while(begIndex < m_Indices.size())
            {
                const size_t indexCount = m_Indices.size();
                while(begIndex < indexCount && m_Indices[begIndex] == UINT_MAX)
                    ++begIndex;
                if(begIndex == indexCount)
                    break;
                size_t endIndex = begIndex + 1;
                while(endIndex < indexCount && m_Indices[endIndex] != UINT_MAX)
                    ++endIndex;
                // m_Indices.size() can change here!
                FlipTriangleStripInArray<uint32_t>(m_Indices, begIndex, endIndex);
                begIndex = endIndex + 1;
            }
        }
        else
            FlipTriangleStripInArray<SVertex>(m_Vertices, 0, m_Vertices.size());
    }
}

Where function template for flipping triangles in selected part of a vector is:

template<typename T>
void CMesh::FlipTriangleStripInArray(std::vector<T>& values, size_t begIndex, size_t endIndex)
{
    const size_t count = endIndex - begIndex;
    if(count < 3) return;
    // Number of elements (and triangles) is odd: Reverse elements.
    if(count % 2)
        std::reverse(values.begin() + begIndex, values.begin() + endIndex);
    // Number of elements (and triangles) is even: Repeat first element.
    else
        values.insert(values.begin() + begIndex, values[begIndex]);
}

Comments | #directx #rendering #algorithms Share

# DirectX 11 Renderer - a Screenshot

Wed
16
Jan 2013

Here is what I've been working on in my free time recently. It's a renderer For PC, Windows, using DirectX 11.

It may not look spectacular here because I've just quickly put random stuff into this scene, but I already have lots of code that can do useful things, like deferred shading with dynamic directional and point lights, a bunch of material parameters, mesh processing and loading from OBJ file format, heightmap generation, particle effects and postprocessing (including bloom of course :)

In the next posts I will describe some pieces of my technology and share some C++ code.

Comments | #rendering #productions #directx Share

# Zootool - My Favourite Bookmarking Service

Fri
21
Dec 2012

I gather and share stuff in many different ways. I post short messages on Twitter, write longer posts on this blog, publish even longer articles as Publications, upload photos to Picasaweb and videos to YouTube. But there is another category of things I like to (mostly) collect, search, access from any place and (maybe also) share - bookmarks to interesting Internet addresses, whether whole websites or specific articles.

Years ago I used TXT files for that purpose. I still use them a lot, but for bookmarking I switched to Delicious some time ago. Then the company was bought by Yahoo and the page started working slower and slower, I don't remember what else but somehow I decided to look for another social bookmarking service. That's how I found Zootool - the service I now use and recommend.

It works like this: First you create your profile. You can set your avatar and fill information about yourself. Then you start bookmarking stuff. You can do it via web interface, but they recommend installing a plugin, available for Safari, Chrome and Firefox, which allows adding bookmark to your "Zoo" as you visit some webpage. You can then open "My Zoo" to see, search and edit your bookmarks using nice, asynchronous interface (AJAX-based - does not reload entire page on every click).

When it comes to features, it's quite standard. Every bookmark has a title, description, URL and tags. Bookmarks can also be made private - invisible on your public profile. The service also offers export, import and JSON API. The company makes money from selling Pro Membership. I wish them many customers and lots of money, but for me the features of free account are sufficient. The only thing I don't like about this whole service is that they generate and show a big screenshot of every bookmark on someone's profile, even in RSS channel and there is no way to switch to more compact list. Anyway, here is my profile on Zootool and I also recommend this service for everyone of you who collect bookmarks to interesting places on the Web.

reg @ Zootool

Update 2012-01-15: After reading comment from Hern (thanks!), I switched to Pinboard. That's another bookmarking service and will now be my favourite. It's not free - registration costs 9.99 USD and the web interface doesn't look very attractive, but otherwise it has all the features I aforementioned plus some more, like marking bookmark as "Unread" to be able to show a "TODO" list of pages to read in my free time, which I implemented before using "foo" tag :) So now I'm reg @ Pinboard (RSS).

Comments | #web Share

# Particle System - How to Store Particle Age?

Wed
12
Dec 2012

Particle effects are nice because they are simple and look interesting. Besides, coding it is fun. So I code it again :) Particle systems can have state (when parameters of each particle are calculated based on previous values and time step) or stateless (when parameters are always recalculated from scratch using fixed function and current time). My current particle system has the state.

Today a question came to my mind about how to store age of a particle to delete it after some expiration time, determined by the emitter and also unique for each particle. First, let's think for a moment about the operations we need to perform on this data. We need to: 1. increment age by time step 2. check if particle expired and should be deleted.

If that was all, the solution would be simple. It would be enough to store just one number, let's call it TimeLeft. Assigned to the particle life duration at the beginning, it would be:

Step with dt: TimeLeft = TimeLeft - dt
Delete if: TimeLeft <= 0

But what if we additionally want to determine the progress of the particle lifetime, e.g. to interpolate its color of other parameters depending on it? The progress can be expressed in seconds (or whatever time unit we use) or in percent (0..1). My first idea was to simply store two numbers, expressed in seconds: Age and MaxAge. Age would be initialized to 0 and MaxAge to particle lifetime duration. Then:

Step with dt: Age = Age + dt
Delete if: Age > MaxAge
Progress: Age
Percent progress: Age / MaxAge

Looks OK, but it involves costly division. So I came up with an idea of pre-dividing everything here by MaxAge, thus defining new parameters: AgeNorm = Age / MaxAge (which goes from 0 to 1 during particle lifetime) and AgeIncrement = 1 / MaxAge. Then it gives:

Step with dt: AgeNorm = AgeNorm + dt * AgeIncrement
Delete if: AgeNorm > 1
Progress: Age / AgeIncrement
Percent progress: AgeNorm

This needs additional multiplication during time step and division when we want to determine progress in seconds. But as I consider progress in percent more useful than the absolute progress value in seconds, that's my solution of choice for now.

Comments | #math #rendering Share

# Silly Venture 2012 - My Photos

Sun
09
Dec 2012

7-9 Dec 2012 in Gdańsk, Poland, another interesting event took place - Silly Venture 2012 - Atari demoscene party. Here are my photos:


Silly Venture 2012 @ PicasaWeb

Although I'm not a fan of Atari platform, as I'm too young to remember the time when it was commonly used (my first computer was 286 PC), I like this kind of events because of nice people I can meet there and the "demoscene spirit" that can there be felt.

I must also admit that the Atari demoscene looks very strong. They have several parties in Poland every year (Głuchołazy, Grzybsoniada, Silly Venture, ...) and lots of productions submitted to many different categories in the competition. This party was international - there were people from Finland, Czech Republic and other countries and all the official announcements, as well as intro videos were in two languages - Polish and English.

The party was very well organized, especially comparing to RiverWash or WeCan multiplatform demoparty. It was in a school where lots of chairs and tables available allowed to bring, setup and present many computers, a classroom was adapted as sleeping room, we were given paper voting forms so we could enter our votes as we watched the productions, we had unlimited beer, limousine ride and other atractions - all included in the ticket fee... So, thanks a lot and see you next year!

Comments | #gallery #atari #demoscene #events Share

Pages: > 1 ... 33 34 35 36 37 ... 150 >

[Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2026