void UIBatch::AddQuad(const Matrix3x4& transform, const IntVector2& a, const IntVector2& b, const IntVector2& c, const IntVector2& d, const IntVector2& texA, const IntVector2& texB, const IntVector2& texC, const IntVector2& texD) { Vector3 v1 = (transform * Vector3((float)a.x_, (float)a.y_, 0.0f)) - posAdjust; Vector3 v2 = (transform * Vector3((float)b.x_, (float)b.y_, 0.0f)) - posAdjust; Vector3 v3 = (transform * Vector3((float)c.x_, (float)c.y_, 0.0f)) - posAdjust; Vector3 v4 = (transform * Vector3((float)d.x_, (float)d.y_, 0.0f)) - posAdjust; Vector2 uv1((float)texA.x_ * invTextureSize_.x_, (float)texA.y_ * invTextureSize_.y_); Vector2 uv2((float)texB.x_ * invTextureSize_.x_, (float)texB.y_ * invTextureSize_.y_); Vector2 uv3((float)texC.x_ * invTextureSize_.x_, (float)texC.y_ * invTextureSize_.y_); Vector2 uv4((float)texD.x_ * invTextureSize_.x_, (float)texD.y_ * invTextureSize_.y_); unsigned begin = vertexData_->Size(); vertexData_->Resize(begin + 6 * UI_VERTEX_SIZE); float* dest = &(vertexData_->At(begin)); vertexEnd_ = vertexData_->Size(); dest[0] = v1.x_; dest[1] = v1.y_; dest[2] = 0.0f; ((unsigned&)dest[3]) = color_; dest[4] = uv1.x_; dest[5] = uv1.y_; dest[6] = v2.x_; dest[7] = v2.y_; dest[8] = 0.0f; ((unsigned&)dest[9]) = color_; dest[10] = uv2.x_; dest[11] = uv2.y_; dest[12] = v3.x_; dest[13] = v3.y_; dest[14] = 0.0f; ((unsigned&)dest[15]) = color_; dest[16] = uv3.x_; dest[17] = uv3.y_; dest[18] = v1.x_; dest[19] = v1.y_; dest[20] = 0.0f; ((unsigned&)dest[21]) = color_; dest[22] = uv1.x_; dest[23] = uv1.y_; dest[24] = v3.x_; dest[25] = v3.y_; dest[26] = 0.0f; ((unsigned&)dest[27]) = color_; dest[28] = uv3.x_; dest[29] = uv3.y_; dest[30] = v4.x_; dest[31] = v4.y_; dest[32] = 0.0f; ((unsigned&)dest[33]) = color_; dest[34] = uv4.x_; dest[35] = uv4.y_; }
void gfx_decal_init (void) { // TODO: The 4x3 transform will need to be // TODO: Eventually we'd like this uv rect to be configurable per decal. Vector2 uv1(0, 0); Vector2 uv2(1, 1); box_op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; Ogre::VertexData *vdata = OGRE_NEW Ogre::VertexData(); box_op.vertexData = vdata; vdata->vertexStart = 0; const unsigned vertex_count = 8; vdata->vertexCount = vertex_count; unsigned vdecl_size = 0; // strict alignment required here struct Vertex { Vector3 position; Vector2 uv1; Vector2 uv2; }; vdecl_size += vdata->vertexDeclaration->addElement( 0, vdecl_size, Ogre::VET_FLOAT3, Ogre::VES_POSITION).getSize(); vdecl_size += vdata->vertexDeclaration->addElement( 0, vdecl_size, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0).getSize(); vdecl_size += vdata->vertexDeclaration->addElement( 0, vdecl_size, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 1).getSize(); Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vdecl_size, vdata->vertexCount, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); vdata->vertexBufferBinding->setBinding(0, vbuf); Vertex vdata_raw[vertex_count] = { { Vector3(-0.5, -0.5, -0.5), uv1, uv2 }, { Vector3(-0.5, -0.5, 0.5), uv1, uv2 }, { Vector3(-0.5, 0.5, -0.5), uv1, uv2 }, { Vector3(-0.5, 0.5, 0.5), uv1, uv2 }, { Vector3( 0.5, -0.5, -0.5), uv1, uv2 }, { Vector3( 0.5, -0.5, 0.5), uv1, uv2 }, { Vector3( 0.5, 0.5, -0.5), uv1, uv2 }, { Vector3( 0.5, 0.5, 0.5), uv1, uv2 } }; vbuf->writeData(vdata->vertexStart, vdata->vertexCount*vdecl_size, vdata_raw, true); Ogre::IndexData *idata = OGRE_NEW Ogre::IndexData(); box_op.indexData = idata; box_op.useIndexes = true; const unsigned indexes = 36; // 3 per triangle therefore 6 per face, 6 faces total idata->indexStart = 0; idata->indexCount = indexes; idata->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT, indexes, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); uint16_t idata_raw[indexes] = { quad_vertexes(2,6,0,4), quad_vertexes(7,3,5,1), quad_vertexes(3,2,1,0), quad_vertexes(6,7,4,5), quad_vertexes(0,4,1,5), quad_vertexes(3,7,2,6) }; idata->indexBuffer->writeData(0, sizeof(idata_raw), idata_raw, true); }
void Image(const Texture& texture, const Vector2f& size, const Rectf& textureRect, const Color& tintColor, const Color& borderColor) { Vector2f textureSize = static_cast<Vector2f>(texture.getSize()); ImVec2 uv0(textureRect.left / textureSize.x, textureRect.top / textureSize.y); ImVec2 uv1((textureRect.left + textureRect.width) / textureSize.x, (textureRect.top + textureRect.height) / textureSize.y); ImGui::Image((void*)texture.getNativeHandle(), size, uv0, uv1, tintColor, borderColor); }
ManualObject* OgreNewtonMesh::CreateEntity (const String& name) const { ManualObject* const object = new ManualObject(name); int pointCount = GetPointCount(); int indexCount = GetTotalIndexCount(); dNewtonScopeBuffer<int> indexList (indexCount); dNewtonScopeBuffer<int> remapIndex (indexCount); dNewtonScopeBuffer<dNewtonMesh::dPoint> posits (pointCount); dNewtonScopeBuffer<dNewtonMesh::dPoint> normals (pointCount); dNewtonScopeBuffer<dNewtonMesh::dUV> uv0 (pointCount); dNewtonScopeBuffer<dNewtonMesh::dUV> uv1 (pointCount); GetVertexStreams(&posits[0], &normals[0], &uv0[0], &uv1[0]); void* const materialsHandle = BeginMaterialHandle (); for (int handle = GetMaterialIndex (materialsHandle); handle != -1; handle = GetNextMaterialIndex (materialsHandle, handle)) { int materialIndex = MaterialGetMaterial (materialsHandle, handle); int indexCount = MaterialGetIndexCount (materialsHandle, handle); MaterialGetIndexStream (materialsHandle, handle, &indexList[0]); MaterialMap::const_iterator materialItr = m_materialMap.find(materialIndex); //object->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_LIST); object->begin(materialItr->second->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST); // ogre does not support shared vertex for sub mesh, we will have remap the vertex data int vertexCount = 0; memset (&remapIndex[0], 0xff, indexCount * sizeof (remapIndex[0])); for( int i = 0; i < indexCount; i ++) { int index = indexList[i]; if (remapIndex[index] == -1) { remapIndex[index] = vertexCount; object->position (posits[index].m_x, posits[index].m_y, posits[index].m_z); object->normal (normals[index].m_x, normals[index].m_y, normals[index].m_z); object->textureCoord (uv0[index].m_u, uv0[index].m_v); vertexCount ++; } indexList[i] = remapIndex[index]; } for (int i = 0; i < indexCount; i += 3) { object->triangle (indexList[i + 0], indexList[i + 1], indexList[i + 2]); } object->end(); } EndMaterialHandle (materialsHandle); return object; }
PyObject* VRPyPath::set(VRPyPath* self, PyObject* args) { if (self->obj == 0) { PyErr_SetString(err, "VRPyPath::set, Object is invalid"); return NULL; } int i; PyObject *p1, *p2, *n1, *n2, *u1 = 0, *u2 = 0; if (PyList_GET_SIZE(args) <= 5) { if (! PyArg_ParseTuple(args, "OOOOi", &p1, &n1, &p2, &n2, &i)) return NULL; } else if (! PyArg_ParseTuple(args, "OOOOOOi", &p1, &n1, &u1, &p2, &n2, &u2, &i)) return NULL; OSG::Vec3f c, uv1(0,1,0), uv2(0,1,0); if (u1) uv1 = parseVec3fList(u1); if (u2) uv2 = parseVec3fList(u2); self->obj->addPoint(parseVec3fList(p1), parseVec3fList(n1), c, uv1); self->obj->addPoint(parseVec3fList(p2), parseVec3fList(n2), c, uv2); self->obj->compute(i); Py_RETURN_TRUE; }
void Triangle::build() { //Dessin 2D //glm::vec3 pos0(-1.0f, -1.0f, 0.0f); glm::vec3 pos0(-1.f, -1.f, 0.0f); glm::vec3 norm0(0.f, 0.f, 1.0f); glm::vec2 uv0(0.f, 0.f); //glm::vec3 pos1(1.0f, -1.0f, 0.0f); glm::vec3 pos1(3.f, -1.f, 0.0f); glm::vec3 norm1(0.f, 0.f, 1.0f); glm::vec2 uv1(2.f, 0.f); //glm::vec3 pos2(0.f, 0.5f, 0.0f); glm::vec3 pos2(-1.f, 3.0f, 0.0f); glm::vec3 norm2(0.f, 0.f, 1.0f); glm::vec2 uv2(0.f, 2.f); /* Pour un triangle faisant tout l'écran -1.0 -1.0 0.000000 1.0 -1.0 0.000000 0.0 0.5 0.000000 */ _vertices[0].position = pos0; _vertices[0].normal = norm0; _vertices[0].uv = uv0; _vertices[1].position = pos1; _vertices[1].normal = norm1; _vertices[1].uv = uv1; _vertices[2].position = pos2; _vertices[2].normal = norm2; _vertices[2].uv = uv2; _indices[0] = 0; _indices[1] = 1; _indices[2] = 2; }
void EERIEDrawBitmap2DecalY(Rectf rect, float z, TextureContainer * tex, Color color, float _fDeltaY) { rect.move(-.5f, -.5f); rect.top = rect.top + _fDeltaY * rect.height(); Vec2f uv = (tex) ? tex->uv : Vec2f_ZERO; float sv = uv.y * _fDeltaY; ColorRGBA col = color.toRGBA(); Vec2f uv1(0.f, sv); Vec2f uv2(uv.x, sv); Vec2f uv3(uv.x, uv.y); Vec2f uv4(0.f, uv.y); TexturedVertex v[4]; v[0] = TexturedVertex(Vec3f(rect.topLeft(), z), 1.f, col, uv1); v[1] = TexturedVertex(Vec3f(rect.topRight(), z), 1.f, col, uv2); v[2] = TexturedVertex(Vec3f(rect.bottomRight(), z), 1.f, col, uv3); v[3] = TexturedVertex(Vec3f(rect.bottomLeft(), z), 1.f, col, uv4); SetTextureDrawPrim(tex, v, Renderer::TriangleFan); }
void GSVertexTrace::FindMinMax(const void* vertex, const uint32* index, int count) { const GSDrawingContext* context = m_state->m_context; int n = 1; switch(primclass) { case GS_POINT_CLASS: n = 1; break; case GS_LINE_CLASS: case GS_SPRITE_CLASS: n = 2; break; case GS_TRIANGLE_CLASS: n = 3; break; } GSVector4 tmin = s_minmax.xxxx(); GSVector4 tmax = s_minmax.yyyy(); GSVector4i cmin = GSVector4i::xffffffff(); GSVector4i cmax = GSVector4i::zero(); #if _M_SSE >= 0x401 GSVector4i pmin = GSVector4i::xffffffff(); GSVector4i pmax = GSVector4i::zero(); #else GSVector4 pmin = s_minmax.xxxx(); GSVector4 pmax = s_minmax.yyyy(); #endif const GSVertex* RESTRICT v = (GSVertex*)vertex; for(int i = 0; i < count; i += n) { if(primclass == GS_POINT_CLASS) { GSVector4i c(v[index[i]].m[0]); if(color) { cmin = cmin.min_u8(c); cmax = cmax.max_u8(c); } if(tme) { if(!fst) { GSVector4 stq = GSVector4::cast(c); GSVector4 q = stq.wwww(); stq = (stq.xyww() * q.rcpnr()).xyww(q); tmin = tmin.min(stq); tmax = tmax.max(stq); } else { GSVector4i uv(v[index[i]].m[1]); GSVector4 st = GSVector4(uv.uph16()).xyxy(); tmin = tmin.min(st); tmax = tmax.max(st); } } GSVector4i xyzf(v[index[i]].m[1]); GSVector4i xy = xyzf.upl16(); GSVector4i z = xyzf.yyyy(); #if _M_SSE >= 0x401 GSVector4i p = xy.blend16<0xf0>(z.uph32(xyzf)); pmin = pmin.min_u32(p); pmax = pmax.max_u32(p); #else GSVector4 p = GSVector4(xy.upl64(z.srl32(1).upl32(xyzf.wwww()))); pmin = pmin.min(p); pmax = pmax.max(p); #endif } else if(primclass == GS_LINE_CLASS) { GSVector4i c0(v[index[i + 0]].m[0]); GSVector4i c1(v[index[i + 1]].m[0]); if(color) { if(iip) { cmin = cmin.min_u8(c0.min_u8(c1)); cmax = cmax.max_u8(c0.max_u8(c1)); } else { cmin = cmin.min_u8(c1); cmax = cmax.max_u8(c1); } } if(tme) { if(!fst) { GSVector4 stq0 = GSVector4::cast(c0); GSVector4 stq1 = GSVector4::cast(c1); GSVector4 q = stq0.wwww(stq1).rcpnr(); stq0 = (stq0.xyww() * q.xxxx()).xyww(stq0); stq1 = (stq1.xyww() * q.zzzz()).xyww(stq1); tmin = tmin.min(stq0.min(stq1)); tmax = tmax.max(stq0.max(stq1)); } else { GSVector4i uv0(v[index[i + 0]].m[1]); GSVector4i uv1(v[index[i + 1]].m[1]); GSVector4 st0 = GSVector4(uv0.uph16()).xyxy(); GSVector4 st1 = GSVector4(uv1.uph16()).xyxy(); tmin = tmin.min(st0.min(st1)); tmax = tmax.max(st0.max(st1)); } } GSVector4i xyzf0(v[index[i + 0]].m[1]); GSVector4i xyzf1(v[index[i + 1]].m[1]); GSVector4i xy0 = xyzf0.upl16(); GSVector4i z0 = xyzf0.yyyy(); GSVector4i xy1 = xyzf1.upl16(); GSVector4i z1 = xyzf1.yyyy(); #if _M_SSE >= 0x401 GSVector4i p0 = xy0.blend16<0xf0>(z0.uph32(xyzf0)); GSVector4i p1 = xy1.blend16<0xf0>(z1.uph32(xyzf1)); pmin = pmin.min_u32(p0.min_u32(p1)); pmax = pmax.max_u32(p0.max_u32(p1)); #else GSVector4 p0 = GSVector4(xy0.upl64(z0.srl32(1).upl32(xyzf0.wwww()))); GSVector4 p1 = GSVector4(xy1.upl64(z1.srl32(1).upl32(xyzf1.wwww()))); pmin = pmin.min(p0.min(p1)); pmax = pmax.max(p0.max(p1)); #endif } else if(primclass == GS_TRIANGLE_CLASS) { GSVector4i c0(v[index[i + 0]].m[0]); GSVector4i c1(v[index[i + 1]].m[0]); GSVector4i c2(v[index[i + 2]].m[0]); if(color) { if(iip) { cmin = cmin.min_u8(c2).min_u8(c0.min_u8(c1)); cmax = cmax.max_u8(c2).max_u8(c0.max_u8(c1)); } else { cmin = cmin.min_u8(c2); cmax = cmax.max_u8(c2); } } if(tme) { if(!fst) { GSVector4 stq0 = GSVector4::cast(c0); GSVector4 stq1 = GSVector4::cast(c1); GSVector4 stq2 = GSVector4::cast(c2); GSVector4 q = stq0.wwww(stq1).xzww(stq2).rcpnr(); stq0 = (stq0.xyww() * q.xxxx()).xyww(stq0); stq1 = (stq1.xyww() * q.yyyy()).xyww(stq1); stq2 = (stq2.xyww() * q.zzzz()).xyww(stq2); tmin = tmin.min(stq2).min(stq0.min(stq1)); tmax = tmax.max(stq2).max(stq0.max(stq1)); } else { GSVector4i uv0(v[index[i + 0]].m[1]); GSVector4i uv1(v[index[i + 1]].m[1]); GSVector4i uv2(v[index[i + 2]].m[1]); GSVector4 st0 = GSVector4(uv0.uph16()).xyxy(); GSVector4 st1 = GSVector4(uv1.uph16()).xyxy(); GSVector4 st2 = GSVector4(uv2.uph16()).xyxy(); tmin = tmin.min(st2).min(st0.min(st1)); tmax = tmax.max(st2).max(st0.max(st1)); } } GSVector4i xyzf0(v[index[i + 0]].m[1]); GSVector4i xyzf1(v[index[i + 1]].m[1]); GSVector4i xyzf2(v[index[i + 2]].m[1]); GSVector4i xy0 = xyzf0.upl16(); GSVector4i z0 = xyzf0.yyyy(); GSVector4i xy1 = xyzf1.upl16(); GSVector4i z1 = xyzf1.yyyy(); GSVector4i xy2 = xyzf2.upl16(); GSVector4i z2 = xyzf2.yyyy(); #if _M_SSE >= 0x401 GSVector4i p0 = xy0.blend16<0xf0>(z0.uph32(xyzf0)); GSVector4i p1 = xy1.blend16<0xf0>(z1.uph32(xyzf1)); GSVector4i p2 = xy2.blend16<0xf0>(z2.uph32(xyzf2)); pmin = pmin.min_u32(p2).min_u32(p0.min_u32(p1)); pmax = pmax.max_u32(p2).max_u32(p0.max_u32(p1)); #else GSVector4 p0 = GSVector4(xy0.upl64(z0.srl32(1).upl32(xyzf0.wwww()))); GSVector4 p1 = GSVector4(xy1.upl64(z1.srl32(1).upl32(xyzf1.wwww()))); GSVector4 p2 = GSVector4(xy2.upl64(z2.srl32(1).upl32(xyzf2.wwww()))); pmin = pmin.min(p2).min(p0.min(p1)); pmax = pmax.max(p2).max(p0.max(p1)); #endif } else if(primclass == GS_SPRITE_CLASS) { GSVector4i c0(v[index[i + 0]].m[0]); GSVector4i c1(v[index[i + 1]].m[0]); if(color) { if(iip) { cmin = cmin.min_u8(c0.min_u8(c1)); cmax = cmax.max_u8(c0.max_u8(c1)); } else { cmin = cmin.min_u8(c1); cmax = cmax.max_u8(c1); } } if(tme) { if(!fst) { GSVector4 stq0 = GSVector4::cast(c0); GSVector4 stq1 = GSVector4::cast(c1); GSVector4 q = stq1.wwww().rcpnr(); stq0 = (stq0.xyww() * q).xyww(stq1); stq1 = (stq1.xyww() * q).xyww(stq1); tmin = tmin.min(stq0.min(stq1)); tmax = tmax.max(stq0.max(stq1)); } else { GSVector4i uv0(v[index[i + 0]].m[1]); GSVector4i uv1(v[index[i + 1]].m[1]); GSVector4 st0 = GSVector4(uv0.uph16()).xyxy(); GSVector4 st1 = GSVector4(uv1.uph16()).xyxy(); tmin = tmin.min(st0.min(st1)); tmax = tmax.max(st0.max(st1)); } } GSVector4i xyzf0(v[index[i + 0]].m[1]); GSVector4i xyzf1(v[index[i + 1]].m[1]); GSVector4i xy0 = xyzf0.upl16(); GSVector4i z0 = xyzf0.yyyy(); GSVector4i xy1 = xyzf1.upl16(); GSVector4i z1 = xyzf1.yyyy(); #if _M_SSE >= 0x401 GSVector4i p0 = xy0.blend16<0xf0>(z0.uph32(xyzf1)); GSVector4i p1 = xy1.blend16<0xf0>(z1.uph32(xyzf1)); pmin = pmin.min_u32(p0.min_u32(p1)); pmax = pmax.max_u32(p0.max_u32(p1)); #else GSVector4 p0 = GSVector4(xy0.upl64(z0.srl32(1).upl32(xyzf1.wwww()))); GSVector4 p1 = GSVector4(xy1.upl64(z1.srl32(1).upl32(xyzf1.wwww()))); pmin = pmin.min(p0.min(p1)); pmax = pmax.max(p0.max(p1)); #endif } } #if _M_SSE >= 0x401 pmin = pmin.blend16<0x30>(pmin.srl32(1)); pmax = pmax.blend16<0x30>(pmax.srl32(1)); #endif GSVector4 o(context->XYOFFSET); GSVector4 s(1.0f / 16, 1.0f / 16, 2.0f, 1.0f); m_min.p = (GSVector4(pmin) - o) * s; m_max.p = (GSVector4(pmax) - o) * s; if(tme) { if(fst) { s = GSVector4(1.0f / 16, 1.0f).xxyy(); } else { s = GSVector4(1 << context->TEX0.TW, 1 << context->TEX0.TH, 1, 1); } m_min.t = tmin * s; m_max.t = tmax * s; } else { m_min.t = GSVector4::zero(); m_max.t = GSVector4::zero(); } if(color) { m_min.c = cmin.zzzz().u8to32(); m_max.c = cmax.zzzz().u8to32(); } else { m_min.c = GSVector4i::zero(); m_max.c = GSVector4i::zero(); } }
void RenderQuad() { if (quadVAO == 0) { // positions glm::vec3 pos1(-1.0, 1.0, 0.0); glm::vec3 pos2(-1.0, -1.0, 0.0); glm::vec3 pos3(1.0, -1.0, 0.0); glm::vec3 pos4(1.0, 1.0, 0.0); // texture coordinates glm::vec2 uv1(0.0, 1.0); glm::vec2 uv2(0.0, 0.0); glm::vec2 uv3(1.0, 0.0); glm::vec2 uv4(1.0, 1.0); // normal vector glm::vec3 nm(0.0, 0.0, 1.0); // calculate tangent/bitangent vectors of both triangles glm::vec3 tangent1, bitangent1; glm::vec3 tangent2, bitangent2; // - triangle 1 glm::vec3 edge1 = pos2 - pos1; glm::vec3 edge2 = pos3 - pos1; glm::vec2 deltaUV1 = uv2 - uv1; glm::vec2 deltaUV2 = uv3 - uv1; GLfloat f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y); tangent1.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x); tangent1.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y); tangent1.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z); tangent1 = glm::normalize(tangent1); bitangent1.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x); bitangent1.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); bitangent1.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); bitangent1 = glm::normalize(bitangent1); // - triangle 2 edge1 = pos3 - pos1; edge2 = pos4 - pos1; deltaUV1 = uv3 - uv1; deltaUV2 = uv4 - uv1; f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y); tangent2.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x); tangent2.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y); tangent2.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z); tangent2 = glm::normalize(tangent2); bitangent2.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x); bitangent2.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); bitangent2.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); bitangent2 = glm::normalize(bitangent2); GLfloat quadVertices[] = { // Positions // normal // TexCoords // Tangent // Bitangent pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z, pos2.x, pos2.y, pos2.z, nm.x, nm.y, nm.z, uv2.x, uv2.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z, pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z, pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z, pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z, pos4.x, pos4.y, pos4.z, nm.x, nm.y, nm.z, uv4.x, uv4.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z }; // Setup plane VAO glGenVertexArrays(1, &quadVAO); glGenBuffers(1, &quadVBO); glBindVertexArray(quadVAO); glBindBuffer(GL_ARRAY_BUFFER, quadVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(8 * sizeof(GLfloat))); glEnableVertexAttribArray(4); glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(11 * sizeof(GLfloat))); } glBindVertexArray(quadVAO); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); }
void DrawCharRect(Vector2 p0, Vector2 p1, int sprite, int flags, Colour colour) { if ((gRectVertCount + 6) > kMaxRectVerts) { DebugLn("DrawRect overflow"); return; } Vertex* v = &gRectVerts[gRectVertCount]; gRectVertCount += 6; int sx = sprite & 0x1F; int sy = sprite >> 5; Vector2 uv0(sx / 32.0f, sy / 32.0f); Vector2 uv1((sx + 1) / 32.0f, (sy + 1) / 32.0f); Vector2 scale(2.0f / (float)kWinWidth, -2.0f / (float)kWinHeight); if (flags & kFlipX) Swap(uv0.x, uv1.x); if (flags & kFlipY) Swap(uv0.y, uv1.y); // t0 v->pos.x = p0.x * scale.x; v->pos.y = p0.y * scale.y; v->uv.x = uv0.x; v->uv.y = uv0.y; v->colour = colour; v++; v->pos.x = p1.x * scale.x; v->pos.y = p0.y * scale.y; v->uv.x = uv1.x; v->uv.y = uv0.y; v->colour = colour; v++; v->pos.x = p1.x * scale.x; v->pos.y = p1.y * scale.y; v->uv.x = uv1.x; v->uv.y = uv1.y; v->colour = colour; v++; // t1 v->pos.x = p0.x * scale.x; v->pos.y = p0.y * scale.y; v->uv.x = uv0.x; v->uv.y = uv0.y; v->colour = colour; v++; v->pos.x = p1.x * scale.x; v->pos.y = p1.y * scale.y; v->uv.x = uv1.x; v->uv.y = uv1.y; v->colour = colour; v++; v->pos.x = p0.x * scale.x; v->pos.y = p1.y * scale.y; v->uv.x = uv0.x; v->uv.y = uv1.y; v->colour = colour; }
void compute_tangent_vectors(mesh_t &mesh) { int vertex_count = mesh.vertices.size() / 3; int face_count = mesh.indices.size() / 3; std::vector<glm::vec3> tangents; tangents.resize(vertex_count); int *tangent_counts = new int[vertex_count]; for (int i = 0; i < vertex_count; i++) tangent_counts[i] = 0; std::vector<float> &vertices = mesh.vertices; std::vector<float> &normals = mesh.normals; std::vector<float> &tex_coords = mesh.tex_coords; std::vector<unsigned int> &indices = mesh.indices; for (int i = 0; i < face_count; i++) { int i0 = indices[3*i]; int i1 = indices[3*i + 1]; int i2 = indices[3*i + 2]; int j0 = 2*i0; int j1 = 2*i1; int j2 = 2*i2; glm::vec2 uv0(tex_coords[j0], tex_coords[j0 + 1]); glm::vec2 uv1(tex_coords[j1], tex_coords[j1 + 1]); glm::vec2 uv2(tex_coords[j2], tex_coords[j2 + 1]); glm::vec2 st1 = uv1 - uv0; glm::vec2 st2 = uv2 - uv0; float det = st1.x*st2.y - st2.x*st1.y; if (det == 0.0f) continue; // pass if inverse matrix does not exist // assert(det != 0.0f); int k0 = 3*i0; int k1 = 3*i1; int k2 = 3*i2; glm::vec3 p0(vertices[k0], vertices[k0 + 1], vertices[k0 + 2]); glm::vec3 p1(vertices[k1], vertices[k1 + 1], vertices[k1 + 2]); glm::vec3 p2(vertices[k2], vertices[k2 + 1], vertices[k2 + 2]); glm::vec3 q1 = p1 - p0; glm::vec3 q2 = p2 - p0; float coef = 1.0f / det; glm::mat3 m( q1.x, q2.x, 0.0f, q1.y, q2.y, 0.0f, q1.z, q2.z, 0.0f ); glm::vec3 t = coef * glm::vec3(st2.y, -st1.y, 0.0f) * m; tangents[i0] += t; tangents[i1] += t; tangents[i2] += t; tangent_counts[i0]++; tangent_counts[i1]++; tangent_counts[i2]++; } mesh.tangents.resize(3*vertex_count); for (int i = 0; i < vertex_count; i++) { const glm::vec3 n(normals[3*i], normals[3*i + 1], normals[3*i + 2]); const glm::vec3 t = tangent_counts[i] > 0 ? tangents[i] / (float)tangent_counts[i] : tangents[i]; tangents[i] = glm::normalize(t - glm::dot(n, t) * n); mesh.tangents[3*i] = tangents[i].x; mesh.tangents[3*i + 1] = tangents[i].y; mesh.tangents[3*i + 2] = tangents[i].z; } delete [] tangent_counts; }
// // MQO // 面倒なので四角ポリゴンはないものと仮定 // void build_from_mqo( mqo_reader::document_type& doc, float scale, DWORD color, TextureCache& tc ) { clear(); // マテリアル for( mqo_reader::materials_type::const_iterator i = doc.materials.begin() ; i != doc.materials.end() ; ++i ) { SubModel m; m.vb = NULL; m.ib = NULL; m.texture = NULL; if( (*i).texture != "" ) { m.texture = tc.get_texture( (*i).texture ); } submodels_.push_back( m ); } { // default material SubModel m; m.vb = NULL; m.ib = NULL; submodels_.push_back( m ); } // 頂点, 面 for( mqo_reader::objdic_type::const_iterator i = doc.objects.begin() ; i != doc.objects.end() ; ++i ) { const mqo_reader::object_type& obj = (*i).second; // dictionary: // ( source vertex index, uv ) => destination vertex index struct VertexKey { int index; D3DXVECTOR2 uv; VertexKey(){} VertexKey( int aindex, const D3DXVECTOR2& auv ) : index( aindex ), uv( auv ) { } bool operator<( const VertexKey& a ) const { if( index < a.index ) { return true; } if( a.index < index ) { return false; } if( uv.x < a.uv.x ) { return true; } if( a.uv.x < uv.x ) { return false; } return uv.y < a.uv.y; } }; std::vector< std::map< VertexKey, int > > used_vertices; used_vertices.resize( submodels_.size() ); // マテリアルごとに使用頂点を分類 for( mqo_reader::faces_type::const_iterator j = obj.faces.begin() ; j != obj.faces.end() ; ++j ) { const mqo_reader::face_type& face = *j; int material_index = face.material_index; if( material_index == -1 ) { material_index = int( submodels_.size() - 1 ); } int i0 = face.vertex_indices[0]; int i1 = face.vertex_indices[1]; int i2 = face.vertex_indices[2]; D3DXVECTOR2 uv0( face.uv[0].u, face.uv[0].v ); D3DXVECTOR2 uv1( face.uv[1].u, face.uv[1].v ); D3DXVECTOR2 uv2( face.uv[2].u, face.uv[2].v ); std::map< VertexKey, int >& c = used_vertices[material_index]; c[ VertexKey( i0, uv0 ) ] = -1 ; c[ VertexKey( i1, uv1 ) ] = -1 ; c[ VertexKey( i2, uv2 ) ] = -1 ; } // マテリアルごとに使われている頂点を追加 size_t n = submodels_.size(); for( size_t i = 0 ; i < n ; i++ ) { SubModel& m = submodels_[i]; std::map< VertexKey, int >& c = used_vertices[i]; int no = int( m.vertex_source.size() ); for( std::map< VertexKey, int >::iterator j = c.begin(); j != c.end() ; ++j ) { const mqo_reader::vertex_type& src = obj.vertices[(*j).first.index]; model_vertex_type dst; dst.position = D3DXVECTOR3( src.x * scale, src.y * scale, src.z * -scale ); dst.normal = D3DXVECTOR3( 0, 0, 0 ); dst.diffuse = color; dst.uv = (*j).first.uv; m.vertex_source.push_back( dst ); (*j).second = no++; } } // マテリアルごとに面を追加 for( mqo_reader::faces_type::const_iterator j = obj.faces.begin() ; j != obj.faces.end() ; ++j ) { const mqo_reader::face_type& face = *j; int material_index = face.material_index; if( material_index == -1 ) { material_index = int( submodels_.size() - 1 ); } int i0 = face.vertex_indices[0]; int i1 = face.vertex_indices[1]; int i2 = face.vertex_indices[2]; D3DXVECTOR2 uv0( face.uv[0].u, face.uv[0].v ); D3DXVECTOR2 uv1( face.uv[1].u, face.uv[1].v ); D3DXVECTOR2 uv2( face.uv[2].u, face.uv[2].v ); std::map< VertexKey, int >& c = used_vertices[material_index]; int k0 = c[VertexKey( i0, uv0 )]; int k1 = c[VertexKey( i1, uv1 )]; int k2 = c[VertexKey( i2, uv2 )]; SubModel& m = submodels_[material_index]; m.index_source.push_back( k0 ); m.index_source.push_back( k1 ); m.index_source.push_back( k2 ); model_vertex_type& v0 = m.vertex_source[ k0 ]; model_vertex_type& v1 = m.vertex_source[ k1 ]; model_vertex_type& v2 = m.vertex_source[ k2 ]; D3DXVECTOR3 normal = cross( v1.position - v0.position, v2.position - v0.position ); v0.normal += normal; v1.normal += normal; v2.normal += normal; } } // 法線後処理 size_t n = submodels_.size(); for( size_t j = 0 ; j < n ; j++ ) { SubModel& m = submodels_[j]; for( std::vector< model_vertex_type >::iterator i = m.vertex_source.begin() ; i != m.vertex_source.end() ; ++i ) { D3DXVec3Normalize( &(*i).normal, &(*i).normal ); } } build_submodels(); }
// 建立矩形的VAO数据 void setupQuadVAO() { // 顶点位置 glm::vec3 pos1(-1.0, 1.0, 0.0); glm::vec3 pos2(-1.0, -1.0, 0.0); glm::vec3 pos3(1.0, -1.0, 0.0); glm::vec3 pos4(1.0, 1.0, 0.0); // 纹理坐标 glm::vec2 uv1(0.0, 1.0); glm::vec2 uv2(0.0, 0.0); glm::vec2 uv3(1.0, 0.0); glm::vec2 uv4(1.0, 1.0); // 法向量 glm::vec3 nm(0.0, 0.0, 1.0); // 计算两个三角形的TB向量 glm::vec3 tangent1, bitangent1; glm::vec3 tangent2, bitangent2; // 三角形1 glm::vec3 edge1 = pos2 - pos1; glm::vec3 edge2 = pos3 - pos1; glm::vec2 deltaUV1 = uv2 - uv1; glm::vec2 deltaUV2 = uv3 - uv1; GLfloat f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y); tangent1.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x); tangent1.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y); tangent1.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z); tangent1 = glm::normalize(tangent1); bitangent1.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x); bitangent1.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); bitangent1.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); bitangent1 = glm::normalize(bitangent1); // 三角形2 edge1 = pos3 - pos1; edge2 = pos4 - pos1; deltaUV1 = uv3 - uv1; deltaUV2 = uv4 - uv1; f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y); tangent2.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x); tangent2.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y); tangent2.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z); tangent2 = glm::normalize(tangent2); bitangent2.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x); bitangent2.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); bitangent2.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); bitangent2 = glm::normalize(bitangent2); // 每个三角形的TB向量提前计算出来 也可以由Geometry shader计算 GLfloat quadVertices[] = { // 位置 // 法向量 // 纹理 // Tangent 向量 // Bitangent 向量 pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z, pos2.x, pos2.y, pos2.z, nm.x, nm.y, nm.z, uv2.x, uv2.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z, pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z, pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z, pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z, pos4.x, pos4.y, pos4.z, nm.x, nm.y, nm.z, uv4.x, uv4.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z }; glGenVertexArrays(1, &quadVAOId); glGenBuffers(1, &quadVBOId); glBindVertexArray(quadVAOId); glBindBuffer(GL_ARRAY_BUFFER, quadVBOId); glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(8 * sizeof(GLfloat))); glEnableVertexAttribArray(4); glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(11 * sizeof(GLfloat))); glBindVertexArray(0); }
void CoronaRenderer::defineMesh(mtco_MayaObject *obj) { MObject meshObject = obj->mobject; MStatus stat = MStatus::kSuccess; bool hasDisplacement = false; Corona::Abstract::Map *displacementMap = NULL; float displacementMin = 0.0f; float displacementMax = 0.01f; // I do it here for displacement mapping, maybe we should to another place getObjectShadingGroups(obj->dagPath, obj->perFaceAssignments, obj->shadingGroups); if( obj->shadingGroups.length() > 0) { MFnDependencyNode shadingGroup(obj->shadingGroups[0]); MString sgn = shadingGroup.name(); MObject displacementObj = getConnectedInNode(obj->shadingGroups[0], "displacementShader"); MString doo = getObjectName(displacementObj); if( (displacementObj != MObject::kNullObj) && (displacementObj.hasFn(MFn::kDisplacementShader))) { MObject displacementMapObj = getConnectedInNode(displacementObj, "displacement"); if( (displacementMapObj != MObject::kNullObj) && (displacementMapObj.hasFn(MFn::kFileTexture))) { MFnDependencyNode displacmentMapNode(displacementObj); getFloat("mtco_displacementMin", displacmentMapNode, displacementMin); getFloat("mtco_displacementMax", displacmentMapNode, displacementMax); MString fileTexturePath = getConnectedFileTexturePath(MString("displacement"), displacmentMapNode); if( fileTexturePath != "") { MapLoader loader; displacementMap = loader.loadBitmap(fileTexturePath.asChar()); hasDisplacement = true; } } } } MFnMesh meshFn(meshObject, &stat); CHECK_MSTATUS(stat); MItMeshPolygon faceIt(meshObject, &stat); CHECK_MSTATUS(stat); MPointArray points; meshFn.getPoints(points); MFloatVectorArray normals; meshFn.getNormals( normals, MSpace::kWorld ); MFloatArray uArray, vArray; meshFn.getUVs(uArray, vArray); //logger.debug(MString("Translating mesh object ") + meshFn.name().asChar()); MString meshFullName = makeGoodString(meshFn.fullPathName()); Corona::TriangleData td; Corona::IGeometryGroup* geom = NULL; geom = this->context.scene->addGeomGroup(); obj->geom = geom; for( uint vtxId = 0; vtxId < points.length(); vtxId++) { geom->getVertices().push(Corona::Pos(points[vtxId].x,points[vtxId].y,points[vtxId].z)); } for( uint nId = 0; nId < normals.length(); nId++) { geom->getNormals().push(Corona::Dir(normals[nId].x,normals[nId].y,normals[nId].z)); } for( uint tId = 0; tId < uArray.length(); tId++) { geom->getMapCoords().push(Corona::Pos(uArray[tId],vArray[tId],0.0f)); geom->getMapCoordIndices().push(geom->getMapCoordIndices().size()); } MPointArray triPoints; MIntArray triVtxIds; MIntArray faceVtxIds; MIntArray faceNormalIds; for(faceIt.reset(); !faceIt.isDone(); faceIt.next()) { int faceId = faceIt.index(); int numTris; faceIt.numTriangles(numTris); faceIt.getVertices(faceVtxIds); MIntArray faceUVIndices; faceNormalIds.clear(); for( uint vtxId = 0; vtxId < faceVtxIds.length(); vtxId++) { faceNormalIds.append(faceIt.normalIndex(vtxId)); int uvIndex; faceIt.getUVIndex(vtxId, uvIndex); faceUVIndices.append(uvIndex); } for( int triId = 0; triId < numTris; triId++) { int faceRelIds[3]; faceIt.getTriangle(triId, triPoints, triVtxIds); for( uint triVtxId = 0; triVtxId < 3; triVtxId++) { for(uint faceVtxId = 0; faceVtxId < faceVtxIds.length(); faceVtxId++) { if( faceVtxIds[faceVtxId] == triVtxIds[triVtxId]) { faceRelIds[triVtxId] = faceVtxId; } } } uint vtxId0 = faceVtxIds[faceRelIds[0]]; uint vtxId1 = faceVtxIds[faceRelIds[1]]; uint vtxId2 = faceVtxIds[faceRelIds[2]]; uint normalId0 = faceNormalIds[faceRelIds[0]]; uint normalId1 = faceNormalIds[faceRelIds[1]]; uint normalId2 = faceNormalIds[faceRelIds[2]]; uint uvId0 = faceUVIndices[faceRelIds[0]]; uint uvId1 = faceUVIndices[faceRelIds[1]]; uint uvId2 = faceUVIndices[faceRelIds[2]]; if( hasDisplacement ) { Corona::DisplacedTriangleData tri; tri.displacement.map = displacementMap; MPoint p0 = points[vtxId0]; MPoint p1 = points[vtxId1]; MPoint p2 = points[vtxId2]; tri.v[0] = Corona::AnimatedPos(Corona::Pos(p0.x, p0.y, p0.z)); tri.v[1] = Corona::AnimatedPos(Corona::Pos(p1.x, p1.y, p1.z)); tri.v[2] = Corona::AnimatedPos(Corona::Pos(p2.x, p2.y, p2.z)); MVector n0 = normals[normalId0]; MVector n1 = normals[normalId1]; MVector n2 = normals[normalId2]; Corona::Dir dir0(n0.x, n0.y, n0.z); Corona::Dir dir1(n1.x, n1.y, n1.z); Corona::Dir dir2(n2.x, n2.y, n2.z); tri.n[0] = Corona::AnimatedDir(dir0); tri.n[1] = Corona::AnimatedDir(dir1); tri.n[2] = Corona::AnimatedDir(dir2); Corona::Pos uv0(uArray[uvId0],vArray[uvId0],0.0); Corona::Pos uv1(uArray[uvId1],vArray[uvId1],0.0); Corona::Pos uv2(uArray[uvId2],vArray[uvId2],0.0); Corona::StaticArray<Corona::Pos, 3> uvp; uvp[0] = uv0; uvp[1] = uv1; uvp[2] = uv2; tri.t.push(uvp); tri.materialId = 0; tri.displacement.min = displacementMin; tri.displacement.max = displacementMax; geom->addPrimitive(tri); }else{ Corona::TriangleData tri; tri.v = Corona::AnimatedPosI3(vtxId0, vtxId1, vtxId2); tri.n = Corona::AnimatedDirI3(normalId0, normalId1, normalId2); tri.t[0] = uvId0; tri.t[1] = uvId1; tri.t[2] = uvId2; tri.materialId = 0; geom->addPrimitive(tri); } } } }
void mesh::calculateTangents() { std::vector<float> tans(3*vertCount, 0); std::vector<float> bitans(3*vertCount, 0); tangents.resize(4 * vertCount); //calculate tentative tangents and bitangents for each triangle for (int i = 0; i < triCount; i++) { //find the vertices of the current triangle, and their UV coords int vi1 = triangles[3*i]; int vi2 = triangles[3*i + 1]; int vi3 = triangles[3*i + 2]; glm::vec3 vert0(vertices[3*vi1], vertices[3*vi1 + 1], vertices[3*vi1 + 2]); glm::vec3 vert1(vertices[3*vi2], vertices[3*vi2 + 1], vertices[3*vi2 + 2]); glm::vec3 vert2(vertices[3*vi3], vertices[3*vi3 + 1], vertices[3*vi3 + 2]); glm::vec2 uv0(texCoords[2*vi1], texCoords[2*vi1 + 1]); glm::vec2 uv1(texCoords[2*vi2], texCoords[2*vi2 + 1]); glm::vec2 uv2(texCoords[2*vi3], texCoords[2*vi3 + 1]); //differences in position and UV coords glm::vec3 dPos1 = vert1 - vert0; glm::vec3 dPos2 = vert2 - vert0; glm::vec2 dUV1 = uv1 - uv0; glm::vec2 dUV2 = uv2 - uv0; //calculate and store the tangent and bitangent float coeff = 1.0f / (dUV1.x * dUV2.y - dUV1.y * dUV2.x); glm::vec3 tan = dPos1 * dUV2.y - dPos2 * dUV1.y; glm::vec3 bitan = dPos2 * dUV1.x - dPos1 * dUV2.x; tan *= coeff; bitan *= coeff; tans[3*vi1] += tan.x; tans[3*vi1 + 1] += tan.y; tans[3*vi1 + 2] += tan.z; tans[3*vi2] += tan.x; tans[3*vi2 + 1] += tan.y; tans[3*vi2 + 2] += tan.z; tans[3*vi3] += tan.x; tans[3*vi3 + 1] += tan.y; tans[3*vi3 + 2] += tan.z; bitans[3*vi1] += bitan.x; bitans[3*vi1 + 1] += bitan.y; bitans[3*vi1 + 2] += bitan.z; bitans[3*vi2] += bitan.x; bitans[3*vi2 + 1] += bitan.y; bitans[3*vi2 + 2] += bitan.z; bitans[3*vi3] += bitan.x; bitans[3*vi3 + 1] += bitan.y; bitans[3*vi3 + 2] += bitan.z; } //find the final tangent (and bitangent) for each vertex for (int j = 0; j < vertCount; j++) { glm::vec3 normal (normals[3*j], normals[3*j + 1], normals[3*j + 2]); glm::vec3 tangent (tans[3*j], tans[3*j + 1], tans[3*j + 2]); glm::vec3 bitangent (bitans[3*j], bitans[3*j + 1], bitans[3*j + 2]); glm::normalize(tangent); glm::normalize(bitangent); //orthagonalize glm::vec3 tangent_orth(normal); tangent_orth *= glm::dot(normal, tangent); tangent_orth = tangent - tangent_orth; glm::normalize(tangent_orth); //compute handedness float handedness = 1.0f; glm::vec3 nCrossT = glm::cross(normal, tangent_orth); if(glm::dot(nCrossT, bitangent) > 0) { handedness = 1.0f; } else { handedness = -1.0f; } //store the orthagonalized tangent and handedness tangents[4*j] = tangent_orth.x; tangents[4*j + 1] = tangent_orth.y; tangents[4*j + 2] = tangent_orth.z; tangents[4*j + 3] = handedness; } }