Array member by index

Don’t think I got round to posting what glX is

#ifdef _DEBUG
#define glX( UD, CALL ) \
	{ \
		glClearErrors(); \
		CALL; \
		glHadNoErrors( UD, __FILE__, __LINE__, #CALL ); \
	}
#else
#define glX( UD, CALL ) CALL
#endif

And the definitions:

void glClearErrors()
{
	while ( glGetError() );
}
bool glHadNoErrors
(
	void *ud,
	char const * const file,
	uint line,
	char const * const call
)
{
	int fault = glGetError();

	if ( fault )
	{
		print___x( errout, file, line, glReportToString(fault) );
		fprintf( errout, " %s\n", call );
		return false;
	}

	return true;
}
void GLAPIENTRY glDebugMsgCB
(
	GLenum source
	, GLenum report
	, GLuint id
	, GLenum weight
	, GLsizei length
	, const GLchar *msg
	, const void *ud
)
{
	fprintf
	(
		stderr
		, "%s (%u) source %s, weight, %s:\n\n%s\n"
		, glReportToString( report )
		, id
		, glSourceToString( source )
		, glWeightToString( weight )
		, msg
	);
}

Finally got somewhere, not what I expected but it still progress, only the draw calls have changed so I’ll post just the refresh function:

void glfwRefreshCB( GLFWwindow *window )
{
	BUFF *SpotIndexBuffers = core.SpotIndexBuffers;
	LIST *Trigons = &(core.Trigons);
	TRIGON *trigons = get_list_addr(Trigons);

	for ( uint trigon = 0; trigon < get_list_used(Trigons); ++trigon )
	{
		if ( list_is_taken( Trigons, trigon, -1 ) )
			continue;
		add_trigon_to_index_buffers( &core, trigons + trigon );
	}

	// Clear the screen
	glX( NULL, glUseProgram( core.Proc->ID ));
	glX( NULL, glClearColor( 0, 0, 0, 0 ));
	glX( NULL, glClear( GL_COLOR_BUFFER_BIT ));

	glX( NULL, glBindVertexArray( core.FloatsArrayID ) );

	glX( NULL, glInvalidateBufferData( core.FloatsBufferID ));
	glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.FloatsBufferID ) );
	glX( NULL, glBufferData
	(
		GL_ARRAY_BUFFER,
		core.Floats.size,
		core.Floats.addr,
		GL_STATIC_DRAW
	) );
	glX( NULL, glVertexArrayElementBuffer( core.FloatsArrayID, core.FloatsBufferID ));

	for ( uint attr = 0; attr < SPOT_COUNT; ++attr )
	{
		BUFF *Indices = SpotIndexBuffers + attr;
		uint values;
		uint bufferId = core.SpotIDs[attr];
		uint location = core.SpotAttribLocations[attr];

		if ( attr != SPOT_PLACE && attr != SPOT_COLOR )
			continue;

		glX( NULL, glEnableVertexAttribArray( location ));

		if ( attr == SPOT_COLOR )
			values = 4;
		else if ( attr == SPOT_COORD )
			values = 2;
		else
			values = 3;

		glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, core.FloatsBufferID ) );
#if 0
		glX( NULL, glVertexAttribFormat
		(
			location,
			values,
			GL_FLOAT,
			GL_FALSE,
			0
		));
#else
		glX( NULL, glVertexAttribPointer
		(
			location,
			values,
			GL_FLOAT,
			GL_FALSE,
			values * sizeof(float),
			NULL
		));
#endif
		glX( NULL, glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, bufferId ) );
		glX( NULL, glBufferData
		(
			GL_ELEMENT_ARRAY_BUFFER,
			SpotIndexBuffers->used * sizeof(uint),
			Indices->addr,
			GL_DYNAMIC_DRAW
		));
		//glX( NULL, glVertexAttribBinding( core.FloatsBufferID, 0 ));
	}

	glX( NULL, glBindVertexArray( core.FloatsArrayID ) );
	//glX( NULL, glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL ) );
	glX( NULL, glDrawArrays( GL_TRIANGLES, 6, GL_FLOAT ) );
	for ( uint attr = 0; attr < SPOT_COUNT; ++attr )
	{
		if ( attr != SPOT_PLACE && attr != SPOT_COLOR )
			continue;

		glX( NULL, glDisableVertexAttribArray( core.SpotAttribLocations[attr] ));
	}
	glfwSwapBuffers(window);
	set_index_buffers_count( &core, 0 );
}

I’ve been looking at this thread trying to get anything on screen

Just made a screen shot, gonna crop it a bit then post it along with the vertices I gave, in the mean time tell me if you see any improper gl related calls

And the vertices:

/* Add triangles */
trigon1 = add_trigon( &core );
trigon2 = add_trigon( &core );
Trigons = &(core.Trigons);
trigons = get_list_addr(Trigons);
Trigon1 = trigons + trigon1;
Trigon2 = trigons + trigon2;
Trigons->Buff.used = 2;

/* Add default vertex information */
if
(
	find_trio( &core, Trio.raw ) == (uint)-1
	|| find_quad( &core, Quad.raw ) == (uint)-1
)
{
	print___x( errout, __FILE__, __LINE__, "[FATAL ERROR]" );
	fprintf( errout, "%s\n", "Couldn't add default floats" );
	empty_core( &core );
	return EXIT_FAILURE;
}

Quad.w =  1.0;
/* Add our triangles, we don't check for success here because the memory
 * has already been allocated above */
Trio.x =  0.25;
Trio.y =  0.25;
Quad.z =  1.0;
Quad.y =  0.75;
Trigon1->a[SPOT_PLACE] = find_trio( &core, Trio.raw );
Trigon1->a[SPOT_COLOR] = find_quad( &core, Quad.raw );

Trio.x = -0.25;
Trio.y =  0.25;
Quad.z =  1.0;
Quad.y =  0.5;
Trigon1->b[SPOT_PLACE] = find_trio( &core, Trio.raw );
Trigon1->b[SPOT_COLOR] = find_quad( &core, Quad.raw );

Trio.x =  0.0;
Trio.y =  0.5;
Quad.z =  1.0;
Quad.y =  0.25;
Trigon1->c[SPOT_PLACE] = find_trio( &core, Trio.raw );
Trigon1->c[SPOT_COLOR] = find_quad( &core, Quad.raw );

Trio.x =  0.25;
Trio.y = -0.25;
Quad.z =  0.75;
Quad.y =  1.0;
Trigon2->a[SPOT_PLACE] = find_trio( &core, Trio.raw );
Trigon2->a[SPOT_COLOR] = find_quad( &core, Quad.raw );

Trio.x = -0.25;
Trio.y = -0.25;
Quad.z =  0.5;
Quad.y =  1.0;
Trigon2->b[SPOT_PLACE] = find_trio( &core, Trio.raw );
Trigon2->b[SPOT_COLOR] = find_quad( &core, Quad.raw );

Trio.x =  0.0;
Trio.y = -0.5;
Quad.z =  0.25;
Quad.y =  1.0;
Trigon2->c[SPOT_PLACE] = find_trio( &core, Trio.raw );
Trigon2->c[SPOT_COLOR] = find_quad( &core, Quad.raw );

Edit: I was expecting the 2 triangles to point up and down with a gap between, I chose different colors so I could differentiate them once I start trying to move them independently of each other

Edit 2: Did a print out of the values (had an #if 0 statement beneath the above code

main.c:187: Trigon1
.a = Coord { 0.000000, 0.000000 }
.a = Color { 0.000000, 0.750000, 1.000000, 1.000000 }
.a = Place { 0.250000, 0.250000, 0.000000 }
.a = Normal { 0.000000, 0.000000, 0.000000 }
.a = Tangent { 0.000000, 0.000000, 0.000000 }
.a = BiNormal { 0.000000, 0.000000, 0.000000 }
.b = Coord { 0.000000, 0.000000 }
.b = Color { 0.000000, 0.500000, 1.000000, 1.000000 }
.b = Place { -0.250000, 0.250000, 0.000000 }
.b = Normal { 0.000000, 0.000000, 0.000000 }
.b = Tangent { 0.000000, 0.000000, 0.000000 }
.b = BiNormal { 0.000000, 0.000000, 0.000000 }
.c = Coord { 0.000000, 0.000000 }
.c = Color { 0.000000, 0.250000, 1.000000, 1.000000 }
.c = Place { 0.000000, 0.500000, 0.000000 }
.c = Normal { 0.000000, 0.000000, 0.000000 }
.c = Tangent { 0.000000, 0.000000, 0.000000 }
.c = BiNormal { 0.000000, 0.000000, 0.000000 }
main.c:189: Trigon2
.a = Coord { 0.000000, 0.000000 }
.a = Color { 0.000000, 1.000000, 0.750000, 1.000000 }
.a = Place { 0.250000, -0.250000, 0.000000 }
.a = Normal { 0.000000, 0.000000, 0.000000 }
.a = Tangent { 0.000000, 0.000000, 0.000000 }
.a = BiNormal { 0.000000, 0.000000, 0.000000 }
.b = Coord { 0.000000, 0.000000 }
.b = Color { 0.000000, 1.000000, 0.500000, 1.000000 }
.b = Place { -0.250000, -0.250000, 0.000000 }
.b = Normal { 0.000000, 0.000000, 0.000000 }
.b = Tangent { 0.000000, 0.000000, 0.000000 }
.b = BiNormal { 0.000000, 0.000000, 0.000000 }
.c = Coord { 0.000000, 0.000000 }
.c = Color { 0.000000, 1.000000, 0.250000, 1.000000 }
.c = Place { 0.000000, -0.500000, 0.000000 }
.c = Normal { 0.000000, 0.000000, 0.000000 }
.c = Tangent { 0.000000, 0.000000, 0.000000 }
.c = BiNormal { 0.000000, 0.000000, 0.000000 }

Managed to track down a clue, seems the indices I’m giving don’t appear to match up with what the card/gpu maps those indices to, I’m assuming I’ve made a mistake in the tracking or adding down of said indices. Here’s the code from the only file directly handling those indices, maybe someone here will see what I’ve yet to see:

#include "core.h"


uint have_quads( CORE *Core ) { return Core->Floats.have / 4; }
uint have_trios( CORE *Core ) { return Core->Floats.have / 3; }
uint have_pairs( CORE *Core ) { return Core->Floats.have / 2; }

uint used_quads( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	return (Floats->used / 4) + !!(Floats->used % 4);
}

uint used_trios( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	return (Floats->used / 3) + !!(Floats->used % 3);
}

uint used_pairs( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	return (Floats->used / 2) + !!(Floats->used % 2);
}

uint floats_need( uint want ) { return ((want / 12) + !!(want % 12)) * 12; }
BUFF * more_floats( CORE *Core, uint want )
{
	return buff_inc_only
	(
		&(Core->Alloc),
		&(Core->Floats),
		float,
		floats_need(want)
	);
}

BUFF * more_vec4( CORE *Core, uint want )
{
	return more_floats( Core, want * 4 );
}

BUFF * more_vec3( CORE *Core, uint want )
{
	return more_floats( Core, want * 3 );
}

BUFF * more_vec2( CORE *Core, uint want )
{
	return more_floats( Core, want * 2 );
}

uint next_quad( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	uint quad = used_quads( Core );
	uint need = floats_need( quad );

	if ( Floats->have > need )
	{
		Floats->used = need;
		return quad;
	}

	Floats = more_vec4( Core, quad + 1000 );

	if ( !Floats )
		return -1;

	Floats->used = need;
	return quad;
}

uint find_quad( CORE *Core, vec4 Quad )
{
	BUFF *Floats = &(Core->Floats);
	uint used = used_quads( Core ), vec;
	vec4 *vecs = Floats->addr;

	for ( vec = 0; vec < used; ++vec )
	{
		if ( memcmp( vecs + vec, Quad, sizeof(vec4) ) == 0 )
			return vec;
	}

	if ( Floats->have < floats_need( vec ) || next_quad( Core ) == (uint)-1 )
	{
		print___x( errout, __FILE__, __LINE__, "[WARNING]" );
		fprintf( errout, "%s\n", "Not enough quads avaialable" );
		return -1;
	}

	vecs = Floats->addr;
	memcpy( vecs + used, Quad, sizeof(vec4) );
	Floats->used = (used+1) * 4;
	return used;
}

uint next_trio( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	uint trio = used_trios( Core );
	uint need = floats_need( trio );

	if ( Floats->have > need )
	{
		Floats->used = need;
		return trio;
	}

	Floats = more_vec3( Core, trio + 1000 );

	if ( !Floats )
	{
		print___x( errout, __FILE__, __LINE__, "[WARNING]" );
		fprintf( errout, "%s\n", "Not enough memory available" );
		return -1;
	}

	Floats->used = need;
	return trio;
}

uint find_trio( CORE *Core, vec3 Trio )
{
	BUFF *Floats = &(Core->Floats);
	uint used = used_trios( Core ), vec;
	vec3 *vecs = Floats->addr;

	for ( vec = 0; vec < used; ++vec )
	{
		if ( memcmp( vecs + vec, Trio, sizeof(vec3) ) == 0 )
			return vec;
	}

	if ( Floats->have < floats_need( vec ) || next_trio( Core ) == (uint)-1 )
	{
		print___x( errout, __FILE__, __LINE__, "[WARNING]" );
		fprintf( errout, "%s\n", "Not enough trios avaialable" );
		return -1;
	}

	vecs = Floats->addr;
	memcpy( vecs + used, Trio, sizeof(vec3) );
	Floats->used = (used+1) * 3;
	return used;
}

uint next_pair( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	uint pair = used_pairs( Core );
	uint need = floats_need( pair );

	if ( Floats->have > need )
	{
		Floats->used = need;
		return pair;
	}

	Floats = more_vec2( Core, pair + 1000 );

	if ( !Floats )
		return -1;

	Floats->used = need;
	return pair;
}

uint find_pair( CORE *Core, vec2 Pair )
{
	BUFF *Floats = &(Core->Floats);
	uint used = used_pairs( Core ), vec;
	vec2 *vecs = Floats->addr;

	for ( vec = 0; vec < used; ++vec )
	{
		if ( memcmp( vecs + vec, Pair, sizeof(vec2) ) == 0 )
			return vec;
	}

	if ( Floats->have < floats_need( used ) || next_pair( Core ) == (uint)-1 )
		return -1;

	vecs = Floats->addr;
	memcpy( vecs + used, Pair, sizeof(vec2) );
	Floats->used = (used+1) * 2;
	return used;
}

I found that clue after re-ordering the adding of those floats to the main array and getting a different output

Edit: Start from the find_*() functions because that’s what’s called to add the floats to the buffer

Turned the TRIGON object into a union and simplified the construction process, also simplified the implementation of find_*(), I’ll post hose in a minute, first the simplified construction:

/* Add triangles */
int add_trigons( CORE *Core )
{
	LIST *Trigons;
	TRIGON *trigons, *Trigon1, *Trigon2;
	uint trigon1, trigon2;

	vec4s Quad = {{0.0}}, quads[3] =
	{
		{{ 0.0, 0.25, 1.0, 1.0 }},
		{{ 0.0, 0.5,  1.0, 1.0 }},
		{{ 0.0, 0.75, 1.0, 1.0 }}
	};
	vec3s Trio = {{0.0}}, trios[3] =
	{
		{{ -0.25, 0.25, 0.0 }},
		{{  0.25, 0.25, 0.0 }},
		{{  0.0,  0.5,  0.0 }}
	};

	trigon1 = add_trigon( &core );
	trigon2 = add_trigon( &core );
	Trigons = &(core.Trigons);
	trigons = get_list_addr(Trigons);
	Trigon1 = trigons + trigon1;
	Trigon2 = trigons + trigon2;
	Trigons->Buff.used = 2;

	/* Add default vertex information */
	if ( find_quad( &core, Quad.raw ) == (uint)-1 )
	{
		print___x( errout, __FILE__, __LINE__, "[FATAL ERROR]" );
		fprintf( errout, "%s\n", "Couldn't add default floats" );
		empty_core( &core );
		return EXIT_FAILURE;
	}

	for ( uint v = 0; v < 3; ++v )
	{
		Quad = quads[v];
		Trio = trios[v];

		Trigon1->raw[v][SPOT_COLOR] = find_quad( &core, Quad.raw );
		Trigon1->raw[v][SPOT_PLACE] = find_trio( &core, Trio.raw );

		Quad.y = quads[v].z;
		Quad.z = quads[v].y;
		Trio.y = -(Trio.y);

		Trigon2->raw[v][SPOT_COLOR] = find_quad( &core, Quad.raw );
		Trigon2->raw[v][SPOT_PLACE] = find_trio( &core, Trio.raw );
	}

#if 1
	print___trigon( errout, __FILE__, __LINE__, "Trigon1", &core, Trigon1 );
	fputc( '\n', errout );
	print___trigon( errout, __FILE__, __LINE__, "Trigon2", &core, Trigon2 );
#endif
	return 0;
}

Now for the find_*() implementations:

uint find_quad( CORE *Core, vec4 Quad )
{
	BUFF *Floats = &(Core->Floats);
	uint used = used_quads( Core ), have = have_quads( Core ), quad;
	vec4 *quads = Floats->addr;

	for ( quad = 0; quad < used; ++quad )
	{
		if ( memcmp( quads + quad, Quad, sizeof(vec4) ) == 0 )
			return quad;
	}

	if ( used >= have && !more_floats( Core, (used + 1000) * 4 ) )
	{
		print___x( errout, __FILE__, __LINE__, "[WARNING]" );
		fprintf( errout, "%s\n", "Not enough quads avaialable" );
		return -1;
	}

	quads = Floats->addr;
	memcpy( quads + used, Quad, sizeof(vec4) );
	Floats->used = (used+1) * 4;
	return used;
}

uint find_trio( CORE *Core, vec3 Trio )
{
	BUFF *Floats = &(Core->Floats);
	uint used = used_trios( Core ), have = have_trios( Core ), trio;
	vec3 *trios = Floats->addr;

	for ( trio = 0; trio < used; ++trio )
	{
		if ( memcmp( trios + trio, Trio, sizeof(vec3) ) == 0 )
			return trio;
	}

	if ( used >= have && !more_floats( Core, (used + 1000) * 3 ) )
	{
		print___x( errout, __FILE__, __LINE__, "[WARNING]" );
		fprintf( errout, "%s\n", "Not enough trios avaialable" );
		return -1;
	}

	trios = Floats->addr;
	memcpy( trios + used, Trio, sizeof(vec3) );
	Floats->used = (used+1) * 3;
	return used;
}

uint find_pair( CORE *Core, vec2 Pair )
{
	BUFF *Floats = &(Core->Floats);
	uint used = used_pairs( Core ), have = have_pairs( Core ), pair;
	vec2 *pairs = Floats->addr;

	for ( pair = 0; pair < used; ++pair )
	{
		if ( memcmp( pairs + pair, Pair, sizeof(vec2) ) == 0 )
			return pair;
	}

	if ( used >= have && !more_floats( Core, (used + 1000) * 2 ) )
	{
		print___x( errout, __FILE__, __LINE__, "[WARNING]" );
		fprintf( errout, "%s\n", "Not enough pairs avaialable" );
		return -1;
	}

	pairs = Floats->addr;
	memcpy( pairs + used, Pair, sizeof(vec2) );
	Floats->used = (used+1) * 4;
	return used;
}

Still not getting the expected result of 2 triangles facing opposite directions with a gap between, really appreciate any help I get here.

Changed the implementation of used_*() as well:

uint used_quads( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	uint used = Floats->used;
	uint quads = used / 4;
	while ( (quads * 4) < used ) ++quads;
	return quads;
}

uint used_trios( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	uint used = Floats->used;
	uint trios = used / 3;
	while ( (trios * 3) < used ) ++trios;
	return trios;
}

uint used_pairs( CORE *Core )
{
	BUFF *Floats = &(Core->Floats);
	uint used = Floats->used;
	uint pairs = used / 2;
	while ( (pairs * 2) < used ) ++pairs;
	return pairs;
}

Still not getting the expected output though

Finally noticed that I used glDrawArrays instead of glDrawElements, changing that resolved the orientation of the 1st triangle but there’s no sign of the 2nd triangle that has the inverted y axis

Finally found he cause of my missing triangle, I used ‘index’ instead of ‘i’ when reading the byte at the end of this function (which I’ve already corrected before making this post.

int list_is_taken( struct _LIST *List, uint index, int take )
{
	BUFF *Took = &(List->Took);
	unsigned char *took = Took->addr, b;
	uint i = index / CHAR_BIT;

	if ( Took->have <= i )
	{
		print___x( errout, __FILE__, __LINE__, "index" );
		fprintf( errout, "%s\n", "was out of range" );
		return -1;
	}

	b = !!take;
	b <<= (index % CHAR_BIT);

	if ( take >= 0 )
		took[i] |= b;

	return !!(took[i] & b);
}

Releasing however that the method I’m using is inefficient for storing indices, gonna re-think that before I move onto texture’s, in the meantime what material would people suggest I read for textures (assuming the code I’m converting from tinyrenderer’s textures is not enough for me to get it right)?

Just in case anyone has some suggestions, this is the current structure set I plan to use:

typedef struct _STRIP
{
	uint Draw;
	uint ShapesID;
	LIST Shapes;
} STRIP;

typedef struct _MODEL
{
	vec3s Place;
	BUFF Floats;
	BUFF Strips;
} MODEL;

typedef struct _FIELD
{
	BUFF BufferIDs;
	BUFF Models;
} FIELD;

typedef struct _SCENE
{
	BUFF FieldIDs;
	BUFF Fields;
} SCENE;

The SCENE object will represent entire “maps”, like for example in FFXV there’s the main continent that would serve as a map and nearby islands that would serve as scenes as well, furthermore the scenes position will always be relative to another scene (I’ll work out the implementation for this detail later), this would eliminate the infinity issue on a global scale, I’m considering having sub scene support for the case that a scene is still large enough to cause an infinity issue.

The FIELD object would be individual cells within these scenes, they would provide a normalised environment for models (which would solve the infinity issue on a local scale), these fields will hold indices for nearby fields, the positions will be calculated at load time, these positions will likewise fall into a normalised environment, just with a ±1 to the x,y &/or z axis.

In other words every object should only see a normalised environment from it’s direct parent and not care about how where it is in other ancestors. The first model in a field is reserved for the the field model, the last model or group of models are reserved for active models (like the player, NPCs & enemies), all between is for “static” objects, ie, they don’t move from their position, even if they’re a breakable, instead their strips just move relative to their model’s position, this also make’s it easy to produce re-spawnable objects because you just have to go far enough that it would be unloaded before going back to have them re-loaded.

Again if anyone has suggestions feel free to mention them

By the lack of responses I guessing peops either had no suggestions or just didn’t care, I’m betting the later,that’s fine, at least I tried getting input.

Anyways, for anyone that still struggling to use index buffers I’m now uploading my code to Lee Shallis / glEngine · GitLab, the main function to look at is glfwRefreshCB(), I’m not going to claim it’s a good example, but it should get you on the right track, just be warned, this project is not intended for other people to use, it’s only meant for my experiments so expect the code to be a mess to some extent.

In the process of trying to fix some errors I realised I was still understanding the vertex array id wrong, it just happened to work because I was only linking to one cache of floats (gave up trying to keep them all in one buffer for time being), if my understanding is finally correct then each vertex array is only supposed to hold 1 buffer of floats and as many index buffers as one pleases (within memory limits obviously), this kind of information would be helpful in the guides but not a single one mentions that, as if they expect people to figure that out without any help (despite the fact they’re consulting a guide in the 1st place).

Anyways I’ve currently switched to a paired cache buffer & index buffer system but opengl is now throwing errors at me when I mainly just moved code to a more appropriate place for this system. Here’s the code block that’s throwing errors:

			for ( uint strip = 0; strip < Strips->used; ++strip )
			{
				STRIP *Strip = strips + strip;
				BUFF *traits = Strip->Traits;
				uint used = traits->used;

				for ( uint trait = 0; trait < TRAIT_COUNT; ++trait )
				{
					BUFF *Trait = traits + trait;
					BUFF *Cache = Caches + Traits->UseCache[trait];
					uint values = Traits->PerTrait[trait];
					uint TraitID = Traits->TraitIDs[trait];
					uint CacheID = Traits->CacheIDs[trait];
					uint IndexID = Traits->IndexIDs[trait];
					uint location = Core->TraitLoc[trait];

					if ( trait != TRAIT_PLACE && trait != TRAIT_COLOR )
						continue;

					glX( NULL, glEnableVertexAttribArray( location ));

#ifdef _DEBUG
					fprintf
					(
						errout,
						"model = %u, trait = %u, Cache->size = %zu\n",
						model,
						trait,
						Cache->size
					);
#endif

					glX( NULL, glBindVertexArray( TraitID ) );
					//glX( NULL, glInvalidateBufferData( CacheID ) );
					glX( NULL, glBindBuffer( GL_ARRAY_BUFFER, CacheID ) );
					glX( NULL, glBufferData
					(
						GL_ARRAY_BUFFER,
						Cache->size,
						Cache->addr,
						GL_DYNAMIC_DRAW
					) );
					glX( NULL, glVertexAttribPointer
					(
						location,
						values,
						GL_FLOAT,
						GL_FALSE,
						0,
						NULL
					));
					glX( NULL, glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexID ) );
					glX( NULL, glBufferData
					(
						GL_ELEMENT_ARRAY_BUFFER,
						used * sizeof(uint),
						Trait->addr,
						GL_DYNAMIC_DRAW
					));
				}

				glX( NULL, glDrawElements( Strip->DrawAs, used, GL_UNSIGNED_INT, NULL ));
			}

And here’s the errors (duplicates were cropped out before posting):

model = 0, trait = 1, Cache->size = 4096
main.c:576: GL_INVALID_OPERATION  glBufferData ( GL_ARRAY_BUFFER, Cache->size, Cache->addr, GL_DYNAMIC_DRAW )
main.c:585: GL_INVALID_OPERATION  glVertexAttribPointer ( location, values, GL_FLOAT, GL_FALSE, 0, NULL )
main.c:593: GL_INVALID_OPERATION  glBufferData ( GL_ELEMENT_ARRAY_BUFFER, used * sizeof(uint), Trait->addr, GL_DYNAMIC_DRAW )
model = 0, trait = 2, Cache->size = 4096
main.c:576: GL_INVALID_OPERATION  glBufferData ( GL_ARRAY_BUFFER, Cache->size, Cache->addr, GL_DYNAMIC_DRAW )
main.c:585: GL_INVALID_OPERATION  glVertexAttribPointer ( location, values, GL_FLOAT, GL_FALSE, 0, NULL )
main.c:593: GL_INVALID_OPERATION  glBufferData ( GL_ELEMENT_ARRAY_BUFFER, used * sizeof(uint), Trait->addr, GL_DYNAMIC_DRAW )
main.c:596: GL_INVALID_OPERATION  glDrawElements( Strip->DrawAs, used, GL_UNSIGNED_INT, NULL )
model = 1, trait = 1, Cache->size = 4096
main.c:576: GL_INVALID_OPERATION  glBufferData ( GL_ARRAY_BUFFER, Cache->size, Cache->addr, GL_DYNAMIC_DRAW )
main.c:585: GL_INVALID_OPERATION  glVertexAttribPointer ( location, values, GL_FLOAT, GL_FALSE, 0, NULL )
main.c:593: GL_INVALID_OPERATION  glBufferData ( GL_ELEMENT_ARRAY_BUFFER, used * sizeof(uint), Trait->addr, GL_DYNAMIC_DRAW )
model = 1, trait = 2, Cache->size = 4096
main.c:576: GL_INVALID_OPERATION  glBufferData ( GL_ARRAY_BUFFER, Cache->size, Cache->addr, GL_DYNAMIC_DRAW )
main.c:585: GL_INVALID_OPERATION  glVertexAttribPointer ( location, values, GL_FLOAT, GL_FALSE, 0, NULL )
main.c:593: GL_INVALID_OPERATION  glBufferData ( GL_ELEMENT_ARRAY_BUFFER, used * sizeof(uint), Trait->addr, GL_DYNAMIC_DRAW )
main.c:596: GL_INVALID_OPERATION  glDrawElements( Strip->DrawAs, used, GL_UNSIGNED_INT, NULL )
model = 2, trait = 1, Cache->size = 4096
main.c:576: GL_INVALID_OPERATION  glBufferData ( GL_ARRAY_BUFFER, Cache->size, Cache->addr, GL_DYNAMIC_DRAW )
main.c:585: GL_INVALID_OPERATION  glVertexAttribPointer ( location, values, GL_FLOAT, GL_FALSE, 0, NULL )
main.c:593: GL_INVALID_OPERATION  glBufferData ( GL_ELEMENT_ARRAY_BUFFER, used * sizeof(uint), Trait->addr, GL_DYNAMIC_DRAW )
model = 2, trait = 2, Cache->size = 4096
main.c:576: GL_INVALID_OPERATION  glBufferData ( GL_ARRAY_BUFFER, Cache->size, Cache->addr, GL_DYNAMIC_DRAW )
main.c:585: GL_INVALID_OPERATION  glVertexAttribPointer ( location, values, GL_FLOAT, GL_FALSE, 0, NULL )
main.c:593: GL_INVALID_OPERATION  glBufferData ( GL_ELEMENT_ARRAY_BUFFER, used * sizeof(uint), Trait->addr, GL_DYNAMIC_DRAW )
main.c:596: GL_INVALID_OPERATION  glDrawElements( Strip->DrawAs, used, GL_UNSIGNED_INT, NULL )

Any ideas to what I should be looking for? Or even better what I should change?

Never mind, turned out I gave Traits the wrong pointer so it was giving the wrong IDs (which had all been initialised to 0 in the process of initializing buffer data from their relative BUFF object via their MODEL object)

This is completely wrong.

You’ve either got your terminology badly mixed-up, or what you’re doing is just accidentally working.

accidentally then because when I tried do a paired system I just got a black screen, the moment I went back to one “vertex array object” and just bound all the buffers to that one the triangles I was expecting appeared, didn’t get round to texture mapping though, for the first one I plan to just use a buffer generated by rand_r, the 2nd one I plan to try using SAIL to load an image and layer it over, I’m trying to go with a different triangle for each format so that I can trace the difference in handling every time I look back on this project

Help please, finally finished following the guide for a simple 2D texture while substituting a randomised array of vec4s (in RGBA order) but when I tried to run it the triangle that should’ve been textured appeared to have no texture, here’s what I have:

Draw Code:

			glUniform1ui( Core->CoveredLoc, !!(Strip->Covered) );

			if ( Strip->Covered )
			{
				COVER *Cover = covers + Strip->Covered;
				glBindTexture( Cover->UsedAs, Cover->ID );
			}

Initialisation Code:

typedef int (*rand_r_cb)( uint *seed );

typedef struct _RAND
{
	uint seed;
	rand_r_cb rand_r;
} RAND;

typedef union RGBA_RAND
{
	RAND raw[4];
	struct
	{
		RAND r;
		RAND g;
		RAND b;
		RAND a;
	};
} RGBA_RAND;

void generate_raw_cover( COVER *Cover, RGBA_RAND *gen )
{
	double max = UINT_MAX;
	uint have = Cover->Buffer.size / sizeof(vec4);
	vec4s *vecs = Cover->Buffer.addr;
	for ( uint v = 0; v < have; ++v )
	{
		double r = gen->r.rand_r( &(gen->r.seed) );
		double g = gen->g.rand_r( &(gen->g.seed) );
		double b = gen->b.rand_r( &(gen->b.seed) );
		double a = gen->a.rand_r( &(gen->a.seed) );
		vec4s * vec = vecs + v;

		vec->raw[0] = r / max;
		vec->raw[1] = g / max;
		vec->raw[2] = b / max;
		vec->raw[3] = a / max;
	}
}
...
	Covers = buff_inc_only( &(Core->Alloc), &(Core->Covers), COVER, 64 );

	if ( !Covers )
	{
		print___x( errout, __FILE__, __LINE__, "[FATAL ERROR]" );
		fprintf( errout, "%s\n", "Couldn't allocate cover objects" );
		empty_core( Core );
		return -1;
	}

	covers = Covers->addr;
	cover = 1;
	Cover = covers + cover;

	for ( uint r = 0; r < 4; ++r )
	{
		rgba_rand.raw[r].seed = time(NULL);
		rgba_rand.raw[r].rand_r = rand_r;
	}

	glGenTextures( 1, &(Cover->ID) );
	Cover->Formed = true;
	Cover->Bounds.x = 256;
	Cover->Bounds.y = 256;
	if
	(
		!buff_inc_only
		(
			&(Core->Alloc),
			&(Cover->Buffer),
			vec4,
			Cover->Bounds.x * Cover->Bounds.y
		)
	)
	{
		print___x( errout, __FILE__, __LINE__, "[FATAL ERROR]" );
		fprintf( errout, "%s\n", "Couldn't allocate cover buffer" );
		empty_core( Core );
		return -1;
	}
	generate_raw_cover( Cover, &rgba_rand );
	Cover->UsedAs = GL_TEXTURE_2D;
	glBindTexture( Cover->UsedAs, Cover->ID );
	glTexImage2D
	(
		Cover->UsedAs,
		0,
		GL_RGBA,
		Cover->Bounds.x,
		Cover->Bounds.y,
		0,
		GL_RGBA,
		GL_FLOAT,
		Cover->Buffer.addr
	);
	glGenerateMipmap(Cover->UsedAs);

Never mind, I overlooked a piece of code from the guide, adding that in fixed the issue

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.