06/7/12

Lightning!

It’s been a busy month, and I haven’t spent as much time coding as I would like. I did get beam noise particle stuff working, though. Here’s a picture!

lightning particles. I guess it's cooler looking in motion.

I also started porting some of my demos to the Visual Studio 11 beta compiler. It’s a bit depressing how few of the new features in the C++11 standard are implemented. The biggest one is variadic templates and constexpr. Variadic templates you can “fix” by making overloads that take multiple arguments.

Most of the other stuff I’m using is there, except for initialization lists. I’m using initialization lists everywhere right now, but it’s not a huge loss to switch it so it’s compatible and it’s mostly syntax fluff anyways. The only problem I’ve run into with them is that I was using global std::vectors that I was initializing with something like:

std::vector<SomethingThatTakesArguments> g_globalThingy = {
 { ENUM_Arg1, "arg1" },
 { ENUM_Arg2, "arg2" },
};

And I can’t do that anymore. Which doesn’t matter that much for me, as there’s no reason I can’t just use normal arrays.

In any case, my particle prototype thingy is nearly done. I kind of want to start something new now, so I’ll probably leave it in its prototype state until I feel like revisiting it. I got sidetracked a lot while making it, so now I have new serialization code (again), some updated parsing stuff, memory tags for my allocations… and more, I actually sort of forget, but it got out of hand. Most of the changes were good, though!

05/14/12

particle system (work in progress)

I’m working on a “programmable” particle system project. It’s programmable in the sense that you can specify how they are updated fairly freely, depending mostly on what commands are available. I’m not sure if I’ll get around to making a text-based parser for the particles, as right now I’m hard coding the streams. The stream for some ‘sparks’ might look something like:

  1. OP_Spawn (SpawnBufferId=0, Rate=100.f)
  2. OP_InitOBB (OBB=….)
  3. OP_InitSize (Size=3.f)
  4. OP_InitColor (Color={1.f,0.8f,0.8f.1.f})
  5. OP_FinalizeInit
  6. OP_ForceField (Force={0, 0, -100.f})
  7. OP_AttractPoint(Point={0,0,20}, Radius={some curve}, Magnitude={some curve})
  8. OP_SizeAge(Size={some curve}, TimeMultiplier=1.f)
  9. OP_ColorAge(Color={some curve}, TimeMultiplier=1.f)
  10. OP_KillAge(Age=1.f)

This would create particles at a rapid rate, the particles would begin to fall and then gravitate towards a nearby point, while slowly getting larger and more ‘red’ and translucent, before dying after a second of life.

Each particle system has a set of emitters, and each emitter has particle instance data. Particle emitter definitions contain a static command stream that specifies how the emitter instance is initialized and updated. Some commands only work with certain particle emitter types (applying a force to beam particles doesn’t necessarily make sense).

The system uses several fixed sized pool allocators as well as some static data to keep allocations constrained. The obvious downside is that the system allocates memory and can leave some of it unused. Right now I have it capped so it will never use more memory than I have set, but it could be easily changed so that the pool blocks are allocated as needed. Allocation works roughly like so:

  • Given a ‘particle system definition’, allocate a particle system class (using a pool allocator).
  • Depending on the number of emitters in the system, allocate some instance data from a set of graded pools (64bytes, 512bytes, 2048bytes, and 16k I think. The 64 & 512byte pools are meant for this purpose.). This used to contain an array of emitter ids (instead of an std::vector or similar).
  • Allocate an emitter (using a pool allocator).
  • Calculate size of the emitter’s instance data (sim data such as position and velocity, any data used by the command streams, and attach points), and allocate from the graded pools listed above.
  • Run the init stream to initialize any command stream buffers.

The particle system manager allocates a fixed sized vertex and index buffer as well. These buffer objects are write-only and have a dynamic-draw usage in GL. When rendering, these are mapped using glMapBuffer() and written to using a class that wraps writing to memory buffers.

// somewhere way before...
vertBuffer.Map();

...

MemWriter writer;
size_t vbOffset;
std::tie(writer, vbOffset) = vertBuffer.Reserve(kBillboardVtxStride * numAlive);
if(writer) {
    ...
    // write to buffer using writer.PutVec3() and writer.Put<>().
    ...
}

...

vertBuffer.Unmap();

A header block is added to a linked list in the frame data (again allocated from a special bit of memory – frame data is cleared every frame, but can be allocated as needed in the current update). The header block contains the offsets in the vertex buffer, texture to use, and type of particle to be rendered, to be used later by the frame renderer.

Some issues that I’ve run into that I don’t quite know how to resolve yet are:

  • Alpha sorting different emitters. You can sort the particles within an emitter easily enough, but if you have several different emitters, it’s not necessarily clear how to sort them, and sorting them on a per-particle basis seems silly.
  • Particle shadows – I’m having trouble thinking of a way to do this cheaply.
  • Beam particles (like lightning) are composed of several rotated sheets. They look best when using an additive blend (glBlendFunc(GL_SRC_ALPHA, GL_ONE)), but the brightness depends on the number of sheets used. I suppose I could multiply each sheet by some weight so that the combined weight is correct, but I think part of the reason it ends up looking good is because the colors are saturating in places that would have artifacts. I’m not sure what the “right” way of doing this is.
  • Collisions: my sprite & billboard particles have optional collisions, and currently I’m using line segment tests to test this. This is fine, visually, until particles become slow and are supposed to rest on a surface, then they leak through the geometry. I think I’d prefer to do some kind of moving sphere intersection, and perhaps mark particles that are resting, but for now all I have implemented is ray & line segment tests.

It is surprisingly hard to google for common ways to do particle system stuff – usually I just end up with how to do something in Unity or UDK, which isn’t particularly helpful. I’d like to know if what I’m doing is crazy or not. So, there may be better ways to do all of this! As a side project, it’s taking a bit longer than I wanted it to, and it’s nearly time to stop working on it despite it not being super polished. The extra time is partially due to me wanting to keep memory allocation constant and trying to share the same code path for all particle types. I went through a couple of rewrites before settling on something that seems to work. In any case, I’ll probably be posting whatever code I end up with in the next week or two.

04/11/12

Project page is up!

I’ve populated my projects page! Each project has a link to source and a video or two. I wrote as much of a description as I could remember for each.

These projects are a way for me to explore some stuff I probably wouldn’t get to do in many settings (like C++11 features). Sometimes this results in some weird code as I’m figuring things out. An example is my use of std::shared_ptrs. While they are awesome and I will continue to use them, I went overboard with my interfaces in some places and required heap objects where I shouldn’t have, like simple wrappers around GL objects. I’m fixing this in newer projects. One weird thing about using shared_ptr  is that you have to be careful about where you pass shared_ptrs and where you pass raw pointers, and it’s annoying to fix it all if you change your mind. Another example of ‘bad code while figuring things out’ is most of the design of the motion graph editor project. In my defense, I wrote the majority of that in about 2 weeks while completely overdosed on caffeine.

The newer demos actually started out in C, and later I switched back to C++. This happens cyclically, and  usually starts because I’m thinking, “I know C! C is manly!” and then I get bored of rewriting data structures and using linked lists for everything. Suddenly I remember how nice it is to have constructors and destructors and templates and my god it saves so much time. When I switched I switched *hard*, and went way into the other side of C++ into C++11 land. I’m sure the C sickness will return one day, though.

 

04/11/12

Hello, world!

So I have a new blog again. I would have transferred all of my posts from my jigsy page, but I seem to have lost all of the ones that actually matter. So, I’ll be starting over again and abandoning the jigsy blog, further littering the interwebs with the wreckage of my old websites. I’ll do it right this time, I swear.

Continue reading