/*! * 3D vector perspective projection * Projects 3D vector into 2D screen space * \param v3d 3D vector to project * \param[out] v2d resulting 2D vector * \return projected z component of v2d */ int32_t pie_RotateProject(const Vector3i *v3d, const glm::mat4& matrix, Vector2i *v2d) { float hackScaleFactor = 1.0f / (3 * 330); // HACK: This seems to work by experimentation, not sure why. /* * v = curMatrix . v3d */ glm::vec4 v(pie_PerspectiveGet() * matrix * glm::vec4(*v3d, 1.f)); const float xx = v.x / v.w; const float yy = v.y / v.w; if (v.w < 256 * hackScaleFactor) { v2d->x = LONG_WAY; //just along way off screen v2d->y = LONG_WAY; } else { v2d->x = (.5 + .5 * xx) * pie_GetVideoBufferWidth(); v2d->y = (.5 - .5 * yy) * pie_GetVideoBufferHeight(); } return v.w; }
void pie_DrawSkybox(float scale, const glm::mat4 &viewMatrix) { // no use in updating the depth buffer glDepthMask(GL_FALSE); // enable alpha pie_SetRendMode(REND_ALPHA); // Apply scale matrix skyboxGfx->draw(pie_PerspectiveGet() * viewMatrix * glm::scale(scale, scale / 2.f, scale)); }
void pie_TransColouredTriangle(const std::array<Vector3f, 3> &vrt, PIELIGHT c, const glm::mat4 &modelViewMatrix) { pie_SetTexturePage(TEXPAGE_NONE); pie_SetRendMode(REND_ADDITIVE); glm::vec4 color(c.byte.r / 255.f, c.byte.g / 255.f, c.byte.b / 255.f, 128.f / 255.f); const auto &program = pie_ActivateShader(SHADER_GENERIC_COLOR, pie_PerspectiveGet() * modelViewMatrix, color); static glBufferWrapper buffer; glBindBuffer(GL_ARRAY_BUFFER, buffer.id); glBufferData(GL_ARRAY_BUFFER, 3 * sizeof(Vector3f), vrt.data(), GL_STREAM_DRAW); glVertexAttribPointer(program.locVertex, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glEnableVertexAttribArray(program.locVertex); glDrawArrays(GL_TRIANGLE_FAN, 0, 3); glDisableVertexAttribArray(program.locVertex); }
/// Draw the shadow for a shape static void pie_DrawShadow(iIMDShape *shape, int flag, int flag_data, const glm::vec4 &light, const glm::mat4 &modelViewMatrix) { static std::vector<EDGE> edgelist; // Static, to save allocations. static std::vector<EDGE> edgelistFlipped; // Static, to save allocations. static std::vector<EDGE> edgelistFiltered; // Static, to save allocations. EDGE *drawlist = NULL; unsigned edge_count; Vector3f *pVertices = shape->points; if (flag & pie_STATIC_SHADOW && shape->shadowEdgeList) { drawlist = shape->shadowEdgeList; edge_count = shape->nShadowEdges; } else { edgelist.clear(); iIMDPoly *end = shape->polys + shape->npolys; for (iIMDPoly *pPolys = shape->polys; pPolys != end; ++pPolys) { glm::vec3 p[3]; for (int j = 0; j < 3; ++j) { int current = pPolys->pindex[j]; p[j] = glm::vec3(pVertices[current].x, scale_y(pVertices[current].y, flag, flag_data), pVertices[current].z); } if (glm::dot(glm::cross(p[2] - p[0], p[1] - p[0]), glm::vec3(light)) > 0.0f) { for (int n = 0; n < 3; ++n) { // Add the edges edgelist.push_back({pPolys->pindex[n], pPolys->pindex[(n + 1)%3]}); } } } // Remove duplicate pairs from the edge list. For example, in the list ((1 2), (2 6), (6 2), (3, 4)), remove (2 6) and (6 2). edgelistFlipped = edgelist; std::for_each(edgelistFlipped.begin(), edgelistFlipped.end(), flipEdge); std::sort(edgelist.begin(), edgelist.end(), edgeLessThan); std::sort(edgelistFlipped.begin(), edgelistFlipped.end(), edgeLessThan); edgelistFiltered.resize(edgelist.size()); edgelistFiltered.erase(std::set_difference(edgelist.begin(), edgelist.end(), edgelistFlipped.begin(), edgelistFlipped.end(), edgelistFiltered.begin(), edgeLessThan), edgelistFiltered.end()); drawlist = &edgelistFiltered[0]; edge_count = edgelistFiltered.size(); //debug(LOG_WARNING, "we have %i edges", edge_count); if (flag & pie_STATIC_SHADOW) { // then store it in the imd shape->nShadowEdges = edge_count; shape->shadowEdgeList = (EDGE *)realloc(shape->shadowEdgeList, sizeof(EDGE) * shape->nShadowEdges); std::copy(drawlist, drawlist + edge_count, shape->shadowEdgeList); } } std::vector<Vector3f> vertexes; for (unsigned i = 0; i < edge_count; i++) { int a = drawlist[i].from, b = drawlist[i].to; glm::vec3 v1(pVertices[b].x, scale_y(pVertices[b].y, flag, flag_data), pVertices[b].z); glm::vec3 v2(pVertices[b].x + light[0], scale_y(pVertices[b].y, flag, flag_data) + light[1], pVertices[b].z + light[2]); glm::vec3 v3(pVertices[a].x + light[0], scale_y(pVertices[a].y, flag, flag_data) + light[1], pVertices[a].z + light[2]); glm::vec3 v4(pVertices[a].x, scale_y(pVertices[a].y, flag, flag_data), pVertices[a].z); vertexes.push_back(v1); vertexes.push_back(v2); vertexes.push_back(v3); vertexes.push_back(v3); vertexes.push_back(v4); vertexes.push_back(v1); } // draw the shadow volume const auto &program = pie_ActivateShader(SHADER_GENERIC_COLOR, pie_PerspectiveGet() * modelViewMatrix, glm::vec4()); static glBufferWrapper buffer; glBindBuffer(GL_ARRAY_BUFFER, buffer.id); glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3f) * vertexes.size(), vertexes.data(), GL_STREAM_DRAW); glEnableVertexAttribArray(program.locVertex); glVertexAttribPointer(program.locVertex, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glDrawArrays(GL_TRIANGLES, 0, edge_count * 2 * 3); glDisableVertexAttribArray(program.locVertex); pie_DeactivateShader(); }
static void pie_Draw3DShape2(const iIMDShape *shape, int frame, PIELIGHT colour, PIELIGHT teamcolour, int pieFlag, int pieFlagData, glm::mat4 const &matrix) { bool light = true; /* Set fog status */ if (!(pieFlag & pie_FORCE_FOG) && (pieFlag & pie_ADDITIVE || pieFlag & pie_TRANSLUCENT || pieFlag & pie_PREMULTIPLIED)) { pie_SetFogStatus(false); } else { pie_SetFogStatus(true); } /* Set tranlucency */ if (pieFlag & pie_ADDITIVE) { pie_SetRendMode(REND_ADDITIVE); colour.byte.a = (UBYTE)pieFlagData; light = false; } else if (pieFlag & pie_TRANSLUCENT) { pie_SetRendMode(REND_ALPHA); colour.byte.a = (UBYTE)pieFlagData; light = false; } else if (pieFlag & pie_PREMULTIPLIED) { pie_SetRendMode(REND_PREMULTIPLIED); light = false; } else { pie_SetRendMode(REND_OPAQUE); } if (pieFlag & pie_ECM) { pie_SetRendMode(REND_ALPHA); light = true; pie_SetShaderEcmEffect(true); } glm::vec4 sceneColor(lighting0[LIGHT_EMISSIVE][0], lighting0[LIGHT_EMISSIVE][1], lighting0[LIGHT_EMISSIVE][2], lighting0[LIGHT_EMISSIVE][3]); glm::vec4 ambient(lighting0[LIGHT_AMBIENT][0], lighting0[LIGHT_AMBIENT][1], lighting0[LIGHT_AMBIENT][2], lighting0[LIGHT_AMBIENT][3]); glm::vec4 diffuse(lighting0[LIGHT_DIFFUSE][0], lighting0[LIGHT_DIFFUSE][1], lighting0[LIGHT_DIFFUSE][2], lighting0[LIGHT_DIFFUSE][3]); glm::vec4 specular(lighting0[LIGHT_SPECULAR][0], lighting0[LIGHT_SPECULAR][1], lighting0[LIGHT_SPECULAR][2], lighting0[LIGHT_SPECULAR][3]); SHADER_MODE mode = shape->shaderProgram == SHADER_NONE ? light ? SHADER_COMPONENT : SHADER_NOLIGHT : shape->shaderProgram; pie_internal::SHADER_PROGRAM &program = pie_ActivateShaderDeprecated(mode, shape, teamcolour, colour, matrix, pie_PerspectiveGet(), glm::vec4(currentSunPosition, 0.f), sceneColor, ambient, diffuse, specular); if (program.locations.size() >= 9) glUniform1i(program.locations[8], (pieFlag & pie_PREMULTIPLIED) == 0); pie_SetTexturePage(shape->texpage); frame %= std::max<int>(1, shape->numFrames); enableArray(shape->buffers[VBO_VERTEX], program.locVertex, 3, GL_FLOAT, false, 0, 0); enableArray(shape->buffers[VBO_NORMAL], program.locNormal, 3, GL_FLOAT, false, 0, 0); enableArray(shape->buffers[VBO_TEXCOORD], program.locTexCoord, 2, GL_FLOAT, false, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shape->buffers[VBO_INDEX]); glDrawElements(GL_TRIANGLES, shape->npolys * 3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(frame * shape->npolys * 3 * sizeof(uint16_t))); disableArrays(); polyCount += shape->npolys; pie_SetShaderEcmEffect(false); pie_DeactivateShader(); }
static void pie_Draw3DButton(iIMDShape *shape, PIELIGHT teamcolour, const glm::mat4 &matrix) { const PIELIGHT colour = WZCOL_WHITE; pie_SetFogStatus(false); pie_SetDepthBufferStatus(DEPTH_CMP_LEQ_WRT_ON); pie_internal::SHADER_PROGRAM &program = pie_ActivateShaderDeprecated(SHADER_BUTTON, shape, teamcolour, colour, matrix, pie_PerspectiveGet(), glm::vec4(), glm::vec4(), glm::vec4(), glm::vec4(), glm::vec4()); pie_SetRendMode(REND_OPAQUE); pie_SetTexturePage(shape->texpage); enableArray(shape->buffers[VBO_VERTEX], program.locVertex, 3, GL_FLOAT, false, 0, 0); enableArray(shape->buffers[VBO_NORMAL], program.locNormal, 3, GL_FLOAT, false, 0, 0); enableArray(shape->buffers[VBO_TEXCOORD], program.locTexCoord, 2, GL_FLOAT, false, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shape->buffers[VBO_INDEX]); glDrawElements(GL_TRIANGLES, shape->npolys * 3, GL_UNSIGNED_SHORT, NULL); disableArrays(); polyCount += shape->npolys; pie_DeactivateShader(); pie_SetDepthBufferStatus(DEPTH_CMP_ALWAYS_WRT_ON); }