Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

carangil

Member Since 26 May 2004
Offline Last Active May 07 2013 06:01 PM
-----

Topics I've Started

C99: strict aliasing rule vs compatible pointers

06 April 2013 - 02:28 PM

I'm cleaning up some of my code by compiling with gcc -Wall and -Wstrict-aliasing=1 to look for unclean things I've done.

 

 

This is a fairly common pattern in my C code:

 

typedef struct generic_list_s
{
	int type;
	struct generic_list_s* next;
} generic_list_t;

typedef struct
{
	generic_list_t gen;
	char* str;
} string_t;

typedef struct 
{
	generic_list_t gen;
	int x;
} int_t;

 

The general idea is I have some generic structure that I reuse as the 1st element of larger, more specific structures.  The C standard allows you to cast a pointer back and forth between a struct, and it's 1st member.  A pointer to an int_t or a string_t in the above examples is also a pointer to a generic_list_t.

 

GCC however likes to complain.  If I compile a snippet like this:

	string_t* node0;
	int_t* node1;
	string_t* node2;
		
	node0 = mk_string("Hello");
	node1 = mk_int(123);
	node2 = mk_string("World");

	/* Below seems correct
	  node1 is a pointer to an int_t
	  int_t starts with generic_list_t, so
	  a pointer to int_t is also a pointer to int_t
	  (6.7.2.1.13 says )
	  */
	node0->gen.next = (generic_list_t*) node1;
	node1->gen.next = (generic_list_t*) node2;

with -Wstring-aliasing =1, I get this warning:

 

warning: dereferencing type-punned pointer might break strict-aliasing rules

 

This makes sense, in that node1 is a pointer to an int_t, and node0->gen.next is technically a pointer to a generic_list_t.  I have two different types of pointers pointing to the same thing.  I can make it go away by doing this:

 

node0->gen.next = &(node1->gen);
node1->gen.next = &(node2->gen);

 

Which is more correct, although a pointer to the first element of a struct or a pointer to the struct are supposed to be compatible with each other.

 

The real problem comes with functions like:

 

void print_thing(generic_list_t* n)
{
	if (n->type == TYPE_STRING)
	{
		string_t* s = (string_t*) n;/* warning: dereferencing type-punned pointer might break strict-aliasing rules*/
		printf("%s\n", s->str);
	}

	if (n->type == TYPE_INT)
	{
		int_t* i = (int_t*) n;  /* warning: dereferencing type-punned pointer might break strict-aliasing rules*/
		printf("%d\n", i->x);
	}


}

 Hoe do I clean up these warnings? 


Help me unify camera and object matrices

16 March 2013 - 12:51 PM

Let me explain.  Opengl defines the X+ as to the right, Y+ as up, and Z- into the screen.  I've gotten used to this coordinate system, and it's easy to think in.  Except I have 1 issue with it, I've gotten myself stuck with 2 definitions of rotation matrices in my code, and I'm trying to unify them.

I don't have a problem with translation, so for now let's only consider the 3x3 rotation section of the matrix.

Suppose I want to draw an object, unrotated.  The 3x3 rotation matrix is just identity:

1 0 0
0 1 0
0 0 1

I also represent the camera's current rotation as a matrix.  I form the camera matrix out of the 'look', 'up', and 'right' vectors.  Except, the unrotated camera looks into -z, so the unrotated camera matrix is:

1 0 0         //right (+X)
0 1 0         //up  (+Y)
0 0 -1        //look (+Z)

I have a few dumb negative signs in my code so that when I'm applying a camera matrix, the above matrix acts like identity.  But I want to unify everything, I want applying a matrix to just be applying a matrix.  So I have a few options:

1. Switch to right handed:  if +Z went into the screen, an unrotated camera, and an unrotated object would have the same identity matrix.

2. Don't form a camera matrix with up, left right (edit: brain fog/typo), and look vectors.  Instead use up, left, and 'ass' vectors.  Then the problem goes away, but I need to negate the backwards vector to get which way a camera is looking.

3. Something else?

How does everyone else solve or avoid this problem?

Thanks.
 


which cpu to model in VM interpreter?

11 January 2013 - 06:23 PM

Suppose I'm writing my own virtual machine interpreter, and I want to target it with a 'real' language like C.  I could retarget the backend of gcc, but I hear that work is horrendous.  What I would rather do is abuse GCC already written for another processor.  Back in school, we had a stripped-down gcc that output to a subset of MIPS, and we had to write a MIPs emulator, so it would be similar to that, just much more feature-rich. 

 

I suppose this more of a question for those who have written a lot of assembly language:  What CPU do you think is most ideally suited for writing an interpreter?  Keep in mind that I don't necessarily need to run a modern style OS on the VM, and the memory architecture can be simple.  I'm even considering subsets of certain processors.  For instance, a 386 in real mode has 32-bit registers, floating point support (387), and there's a trick to address 4gb flat from real mode (called unreal mode.)  If my interpreter only acted as a 386 in 'unreal mode', that would be fine by me.  But x87 opcodes are complex... I want a simpler processor.

 

Why do I want to do this?  For fun.  Several years ago, I wrote a little VM and my own language and gave it bindings to a C library I wrote that did basic graphics.  The vm would call functions like, load this image file, draw is image here, etc, and the C library did all the grunt work.  I kind of want to do the same thing again, but with OpenGL 3d graphics.  I could invent a new pet language again, and I might, but if I could get plain C compiling to vm bytecode that would be great.  Some of the optimizations gcc does (loop unrolling, moving constants out of loops etc) would benefit bytecode programs probably quite a bit.

 

And before someone lists it as an x86 interpreter, I am considering just adding opengl calls to dosbox.  If I reserve certain addresses for communication to the outside of the VM, there wouldn't be anything stopping me from writing 3d accelerated apps in qbasic or turbo c!


what is wrong with ssd manufacturers?

07 January 2013 - 07:08 PM

This is a little bit of a rant, but I also sort of want a serious answer:

 

I'm looking into getting an SSD system drive for my PC, but there seems to be a constant issue with firmware issues and bluescreens.  What I want to know, is what is wrong with the manufacturers?  I've never had to update the firmware on a mechanical drive.  Modern mech drives have complex firmware, remapping bad blocks, etc, but I've never heard of a particular model of hard drive being so crappy that it just craps out to blue screens every few hours.  It would never pass Seagate, WD, etc. testing labs.  Also, flash cards like SDHC camera cards, compact flash, etc often have built-in wear leveling and error correction.  And I've never had to update the firmware on an SD card.  And, I shouldn't have to install any weird utilities or drivers at the OS to make it work properly either.  Sure, turn on TRIM in the filesystem driver.  That should be it.  Apart from that, the drive should just look like a plain old mechanical drive on SATA to the OS, just one that's super fast.

 

What is going on? Do the programmers for SSD firmware just suck?


random midpoint displacement self-intersection problem

16 November 2012 - 04:30 PM

I'm having trouble with detecting self-intersecting geometry. Sorry for the long prelude to the problem, but there's a lot of points to get through before I get to the actual problem.

I have a very simple procedurally-generated planet renderer:
  • Each patch of terrain is a quad patch at a fixed tesselation level (such as 33x33 vertices).
  • Patches are arranged in a quadtree; when the average size of a quad in a patch takes up too many pixels, the patch is split into 4 smaller patches; likewise when polygons get too small, a patch and it's siblings are removed and the parent node is put back into the renderlist.
  • The root-level of the quadtree is simply a 6-faced cube, each face is one of these patches that has been deformed to fit on a sphere
  • Yes, at the root-level the points are not evenly distributed; a common problem when squishing a cube into a sphere. but as you get closer, certain areas will split before others, and it's not long before things even out. I don't really care that things are a little uneven when zoomed out; its much less annoying than dealing with polar coordinates!

This is what works:
  • Plain sphere: When it's time to split a patch, I generate a more-detailed patch. In the simple case of a sphere with no added detail, I compute the points on the sphere exactly for the new patches. This works fine, I get a perfect sphere I can zoom into all I want.
  • Bilinear filtering: Instead of computing the points from the sphere, I cut the patch into 4 subpatches (so 33x33 becomes 4x (17x17), and then I up-scale the 17x17 patches to 33x33 be linearly interpolating the in-between vertices.). This works fine when detailing the sphere; the sphere does not become smooth (because it started as a polygonal model), but it does result in becoming more tesselated.
  • Bilinear filtering with random detail: Same as above, I add a random bit of vertical (relative to the center of the sphere) displacement to the interpolated vertices. This results in rocky terrain the gets more and more detailed as you get closer to it. This is what I want. Each successive generation, I pass down a lower 'detail scale' value, so that the smaller I get, the smaller the random displacement details are. So each generation, I divide the detail height value by 2. This seems to scale properly. I don't have any problems with this.
This is what does not work, and this is where I have a problem:

The problem with #3 above, is that the terrain is little more than a heightfield. It can become more detailed, but each point on the sphere has no other points above it. It's kind of 'standard.' I wanted to go a step further than what all the other terrain generators do. So, instead of displacing a random height in the direction away from the center of the sphere, I displace along the point's normal vector. The result is more realistic; sometimes detail will cut into the side of a cliff. It gives the surface some undercuts. Sometimes the undercuts have undercuts. If you move the camera into these undercut areas, some places are almost like mini-caves. For the most part, it looks pretty cool.

The problem I am having, is now that I have given the surface this 'extra' degree of freedom it never had before, there are some areas where the terrain will intersect itself. In the case of a cave-like area, its fine, I dont care, the ceiling is touching the floor or something; it's a place where the player can't go past. The barrier doesn't look bad. But it leads to weirdness at the tops of mountains where instead of coming to a point, imagine there's a column and both sides are undercutting into it enough that they sort of pinch past each other, leaving the top part of the column connected to the the bottom by an infinitely thin piece of rock; something completely impossible. Is there any way to prevent, hide or mitigate this?

I can post images later tonight probably.

PARTNERS