Hello again. We're back trying to make this work. We've successfully (I think?) implemented the mandatory functions from extensions.h and we're now trying to draw an image to the screen, but nothing is happening.
We're not exactly sure how to iterate the object to retrieve all the data necessary to draw each region attachment to the screen. I'm going to paste some code and ask you to please tell me if you see something wrong.
First, this is our implementation of the functions in extension.h:
void _AtlasPage_createTexture (AtlasPage* self, const char* path) {
TexturePack* tp = UtilityContainer::getInstance()->imageCache->get(path);
self->width = tp->width;
self->height = tp->height;
self->rendererObject = tp;
}
void _AtlasPage_disposeTexture (AtlasPage* self) {
delete self->rendererObject;
}
char* _Util_readFile (const char* path, int* length) {
FILE *fp;
char *buffer;
fopen_s ( &fp, path , "rb" );
if( !fp ) {
return "\0";
perror(path);
}
fseek( fp , 0L , SEEK_END);
*length = ftell( fp );
rewind( fp );
int bufferlen = *length+1;
buffer = (char*)calloc( 1, bufferlen );
if( !buffer ) {
fclose(fp);
fputs("memory alloc fails",stderr);
return "\0";
}
if( 1!=fread( buffer , *length, 1 , fp) ) {
fclose(fp);
free(buffer);
fputs("entire read fails",stderr);
return "\0";
}
fclose(fp);
return buffer;
}
All of these appear to be working correctly. Now, in my wrapper object I have the following methods:
-
Constructor/destructor
-
Update
-
Draw
Constructor does the following:
SpineEntity::SpineEntity() {
this->x = 480;
this->y = 270;
this->atlas = Atlas_readAtlasFile("assets/spinedata/spineboy.atlas");
printf("First region name: %s, x: %d, y: %d\n", this->atlas->regions->name, this->atlas->regions->x, this->atlas->regions->y);
printf("First page name: %s, size: %d, %d\n", this->atlas->pages->name, this->atlas->pages->width, this->atlas->pages->height);
TexturePack* tp = (TexturePack*)this->atlas->pages->rendererObject;
this->textureid = tp->id;
this->json = SkeletonJson_create(this->atlas);
this->skeletonData = SkeletonJson_readSkeletonDataFile(this->json, "assets/spinedata/spineboy.json");
if (!this->skeletonData) printf("Error: %s\n", this->json->error);
printf("Default skin name: %s\n", this->skeletonData->defaultSkin->name);
this->skeleton = Skeleton_create(this->skeletonData);
this->animation = SkeletonData_findAnimation(this->skeletonData, "walk");
if (!this->animation) printf("Error: %s\n", this->json->error);
printf("Animation timelineCount: %d\n", this->animation->timelineCount);
this->state = AnimationState_create(NULL);
this->timeScale = 1;
}
You can see that most of it is lifted straight from the example.
The update method is lifted straight from the sfml implementation:
void SpineEntity::update (float deltaTime) {
Skeleton_update(this->skeleton, deltaTime);
AnimationState_update(this->state, deltaTime * this->timeScale);
AnimationState_apply(this->state, this->skeleton);
Skeleton_updateWorldTransform(this->skeleton);
}
I am calling it each cycle.
The draw method, I guess, is the problem. Here it is:
void SpineEntity::draw() {
float vertexPositions[8];
for (int i = 0; i < skeleton->slotCount; ++i) {
Slot* slot = skeleton->drawOrder[i];
Attachment* attachment = slot->attachment;
if (!attachment || attachment->type != ATTACHMENT_REGION) { continue; }
RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
RegionAttachment_computeVertices(regionAttachment, slot->skeleton->x, slot->skeleton->y, slot->bone, vertexPositions);
unsigned char r = skeleton->r * slot->r * 255;
unsigned char g = skeleton->g * slot->g * 255;
unsigned char b = skeleton->b * slot->b * 255;
unsigned char a = skeleton->a * slot->a * 255;
SpineVertex vertices[4];
vertices[0].color.r = r; vertices[0].color.g = g; vertices[0].color.b = b; vertices[0].color.a = a;
vertices[1].color.r = r; vertices[1].color.g = g; vertices[1].color.b = b; vertices[1].color.a = a;
vertices[2].color.r = r; vertices[2].color.g = g; vertices[2].color.b = b; vertices[2].color.a = a;
vertices[3].color.r = r; vertices[3].color.g = g; vertices[3].color.b = b; vertices[3].color.a = a;
vertices[0].position.x = vertexPositions[VERTEX_X1];
vertices[0].position.y = vertexPositions[VERTEX_Y1];
vertices[1].position.x = vertexPositions[VERTEX_X2];
vertices[1].position.y = vertexPositions[VERTEX_Y2];
vertices[2].position.x = vertexPositions[VERTEX_X3];
vertices[2].position.y = vertexPositions[VERTEX_Y3];
vertices[3].position.x = vertexPositions[VERTEX_X4];
vertices[3].position.y = vertexPositions[VERTEX_Y4];
vertices[0].texCoords.x = regionAttachment->uvs[VERTEX_X1] * this->x;
vertices[0].texCoords.y = regionAttachment->uvs[VERTEX_Y1] * this->y;
vertices[1].texCoords.x = regionAttachment->uvs[VERTEX_X2] * this->x;
vertices[1].texCoords.y = regionAttachment->uvs[VERTEX_Y2] * this->y;
vertices[2].texCoords.x = regionAttachment->uvs[VERTEX_X3] * this->x;
vertices[2].texCoords.y = regionAttachment->uvs[VERTEX_Y3] * this->y;
vertices[3].texCoords.x = regionAttachment->uvs[VERTEX_X4] * this->x;
vertices[3].texCoords.y = regionAttachment->uvs[VERTEX_Y4] * this->y;
glBindTexture(GL_TEXTURE_2D, this->textureid );
glBegin(GL_QUADS);
glColor4ub(
vertices[i].color.r,
vertices[i].color.g,
vertices[i].color.b,
vertices[i].color.a
);
for (int i = 0; i<4; i++) {
glTexCoord2f( vertices[i].texCoords.x, vertices[i].texCoords.y );
glVertex2f( (float)this->x+vertices[i].position.x, (float)this->y+vertices[i].position.y );
}
glColor4f(1.0f,1.0f,1.0f,1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
}
Again, adapted from the sfml implementation. I am not drawing behind other things and OpenGL is drawing other things correctly. I guess we had some problem understanding some concepts and the result is all wrong?
Apologies for the code dump and thank you in advance.