void D3DCacheInit(d3d_render_cache *pCache, int size, int numStages, DWORD flags) { IDirect3DDevice9_CreateIndexBuffer(gpD3DDevice, size * sizeof(custom_index), flags, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &pCache->indexBuffer.pIBuffer, NULL); IDirect3DDevice9_CreateVertexBuffer(gpD3DDevice, size * sizeof(custom_xyz), flags, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pCache->xyzBuffer.pVBuffer, NULL); IDirect3DDevice9_CreateVertexBuffer(gpD3DDevice, size * sizeof(custom_st), flags, D3DFVF_TEX0, D3DPOOL_DEFAULT, &pCache->stBuffer[0].pVBuffer, NULL); IDirect3DDevice9_CreateVertexBuffer(gpD3DDevice, size * sizeof(custom_st), flags, D3DFVF_TEX1, D3DPOOL_DEFAULT, &pCache->stBuffer[1].pVBuffer, NULL); IDirect3DDevice9_CreateVertexBuffer(gpD3DDevice, size * sizeof(custom_bgra), flags, D3DFVF_DIFFUSE, D3DPOOL_DEFAULT, &pCache->bgraBuffer.pVBuffer, NULL); pCache->numPackets = 0; pCache->bgraBuffer.curIndex = 0; pCache->xyzBuffer.curIndex = 0; pCache->indexBuffer.curIndex = 0; pCache->size = size; }
LPDIRECT3DVERTEXBUFFER d3d_vertex_buffer_new(LPDIRECT3DDEVICE dev, unsigned length, unsigned usage, unsigned fvf, D3DPOOL pool, void *handle) { HRESULT hr; LPDIRECT3DVERTEXBUFFER buf; #ifndef _XBOX if (usage == 0) { if (dev->GetSoftwareVertexProcessing()) usage = D3DUSAGE_SOFTWAREPROCESSING; } #endif #if defined(HAVE_D3D8) hr = IDirect3DDevice8_CreateVertexBuffer(dev, length, usage, fvf, pool, &buf); #elif defined(HAVE_D3D9) hr = IDirect3DDevice9_CreateVertexBuffer(dev, length, usage, fvf, pool, &buf, NULL); #else hr = dev->CreateVertexBuffer(length, usage, fvf, pool, &buf, NULL); #endif if (FAILED(hr)) return NULL; return buf; }
JBKVertexBuffer JBKRender_CreateVertexBuffer(uint32_t sizeInBytes, JBKVertexDataType dataType) { IDirect3DVertexBuffer9* buffer = 0; int32_t stride = 0; DWORD fvf = DataTypeToFVF(dataType, &stride); DXCall( IDirect3DDevice9_CreateVertexBuffer(gDevice, sizeInBytes, 0, fvf, D3DPOOL_MANAGED, &buffer, NULL) ); return buffer; }
static void createVertexBuffersD3D9() { HRESULT hr; LPVOID ptr = NULL; int sizeInBytes = sizeof(float)*3*NUM_VERTICES; D3DVERTEXELEMENT9 decl[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, D3DDECL_END(), }; hr = IDirect3DDevice9_CreateVertexBuffer(gDevicePtr, sizeInBytes, D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &gVertexBufferPtr, NULL); if(FAILED(hr) || !gVertexBufferPtr) { fprintf(stderr, "Failed to create vertex buffer\n"); return; } hr = IDirect3DVertexBuffer9_Lock(gVertexBufferPtr, 0, 0, &ptr, D3DLOCK_DISCARD); if (FAILED(hr) || !ptr) { fprintf(stderr, "Failed to lock vertex buffer\n"); return; } memcpy(ptr, icosahedronVertices, sizeInBytes); hr = IDirect3DVertexBuffer9_Unlock(gVertexBufferPtr); if (FAILED(hr)) { fprintf(stderr, "Failed to unlock vertex buffer\n"); return; } sizeInBytes = sizeof(unsigned short)*3*NUM_INDICES; hr = IDirect3DDevice9_CreateIndexBuffer(gDevicePtr, sizeInBytes, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &gIndexBufferPtr, NULL); if(FAILED(hr) || !gIndexBufferPtr) { fprintf(stderr, "Failed to create index buffer\n"); return; } hr = IDirect3DIndexBuffer9_Lock(gIndexBufferPtr, 0, 0, &ptr, D3DLOCK_DISCARD); if (FAILED(hr) || !ptr) { fprintf(stderr, "Failed to lock index buffer\n"); return; } memcpy(ptr, icosahedronIndices, sizeInBytes); hr = IDirect3DIndexBuffer9_Unlock(gIndexBufferPtr); if (FAILED(hr)) { fprintf(stderr, "Failed to unlock index buffer\n"); return; } hr = IDirect3DDevice9_CreateVertexDeclaration(gDevicePtr, decl, &gVertexDeclPtr); if(FAILED(hr) || !gVertexDeclPtr) { fprintf(stderr, "Failed to create vertex declaration\n"); return; } }
static void d3d9_init( sgui_context* context ) { float m[16], f, iNF, fov_deg = 60.0f, Near = 0.1f, Far = 100.0f; CUSTOMVERTEX vdat[ sizeof(indices)/sizeof(indices[0]) ]; sgui_d3d9_context* ctx = (sgui_d3d9_context*)context; float aspectratio = (float)WIDTH / (float)HEIGHT; unsigned int i, idx, r, g, b; for( i=0; i<sizeof(indices)/sizeof(indices[0]); ++i ) { idx = indices[ i ]; r = vertices[ idx*6+3 ] * 255.0f; g = vertices[ idx*6+4 ] * 255.0f; b = vertices[ idx*6+5 ] * 255.0f; vdat[ i ].x = vertices[ idx*6 ]; vdat[ i ].y = vertices[ idx*6+1 ]; vdat[ i ].z = vertices[ idx*6+2 ]; vdat[ i ].color = D3DCOLOR_ARGB(0xFF,r,g,b); } IDirect3DDevice9_Reset( ctx->device, &ctx->present ); IDirect3DDevice9_CreateVertexBuffer( ctx->device, sizeof(vdat), 0, CUSTOMFVF, D3DPOOL_MANAGED, &v_buffer, NULL ); /* load vertex data */ IDirect3DVertexBuffer9_Lock( v_buffer, 0, 0, (void**)&pVoid, 0 ); memcpy( pVoid, vdat, sizeof(vdat) ); IDirect3DVertexBuffer9_Unlock( v_buffer ); /* setup renderer state */ IDirect3DDevice9_SetRenderState(ctx->device,D3DRS_CULLMODE,D3DCULL_NONE); IDirect3DDevice9_SetRenderState(ctx->device,D3DRS_LIGHTING,FALSE ); IDirect3DDevice9_SetRenderState(ctx->device,D3DRS_ZENABLE, TRUE ); /* set up perspective projection matrix */ f = 1.0 / tan( fov_deg * DEGTORAD * 0.5 ); iNF = 1.0 / ( Near - Far ); m[0]=f/aspectratio; m[4]=0; m[ 8]=0; m[12]=0; m[1]=0; m[5]=f; m[ 9]=0; m[13]=0; m[2]=0; m[6]=0; m[10]=(Far+Near)*iNF; m[14]=2*Far*Near*iNF; m[3]=0; m[7]=0; m[11]=-1; m[15]=0; IDirect3DDevice9_SetTransform(ctx->device,D3DTS_PROJECTION,(D3DMATRIX*)m); drawgui = 0; }
void *d3d9_vertex_buffer_new(void *_dev, unsigned length, unsigned usage, unsigned fvf, INT32 pool, void *handle) { void *buf = NULL; LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)_dev; #ifndef _XBOX if (usage == 0) if (IDirect3DDevice9_GetSoftwareVertexProcessing(dev)) usage = D3DUSAGE_SOFTWAREPROCESSING; #endif if (FAILED(IDirect3DDevice9_CreateVertexBuffer( dev, length, usage, fvf, (D3DPOOL)pool, (LPDIRECT3DVERTEXBUFFER9*)&buf, NULL))) return NULL; return buf; }
LPDIRECT3DVERTEXBUFFER d3d_vertex_buffer_new(LPDIRECT3DDEVICE dev, unsigned length, unsigned usage, unsigned fvf, D3DPOOL pool, void *handle) { HRESULT hr; LPDIRECT3DVERTEXBUFFER buf; #if defined(HAVE_D3D8) hr = IDirect3DDevice8_CreateVertexBuffer(dev, length, usage, fvf, pool, &buf); #elif defined(HAVE_D3D9) hr = IDirect3DDevice9_CreateVertexBuffer(dev, length, usage, fvf, pool, &buf, NULL); #else hr = dev->CreateVertexBuffer(length, usage, fvf, pool, &buf, NULL); #endif if (FAILED(hr)) return NULL; return buf; }
/** * It allocates and initializes the resources needed to render the scene. */ static int Direct3DCreateScene(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev; HRESULT hr; /* * Create a texture for use when rendering a scene * for performance reason, texture format is identical to backbuffer * which would usually be a RGB format */ LPDIRECT3DTEXTURE9 d3dtex; hr = IDirect3DDevice9_CreateTexture(d3ddev, sys->d3dpp.BackBufferWidth, sys->d3dpp.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET, sys->d3dpp.BackBufferFormat, D3DPOOL_DEFAULT, &d3dtex, NULL); if (FAILED(hr)) { msg_Err(vd, "Failed to create texture. (hr=0x%lx)", hr); return VLC_EGENERIC; } /* ** Create a vertex buffer for use when rendering scene */ LPDIRECT3DVERTEXBUFFER9 d3dvtc; hr = IDirect3DDevice9_CreateVertexBuffer(d3ddev, sizeof(CUSTOMVERTEX)*4, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &d3dvtc, NULL); if (FAILED(hr)) { msg_Err(vd, "Failed to create vertex buffer. (hr=0x%lx)", hr); IDirect3DTexture9_Release(d3dtex); return VLC_EGENERIC; } /* */ sys->d3dtex = d3dtex; sys->d3dvtc = d3dvtc; // Texture coordinates outside the range [0.0, 1.0] are set // to the texture color at 0.0 or 1.0, respectively. IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); // Set linear filtering quality IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); IDirect3DDevice9_SetSamplerState(d3ddev, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // set maximum ambient light IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255)); // Turn off culling IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_CULLMODE, D3DCULL_NONE); // Turn off the zbuffer IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ZENABLE, D3DZB_FALSE); // Turn off lights IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_LIGHTING, FALSE); // Enable dithering IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_DITHERENABLE, TRUE); // disable stencil IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_STENCILENABLE, FALSE); // manage blending IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, TRUE); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_SRCBLEND,D3DBLEND_SRCALPHA); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHATESTENABLE,TRUE); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHAREF, 0x10); IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHAFUNC,D3DCMP_GREATER); // Set texture states IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_COLOROP,D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_COLORARG1,D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_COLORARG2,D3DTA_DIFFUSE); // turn off alpha operation IDirect3DDevice9_SetTextureStageState(d3ddev, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); msg_Dbg(vd, "Direct3D scene created successfully"); return VLC_SUCCESS; }
static HRESULT device_create_vertex_buffer(device *dev, UINT length, DWORD usage, DWORD fvf, D3DPOOL pool, vertex_buffer **buf) { IDirect3DDevice9 *device = (IDirect3DDevice9 *)dev; return IDirect3DDevice9_CreateVertexBuffer(device, length, usage, fvf, pool, (IDirect3DVertexBuffer9 **)buf, NULL); }
int main( void ) { LPDIRECT3DVERTEXBUFFER9 v_buffer; sgui_window_description desc; IDirect3DTexture9* texture; sgui_d3d9_context* ctx; sgui_canvas* texcanvas; IDirect3DDevice9* dev; sgui_widget* check2; sgui_widget* check; sgui_widget* butt; sgui_window* wnd; float a=0.0f; VOID* pVoid; float m[16]; sgui_init( ); /*************************** create a window **************************/ desc.parent = NULL; desc.share = NULL; desc.width = 640; desc.height = 480; desc.flags = SGUI_FIXED_SIZE|SGUI_DOUBLEBUFFERED; desc.backend = SGUI_DIRECT3D_9; desc.bits_per_pixel = 32; desc.depth_bits = 16; desc.stencil_bits = 0; desc.samples = 0; wnd = sgui_window_create_desc( &desc ); sgui_window_set_title( wnd, "Direct3D 9 Texture Canvas" ); sgui_window_move_center( wnd ); sgui_window_set_visible( wnd, SGUI_VISIBLE ); sgui_window_set_vsync( wnd, 1 ); /************************ createtexture canvas ************************/ texcanvas = sgui_tex_canvas_create( wnd, sgui_window_get_context( wnd ), 128, 128 ); butt = sgui_button_create( 10, 10, 60, 25, "Button", 0 ); check = sgui_checkbox_create( 10, 40, "Direct3D" ); check2 = sgui_checkbox_create( 10, 65, "Texture" ); sgui_button_set_state( check, 1 ); sgui_button_set_state( check2, 1 ); sgui_widget_add_child( &texcanvas->root, butt ); sgui_widget_add_child( &texcanvas->root, check ); sgui_widget_add_child( &texcanvas->root, check2 ); /************** connect keyboard input to texture canvas **************/ sgui_event_connect( wnd, SGUI_KEY_PRESSED_EVENT, sgui_canvas_send_window_event, texcanvas, SGUI_FROM_EVENT, SGUI_EVENT ); sgui_event_connect( wnd, SGUI_KEY_RELEASED_EVENT, sgui_canvas_send_window_event, texcanvas, SGUI_FROM_EVENT, SGUI_EVENT ); sgui_event_connect( wnd, SGUI_CHAR_EVENT, sgui_canvas_send_window_event, texcanvas, SGUI_FROM_EVENT, SGUI_EVENT ); /*************************** Direct3D setup ***************************/ /* get the device context, set new present parameters */ ctx = (sgui_d3d9_context*)sgui_window_get_context( wnd ); dev = ctx->device; IDirect3DDevice9_Reset( dev, &ctx->present ); /* create a vertex buffer */ IDirect3DDevice9_CreateVertexBuffer( dev, sizeof(vertices), 0, CUSTOMFVF, D3DPOOL_MANAGED, &v_buffer, NULL ); /* load vertex data */ IDirect3DVertexBuffer9_Lock( v_buffer, 0, 0, (void**)&pVoid, 0 ); memcpy( pVoid, vertices, sizeof(vertices) ); IDirect3DVertexBuffer9_Unlock( v_buffer ); /* setup renderer state */ IDirect3DDevice9_SetRenderState( dev, D3DRS_CULLMODE, D3DCULL_NONE ); IDirect3DDevice9_SetRenderState( dev, D3DRS_LIGHTING, FALSE ); IDirect3DDevice9_SetRenderState( dev, D3DRS_ZENABLE, TRUE ); /* set up perspective projection matrix */ perspective( m, 45.0f, (float)desc.width/(float)desc.height, 0.1f, 100.0f ); IDirect3DDevice9_SetTransform( dev, D3DTS_PROJECTION, (D3DMATRIX*)m ); /* set up texturing, bind canvas texture to stage 0 */ texture = sgui_tex_canvas_get_texture( texcanvas ); IDirect3DDevice9_SetTexture( dev, 0, (IDirect3DBaseTexture9*)texture ); IDirect3DDevice9_SetTextureStageState( dev, 0, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA ); IDirect3DDevice9_SetTextureStageState( dev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); IDirect3DDevice9_SetTextureStageState( dev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); IDirect3DDevice9_SetTextureStageState( dev, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); IDirect3DDevice9_SetSamplerState(dev,0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); IDirect3DDevice9_SetSamplerState(dev,0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); /****************************** main loop *****************************/ while( sgui_main_loop_step( ) ) { /* redraw widgets in dirty areas */ sgui_canvas_redraw_widgets( texcanvas, 1 ); /* draw scene */ IDirect3DDevice9_Clear( dev, 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1.0f, 0 ); IDirect3DDevice9_BeginScene( dev ); transform( m, a ); IDirect3DDevice9_SetTransform( dev, D3DTS_VIEW, (D3DMATRIX*)m ); a += 0.01f; IDirect3DDevice9_SetFVF( dev, CUSTOMFVF ); IDirect3DDevice9_SetStreamSource( dev, 0, v_buffer, 0, sizeof(CUSTOMVERTEX) ); IDirect3DDevice9_DrawPrimitive( dev, D3DPT_TRIANGLELIST, 0, 8 ); IDirect3DDevice9_EndScene( dev ); /* swap front and back buffer */ sgui_window_swap_buffers( wnd ); } /****************************** clean up ******************************/ sgui_canvas_destroy( texcanvas ); sgui_widget_destroy( check2 ); sgui_widget_destroy( check ); sgui_widget_destroy( butt ); IDirect3DVertexBuffer9_Release( v_buffer ); sgui_window_destroy( wnd ); sgui_deinit( ); return 0; }
object *load_object(IDirect3DDevice9 *device, char *filename){ matrix position, rotation, scale; vector position_vector, scale_vector; quat rotation_quat; unsigned int submesh_counter; char test[4]; object *temp; file *fp; vertex *dest; if(!filename) return NULL; fp = file_open(filename); if(!fp) return NULL; file_read(test,1,4,fp); if(memcmp(test,"KRO0",4)!=0){ file_close(fp); return NULL; } temp = (object*)malloc(sizeof(object)); if(!temp) return NULL; file_read(&position_vector,sizeof(float),3,fp); file_read(&rotation_quat,sizeof(float),4,fp); file_read(&scale_vector,sizeof(float),3,fp); file_read(&temp->vertex_count,1,4,fp); if(temp->vertex_count==0){ /* dummy-object, skip loading */ file_close(fp); temp->update = FALSE; temp->vertexbuffer = NULL; temp->vertices = 0; temp->submesh_count = 0; temp->submeshes = NULL; /* save prs */ temp->prs.pos = position_vector; temp->prs.rot = rotation_quat; temp->prs.scale = scale_vector; /* build matrix */ matrix_identity(temp->mat); matrix_translate(position, position_vector); matrix_from_quat(rotation, rotation_quat); matrix_scale(scale, scale_vector); matrix_multiply(temp->mat, temp->mat, position); matrix_multiply(temp->mat, temp->mat, rotation); matrix_multiply(temp->mat, temp->mat, scale); return temp; } temp->vertices = (vertex*)malloc(sizeof(vertex)*temp->vertex_count); if(!temp->vertices) return FALSE; file_read(temp->vertices,sizeof(vertex),temp->vertex_count,fp); file_read(&temp->morphtarget_count,1,4,fp); temp->morphtarget_vertices = malloc(sizeof(vector)*temp->vertex_count*temp->morphtarget_count); if(!temp->morphtarget_vertices) return FALSE; file_read(temp->morphtarget_vertices,sizeof(vector),temp->vertex_count*temp->morphtarget_count,fp); file_read(&temp->submesh_count,1,4,fp); temp->submeshes = (submesh*)malloc(sizeof(submesh)*temp->submesh_count); if(!temp->submeshes) return FALSE; for(submesh_counter=0;submesh_counter<temp->submesh_count;submesh_counter++){ unsigned int* dest; char mat_name[256]; char *material_name = file_loadstring(fp); sprintf(mat_name,"%s%s",get_dirname(filename),material_name); temp->submeshes[submesh_counter].mat = material_load(device,mat_name); file_read(&temp->submeshes[submesh_counter].triangle_count,1,4,fp); temp->submeshes[submesh_counter].triangles = (unsigned short*)malloc(sizeof(unsigned short)*3*temp->submeshes[submesh_counter].triangle_count); if(!temp->submeshes[submesh_counter].triangles) return FALSE; file_read(temp->submeshes[submesh_counter].triangles,sizeof(unsigned short)*3,temp->submeshes[submesh_counter].triangle_count,fp); if(FAILED(IDirect3DDevice9_CreateIndexBuffer(device,sizeof(unsigned short)*3*temp->submeshes[submesh_counter].triangle_count,0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&temp->submeshes[submesh_counter].indexbuffer,NULL))) return FALSE; if(IDirect3DIndexBuffer9_Lock(temp->submeshes[submesh_counter].indexbuffer,0,0,&dest,0)==D3D_OK){ memcpy(dest,temp->submeshes[submesh_counter].triangles,sizeof(unsigned short)*3*temp->submeshes[submesh_counter].triangle_count); IDirect3DIndexBuffer9_Unlock(temp->submeshes[submesh_counter].indexbuffer); }else return FALSE; } file_close(fp); if(temp->morphtarget_count > 0) { printf("something shall morph!"); if(FAILED(IDirect3DDevice9_CreateVertexBuffer(device,sizeof(vertex)*temp->vertex_count,D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,OBJECT_VERTEX_TYPE,D3DPOOL_DEFAULT,&temp->vertexbuffer,NULL))) return FALSE; } else { if(FAILED(IDirect3DDevice9_CreateVertexBuffer(device,sizeof(vertex)*temp->vertex_count,0,OBJECT_VERTEX_TYPE,D3DPOOL_MANAGED,&temp->vertexbuffer,NULL))) return FALSE; } if(IDirect3DVertexBuffer9_Lock(temp->vertexbuffer, 0, 0, (BYTE**)&dest, 0)==D3D_OK){ memcpy(dest,temp->vertices,sizeof(vertex)*temp->vertex_count); IDirect3DVertexBuffer9_Unlock(temp->vertexbuffer); temp->update = FALSE; }else return FALSE; /* save prs */ temp->prs.pos = position_vector; temp->prs.rot = rotation_quat; temp->prs.scale = scale_vector; /* build matrix */ matrix_identity(temp->mat); matrix_translate(position, position_vector); matrix_from_quat(rotation, rotation_quat); matrix_scale(scale, scale_vector); matrix_multiply(temp->mat, temp->mat, position); matrix_multiply(temp->mat, temp->mat, rotation); matrix_multiply(temp->mat, temp->mat, scale); return temp; }