|
|
@ -386,7 +386,7 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei |
|
|
|
|
|
|
|
rlCheckRenderBatchLimit(36); |
|
|
|
|
|
|
|
rlEnableTexture(texture.id); |
|
|
|
rlSetTexture(texture.id); |
|
|
|
|
|
|
|
//rlPushMatrix(); |
|
|
|
// NOTE: Transformation is applied in inverse order (scale -> rotate -> translate) |
|
|
@ -435,7 +435,7 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei |
|
|
|
rlEnd(); |
|
|
|
//rlPopMatrix(); |
|
|
|
|
|
|
|
rlDisableTexture(); |
|
|
|
rlSetTexture(0); |
|
|
|
} |
|
|
|
|
|
|
|
// Draw sphere |
|
|
@ -725,7 +725,7 @@ Model LoadModel(const char *fileName) |
|
|
|
else |
|
|
|
{ |
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
for (int i = 0; i < model.meshCount; i++) rlLoadMesh(&model.meshes[i], false); |
|
|
|
for (int i = 0; i < model.meshCount; i++) UploadMesh(&model.meshes[i], false); |
|
|
|
} |
|
|
|
|
|
|
|
if (model.materialCount == 0) |
|
|
@ -813,29 +813,356 @@ void UnloadModelKeepMeshes(Model model) |
|
|
|
TRACELOG(LOG_INFO, "MODEL: Unloaded model (but not meshes) from RAM and VRAM"); |
|
|
|
} |
|
|
|
|
|
|
|
// Load meshes from model file |
|
|
|
Mesh *LoadMeshes(const char *fileName, int *meshCount) |
|
|
|
#define GL_UNSIGNED_BYTE 0x1401 |
|
|
|
#define GL_FLOAT 0x1406 |
|
|
|
|
|
|
|
// Upload vertex data into a VAO (if supported) and VBO |
|
|
|
void UploadMesh(Mesh *mesh, bool dynamic) |
|
|
|
{ |
|
|
|
Mesh *meshes = NULL; |
|
|
|
int count = 0; |
|
|
|
if (mesh->vaoId > 0) |
|
|
|
{ |
|
|
|
// Check if mesh has already been loaded in GPU |
|
|
|
TRACELOG(LOG_WARNING, "VAO: [ID %i] Trying to re-load an already loaded mesh", mesh->vaoId); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
mesh->vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int)); |
|
|
|
|
|
|
|
mesh->vaoId = 0; // Vertex Array Object |
|
|
|
mesh->vboId[0] = 0; // Vertex positions VBO |
|
|
|
mesh->vboId[1] = 0; // Vertex texcoords VBO |
|
|
|
mesh->vboId[2] = 0; // Vertex normals VBO |
|
|
|
mesh->vboId[3] = 0; // Vertex colors VBO |
|
|
|
mesh->vboId[4] = 0; // Vertex tangents VBO |
|
|
|
mesh->vboId[5] = 0; // Vertex texcoords2 VBO |
|
|
|
mesh->vboId[6] = 0; // Vertex indices VBO |
|
|
|
|
|
|
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) |
|
|
|
mesh->vaoId = rlLoadVertexArray(); |
|
|
|
rlEnableVertexArray(mesh->vaoId); |
|
|
|
|
|
|
|
// NOTE: Attributes must be uploaded considering default locations points |
|
|
|
|
|
|
|
// Enable vertex attributes: position (shader-location = 0) |
|
|
|
mesh->vboId[0] = rlLoadVertexBuffer(mesh->vertices, mesh->vertexCount*3*sizeof(float), dynamic); |
|
|
|
rlSetVertexAttribute(0, 3, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(0); |
|
|
|
|
|
|
|
// Enable vertex attributes: texcoords (shader-location = 1) |
|
|
|
mesh->vboId[1] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic); |
|
|
|
rlSetVertexAttribute(1, 2, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(1); |
|
|
|
|
|
|
|
if (mesh->normals != NULL) |
|
|
|
{ |
|
|
|
// Enable vertex attributes: normals (shader-location = 2) |
|
|
|
mesh->vboId[2] = rlLoadVertexBuffer(mesh->normals, mesh->vertexCount*3*sizeof(float), dynamic); |
|
|
|
rlSetVertexAttribute(2, 3, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(2); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Default color vertex attribute set to WHITE |
|
|
|
float value[3] = { 1.0f, 1.0f, 1.0f }; |
|
|
|
rlSetVertexAttributeDefault(2, value, SHADER_ATTRIB_VEC3, 3); |
|
|
|
rlDisableVertexAttribute(2); |
|
|
|
} |
|
|
|
|
|
|
|
if (mesh->colors != NULL) |
|
|
|
{ |
|
|
|
// Enable vertex attribute: color (shader-location = 3) |
|
|
|
mesh->vboId[3] = rlLoadVertexBuffer(mesh->colors, mesh->vertexCount*4*sizeof(unsigned char), dynamic); |
|
|
|
rlSetVertexAttribute(3, 4, GL_UNSIGNED_BYTE, 1, 0, 0); |
|
|
|
rlEnableVertexAttribute(3); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Default color vertex attribute set to WHITE |
|
|
|
float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; |
|
|
|
rlSetVertexAttributeDefault(3, value, SHADER_ATTRIB_VEC4, 4); |
|
|
|
rlDisableVertexAttribute(3); |
|
|
|
} |
|
|
|
|
|
|
|
if (mesh->tangents != NULL) |
|
|
|
{ |
|
|
|
// Enable vertex attribute: tangent (shader-location = 4) |
|
|
|
mesh->vboId[4] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), dynamic); |
|
|
|
rlSetVertexAttribute(4, 4, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(4); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Default tangents vertex attribute |
|
|
|
float value[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; |
|
|
|
rlSetVertexAttributeDefault(4, value, SHADER_ATTRIB_VEC4, 4); |
|
|
|
rlDisableVertexAttribute(4); |
|
|
|
} |
|
|
|
|
|
|
|
if (mesh->texcoords2 != NULL) |
|
|
|
{ |
|
|
|
// Enable vertex attribute: texcoord2 (shader-location = 5) |
|
|
|
mesh->vboId[5] = rlLoadVertexBuffer(mesh->texcoords2, mesh->vertexCount*2*sizeof(float), dynamic); |
|
|
|
rlSetVertexAttribute(5, 2, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(5); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Default texcoord2 vertex attribute |
|
|
|
float value[2] = { 0.0f, 0.0f }; |
|
|
|
rlSetVertexAttributeDefault(5, value, SHADER_ATTRIB_VEC2, 2); |
|
|
|
rlDisableVertexAttribute(5); |
|
|
|
} |
|
|
|
|
|
|
|
// TODO: Load meshes from file (OBJ, IQM, GLTF) |
|
|
|
if (mesh->indices != NULL) |
|
|
|
{ |
|
|
|
mesh->vboId[6] = rlLoadVertexBufferElement(mesh->indices, mesh->triangleCount*3*sizeof(unsigned short), dynamic); |
|
|
|
} |
|
|
|
|
|
|
|
*meshCount = count; |
|
|
|
return meshes; |
|
|
|
if (mesh->vaoId > 0) TRACELOG(LOG_INFO, "VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); |
|
|
|
else TRACELOG(LOG_INFO, "VBO: Mesh uploaded successfully to VRAM (GPU)"); |
|
|
|
|
|
|
|
rlDisableVertexArray(); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// Upload mesh vertex data to GPU |
|
|
|
void UploadMesh(Mesh *mesh) |
|
|
|
// Draw a 3d mesh with material and transform |
|
|
|
void DrawMesh(Mesh mesh, Material material, Matrix transform) |
|
|
|
{ |
|
|
|
rlLoadMesh(mesh, false); // Static mesh by default |
|
|
|
#if defined(GRAPHICS_API_OPENGL_11) |
|
|
|
/* |
|
|
|
glEnable(GL_TEXTURE_2D); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.maps[MATERIAL_MAP_DIFFUSE].texture.id); |
|
|
|
|
|
|
|
// NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model |
|
|
|
glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array |
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array |
|
|
|
if (mesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array |
|
|
|
if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array |
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, mesh.vertices); // Pointer to vertex coords array |
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array |
|
|
|
if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array |
|
|
|
if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array |
|
|
|
|
|
|
|
rlPushMatrix(); |
|
|
|
rlMultMatrixf(MatrixToFloat(transform)); |
|
|
|
rlColor4ub(material.maps[MATERIAL_MAP_DIFFUSE].color.r, material.maps[MATERIAL_MAP_DIFFUSE].color.g, material.maps[MATERIAL_MAP_DIFFUSE].color.b, material.maps[MATERIAL_MAP_DIFFUSE].color.a); |
|
|
|
|
|
|
|
if (mesh.indices != NULL) glDrawArrayElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices); |
|
|
|
else glDrawArrays(0, mesh.vertexCount); |
|
|
|
rlPopMatrix(); |
|
|
|
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array |
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array |
|
|
|
if (mesh.normals != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array |
|
|
|
if (mesh.colors != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable colors array |
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D); |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
*/ |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) |
|
|
|
// Bind shader program |
|
|
|
rlEnableShader(material.shader.id); |
|
|
|
|
|
|
|
// Matrices and other values required by shader |
|
|
|
//----------------------------------------------------- |
|
|
|
// Calculate and send to shader model matrix |
|
|
|
if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) |
|
|
|
{ |
|
|
|
rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], transform); |
|
|
|
} |
|
|
|
|
|
|
|
// Upload to shader material.colDiffuse |
|
|
|
if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1) |
|
|
|
{ |
|
|
|
float values[4] = { |
|
|
|
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f, |
|
|
|
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f, |
|
|
|
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f, |
|
|
|
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f |
|
|
|
}; |
|
|
|
|
|
|
|
rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1); |
|
|
|
} |
|
|
|
|
|
|
|
// Upload to shader material.colSpecular (if available) |
|
|
|
if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1) |
|
|
|
{ |
|
|
|
float values[4] = { |
|
|
|
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.r/255.0f, |
|
|
|
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.g/255.0f, |
|
|
|
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.b/255.0f, |
|
|
|
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.a/255.0f |
|
|
|
}; |
|
|
|
|
|
|
|
rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1); |
|
|
|
} |
|
|
|
|
|
|
|
if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], rlGetMatrixModelview()); |
|
|
|
if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], rlGetMatrixProjection()); |
|
|
|
|
|
|
|
// At this point the modelview matrix just contains the view matrix (camera) |
|
|
|
// That's because BeginMode3D() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() |
|
|
|
Matrix matView = rlGetMatrixModelview(); // View matrix (camera) |
|
|
|
Matrix matProjection = rlGetMatrixProjection(); // Projection matrix (perspective) |
|
|
|
|
|
|
|
// Accumulate several transformations: |
|
|
|
// matView: rlgl internal modelview matrix (actually, just view matrix) |
|
|
|
// rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack |
|
|
|
// transform: function parameter transformation |
|
|
|
Matrix matModelView = MatrixMultiply(transform, MatrixMultiply(rlGetMatrixTransform(), matView)); |
|
|
|
//----------------------------------------------------- |
|
|
|
|
|
|
|
// Bind active texture maps (if available) |
|
|
|
for (int i = 0; i < MAX_MATERIAL_MAPS; i++) |
|
|
|
{ |
|
|
|
if (material.maps[i].texture.id > 0) |
|
|
|
{ |
|
|
|
// Select current shader texture slot |
|
|
|
rlActiveTextureSlot(i); |
|
|
|
|
|
|
|
// Enable texture for active slot |
|
|
|
if ((i == MATERIAL_MAP_IRRADIANCE) || |
|
|
|
(i == MATERIAL_MAP_PREFILTER) || |
|
|
|
(i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id); |
|
|
|
else rlEnableTexture(material.maps[i].texture.id); |
|
|
|
|
|
|
|
rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Try binding vertex array objects (VAO) |
|
|
|
// or use VBOs if not possible |
|
|
|
if (!rlEnableVertexArray(mesh.vaoId)) |
|
|
|
{ |
|
|
|
// Bind mesh VBO data: vertex position (shader-location = 0) |
|
|
|
rlEnableVertexBuffer(mesh.vboId[0]); |
|
|
|
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]); |
|
|
|
|
|
|
|
rlEnableVertexBuffer(mesh.vboId[0]); |
|
|
|
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]); |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex texcoords (shader-location = 1) |
|
|
|
rlEnableVertexBuffer(mesh.vboId[1]); |
|
|
|
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); |
|
|
|
|
|
|
|
if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1) |
|
|
|
{ |
|
|
|
// Bind mesh VBO data: vertex normals (shader-location = 2) |
|
|
|
rlEnableVertexBuffer(mesh.vboId[2]); |
|
|
|
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]); |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex colors (shader-location = 3, if available) |
|
|
|
if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1) |
|
|
|
{ |
|
|
|
if (mesh.vboId[3] != 0) |
|
|
|
{ |
|
|
|
rlEnableVertexBuffer(mesh.vboId[3]); |
|
|
|
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, 1, 0, 0); |
|
|
|
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Set default value for unused attribute |
|
|
|
// NOTE: Required when using default shader and no VAO support |
|
|
|
float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; |
|
|
|
rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC2, 4); |
|
|
|
rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex tangents (shader-location = 4, if available) |
|
|
|
if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1) |
|
|
|
{ |
|
|
|
rlEnableVertexBuffer(mesh.vboId[4]); |
|
|
|
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]); |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) |
|
|
|
if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1) |
|
|
|
{ |
|
|
|
rlEnableVertexBuffer(mesh.vboId[5]); |
|
|
|
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, GL_FLOAT, 0, 0, 0); |
|
|
|
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); |
|
|
|
} |
|
|
|
|
|
|
|
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]); |
|
|
|
} |
|
|
|
|
|
|
|
//rlDrawVertexData(int vertexCount, Matrix matModelView, bool stereo) |
|
|
|
|
|
|
|
int eyesCount = 1; |
|
|
|
//if (RLGL.State.stereoRender) eyesCount = 2; |
|
|
|
|
|
|
|
for (int eye = 0; eye < eyesCount; eye++) |
|
|
|
{ |
|
|
|
if (eyesCount == 1) rlSetMatrixModelview(matModelView); |
|
|
|
else |
|
|
|
{ |
|
|
|
// Setup current eye viewport (half screen width) |
|
|
|
//rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight()); |
|
|
|
|
|
|
|
// Set current eye view offset to modelview matrix |
|
|
|
//rlSetMatrixModelview(MatrixMultiply(matModelView, RLGL.State.offsetStereo[eye])); |
|
|
|
|
|
|
|
// Set current eye projection matrix |
|
|
|
//rlSetMatrixProjection(RLGL.State.projectionStereo[eye]); |
|
|
|
} |
|
|
|
|
|
|
|
// Calculate model-view-projection matrix (MVP) |
|
|
|
Matrix matMVP = MatrixMultiply(rlGetMatrixModelview(), rlGetMatrixProjection()); // Transform to screen-space coordinates |
|
|
|
|
|
|
|
// Send combined model-view-projection matrix to shader |
|
|
|
rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matMVP); |
|
|
|
|
|
|
|
// Draw calls |
|
|
|
if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3); |
|
|
|
else rlDrawVertexArray(0, mesh.vertexCount); |
|
|
|
} |
|
|
|
|
|
|
|
// Unbind all binded texture maps |
|
|
|
for (int i = 0; i < MAX_MATERIAL_MAPS; i++) |
|
|
|
{ |
|
|
|
// Select current shader texture slot |
|
|
|
rlActiveTextureSlot(i); |
|
|
|
|
|
|
|
// Disable texture for active slot |
|
|
|
if ((i == MATERIAL_MAP_IRRADIANCE) || |
|
|
|
(i == MATERIAL_MAP_PREFILTER) || |
|
|
|
(i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap(); |
|
|
|
else rlDisableTexture(); |
|
|
|
} |
|
|
|
|
|
|
|
// Disable all possible vertex array objects (or VBOs) |
|
|
|
rlDisableVertexArray(); |
|
|
|
rlDisableVertexBuffer(); |
|
|
|
rlDisableVertexBufferElement(); |
|
|
|
|
|
|
|
// Disable shader program |
|
|
|
rlDisableShader(); |
|
|
|
|
|
|
|
// Restore rlgl internal modelview and projection matrices |
|
|
|
rlSetMatrixModelview(matView); |
|
|
|
rlSetMatrixProjection(matProjection); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// Unload mesh from memory (RAM and/or VRAM) |
|
|
|
// Unload mesh from memory (RAM and VRAM) |
|
|
|
void UnloadMesh(Mesh mesh) |
|
|
|
{ |
|
|
|
// Unload rlgl mesh vboId data |
|
|
|
rlUnloadMesh(&mesh); |
|
|
|
rlUnloadVertexArray(mesh.vaoId); |
|
|
|
|
|
|
|
for (int i = 0; i < MAX_MESH_VERTEX_BUFFERS; i++) rlUnloadVertexBuffer(mesh.vboId[i]); |
|
|
|
RL_FREE(mesh.vboId); |
|
|
|
|
|
|
|
RL_FREE(mesh.vertices); |
|
|
|
RL_FREE(mesh.texcoords); |
|
|
@ -918,6 +1245,7 @@ bool ExportMesh(Mesh mesh, const char *fileName) |
|
|
|
return success; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Load materials from model file |
|
|
|
Material *LoadMaterials(const char *fileName, int *materialCount) |
|
|
|
{ |
|
|
@ -1076,8 +1404,8 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) |
|
|
|
} |
|
|
|
|
|
|
|
// Upload new vertex data to GPU for model drawing |
|
|
|
rlUpdateBuffer(model.meshes[m].vboId[0], model.meshes[m].animVertices, model.meshes[m].vertexCount*3*sizeof(float)); // Update vertex position |
|
|
|
rlUpdateBuffer(model.meshes[m].vboId[2], model.meshes[m].animNormals, model.meshes[m].vertexCount*3*sizeof(float)); // Update vertex normals |
|
|
|
rlUpdateVertexBuffer(model.meshes[m].vboId[0], model.meshes[m].animVertices, model.meshes[m].vertexCount*3*sizeof(float), 0); // Update vertex position |
|
|
|
rlUpdateVertexBuffer(model.meshes[m].vboId[2], model.meshes[m].animNormals, model.meshes[m].vertexCount*3*sizeof(float), 0); // Update vertex normals |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -1180,8 +1508,8 @@ Mesh GenMeshPoly(int sides, float radius) |
|
|
|
RL_FREE(texcoords); |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
// NOTE: mesh.vboId array is allocated inside rlLoadMesh() |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
// NOTE: mesh.vboId array is allocated inside UploadMesh() |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
|
|
|
|
return mesh; |
|
|
|
} |
|
|
@ -1314,7 +1642,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ) |
|
|
|
#endif |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
|
|
|
|
return mesh; |
|
|
|
} |
|
|
@ -1479,7 +1807,7 @@ par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron |
|
|
|
#endif |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
|
|
|
|
return mesh; |
|
|
|
} |
|
|
@ -1519,7 +1847,7 @@ RLAPI Mesh GenMeshSphere(float radius, int rings, int slices) |
|
|
|
par_shapes_free_mesh(sphere); |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
} |
|
|
|
else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: sphere"); |
|
|
|
|
|
|
@ -1563,7 +1891,7 @@ RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices) |
|
|
|
par_shapes_free_mesh(sphere); |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
} |
|
|
|
else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: hemisphere"); |
|
|
|
|
|
|
@ -1626,7 +1954,7 @@ Mesh GenMeshCylinder(float radius, float height, int slices) |
|
|
|
par_shapes_free_mesh(cylinder); |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
} |
|
|
|
else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cylinder"); |
|
|
|
|
|
|
@ -1672,7 +2000,7 @@ Mesh GenMeshTorus(float radius, float size, int radSeg, int sides) |
|
|
|
par_shapes_free_mesh(torus); |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
} |
|
|
|
else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: torus"); |
|
|
|
|
|
|
@ -1716,7 +2044,7 @@ Mesh GenMeshKnot(float radius, float size, int radSeg, int sides) |
|
|
|
par_shapes_free_mesh(knot); |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
} |
|
|
|
else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: knot"); |
|
|
|
|
|
|
@ -1853,7 +2181,7 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size) |
|
|
|
UnloadImageColors(pixels); // Unload pixels color data |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
|
|
|
|
return mesh; |
|
|
|
} |
|
|
@ -2204,7 +2532,7 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) |
|
|
|
UnloadImageColors(pixels); // Unload pixels color data |
|
|
|
|
|
|
|
// Upload vertex data to GPU (static mesh) |
|
|
|
rlLoadMesh(&mesh, false); |
|
|
|
UploadMesh(&mesh, false); |
|
|
|
|
|
|
|
return mesh; |
|
|
|
} |
|
|
@ -2315,7 +2643,7 @@ void MeshTangents(Mesh *mesh) |
|
|
|
RL_FREE(tan2); |
|
|
|
|
|
|
|
// Load a new tangent attributes buffer |
|
|
|
mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->vaoId, SHADER_LOC_VERTEX_TANGENT, mesh->tangents, mesh->vertexCount*4*sizeof(float), false); |
|
|
|
mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false); |
|
|
|
|
|
|
|
TRACELOG(LOG_INFO, "MESH: Tangents data computed for provided mesh"); |
|
|
|
} |
|
|
@ -2367,7 +2695,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota |
|
|
|
colorTint.a = (unsigned char)((((float)color.a/255.0)*((float)tint.a/255.0))*255.0f); |
|
|
|
|
|
|
|
model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = colorTint; |
|
|
|
rlDrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform); |
|
|
|
DrawMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform); |
|
|
|
model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = color; |
|
|
|
} |
|
|
|
} |
|
|
@ -2433,7 +2761,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector |
|
|
|
|
|
|
|
rlCheckRenderBatchLimit(4); |
|
|
|
|
|
|
|
rlEnableTexture(texture.id); |
|
|
|
rlSetTexture(texture.id); |
|
|
|
|
|
|
|
rlBegin(RL_QUADS); |
|
|
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a); |
|
|
@ -2455,7 +2783,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector |
|
|
|
rlVertex3f(b.x, b.y, b.z); |
|
|
|
rlEnd(); |
|
|
|
|
|
|
|
rlDisableTexture(); |
|
|
|
rlSetTexture(0); |
|
|
|
} |
|
|
|
|
|
|
|
// Draw a bounding box with wires |
|
|
|