ParticleEmitter* ParticleEmitter::create(const char* textureFile, TextureBlending textureBlending, unsigned int particleCountMax) { Texture* texture = NULL; texture = Texture::create(textureFile, false); if (!texture) { GP_ERROR("Failed to create texture for particle emitter."); return NULL; } GP_ASSERT(texture->getWidth()); GP_ASSERT(texture->getHeight()); // Use default SpriteBatch material. SpriteBatch* batch = SpriteBatch::create(texture, NULL, particleCountMax); texture->release(); // batch owns the texture. GP_ASSERT(batch); ParticleEmitter* emitter = new ParticleEmitter(batch, particleCountMax); GP_ASSERT(emitter); // By default assume only one frame which uses the entire texture. emitter->setTextureBlending(textureBlending); emitter->_spriteTextureWidth = texture->getWidth(); emitter->_spriteTextureHeight = texture->getHeight(); emitter->_spriteTextureWidthRatio = 1.0f / (float)texture->getWidth(); emitter->_spriteTextureHeightRatio = 1.0f / (float)texture->getHeight(); Rectangle texCoord((float)texture->getWidth(), (float)texture->getHeight()); emitter->setSpriteFrameCoords(1, &texCoord); return emitter; }
void Cc3dMesh::initTexCoordList(const float texCoordArray[],int texCoordArrayLen){ m_texCoordList.clear(); for(int i=0;i<texCoordArrayLen;i+=2){ Cc3dVector2 texCoord(texCoordArray[i],texCoordArray[i+1]); m_texCoordList.push_back(texCoord); } }
void Triangle2::convertBarycentricToUVs(float &u, float &v) { // TODO: Make it work for polygon (tri/quad). Vector3D t0 = texCoord(0)->data().position; Vector3D t1 = texCoord(1)->data().position; Vector3D t2 = texCoord(2)->data().position; Vector3D e1 = t1 - t0; Vector3D e2 = t2 - t0; Vector3D final = t0 + e1 * u + e2 * v; u = final.x; v = final.y; }
void EarthWidget::buildModel() { // load texture QImage im(":/images/earthmap.jpg"); Q_ASSERT(!im.isNull()); _textureId = bindTexture(im); // build sphere data _vertexPositions.reserve(M * N); _normals.reserve(M * N); _texCoords.reserve(M * N); _vertIds = QVector<QVector<int>>(M, QVector<int>(N)); for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { float xratio = 1.0f / (N - 1) * j; float yratio = 1.0f / (M - 1) * i; float xangle = M_PI * 2 * xratio; float yangle = M_PI * yratio - M_PI_2; QVector4D pos(cos(xangle)*cos(yangle), sin(yangle), sin(xangle)*cos(yangle), 1); _vertexPositions << pos; QVector3D normal(cos(xangle)*cos(yangle), sin(yangle), sin(xangle)*cos(yangle)); _normals << normal; QVector2D texCoord(1.0 - xratio, yratio); _texCoords << texCoord; _vertIds[i][j] = _texCoords.size() - 1; } } }
std::shared_ptr<SimpleMesh> SimpleMeshCreator::sphere(float radius, unsigned int numLoops, unsigned int segmentsPerLoop, vec4 color) { auto spheremesh = std::make_shared<SimpleMesh>(); numLoops = std::max(4u, numLoops); segmentsPerLoop = std::max(8u, segmentsPerLoop); // Set identity matrix spheremesh->setModelMatrix(mat4(1.f)); // Create Vertices auto normals = std::make_shared<Vec3BufferRAM>((numLoops + 1) * (segmentsPerLoop + 1)); auto normalBuffer = std::make_shared<Buffer<vec3>>(normals); unsigned int pointsPerLine = segmentsPerLoop + 1; for (unsigned int i = 0; i <= numLoops; ++i) { for (unsigned int j = 0; j <= segmentsPerLoop; ++j) { float theta = (i * static_cast<float>(M_PI) / numLoops); // + ((static_cast<float>(M_PI) * j) / (segmentsPerLoop * numLoops)); if (i == numLoops) theta = static_cast<float>(M_PI); float phi = j * 2 * static_cast<float>(M_PI) / segmentsPerLoop; float sinTheta = std::sin(theta); float sinPhi = std::sin(phi); float cosTheta = std::cos(theta); float cosPhi = std::cos(phi); vec3 normal(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta); vec3 vert(normal * radius); vec3 texCoord(static_cast<float>(j) / segmentsPerLoop, static_cast<float>(i) / numLoops, 0.0f); spheremesh->addVertex(vert, texCoord, color); normals->set(i * pointsPerLine + j, normal); } } spheremesh->addBuffer(BufferType::NormalAttrib, normalBuffer); // Create Indices // compute indices spheremesh->setIndicesInfo(DrawType::Triangles, ConnectivityType::None); for (unsigned int y = 0; y < numLoops; ++y) { auto indices = std::make_shared<IndexBufferRAM>(pointsPerLine * 2); auto indexBuf = std::make_shared<IndexBuffer>(indices); unsigned int offset = y * pointsPerLine; std::size_t count = 0; for (unsigned int x = 0; x < pointsPerLine; ++x) { indices->set(count++, offset + x); indices->set(count++, offset + x + pointsPerLine); } spheremesh->addIndicies(Mesh::MeshInfo(DrawType::Triangles, ConnectivityType::Strip), indexBuf); } return spheremesh; }
void Triangle2::computeNormalsIfNeeded() { // TODO: Make it work for polygon (tri/quad). if (normalsAreValid) return; Vector3D u, v; u = texCoord(0)->data().position - texCoord(1)->data().position; v = texCoord(1)->data().position - texCoord(2)->data().position; texCoordNormal = u.Cross(v); u = vertex(0)->data().position - vertex(1)->data().position; v = vertex(1)->data().position - vertex(2)->data().position; vertexNormal = u.Cross(v); normalsAreValid = true; }
TexCoordNode *Triangle2::texCoordNotInEdge(const TexCoordEdge *edge) const { for (unsigned int i = 0; i < count(); i++) { TexCoordNode *currentTexCoord = texCoord(i); if (currentTexCoord != edge->texCoord(0) && currentTexCoord != edge->texCoord(1)) return currentTexCoord; } return NULL; }
void GeometryCreator::fillGridData(std::vector<Vertex_PositionTexCoord>& vertices, unsigned int rowCount, unsigned int columnCount) { for (unsigned int rowIndex = 0; rowIndex < rowCount; rowIndex++) { for (unsigned int columnIndex = 0; columnIndex < columnCount; columnIndex++) { // Normalize the row position to get it in a 0 to 1 range glm::vec2 texCoord(rowIndex / static_cast<float>(rowCount), columnIndex / static_cast<float>(columnCount)); int index = rowIndex * columnCount + columnIndex; vertices[index].texCoord = texCoord; } } }
void CText2D::Render(float _posX, float _posY) { __INT32 posX = __INT32 (_posX); __INT32 posY = __INT32 (_posY); for(int i = 0; i < strlen(m_strText); i++) { SCharMap* map = m_CharMap->GetMap(m_strText[i]); if(map != NULL) { SRect<__INT32> border(posX, posY, 30, 30); SRect<__INT32> texCoord(map->x, map->y, map->w, map->h); g->DrawImageRegion(border, texCoord, m_img); posX += 30; } } }
void GLES20RenderEngine::endGroup() { const Group group(mGroupStack.top()); mGroupStack.pop(); // activate the previous render target GLuint fbo = 0; if (!mGroupStack.isEmpty()) { fbo = mGroupStack.top().fbo; } glBindFramebuffer(GL_FRAMEBUFFER, fbo); // set our state Texture texture(Texture::TEXTURE_2D, group.texture); texture.setDimensions(group.width, group.height); glBindTexture(GL_TEXTURE_2D, group.texture); mState.setPlaneAlpha(1.0f); mState.setPremultipliedAlpha(true); mState.setOpaque(false); mState.setTexture(texture); mState.setColorMatrix(group.colorTransform); glDisable(GL_BLEND); Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2); Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); Mesh::VertexArray<vec2> texCoord(mesh.getTexCoordArray<vec2>()); position[0] = vec2(0, 0); position[1] = vec2(group.width, 0); position[2] = vec2(group.width, group.height); position[3] = vec2(0, group.height); texCoord[0] = vec2(0, 0); texCoord[1] = vec2(1, 0); texCoord[2] = vec2(1, 1); texCoord[3] = vec2(0, 1); drawMesh(mesh); // reset color matrix mState.setColorMatrix(mat4()); // free our fbo and texture glDeleteFramebuffers(1, &group.fbo); glDeleteTextures(1, &group.texture); }
void RPG_GuiMinimap_VisionGUI::OnPaint(VGraphicsInfo &Graphics, const VItemRenderInfo &parentState) { VASSERT(m_maskShader); VImageState &img = m_Image.m_States[GetCurrentState()]; VColorRef iColor = parentState.iFadeColor; VRectanglef rect = GetBoundingBox(); VRectanglef texCoord(0.f, 0.f, 1.f, 1.f); VTextureObject *pTex = img.GetCurrentTexture(); // Update shader registers in the const tables of the shader pass: m_regTransform.SetRegisterValueF(m_maskShader, m_transform.data); m_regFadeColor.SetRegisterValueF(m_maskShader, m_fadeColor.data); // Render the quad with our mask shader Overlay2DVertex_t v[6]; IVRender2DInterface::CreateQuadVertices(rect.m_vMin.x,rect.m_vMin.y,rect.m_vMax.x,rect.m_vMax.y,texCoord.m_vMin.x,texCoord.m_vMin.y,texCoord.m_vMax.x,texCoord.m_vMax.y,iColor,v); VSimpleRenderState_t state = VGUIManager::DefaultGUIRenderState(); Graphics.Renderer.Draw2DBufferWithShader(6, v, pTex, *m_maskShader); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::Vec2f RivTernaryScalarMapper::mapToTextureCoord(double soil, double sgas, bool isTransparent) const { // Clamp the float texture coordinate to avoid edge issues when looking up the texture coordinate // The issue was detected on Linux, no similar issues has been seen on Windows double edgeClampDelta = 0.001; double soilNormalized = (soil - m_rangeMinSoil) * m_soilFactor; soilNormalized = cvf::Math::clamp(soilNormalized, edgeClampDelta, 1.0 - edgeClampDelta); double sgasNormalized = (sgas - m_rangeMinSgas) * m_sgasFactor; sgasNormalized = cvf::Math::clamp(sgasNormalized, edgeClampDelta, 1.0 - soilNormalized); sgasNormalized /= 2.0; if (isTransparent) { sgasNormalized += 0.5; } cvf::Vec2f texCoord(static_cast<float>(soilNormalized), static_cast<float>(sgasNormalized)); return texCoord; }
// // Creates a cylinder at the origin oriented along the Z-axis. 'radius' // represents the distance from the center to the inner ring. 'height' // represents the amount to extrude along the Z-axis. 'numStacks' is the // number of layers along the Z-axis, 'numSlices' is the number of radial // divisions. // STShape* CreateCylinder( float radius, float height, unsigned int numSlices, unsigned int numStacks) { STShape* result = new STShape(); for(unsigned int ii = 0; ii <= numStacks; ++ii) { for(unsigned int jj = 0; jj < numSlices; ++jj) { const float theta = float(jj) * 2.0f * float(M_PI) / float(numSlices); STPoint3 position(radius * cosf(theta), radius * sinf(theta), height * (float(ii) / numStacks)); STPoint2 texCoord(ii / float(numStacks), jj / float(numSlices - 1)); result->AddVertex( STShape::Vertex(position, STVector3::Zero, texCoord)); } } for(unsigned int ii = 0; ii < numStacks; ii++) { for(unsigned int jj = 0; jj < numSlices; jj++) { int jjPlus1 = (jj + 1) % numSlices; result->AddFace(STShape::Face( (ii + 1)*numSlices + jj, (ii + 0)*numSlices + jj, (ii + 0)*numSlices + jjPlus1)); result->AddFace(STShape::Face( (ii + 1)*numSlices + jj, (ii + 0)*numSlices + jjPlus1, (ii + 1)*numSlices + jjPlus1)); } } result->GenerateNormals(); return result; }
void ParticleEmitter::setTexture(Texture* texture, BlendMode blendMode) { // Create new batch before releasing old one, in case the same texture // is used for both (so it's not released before passing to the new batch). SpriteBatch* batch = SpriteBatch::create(texture, NULL, _particleCountMax); batch->getSampler()->setFilterMode(Texture::LINEAR_MIPMAP_LINEAR, Texture::LINEAR); // Free existing batch SAFE_DELETE(_spriteBatch); _spriteBatch = batch; _spriteBatch->getStateBlock()->setDepthWrite(false); _spriteBatch->getStateBlock()->setDepthTest(true); setBlendMode(blendMode); _spriteTextureWidth = texture->getWidth(); _spriteTextureHeight = texture->getHeight(); _spriteTextureWidthRatio = 1.0f / (float)texture->getWidth(); _spriteTextureHeightRatio = 1.0f / (float)texture->getHeight(); // By default assume only one frame which uses the entire texture. Rectangle texCoord((float)texture->getWidth(), (float)texture->getHeight()); setSpriteFrameCoords(1, &texCoord); }
void Cball::makeBall(float r,int nSlice,int nStack,string texFilePath){ //make ball float dA=360.0/nSlice; float dB=180.0/nStack; const float PIDIV180=c3d_PI/180; vector<Cc3dVector4> positionList; vector<Cc3dVector2> texCoordList; vector<Cc3dVector4> normalList; vector<Cc3dIDTriangle> IDtriList; //generate positionList, texCoordList, normalList, colorList for(int i=0;i<=nStack;i++){ float B=-90+i*dB; float y=r*sinf(B*PIDIV180); float cosB=cosf(B*PIDIV180); for (int j=0; j<=nSlice; j++) { float A=j*dA; float R=r*cosB; float x=R*cosf(A*PIDIV180); float z=R*sinf(A*PIDIV180); Cc3dVector4 position(x,y,z,1); float s=(float)j/nSlice+0.25; float t=1-(float)i/nStack; Cc3dVector2 texCoord(s,t); Cc3dVector4 normal=normalize(cc3dv4(position.x(), position.y(), position.z(), 0)); positionList.push_back(position); texCoordList.push_back(texCoord); normalList.push_back(normal); } } //generate IDtriList for(int i=0;i<nStack;i++){ for(int j=0;j<nSlice;j++){ int vID_ld=(nSlice+1)*i+j; int vID_rd=vID_ld+1; int vID_ru=vID_rd+(nSlice+1); int vID_lu=vID_ru-1; Cc3dIDTriangle IDtri0(vID_ld,vID_rd,vID_ru); Cc3dIDTriangle IDtri1(vID_ld,vID_ru,vID_lu); IDtriList.push_back(IDtri0); IDtriList.push_back(IDtri1); } } Cc3dSubMesh*subMesh=new Cc3dSubMesh(); subMesh->autorelease(); int nPos=(int)positionList.size(); for(int i=0;i<nPos;i++){ Cc3dVector4&pos=positionList[i]; Cc3dVector2&texCoord=texCoordList[i]; Cc3dVector4&norm=normalList[i]; subMesh->addVertex(Cc3dVertex(pos,texCoord,norm)); } int nIDtri=(int)IDtriList.size(); for(int i=0;i<nIDtri;i++){ Cc3dIDTriangle&IDtri=IDtriList[i]; subMesh->addIDtri(IDtri); } //--texture if(texFilePath.empty()==false){ Cc3dTexture*texture=Cc3dTextureCache::sharedTextureCache()->addImage(texFilePath,GL_CLAMP_TO_EDGE,GL_CLAMP_TO_EDGE); subMesh->setTexture(texture); } //----mesh Cc3dMesh*mesh=new Cc3dMesh(); mesh->autorelease(); mesh->addSubMesh(subMesh); //----model this->addMesh(mesh); }
// // Creates a cylinder at the origin oriented along the Z-axis. // 'innerRadius' represents the distance from the center to the inner ring. // innerRadius + thickness represents the distance from the center to the // outer rng. 'height' represents the amount to extrude along the Z-axis. // 'numStacks' is the number of layers along the Z-axis, 'numSlices' is // the number of radial divisions. // STShape* CreateThickCylinder( float innerRadius, float thickness, float height, unsigned int numSlices, unsigned int numStacks) { STShape* result = new STShape(); // // Vertex packing // // 0 -> Slices * (Stacks + 1) - 1 = Inner ring // Slices * (Stacks + 1) -> Slices * (Stacks + 1) * 2 - 1 = Outer ring // // Face packing // // 0 -> Stacks * Slices * 2 - 1 = Inner ring // Stacks * Slices * 2 -> Stacks * Slices * 4 - 1 = Outer ring // Stacks * Slices * 4 -> Stacks * Slices * 4 - 1 = Connection between rings // const float ringRadii[2] = { innerRadius, innerRadius + thickness }; const int ringVertexOffsets[2] = { 0, numSlices * (numStacks + 1) }; const float PI2_Slices = 2.0f * float(M_PI) / float(numSlices); for (unsigned int ring = 0; ring < 2; ring++) { float ringRadius = ringRadii[ring]; int ringVertexOffset = ringVertexOffsets[ring]; for (unsigned int ii = 0; ii <= numStacks; ++ii) { for (unsigned int jj = 0; jj < numSlices; ++jj) { const float theta = float(jj) * PI2_Slices; STPoint3 position(ringRadius * cosf(theta), ringRadius * sinf(theta), height * (float(ii) / numStacks)); STPoint2 texCoord(ii / float(numStacks), jj / float(numSlices - 1)); result->AddVertex( STShape::Vertex(position, STVector3::Zero, texCoord)); } } for (unsigned int ii = 0; ii < numStacks; ++ii) { for(unsigned int jj = 0; jj < numSlices; jj++) { int jjPlus1 = (jj + 1) % numSlices; STShape::Face firstFace( ringVertexOffset + (ii + 1)*numSlices + jj, ringVertexOffset + (ii + 0)*numSlices + jj, ringVertexOffset + (ii + 0)*numSlices + jjPlus1); STShape::Face secondFace( ringVertexOffset + (ii + 1)*numSlices + jj, ringVertexOffset + (ii + 0)*numSlices + jjPlus1, ringVertexOffset + (ii + 1)*numSlices + jjPlus1); // // The inner face points the opposite direciton // if (ring == 0) { firstFace.ReverseWinding(); secondFace.ReverseWinding(); } result->AddFace(firstFace); result->AddFace(secondFace); } } } for (unsigned int ii = 0; ii <= numStacks; ii += numStacks) { for (unsigned int jj = 0; jj < numSlices; jj++) { int jjPlus1 = (jj + 1) % numSlices; STShape::Face firstFace( ringVertexOffsets[0] + ii * numSlices + jj, ringVertexOffsets[1] + ii * numSlices + jjPlus1, ringVertexOffsets[1] + ii * numSlices + jj); STShape::Face secondFace( ringVertexOffsets[0] + ii * numSlices + jj, ringVertexOffsets[0] + ii * numSlices + jjPlus1, ringVertexOffsets[1] + ii * numSlices + jjPlus1); // // The bottom face points the opposite direciton // if (ii == numStacks) { firstFace.ReverseWinding(); secondFace.ReverseWinding(); } result->AddFace(firstFace); result->AddFace(secondFace); } } result->GenerateNormals(); return result; }
bool Triangle::hit(const Ray& r, const real_t t0, const real_t t1, hitRecord& hR, bool fullRecord) const { Ray tRay = r.transform(invMat); real_t mult[3]; Vector3 a_minus_b = vertices[0].position - vertices[1].position; Vector3 a_minus_c = vertices[0].position - vertices[2].position; Vector3 a_minus_e = vertices[0].position - tRay.e; real_t a = a_minus_b.x; real_t b = a_minus_b.y; real_t c = a_minus_b.z; real_t d = a_minus_c.x; real_t e = a_minus_c.y; real_t f = a_minus_c.z; real_t g = tRay.d.x; real_t h = tRay.d.y; real_t i = tRay.d.z; real_t j = a_minus_e.x; real_t k = a_minus_e.y; real_t l = a_minus_e.z; real_t ei_minus_hf = e * i - h * f; real_t gf_minus_di = g * f - d * i; real_t dh_minus_eg = d * h - e * g; real_t ak_minus_jb = a * k - j * b; real_t jc_minus_al = j * c - a * l; real_t bl_minus_kc = b * l - k * c; real_t M = a * ei_minus_hf + b * gf_minus_di + c * dh_minus_eg; real_t time = (f * ak_minus_jb + e * jc_minus_al + d * bl_minus_kc) / -M; if (time <= t0 || time >= t1) { return false; } real_t beta = (j * ei_minus_hf + k * gf_minus_di + l * dh_minus_eg) / M; if (beta < 0 || beta > 1) return false; real_t gamma = (i * ak_minus_jb + h * jc_minus_al + g * bl_minus_kc) / M; if (gamma < 0 || gamma > 1 - beta) return false; hR.t = time; hR.shape_ptr = (Geometry*)this; if (!fullRecord) return true; mult[0] = 1-beta-gamma; mult[1] = beta; mult[2] = gamma; Vector2 texCoord(0,0); for(int i=0;i<3;i++) texCoord += mult[i]*vertices[i].tex_coord; texCoord[0] = fmod(texCoord[0],1.0); texCoord[1] = fmod(texCoord[1],1.0); if(texCoord[0]<0) texCoord[0]+=1; if(texCoord[1]<0) texCoord[0]+=1; const Material* materials[] = { vertices[0].material,vertices[1].material,vertices[2].material }; if(!simple) getMaterialProperties(hR.mp, mult, texCoord, materials); else getMaterialProperties(hR.mp,texCoord, materials[0]); hR.n = Vector3(0,0,0); for(int i=0;i<3;i++) hR.n += mult[i]*vertices[i].normal; hR.n = normalize( normMat*hR.n); if (materials[0]) hR.bsdf_ptr = (BSDF*)&(materials[0]->bsdf); Vector3 x, y, z = hR.n; coordinate_system(z, &x, &y); hR.shading_trans = Matrix3(x, y, z); inverse(&hR.inv_shading_trans, hR.shading_trans); hR.p = r.d * time + r.e; return true; }
void Triangle::hitPacket(const Packet& packet, int start, int end, real_t t0, real_t *t1Ptr, std::vector<hitRecord>& hs, bool fullRecord) const { /*Matrix4 nm = this->invMat; nm(3,0)=0; nm(3,1)=0; nm(3,2)=0; Ray rays[256]; for(int i=start;i<end;i++) { rays[i] = packet.rays[i]; packet.rays[i].transform(invMat); }*/ // TODO: static float *texCoord_x, *texCoord_y, *norm_x, *norm_y, *norm_z; texCoord_x = new float[end - start]; texCoord_y = new float[end - start]; norm_x = new float[end - start]; norm_y = new float[end - start]; norm_z = new float[end - start]; int *hit_flag = new int[end - start]; ispc::hit_triangle(packet.e_x, packet.e_y, packet.e_z, packet.d_x, packet.d_y, packet.d_z, t0, t1Ptr, (double*)&vertices[0],(double*)&vertices[1],(double*)&vertices[2], (this->invMat._m), start, end, (int)fullRecord, hit_flag, texCoord_x, texCoord_y, norm_x, norm_y, norm_z); const Material* materials[] = { vertices[0].material,vertices[1].material,vertices[2].material }; for (int i = start; i < end; i++) { if (hit_flag[i - start]) { hs[i].t = t1Ptr[i]; Vector2 texCoord(texCoord_x[i - start], texCoord_y[i - start]); // TODO: interpolation //if(!simple) //getMaterialProperties(hs[i].mp, mult, texCoord, materials); //else getMaterialProperties(hs[i].mp,texCoord, materials[0]); hs[i].n = Vector3(norm_x[i - start], norm_y[i - start], norm_z[i - start]); if (materials[0]) hs[i].bsdf_ptr = (BSDF*)&(materials[0]->bsdf); Vector3 x, y, z = hs[i].n; coordinate_system(z, &x, &y); hs[i].shading_trans = Matrix3(x, y, z); inverse(&hs[i].inv_shading_trans, hs[i].shading_trans); hs[i].shape_ptr = (Geometry*)this; hs[i].p = packet.rays[i].d * hs[i].t + packet.rays[i].e; } } /*for(int i=start;i<end;i++) packet.rays[i]= rays[i];*/ delete[] texCoord_x; delete[] texCoord_y; delete[] norm_x; delete[] norm_y; delete[] norm_z; }
Cc3dMeshData*genSampleCubeWithCode(float cx,float cy,float cz,float dx,float dy,float dz, float k_s, float k_t, int cubUVMode) //用代码生成示例立方体 //cx,cy,cz为中心 //dx,dy,dz分别为x,y,z方向上的边心距 { Cc3dMeshData*meshData=new Cc3dMeshData(); meshData->init(); meshData->autorelease(); meshData->vlist.reserve(8); meshData->IDtriList.reserve(12); //----生成顶点数据 Cc3dVertex tv; //前面 tv.setPos(Cc3dVector3(cx-dx, cy-dy,cz+dz));tv.setTexCoord(Cc3dVector2(0, 0));tv.setNorm(Cc3dVector3(0, 0, 1));//0 meshData->vlist.push_back(tv); tv.setPos(Cc3dVector3(cx+dx, cy-dy,cz+dz));tv.setTexCoord(Cc3dVector2(1, 0));tv.setNorm(Cc3dVector3(0, 0, 1));//1 meshData->vlist.push_back(tv); tv.setPos(Cc3dVector3(cx+dx, cy+dy, cz+dz));tv.setTexCoord(Cc3dVector2(1, 1));tv.setNorm(Cc3dVector3(0, 0, 1));//2 meshData->vlist.push_back(tv); tv.setPos(Cc3dVector3(cx-dx, cy+dy, cz+dz));tv.setTexCoord(Cc3dVector2(0, 1));tv.setNorm(Cc3dVector3(0, 0, 1));//3 meshData->vlist.push_back(tv); //后面 tv.setPos(Cc3dVector3(cx-dx, cy-dy,cz -dz));tv.setTexCoord(Cc3dVector2(0, 0));tv.setNorm(Cc3dVector3(0, 0, -1));//4 meshData->vlist.push_back(tv); tv.setPos(Cc3dVector3(cx+dx, cy-dy, cz-dz));tv.setTexCoord(Cc3dVector2(1, 0));tv.setNorm(Cc3dVector3(0, 0, -1));//5 meshData->vlist.push_back(tv); tv.setPos(Cc3dVector3(cx+dx, cy+dy, cz-dz));tv.setTexCoord(Cc3dVector2(1, 1));tv.setNorm(Cc3dVector3(0, 0, -1));//6 meshData->vlist.push_back(tv); tv.setPos(cx-dx, cy+dy, cz-dz);tv.setTexCoord(0, 1);tv.setNorm(0, 0, -1);//7 meshData->vlist.push_back(tv); //上面 tv.setPos(cx-dx, cy+dy, cz+dz);tv.setTexCoord(0, 0);tv.setNorm(0, 1, 0);//8 meshData->vlist.push_back(tv); tv.setPos(cx+dx, cy+dy, cz+dz);tv.setTexCoord(1, 0);tv.setNorm(0, 1, 0);//9 meshData->vlist.push_back(tv); tv.setPos(cx+dx, cy+dy, cz-dz);tv.setTexCoord(1, 1);tv.setNorm(0, 1, 0);//10 meshData->vlist.push_back(tv); tv.setPos(cx-dx, cy+dy, cz-dz);tv.setTexCoord(0, 1);tv.setNorm(0, 1, 0);//11 meshData->vlist.push_back(tv); //下面 tv.setPos(cx-dx, cy-dy, cz+dz);tv.setTexCoord(0, 0);tv.setNorm(0, -1, 0);//12 meshData->vlist.push_back(tv); tv.setPos(cx+dx, cy-dy, cz+dz);tv.setTexCoord(1, 0);tv.setNorm(0, -1, 0);//13 meshData->vlist.push_back(tv); tv.setPos(cx+dx, cy-dy, cz-dz);tv.setTexCoord(1, 1);tv.setNorm(0, -1, 0);//14 meshData->vlist.push_back(tv); tv.setPos(cx-dx, cy-dy, cz-dz);tv.setTexCoord(0, 1);tv.setNorm(0, -1, 0);//15 meshData->vlist.push_back(tv); //左面 tv.setPos(cx-dx, cy-dy,cz -dz);tv.setTexCoord(0, 0);tv.setNorm(-1, 0, 0);//16 meshData->vlist.push_back(tv); tv.setPos(cx-dx, cy-dy, cz+dz);tv.setTexCoord(1, 0);tv.setNorm(-1, 0, 0);//17 meshData->vlist.push_back(tv); tv.setPos(cx-dx, cy+dy, cz+dz);tv.setTexCoord(1, 1);tv.setNorm(-1, 0, 0);//18 meshData->vlist.push_back(tv); tv.setPos(cx-dx, cy+dy, cz-dz);tv.setTexCoord(0, 1);tv.setNorm(-1, 0, 0);//19 meshData->vlist.push_back(tv); //右面 tv.setPos(cx+dx, cy-dy, cz-dz);tv.setTexCoord(0, 0);tv.setNorm(1, 0, 0);//20 meshData->vlist.push_back(tv); tv.setPos(cx+dx, cy-dy,cz+ dz);tv.setTexCoord(1, 0);tv.setNorm(1, 0, 0);//21 meshData->vlist.push_back(tv); tv.setPos(cx+dx, cy+dy, cz+dz);tv.setTexCoord(1, 1);tv.setNorm(1, 0, 0);//22 meshData->vlist.push_back(tv); tv.setPos(cx+dx, cy+dy, cz-dz);tv.setTexCoord(0, 1);tv.setNorm(1, 0, 0);//23 meshData->vlist.push_back(tv); //----生成索引三角形 Cc3dIDTriangle tIDtri; //前面 tIDtri.setvID(0, 1, 2); meshData->IDtriList.push_back(tIDtri); tIDtri.setvID(0, 2, 3); meshData->IDtriList.push_back(tIDtri); //后面 tIDtri.setvID(4, 6, 5); meshData->IDtriList.push_back(tIDtri); tIDtri.setvID(4, 7, 6); meshData->IDtriList.push_back(tIDtri); //上面 tIDtri.setvID(8, 9, 10); meshData->IDtriList.push_back(tIDtri); tIDtri.setvID(8, 10, 11); meshData->IDtriList.push_back(tIDtri); //下面 tIDtri.setvID(12, 14, 13); meshData->IDtriList.push_back(tIDtri); tIDtri.setvID(12, 15, 14); meshData->IDtriList.push_back(tIDtri); //左面 tIDtri.setvID(16, 17, 18); meshData->IDtriList.push_back(tIDtri); tIDtri.setvID(16, 18, 19); meshData->IDtriList.push_back(tIDtri); //右面 tIDtri.setvID(20, 22, 21); meshData->IDtriList.push_back(tIDtri); tIDtri.setvID(20, 23, 22); meshData->IDtriList.push_back(tIDtri); //----重新计算各三角形各顶点的uv int nv=(int)meshData->vlist.size(); vector<bool> markList(nv);//标记各顶点是否已经重计算过uv,避免多次计算(多次计算可能导致出错),初始全0 int nIDtri=(int)meshData->IDtriList.size(); for(int i=0;i<nIDtri;i++){ Cc3dIDTriangle&IDtri=meshData->IDtriList[i]; //重新计算IDtri各顶点的uv switch(cubUVMode) { case cubUVMode_FITFACE: { //将IDtri中未mark的顶点的uv分别乘以k_s,k_t for(int j=0;j<3;j++){ int vID=IDtri.vID[j];//顶点号 if(markList[vID]==false){//未计算过 //重新计算 Cc3dVertex&v=meshData->vlist[vID]; Cc3dVector2 texCoord=v.getTexCoord(); texCoord.setx(texCoord.x()*k_s); texCoord.sety(texCoord.y()*k_t); v.setTexCoord(texCoord); markList[vID]=true;//标记为已计算 } } }break; case cubUVMode_UNIFORM: { //将IDtri各顶点的uv,重新按顶点坐标来计算,并以k_s,k_t放缩 //判断IDtri的类型 const int type_LR=0;//左或右 const int type_UD=1;//上或下 const int type_FB=2;//前或后 int type=0; Cc3dVector3 norm=meshData->vlist[IDtri.vID[0]].getNorm(); if(fabsf(fabsf(norm.x())-1)<0.01){//左面或右面 type=type_LR; }else if(fabsf(fabsf(norm.y())-1)<0.01){//上面或下面 type=type_UD; }else{//前面或后面 type=type_FB; }//得到type for(int j=0;j<3;j++){ int vID=IDtri.vID[j];//顶点号 if(markList[vID]==false){//未计算过 //重新计算 Cc3dVertex&v=meshData->vlist[vID]; switch (type) { case type_LR:{ //用yz Cc3dVector2 texCoord(v.getPos().y()*k_s,v.getPos().z()*k_t); v.setTexCoord(texCoord); }break; case type_UD:{ //用xz Cc3dVector2 texCoord(v.getPos().x()*k_s,v.getPos().z()*k_t); v.setTexCoord(texCoord); }break; case type_FB:{ //用xy Cc3dVector2 texCoord(v.getPos().x()*k_s,v.getPos().y()*k_t); v.setTexCoord(texCoord); }break; } //标记为已计算 markList[vID]=true; } } }break; default: cout<<"error:未知的cubUV映射类型!"<<endl; assert(false); break; } } return meshData; }
bool AssimpLoadMesh(const Ptr<MeshAsset> & asset, bool bFlipUV, bool bLeftHanded) { if (!Global::GetPlatform()->FileExists(asset->GetLoadPath())) { ToyGE_LOG(LT_WARNING, "Cannot open mesh file when reading! %s", asset->GetLoadPath().c_str()); return false; } auto meshFullPath = asset->GetLoadFullPath(); auto meshDirFullPath = ParentPath(meshFullPath); auto assetsFullBasePath = Global::GetPlatform()->GetPathFullName(Asset::GetAssetsBasePath()); String meshDirRelativePath; if (!Global::GetPlatform()->GetRelativePath(assetsFullBasePath, true, meshDirFullPath, true, meshDirRelativePath)) { ToyGE_LOG(LT_WARNING, "Cannot find relative path for mesh from %s to %s!", assetsFullBasePath.c_str(), meshDirFullPath.c_str()); return false; } // Base path for mesh's resources String basePath = meshDirRelativePath; uint32_t processFlag = aiProcessPreset_TargetRealtime_Quality;// | aiProcess_MakeLeftHanded; if (bFlipUV) processFlag |= aiProcess_FlipUVs; if (bLeftHanded) processFlag |= aiProcess_MakeLeftHanded; Assimp::Importer importer; const aiScene *pAiScene = importer.ReadFile(asset->GetLoadPath(), processFlag); if (nullptr == pAiScene) { ToyGE_LOG(LT_WARNING, "Cannot load mesh! %s", asset->GetLoadPath().c_str()); return false; } // Material std::vector<Ptr<MaterialAsset>> materials; for (uint32_t matIndex = 0; matIndex != pAiScene->mNumMaterials; ++matIndex) { Ptr<MaterialAsset> mat = std::make_shared<MaterialAsset>(); const aiMaterial *pAiMat = pAiScene->mMaterials[matIndex]; // Diffuse for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_DIFFUSE); ++texIndex) { aiString path; uint32_t uvIndex; pAiMat->GetTexture(aiTextureType_DIFFUSE, texIndex, &path, 0, &uvIndex); if (uvIndex >= MaxNumTexCoord::NUM) uvIndex = 0; if(basePath.size() > 0) mat->AddTexture(MaterialTextureType::MAT_TEX_BASECOLOR, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex)); else mat->AddTexture(MaterialTextureType::MAT_TEX_BASECOLOR, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex)); } // Specular for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_SPECULAR); ++texIndex) { aiString path; uint32_t uvIndex; pAiMat->GetTexture(aiTextureType_SPECULAR, texIndex, &path, 0, &uvIndex); if (uvIndex >= MaxNumTexCoord::NUM) uvIndex = 0; //mat->AddTexture(MaterialTextureType::MAT_TEX_METALLIC, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), uvIndex); if (basePath.size() > 0) mat->AddTexture(MaterialTextureType::MAT_TEX_METALLIC, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex)); else mat->AddTexture(MaterialTextureType::MAT_TEX_METALLIC, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex)); } // Normal for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_NORMALS); ++texIndex) { aiString path; uint32_t uvIndex; pAiMat->GetTexture(aiTextureType_NORMALS, texIndex, &path, 0, &uvIndex); if (uvIndex >= MaxNumTexCoord::NUM) uvIndex = 0; //mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), uvIndex); if (basePath.size() > 0) mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex)); else mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex)); } // Height for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_HEIGHT); ++texIndex) { aiString path; uint32_t uvIndex; pAiMat->GetTexture(aiTextureType_HEIGHT, texIndex, &path, 0, &uvIndex); if (uvIndex >= MaxNumTexCoord::NUM) uvIndex = 0; //mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), uvIndex); if (basePath.size() > 0) mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex)); else mat->AddTexture(MaterialTextureType::MAT_TEX_BUMP, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex)); } // Roughness for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_SHININESS); ++texIndex) { aiString path; uint32_t uvIndex; pAiMat->GetTexture(aiTextureType_SHININESS, texIndex, &path, 0, &uvIndex); if (uvIndex >= MaxNumTexCoord::NUM) uvIndex = 0; if (basePath.size() > 0) { auto roughnessPath = ShininessToRoughnessTex(basePath + "/" + path.C_Str()); mat->AddTexture(MaterialTextureType::MAT_TEX_ROUGHNESS, Asset::Find<TextureAsset>(roughnessPath), static_cast<uint8_t>(uvIndex)); } else { auto roughnessPath = ShininessToRoughnessTex(path.C_Str()); mat->AddTexture(MaterialTextureType::MAT_TEX_ROUGHNESS, Asset::Find<TextureAsset>(roughnessPath), static_cast<uint8_t>(uvIndex)); } } // Opacity for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_OPACITY); ++texIndex) { aiString path; uint32_t uvIndex; pAiMat->GetTexture(aiTextureType_OPACITY, texIndex, &path, 0, &uvIndex); if (uvIndex >= MaxNumTexCoord::NUM) uvIndex = 0; //mat->AddTexture(MAT_TEX_OPACITYMASK, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), 0); if (basePath.size() > 0) mat->AddTexture(MaterialTextureType::MAT_TEX_OPACITYMASK, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex)); else mat->AddTexture(MaterialTextureType::MAT_TEX_OPACITYMASK, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex)); } // EMISSIVE for (uint32_t texIndex = 0; texIndex != pAiMat->GetTextureCount(aiTextureType_EMISSIVE); ++texIndex) { aiString path; uint32_t uvIndex; pAiMat->GetTexture(aiTextureType_EMISSIVE, texIndex, &path, 0, &uvIndex); if (uvIndex >= MaxNumTexCoord::NUM) uvIndex = 0; //mat->AddTexture(MAT_TEX_EMISSIVE, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), 0); if (basePath.size() > 0) mat->AddTexture(MaterialTextureType::MAT_TEX_EMISSIVE, Asset::Find<TextureAsset>(basePath + "/" + path.C_Str()), static_cast<uint8_t>(uvIndex)); else mat->AddTexture(MaterialTextureType::MAT_TEX_EMISSIVE, Asset::Find<TextureAsset>(path.C_Str()), static_cast<uint8_t>(uvIndex)); } aiColor3D baseColor; pAiMat->Get(AI_MATKEY_COLOR_DIFFUSE, baseColor); mat->SetBaseColor(float3(baseColor.r, baseColor.g, baseColor.b)); float opacity; pAiMat->Get(AI_MATKEY_OPACITY, opacity); mat->SetOpcacity(opacity); float shininess; pAiMat->Get(AI_MATKEY_SHININESS, shininess); mat->SetRoughness(pow(2.0f / (shininess + 2.0f), 0.25f)); // Set material path aiString matName; pAiMat->Get(AI_MATKEY_NAME, matName); if (matName.length > 0) { if(basePath.size() > 0) mat->SetPath(basePath + "/Material/" + matName.C_Str() + MaterialAsset::GetExtension()); else mat->SetPath(String("Material/") + matName.C_Str() + MaterialAsset::GetExtension()); } else { if (basePath.size() > 0) mat->SetPath(basePath + "/Material/mat_" + std::to_string(matIndex) + MaterialAsset::GetExtension()); else mat->SetPath(String("Material/mat_") + matName.C_Str() + MaterialAsset::GetExtension()); } materials.push_back(mat); } // Mesh std::vector<Ptr<MeshElement>> meshElements; for (uint32_t meshIndex = 0; meshIndex != pAiScene->mNumMeshes; ++meshIndex) { Ptr<MeshElement> meshElement = std::make_shared<MeshElement>(); const aiMesh *pAiMesh = pAiScene->mMeshes[meshIndex]; meshElement->material = materials[pAiMesh->mMaterialIndex]; auto vertexSlot = std::make_shared<MeshVertexSlotData>(); //meshElement->vertexData = std::make_shared<MeshVertexData>(); // Init vertex elements desc std::vector<MeshVertexElementDesc> & elementsDesc = vertexSlot->vertexDesc.elementsDesc; MeshVertexElementDesc elemDesc; int32_t bytesOffset = 0; if (pAiMesh->HasPositions()) { elemDesc.signature = MeshVertexElementSignature::MVET_POSITION; elemDesc.signatureIndex = 0; elemDesc.bytesOffset = bytesOffset; elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3)); elementsDesc.push_back(elemDesc); bytesOffset += elemDesc.bytesSize; } if (pAiMesh->GetNumUVChannels() > 0) { for (uint32_t uvChannel = 0; uvChannel != pAiMesh->GetNumUVChannels(); ++uvChannel) { elemDesc.signature = MeshVertexElementSignature::MVET_TEXCOORD; elemDesc.signatureIndex = static_cast<int32_t>(uvChannel); elemDesc.bytesOffset = bytesOffset; elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3)); elementsDesc.push_back(elemDesc); bytesOffset += elemDesc.bytesSize; } } if (pAiMesh->HasNormals()) { elemDesc.signature = MeshVertexElementSignature::MVET_NORMAL; elemDesc.signatureIndex = 0; elemDesc.bytesOffset = bytesOffset; elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3)); elementsDesc.push_back(elemDesc); bytesOffset += elemDesc.bytesSize; } if (pAiMesh->HasTangentsAndBitangents()) { elemDesc.signature = MeshVertexElementSignature::MVET_TANGENT; elemDesc.signatureIndex = 0; elemDesc.bytesOffset = bytesOffset; elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3)); elementsDesc.push_back(elemDesc); bytesOffset += elemDesc.bytesSize; elemDesc.signature = MeshVertexElementSignature::MVET_BITANGENT; elemDesc.signatureIndex = 0; elemDesc.bytesOffset = bytesOffset; elemDesc.bytesSize = static_cast<int32_t>(sizeof(float3)); elementsDesc.push_back(elemDesc); bytesOffset += elemDesc.bytesSize; } vertexSlot->vertexDesc.bytesSize = bytesOffset; // Init vertex data int32_t stride = bytesOffset; vertexSlot->bufferSize = stride * static_cast<int32_t>(pAiMesh->mNumVertices); vertexSlot->rawBuffer = MakeBufferedDataShared(static_cast<size_t>(vertexSlot->bufferSize)); bytesOffset = 0; uint8_t * data = vertexSlot->rawBuffer.get(); if (pAiMesh->HasPositions()) { for (uint32_t vertexIndex = 0; vertexIndex != pAiMesh->mNumVertices; ++vertexIndex) { float3 pos; pos.x() = pAiMesh->mVertices[vertexIndex].x; pos.y() = pAiMesh->mVertices[vertexIndex].y; pos.z() = pAiMesh->mVertices[vertexIndex].z; memcpy(data, &pos, sizeof(pos)); data += stride; } bytesOffset += static_cast<int32_t>(sizeof(float3)); } if (pAiMesh->GetNumUVChannels() > 0) { data = vertexSlot->rawBuffer.get() + bytesOffset; for (uint32_t vertexIndex = 0; vertexIndex != pAiMesh->mNumVertices; ++vertexIndex) { for (uint32_t uvChannel = 0; uvChannel != pAiMesh->GetNumUVChannels(); ++uvChannel) { auto & uvw = pAiMesh->mTextureCoords[uvChannel][vertexIndex]; float3 texCoord(uvw.x, uvw.y, uvw.z); memcpy(data + sizeof(texCoord) * uvChannel, &texCoord, sizeof(texCoord)); } data += stride; } bytesOffset += static_cast<int32_t>(sizeof(float3) * pAiMesh->GetNumUVChannels()); } if (pAiMesh->HasNormals()) { data = vertexSlot->rawBuffer.get() + bytesOffset; for (uint32_t vertexIndex = 0; vertexIndex != pAiMesh->mNumVertices; ++vertexIndex) { float3 normal; normal.x() = pAiMesh->mNormals[vertexIndex].x; normal.y() = pAiMesh->mNormals[vertexIndex].y; normal.z() = pAiMesh->mNormals[vertexIndex].z; normal = normalize(normal); memcpy(data, &normal, sizeof(normal)); data += stride; } bytesOffset += static_cast<int32_t>(sizeof(float3)); } if (pAiMesh->HasTangentsAndBitangents()) { data = vertexSlot->rawBuffer.get() + bytesOffset; for (uint32_t vertexIndex = 0; vertexIndex != pAiMesh->mNumVertices; ++vertexIndex) { float3 tangent; tangent.x() = pAiMesh->mTangents[vertexIndex].x; tangent.y() = pAiMesh->mTangents[vertexIndex].y; tangent.z() = pAiMesh->mTangents[vertexIndex].z; memcpy(data, &tangent, sizeof(tangent)); float3 bitangent; bitangent.x() = pAiMesh->mBitangents[vertexIndex].x; bitangent.y() = pAiMesh->mBitangents[vertexIndex].y; bitangent.z() = pAiMesh->mBitangents[vertexIndex].z; memcpy(data + sizeof(tangent), &bitangent, sizeof(bitangent)); data += stride; } bytesOffset += static_cast<int32_t>(sizeof(float3)); } meshElement->vertexData.push_back(vertexSlot); // Indices for (uint32_t faceIndex = 0; faceIndex != pAiMesh->mNumFaces; ++faceIndex) { aiFace &pAiFace = pAiMesh->mFaces[faceIndex]; for (uint32_t index = 0; index != pAiFace.mNumIndices; ++index) meshElement->indices.push_back(pAiFace.mIndices[index]); } meshElements.push_back(meshElement); } asset->SetData(meshElements); return true; }
// отрисовка из прошлой лабы, только берём цвета из текстуры void Triangle::draw(Canvas& canvas, Texture* texture = 0) { std::vector<TexturedPoint> points; // преобразование и упорядочивание по x transform(points); std::sort(points.begin(), points.end()); std::vector<Edge> edges; // установка границ int minY = (points.front().y() < 0) ? 0: points.front().y(); int maxY = (points.back().y() < this->maxY) ? points.back().y() : this->maxY - 1; int curY = minY; int i = 0; while (curY < maxY) { int nextY = maxY; while ( i != (int)points.size() && trunc( points[i].y()) <= curY ){ TexturedPoint a = points[i]; TexturedPoint b = points[(points.size() - i - 1 ) % points.size()]; TexturedPoint c = points[(i + 1) % points.size()]; if (b.y() > curY ) { edges.push_back(Edge(a,b)); if ( b.y() < nextY ) { nextY = b.y() ; } } if (c.y() > curY) { edges.push_back(Edge(a,c)); if ( c.y() < nextY) { nextY = c.y(); } } ++i; } while(curY <= nextY && curY <= maxY) { std::vector<TexturedPoint> borderX; for (int i = 0; i < (int)edges.size(); ++i) { int n = curY - edges[i].getA().y(); double curX = (edges[i].getA().x()) + n * edges[i].getK(); TexturedPoint texCoord(curX, curY); texCoord.calcTextureCoordinates(edges[i].getA(), edges[i].getB()); borderX.push_back(texCoord); } std::sort(borderX.begin(), borderX.end(), TexturedPoint::compX); int begin = borderX.front().x() > 0 ? borderX.front().x() : 0; for (int x = begin; x < borderX.back().x() && x < maxX; ++x) { TexturedPoint curPoint(x, curY); curPoint.calcTextureCoordinates(borderX.front(),borderX.back()); if (0 == texture) { // если текстуры нет( то как градиент ) canvas.drawPixel(x, curY, TexturedPoint::transformToColor(curPoint.getTexX(), curPoint.getTexY())); } else { canvas.drawPixel(x, curY, texture->get_color(curPoint)); } } ++curY; } std::vector<Edge>::iterator iter = edges.begin(); while (iter != edges.end()) { if ( (*iter).getB().y() < curY) { edges.erase(iter); } else { ++iter; } } } }
Model* MD2Loader::loadFromFile(const std::string& name) { std::ifstream stream(name.c_str(), std::ios_base::binary); Header head; stream.read(reinterpret_cast<char*>(&head), sizeof(Header)); if(head.magic != _magicId) throw LoadingFailed(name + " magic"); if(head.version != _MD2Version) throw LoadingFailed(name + " version"); std::vector<Texture> textures(head.nbTex); std::vector<TexCoord> texCoord(head.nbTexCoord); std::vector<Triangle> triangles(head.nbTriangles); std::vector<Frame> frames(head.nbFrames); stream.seekg(head.offsetTextures, std::ios_base::beg); stream.read(reinterpret_cast<char*>(&textures[0]), sizeof(Texture)*head.nbTex); stream.seekg(head.offsetTexCoords, std::ios_base::beg); stream.read(reinterpret_cast<char*>(&texCoord[0]), sizeof(TexCoord)*head.nbTexCoord); stream.seekg(head.offsetTriangles, std::ios_base::beg); stream.read(reinterpret_cast<char*>(&triangles[0]), sizeof(Triangle)*head.nbTriangles); stream.seekg(head.offsetFrames, std::ios_base::beg); frames[0].vertices.resize(head.nbVert); stream.read(reinterpret_cast<char*>(&frames[0].scale), sizeof(frames[0].scale)); stream.read(reinterpret_cast<char*>(&frames[0].translate), sizeof(frames[0].translate)); stream.read(reinterpret_cast<char*>(&frames[0].name), sizeof(frames[0].name)); stream.read(reinterpret_cast<char*>(&frames[0].vertices[0]), sizeof(Point)*head.nbVert); std::vector<Model::Vertex> vertices; std::vector<Model::Index> indices; for(int i = 0; i < head.nbTriangles; ++i) { for(int j=0; j<3; ++j) { Model::Vertex v; const Point& vert = frames[0].vertices[triangles[i].vertices[j]]; const TexCoord& texC = texCoord[triangles[i].texCoords[j]]; v.px = vert.x*frames[0].scale.x+frames[0].translate.x; v.py = vert.y*frames[0].scale.y+frames[0].translate.y; v.pz = vert.z*frames[0].scale.z+frames[0].translate.z; v.nx = _normalTable[vert.n].x; v.ny = _normalTable[vert.n].y; v.nz = _normalTable[vert.n].z; v.color = Graphics::D3::Renderer::getInstance().convertColor(Graphics::Color::White); v.tx = texC.u/static_cast<float>(head.texW); v.ty = texC.v/static_cast<float>(head.texH); vertices.push_back(v); indices.push_back(i*3+2-j); } } std::string texName = ""; if(textures[0].name != nullptr) texName = textures[0].name; Model* m = new Model(name, &vertices[0], (int)vertices.size(), &indices[0], (int)indices.size(), texName); return m; }
void csDecal::AddStaticPoly (const csPoly3D & p, csArray<size_t>* indices) { CS_ASSERT(animationControlData.animationControl ? indices != (csArray<size_t>*) nullptr : 1); if (!currMesh) return; size_t a; CS::TriangleT<int> tri; csPoly3D poly = p; if (decalTemplate->HasClipping ()) for (a = 0; a < numClipPlanes; ++a) CutPolyToPlane (poly, clipPlanes[a], indices); size_t vertCount = poly.GetVertexCount (); // only support triangles and up if (vertCount < 3) return; // ensure the polygon isn't facing away from the decal's normal too much csVector3 polyNorm = poly.ComputeNormal (); float polyNormThresholdValue = -polyNorm * localNormal; if (polyNormThresholdValue < decalTemplate->GetPolygonNormalThreshold ()) return; // check if we hit our maximum allowed vertices if (vertexCount + vertCount > CS_DECAL_MAX_VERTS_PER_DECAL) vertCount = CS_DECAL_MAX_VERTS_PER_DECAL - vertexCount; if (vertCount < 3) return; // check if we hit our maximum allowed indices size_t idxCount = (vertCount - 2) * 3; if (indexCount + idxCount > CS_DECAL_MAX_TRIS_PER_DECAL * 3) return; // if this face is too perpendicular, then we'll need to push it out a bit // to avoid z-fighting. We do this by pushing the bottom of the face out // more than the top of the face bool doFaceOffset = false; float faceHighDot = 0.0f; float invHighLowFaceDist = 0.0f; csVector3 faceBottomOffset(0.0f); csVector3 faceCenter(0.0f); if (decalTemplate->HasClipping () && !animationControlData.animationControl) { if (fabs (polyNormThresholdValue) < decalTemplate->GetPerpendicularFaceThreshold ()) { doFaceOffset = true; csVector3 faceHighVert, faceLowVert; float faceLowDot; faceLowVert = faceHighVert = *poly.GetVertex (0); faceLowDot = faceHighDot = (faceLowVert - relPos) * localNormal; faceCenter = faceLowVert; for (a = 1; a < vertCount; ++a) { const csVector3 * vertPos = poly.GetVertex (a); faceCenter += *vertPos; float dot = (*vertPos - relPos) * localNormal; if (dot > faceHighDot) { faceHighVert = *vertPos; faceHighDot = dot; } if (dot < faceLowDot) { faceLowVert = *vertPos; faceLowDot = dot; } } invHighLowFaceDist = 1.0f / (faceHighDot - faceLowDot); faceBottomOffset = -decalTemplate->GetPerpendicularFaceOffset () * polyNorm; faceCenter /= (float)vertCount; } } const csVector2 & minTexCoord = decalTemplate->GetMinTexCoord (); csVector2 texCoordRange = decalTemplate->GetMaxTexCoord () - minTexCoord; tri[0] = (int)vertexCount; for (a = 0; a < vertCount; ++a) { csVector3 vertPos = *poly.GetVertex (a); float distToPos = (vertPos - relPos) * localNormal; if (decalTemplate->HasClipping () && !animationControlData.animationControl) { if (doFaceOffset) { // linear interpolation where high vert goes nowhere and low vert is // full offset float offsetVal = (faceHighDot - distToPos) * invHighLowFaceDist; vertPos += offsetVal * faceBottomOffset; // spread out the base to avoid vertical seams vertPos += (vertPos - faceCenter).Unit () * (decalTemplate->GetPerpendicularFaceOffset () * 2.0f); } } vertPos += vertOffset; csVector3 relVert = vertPos - relPos; size_t vertIdx = vertexCount+a; // copy over vertex data vertexBuffer->CopyInto (&vertPos, 1, vertIdx); // copy over color csColor4 color; if (-distToPos >= 0.0f) { float t = 0.0f; if (topPlaneDist >= 0.01f) t = -distToPos / topPlaneDist; color = decalTemplate->GetMainColor () * (1.0f - t) + decalTemplate->GetTopColor () * t; } else { float t = 0.0f; if (bottomPlaneDist >= 0.01f) t = distToPos / bottomPlaneDist; color = decalTemplate->GetMainColor () * (1.0f - t) + decalTemplate->GetBottomColor () * t; } colorBuffer->CopyInto (&color, 1, vertIdx); // create the index buffer for each triangle in the poly if (a >= 2) { tri[1] = (int)vertIdx-1; tri[2] = (int)vertIdx; indexBuffer->CopyInto (&tri, 3, indexCount); indexCount += 3; } // generate uv coordinates csVector2 texCoord ( minTexCoord.x + texCoordRange.x * 0.5f + texCoordRange.x * localRight * invWidth * relVert, minTexCoord.y + texCoordRange.y * 0.5f - texCoordRange.y * localUp * invHeight * relVert); texCoordBuffer->CopyInto (&texCoord, 1, vertIdx); // TODO: compute tangents/binormals // copy over normal normalBuffer->CopyInto (&localNormal, 1, vertIdx); } vertexCount += vertCount; if (indices) animationControlData.animatedIndices.Merge (*indices); }
//------------------------------------------------------------------------- FKCW_3D_Mesh* CreateConeMesh(float r,float h,int nSlice,int nStack,bool isHaveBottom, const FKCW_3D_Vector4&headColor,const FKCW_3D_Vector4&bottomColor) //why cone need nStack ? because even a plane need subdivision to achieve better specular effect { float dA=360.0f/nSlice; const float PIDIV180= static_cast<float>(M_PI/180.0f); vector<FKCW_3D_Vector4> positionList; vector<FKCW_3D_Vector2> texCoordList; vector<FKCW_3D_Vector4> normalList; vector<FKCW_3D_Vector4> colorList; vector<FKCW_3D_IDTriangle> IDtriList; //----generate side //generate positionList, texCoordList, normalList, colorList for(int i=0;i<=nStack;i++){ float y=i*h/nStack; for (int j=0; j<=nSlice; j++) { float A=j*dA; float R=r-i*r/nStack; float cosA=cosf(A*PIDIV180); float sinA=sinf(A*PIDIV180); float x=R*cosA; float z=R*sinA; FKCW_3D_Vector4 position(x,y,z,1); float s=(float)j/nSlice+0.25f; float t=1-(float)i/nStack; FKCW_3D_Vector2 texCoord(s,t); float ny=r/sqrtf(FKCW_Square(h)+FKCW_Square(r)); float nx,nz;//nx*nx+ny*ny+nz*nz=1 and nx:nz=cosA:sinA => k=sqrt((1-ny*ny)/(cosA*cosA+sinA*sinA)), nx=cosA*k, nz=sinA*k float k=sqrtf((1-ny*ny)/(cosA*cosA+sinA*sinA)); nx=cosA*k; nz=sinA*k; FKCW_3D_Vector4 normal=normalize(FKCW_3D_Vector4(nx,ny,nz,0)); FKCW_3D_Vector4 color=bottomColor*(1-(float)i/nStack)+headColor*((float)i/nStack); positionList.push_back(position); texCoordList.push_back(texCoord); normalList.push_back(normal); colorList.push_back(color); } } //generate IDtriList for(int i=0;i<nStack;i++){ for(int j=0;j<nSlice;j++){ int vID_ld=(nSlice+1)*i+j; int vID_rd=vID_ld+1; int vID_ru=vID_rd+(nSlice+1); int vID_lu=vID_ru-1; FKCW_3D_IDTriangle IDtri0(vID_ld,vID_rd,vID_ru); FKCW_3D_IDTriangle IDtri1(vID_ld,vID_ru,vID_lu); IDtriList.push_back(IDtri0); IDtriList.push_back(IDtri1); } } //----generate bottom if(isHaveBottom){ vector<FKCW_3D_Vector4> _positionList=positionList; vector<FKCW_3D_Vector2> _texCoordList=texCoordList; vector<FKCW_3D_Vector4> _normalList=normalList; vector<FKCW_3D_Vector4> _colorList=colorList; vector<FKCW_3D_IDTriangle> _IDtriList=IDtriList; //all postion in _positionList set y to zero int _nPosition=(int)_positionList.size(); for(int i=0;i<_nPosition;i++){ FKCW_3D_Vector4&position=_positionList[i]; position.sety(0); } //all normal in _normalList set to (0,-1,0,0) int _nNormal=(int)_normalList.size(); for(int i=0;i<_nNormal;i++){ FKCW_3D_Vector4&normal=_normalList[i]; normal=FKCW_3D_Vector4(0, -1, 0, 0); } //all index in _IDtriList should be plus offset=(int)positionList.size() const int offset=(int)positionList.size(); int _nIDtri=(int)_IDtriList.size(); for(int i=0;i<_nIDtri;i++){ FKCW_3D_IDTriangle&IDtri=_IDtriList[i]; int ID0=IDtri.vID(0); int ID1=IDtri.vID(1); int ID2=IDtri.vID(2); IDtri.init(ID0+offset, ID1+offset, ID2+offset); } //connect side and bottom positionList=connectList(positionList,_positionList); texCoordList=connectList(texCoordList,_texCoordList); normalList=connectList(normalList,_normalList); colorList=connectList(colorList,_colorList); IDtriList=connectList(IDtriList,_IDtriList); } //----create mesh FKCW_3D_SubMeshData*subMeshData=new FKCW_3D_SubMeshData(); subMeshData->autorelease(); subMeshData->init(); subMeshData->initPositionList(positionList); subMeshData->initTexCoordList(texCoordList); subMeshData->initNormalList(normalList); subMeshData->initColorList(colorList); subMeshData->initIDtriList(IDtriList); FKCW_3D_SubMesh* subMesh=new FKCW_3D_SubMesh(); subMesh->autorelease(); subMesh->init(); subMesh->setSubMeshData(subMeshData); FKCW_3D_Mesh* mesh=new FKCW_3D_Mesh(); mesh->autorelease(); mesh->init(); mesh->addSubMesh(subMesh); return mesh; }
//------------------------------------------------------------------------- FKCW_3D_Mesh* CreateBallMesh(float r,int nSlice,int nStack, const FKCW_3D_Vector4&northPoleColor,const FKCW_3D_Vector4&southPoleColor) { float dA=360.0f/nSlice; float dB=180.0f/nStack; const float PIDIV180=static_cast<float>(M_PI/180.0f); vector<FKCW_3D_Vector4> positionList; vector<FKCW_3D_Vector2> texCoordList; vector<FKCW_3D_Vector4> normalList; vector<FKCW_3D_Vector4> colorList; vector<FKCW_3D_IDTriangle> IDtriList; //generate positionList, texCoordList, normalList, colorList for(int i=0;i<=nStack;i++){ float B=-90+i*dB; float y=r*sinf(B*PIDIV180); float cosB=cosf(B*PIDIV180); for (int j=0; j<=nSlice; j++) { float A=j*dA; float R=r*cosB; float x=R*cosf(A*PIDIV180); float z=R*sinf(A*PIDIV180); FKCW_3D_Vector4 position(x,y,z,1); float s=(float)j/nSlice+0.25f; float t=1-(float)i/nStack; FKCW_3D_Vector2 texCoord(s,t); FKCW_3D_Vector4 normal=normalize(FKCW_3D_Vector4(position.x(), position.y(), position.z(), 0)); FKCW_3D_Vector4 color=southPoleColor*(1-(float)i/nStack)+northPoleColor*((float)i/nStack); positionList.push_back(position); texCoordList.push_back(texCoord); normalList.push_back(normal); colorList.push_back(color); } } //generate IDtriList for(int i=0;i<nStack;i++){ for(int j=0;j<nSlice;j++){ int vID_ld=(nSlice+1)*i+j; int vID_rd=vID_ld+1; int vID_ru=vID_rd+(nSlice+1); int vID_lu=vID_ru-1; FKCW_3D_IDTriangle IDtri0(vID_ld,vID_rd,vID_ru); FKCW_3D_IDTriangle IDtri1(vID_ld,vID_ru,vID_lu); IDtriList.push_back(IDtri0); IDtriList.push_back(IDtri1); } } FKCW_3D_SubMeshData*subMeshData=new FKCW_3D_SubMeshData(); subMeshData->autorelease(); subMeshData->init(); subMeshData->initPositionList(positionList); subMeshData->initTexCoordList(texCoordList); subMeshData->initNormalList(normalList); subMeshData->initColorList(colorList); subMeshData->initIDtriList(IDtriList); FKCW_3D_SubMesh* subMesh=new FKCW_3D_SubMesh(); subMesh->autorelease(); subMesh->init(); subMesh->setSubMeshData(subMeshData); FKCW_3D_Mesh* mesh=new FKCW_3D_Mesh(); mesh->autorelease(); mesh->init(); mesh->addSubMesh(subMesh); return mesh; }
void loadObj(const string& fileName, const D3DXCOLOR& color, float scale, vector<Vertex>& vertices, unsigned int normalCount, unsigned int positionCount, unsigned int texCoordCount, unsigned int vertexCount) { vertices.reserve(vertexCount); ifstream inputFileStream(fileName.c_str()); if (inputFileStream.fail()) { throw exception(); } char* rawSplit = new char[MAX_SPLIT_LENGTH]; vector<string> lines = splitString(rawSplit, inputFileStream, '\n', normalCount + positionCount + texCoordCount + vertexCount / 3 + 50); vector<vector<string> > faces; faces.reserve(vertexCount / 3); vector<D3DXVECTOR3> normals; normals.reserve(normalCount); vector<D3DXVECTOR3> positions; positions.reserve(positionCount); vector<D3DXVECTOR2> texCoords; texCoords.reserve(texCoordCount); for (unsigned int lineIndex = 0; lineIndex < lines.size(); lineIndex++) { if (lines[lineIndex].empty()) { continue; } istringstream inputLineStream(lines[lineIndex]); vector<string> splitLine = splitString(rawSplit, inputLineStream, ' ', 4); if (splitLine[0] == "v") { D3DXVECTOR3 position( (float) atof(splitLine[1].c_str()) * scale, (float) atof(splitLine[2].c_str()) * scale, (float) atof(splitLine[3].c_str()) * scale); positions.push_back(position); } else if (splitLine[0] == "vn") { D3DXVECTOR3 normal( (float) atof(splitLine[1].c_str()), (float) atof(splitLine[2].c_str()), (float) atof(splitLine[3].c_str())); normals.push_back(normal); } else if (splitLine[0] == "vt") { D3DXVECTOR2 texCoord( (float) atof(splitLine[1].c_str()), 1.0f - (float) atof(splitLine[2].c_str())); texCoords.push_back(texCoord); } else if (splitLine[0] == "f") { faces.push_back(splitLine); } } // Read the faces from the file and populate the arrays. for (unsigned int faceIndex = 0; faceIndex < faces.size(); faceIndex++) { vector<string> face = faces[faceIndex]; for (unsigned int vertexIndex = 1; vertexIndex < face.size() - 1; vertexIndex++) { istringstream inputFaceStream(face[vertexIndex]); vector<string> splitVertex = splitString(rawSplit, inputFaceStream, '/', 3); Vertex vertex; vertex.color = color; if (!normals.empty()) { vertex.normal = normals[atoi(splitVertex[2].c_str()) - 1]; } vertex.position = positions[atoi(splitVertex[0].c_str()) - 1]; if (!texCoords.empty()) { vertex.texCoord = texCoords[atoi(splitVertex[1].c_str()) - 1]; } vertices.push_back(vertex); } // Create face normals if none were provided. if (normals.empty()) { unsigned int vertexCount = vertices.size(); D3DXVECTOR3 edge0 = vertices[vertexCount - 1].position - vertices[vertexCount - 2].position; D3DXVECTOR3 edge1 = vertices[vertexCount - 1].position - vertices[vertexCount - 3].position; D3DXVECTOR3 faceNormal; D3DXVec3Cross(&faceNormal, &edge0, &edge1); D3DXVec3Normalize(&faceNormal, &faceNormal); vertices[vertexCount - 1].normal = faceNormal; vertices[vertexCount - 2].normal = faceNormal; vertices[vertexCount - 3].normal = faceNormal; } } delete rawSplit; }
void GridMesh::GenerateGrid() { uint numVerticies = rows * columns; vector<PositionTexCoordVertex> vertices(numVerticies); vector<vec3> points; auto width = columns * scale; auto height = rows * scale; auto halfWidth = width * 0.5f; auto halfHeight = height * 0.5f; vec3 originPosition(-halfWidth, 0, -halfHeight); for (uint row = 0; row < rows; row++) { for (uint column = 0; column < columns; column++) { auto index = row * columns + column; auto columnPosition = (float)column * scale; auto rowPosition = row * scale; vec3 position(columnPosition, 0, rowPosition); points.push_back(position); vertices[index].position = glm::vec4((originPosition + position), 1); glm::vec2 texCoord(row / (float)(rows), column / (float)columns); vertices[index].textureCoordinate = texCoord; } } //AddNoise(vertices); boundingSphere.Fit(points); auto numIndices = (rows - 1) * (columns - 1) * 6; vector<uint> indices(numIndices); uint index = 0; for (uint row = 0; row < rows - 1; row++) { for (uint column = 0; column < columns - 1; column++) { auto currentIndex = row * columns + column; auto nextRow = (row + 1) * columns + column; auto nextColumn = currentIndex + 1; auto nextRowNextColumn = nextRow + 1; assert(index + 6 <= numIndices); // First triangle indices[index++] = currentIndex; indices[index++] = nextRow; indices[index++] = nextRowNextColumn; // Second triangle indices[index++] = currentIndex; indices[index++] = nextRowNextColumn; indices[index++] = nextColumn; } } DynamicEnum texturePaths; texturePaths.Add(texturePath); BindVertexAndIndexData(&renderData, vertices, indices); BuildMaterialFromLoaderNode(&material, texturePaths); }