bool isRayPlaneIntersection(const MVector3 & origin, const MVector3 & direction, const MVector3 & planePoint, const MVector3 & planeNormal, MVector3 * point) { float constant = - planeNormal.dotProduct(planePoint); float normalDotDir = planeNormal.dotProduct(direction); float planeDistance = planeNormal.dotProduct(origin) + constant; float t = - planeDistance / normalDotDir; point->x = (origin.x + (t * direction.x)); point->y = (origin.y + (t * direction.y)); point->z = (origin.z + (t * direction.z)); return true; }
bool isPointInTriangle(const MVector3 & point, const MVector3 & a, const MVector3 & b, const MVector3 & c, const MVector3 & normal) { MVector3 nrm = getTriangleNormal(point, a, b); if(nrm.dotProduct(normal) < 0) return false; nrm = getTriangleNormal(point, b, c); if(nrm.dotProduct(normal) < 0) return false; nrm = getTriangleNormal(point, c, a); if(nrm.dotProduct(normal) < 0) return false; return true; }
bool isRaySphereIntersection(const MVector3 & origin, const MVector3 & direction, const MVector3 & sphereCenter, float sphereRadius, MVector3 * point) { MVector3 vec = origin - sphereCenter; float b = direction.dotProduct(vec); float c = vec.getSquaredLength() - (sphereRadius * sphereRadius); float d = (b * b) - c; if(d < 0) return false; float distance = -b - sqrtf(d); point->x = (origin.x + (distance * direction.x)); point->y = (origin.y + (distance * direction.y)); point->z = (origin.z + (distance * direction.z)); return true; }
void generateTangents(MSubMesh * subMesh) { MVector3 * vertices = subMesh->getVertices(); MVector3 * normals = subMesh->getNormals(); MVector2 * texCoords = subMesh->getTexCoords(); if(! (vertices && normals && texCoords)) return; bool generate = false; unsigned int mapChannel; // find normal mapChannel unsigned int d; unsigned int dSize = subMesh->getDisplaysNumber(); for(d=0; d<dSize; d++) { MDisplay * display = subMesh->getDisplay(d); MMaterial * material = display->getMaterial(); if(material) { if(material->getType() == 1) // standard { if(material->getTexturesPassNumber() > 2) { MTexturePass * texturePass = material->getTexturePass(2); // Normal map pass if(texturePass) { mapChannel = texturePass->getMapChannel(); generate = true; } } } else { unsigned tSize = material->getTexturesPassNumber(); unsigned int t; for(t=0; t<tSize; t++) { MTexturePass * texturePass = material->getTexturePass(t); if(texturePass) { if(texturePass->getCombineMode() == M_TEX_COMBINE_DOT) { mapChannel = texturePass->getMapChannel(); generate = true; } } } } } } // generate if(generate) { M_TYPES indicesType = subMesh->getIndicesType(); void * indices = subMesh->getIndices(); MVector3 * tangents = subMesh->allocTangents(subMesh->getNormalsSize()); // texCoord offset unsigned int offset = 0; if(subMesh->isMapChannelExist(mapChannel)) offset = subMesh->getMapChannelOffset(mapChannel); texCoords = texCoords + offset; // scan triangles to generate tangents from vertices and texCoords for(d=0; d<dSize; d++) { MDisplay * display = subMesh->getDisplay(d); if(display->getPrimitiveType() == M_PRIMITIVE_TRIANGLES) { unsigned int begin = display->getBegin(); unsigned int size = display->getSize(); if(! indices) { for(unsigned int i=begin; i<(begin+size); i+=3) { MVector3 * P1 = &vertices[i]; MVector3 * P2 = &vertices[i+1]; MVector3 * P3 = &vertices[i+2]; MVector3 * N1 = &normals[i]; MVector3 * N2 = &normals[i+1]; MVector3 * N3 = &normals[i+2]; MVector2 * UV1 = &texCoords[i]; MVector2 * UV2 = &texCoords[i+1]; MVector2 * UV3 = &texCoords[i+2]; MVector3 tangent = computeTangent(*P1, *P2, *P3, *UV1, *UV2, *UV3); tangents[i] = (tangent - ((*N1) * tangent.dotProduct(*N1))).getNormalized(); tangents[i+1] = (tangent - ((*N2) * tangent.dotProduct(*N2))).getNormalized(); tangents[i+2] = (tangent - ((*N3) * tangent.dotProduct(*N3))).getNormalized(); } } else if(indicesType == M_USHORT) { unsigned short * _indices = (unsigned short *)indices; for(unsigned int i=begin; i<(begin+size); i+=3) { unsigned short A = _indices[i]; unsigned short B = _indices[i+1]; unsigned short C = _indices[i+2]; MVector3 * P1 = &vertices[A]; MVector3 * P2 = &vertices[B]; MVector3 * P3 = &vertices[C]; MVector3 * N1 = &normals[A]; MVector3 * N2 = &normals[B]; MVector3 * N3 = &normals[C]; MVector2 * UV1 = &texCoords[A]; MVector2 * UV2 = &texCoords[B]; MVector2 * UV3 = &texCoords[C]; MVector3 tangent = computeTangent(*P1, *P2, *P3, *UV1, *UV2, *UV3); tangents[A] = (tangent - ((*N1) * tangent.dotProduct(*N1))).getNormalized(); tangents[B] = (tangent - ((*N2) * tangent.dotProduct(*N2))).getNormalized(); tangents[C] = (tangent - ((*N3) * tangent.dotProduct(*N3))).getNormalized(); } } else if(indicesType == M_UINT) { unsigned int * _indices = (unsigned int *)indices; for(unsigned int i=begin; i<(begin+size); i+=3) { unsigned int A = _indices[i]; unsigned int B = _indices[i+1]; unsigned int C = _indices[i+2]; MVector3 * P1 = &vertices[A]; MVector3 * P2 = &vertices[B]; MVector3 * P3 = &vertices[C]; MVector3 * N1 = &normals[A]; MVector3 * N2 = &normals[B]; MVector3 * N3 = &normals[C]; MVector2 * UV1 = &texCoords[A]; MVector2 * UV2 = &texCoords[B]; MVector2 * UV3 = &texCoords[C]; MVector3 tangent = computeTangent(*P1, *P2, *P3, *UV1, *UV2, *UV3); tangents[A] = (tangent - ((*N1) * tangent.dotProduct(*N1))).getNormalized(); tangents[B] = (tangent - ((*N2) * tangent.dotProduct(*N2))).getNormalized(); tangents[C] = (tangent - ((*N3) * tangent.dotProduct(*N3))).getNormalized(); } } } } } }
void MBLookAt::update(void) { MEngine * engine = MEngine::getInstance(); MLevel * level = engine->getLevel(); MScene * scene = level->getCurrentScene(); MObject3d * parent = getParentObject(); const char * targetName = m_targetName.getData(); if(strcmp(targetName, "none") == 0) return; // target object MObject3d * object = scene->getObjectByName(targetName); if(! object) return; // direction MVector3 direction = object->getTransformedPosition() - parent->getTransformedPosition(); if(direction.x == 0 && direction.y == 0 && direction.z == 0) return; float angle; float roll; MVector3 axis; // compute initial roll MVector3 ZAxis = parent->getInverseRotatedVector(MVector3(0, 0, 1)).getNormalized(); ZAxis.z = 0; ZAxis.normalize(); if(ZAxis.x == 0 && ZAxis.y == 0) { MVector3 YAxis = parent->getInverseRotatedVector(MVector3(0, 1, 0)).getNormalized(); YAxis.z = 0; YAxis.normalize(); axis = MVector3(0, 1, 0).crossProduct(YAxis); roll = acosf(MVector3(0, 1, 0).dotProduct(YAxis)); if(MVector3(0, 0, 1).dotProduct(axis) < 0) roll = -roll; } else { axis = MVector3(0, 1, 0).crossProduct(ZAxis); roll = acosf(MVector3(0, 1, 0).dotProduct(ZAxis)); if(MVector3(0, 0, 1).dotProduct(axis) < 0) roll = -roll; } if(roll < 0.001f && roll > -0.001f) roll = 0; // look-at MVector3 cameraAxis = MVector3(0, 0, -1); axis = cameraAxis.crossProduct(direction); angle = acosf(cameraAxis.dotProduct(direction.getNormalized())); parent->setAxisAngleRotation(axis, (float)(angle * RAD_TO_DEG)); parent->updateMatrix(); // set roll ZAxis = parent->getInverseRotatedVector(MVector3(0, 0, 1)).getNormalized();; ZAxis.z = 0; ZAxis.normalize(); if(ZAxis.x == 0 && ZAxis.y == 0) { parent->addAxisAngleRotation(MVector3(0, 0, 1), (float)(-roll*RAD_TO_DEG)); } else { axis = MVector3(0, 1, 0).crossProduct(ZAxis); angle = acosf(MVector3(0, 1, 0).dotProduct(ZAxis)); if(angle < 0.001f && angle > -0.001f) angle = 0; if(MVector3(0, 0, 1).dotProduct(axis) < 0) angle = -angle; parent->addAxisAngleRotation(MVector3(0, 0, 1), (float)((angle-roll)*RAD_TO_DEG)); } }