//----------------------------------------------------------------------------- //! その座標から一番近い三角形との衝突点の取得 //! @param [in] positon チェックする位置 //! @param [in] radius 半径 //! @retval 衝突点 //----------------------------------------------------------------------------- Vector3 CollisionWall::getHitPos(const Vector3& position, const f32 radius, bool isNear) //Vector3 CollisionWall::getHitPos(const AABB aabb) { // 接触点 Vector3 resultPos(0.0f,0.0f,0.0f); /*Vector3 v1 = aabb._max; v1._y = 0.0f; Vector3 v2 = aabb._min; v2._y = 0.0f;*/ //f32 radius = abs((v1 - v2).length() * 0.5f); // 衝突点までの距離(二乗で比較) f32 nearestHitPosLength = radius * radius; //f32 nearestHitPosLength = FLT_MAX; // 衝突したかどうか static bool isHit = false; // オフセット値 static s32 Count = 0; static Vector3 offsetList[5] = { Vector3( 0, 0, 0 ), // 中央 Vector3( 0, 0, 1 ), // 前 Vector3( 0, 0, -1 ), // 後 Vector3( -1, 0, 0 ), // 左 Vector3( 1, 0, 0 ), // 右 }; // もらった座標をインデックス番号に変更 s32 x = ( (s32)(position._x) + _offsetX ) / _divX; s32 y = ( (s32)(position._z) + _offsetZ ) / _divZ; _checkIndex._x = (f32)( x ); _checkIndex._y = (f32)( y ); //// 前回衝突がなくカウントが更新されてたら //if( !isHit ) //{ // // 最大数をこえてたら処理終了 // if( Count >= 5 ) { // // リセット // Count = 0; // return resultPos; // } // // オフセット分ずらす // x += offsetList[Count]._x; // y += offsetList[Count]._z; // // つぎへ // Count++; //} // 範囲外なら処理しない if( x >= _DivCount || y >= _DivCount || x < 0 || y < 0 ) return resultPos; static f32 prevMinLength = -1; // その番号のオブジェクトを調べる SystemCollision::Object* pObject = getObject(y * _DivCount + x); // 初期化 isHit = false; // そのオブジェクトの当たり判定情報を調べる //for( s32 t=0; t<pObject->getTriangleCount(); t++ ) for( s32 t=0; t<pObject->getColDataCount(); t++ ) { //Triangle* pTriangle = pObject->getTriangle(t); Triangle* pTriangle = &pObject->getColData(t)->_triangle; // 三角形の法線取得 Vector3 triNormal = pTriangle->getNormal(); // この法線の逆ベクトルをポジションから伸ばす // 法線を正規化 triNormal = triNormal.normalize(); // 半径に伸ばす triNormal *= radius; // 当たり判定用ラインの作成 Line line; line._position[0] = position; line._position[1] = position + ( -triNormal ); Vector3 hitPos; f32 h; // ラインが伸びてなかったら処理しない if( line._position[0] == line._position[1] ) continue; if( isNear ){ // 三角形と当たってたら高さ記録 collision::checkHitPos( *pTriangle, line, &hitPos ); h = hitPos._y; }else{ // 三角形と当たってたら高さ記録 if( collision::isHit( *pTriangle, line, &hitPos ) ) { h = hitPos._y; }else{ continue; } } //----------------------------------------------------------- // 衝突あり //----------------------------------------------------------- // 頭上の高さ上限チェック if( h > position._y + radius * 2.0f ) { continue; } f32 checkLength = (position - hitPos).squareLength(); if( prevMinLength == checkLength ) { // 三角形と当たってたら高さ記録 collision::checkHitPos( *pTriangle, line, &hitPos ); } // 遠い点なら処理終了 if( checkLength >= nearestHitPosLength ) { continue; } // 接触点記録 resultPos = hitPos; // 一番近い点までの距離を記録 nearestHitPosLength = checkLength; // 当たった三角形の保存 _LastHitTriangle = pTriangle; // 衝突済み isHit = true; } prevMinLength = nearestHitPosLength; // この時点で見つかったら処理終了 if( isHit )return resultPos; //// 最大までいってなかったら ////if( Count < 4 ) //{ // resultPos = getHitPos(position, radius); //} // カウント初期化 Count = 0; return resultPos; }
// http://sourceforge.net/projects/assimp/forums/forum/817654/topic/3880745 void ofxAssimpModelLoader::updateGLResources(){ // update mesh position for the animation for (unsigned int i = 0; i < modelMeshes.size(); ++i){ // current mesh we are introspecting const aiMesh* mesh = modelMeshes[i].mesh; // calculate bone matrices std::vector<aiMatrix4x4> boneMatrices( mesh->mNumBones); for( size_t a = 0; a < mesh->mNumBones; ++a) { const aiBone* bone = mesh->mBones[a]; // find the corresponding node by again looking recursively through the node hierarchy for the same name aiNode* node = scene->mRootNode->FindNode(bone->mName); // start with the mesh-to-bone matrix boneMatrices[a] = bone->mOffsetMatrix; // and now append all node transformations down the parent chain until we're back at mesh coordinates again const aiNode* tempNode = node; while( tempNode) { // check your matrix multiplication order here!!! boneMatrices[a] = tempNode->mTransformation * boneMatrices[a]; // boneMatrices[a] = boneMatrices[a] * tempNode->mTransformation; tempNode = tempNode->mParent; } } // all using the results from the previous code snippet std::vector<aiVector3D> resultPos( mesh->mNumVertices); std::vector<aiVector3D> resultNorm( mesh->mNumVertices); // loop through all vertex weights of all bones for( size_t a = 0; a < mesh->mNumBones; ++a) { const aiBone* bone = mesh->mBones[a]; const aiMatrix4x4& posTrafo = boneMatrices[a]; // 3x3 matrix, contains the bone matrix without the translation, only with rotation and possibly scaling aiMatrix3x3 normTrafo = aiMatrix3x3( posTrafo); for( size_t b = 0; b < bone->mNumWeights; ++b) { const aiVertexWeight& weight = bone->mWeights[b]; size_t vertexId = weight.mVertexId; const aiVector3D& srcPos = mesh->mVertices[vertexId]; const aiVector3D& srcNorm = mesh->mNormals[vertexId]; resultPos[vertexId] += weight.mWeight * (posTrafo * srcPos); resultNorm[vertexId] += weight.mWeight * (normTrafo * srcNorm); } } // now upload the result position and normal along with the other vertex attributes into a dynamic vertex buffer, VBO or whatever // get mesh helper for this mesh; ofxAssimpMeshHelper meshHelper = modelMeshes[i]; glBindBuffer(GL_ARRAY_BUFFER, meshHelper.vertexBuffer); aiVertex* verts = (aiVertex*)glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); for (unsigned int x = 0; x < mesh->mNumVertices; ++x) { //verts->vPosition = mesh->mVertices[x]; verts->vPosition = resultPos[x]; if (NULL == mesh->mNormals) verts->vNormal = aiVector3D(0.0f,0.0f,0.0f); else verts->vNormal = resultNorm[x]; if (mesh->HasVertexColors(0)) { verts->dColorDiffuse = mesh->mColors[0][x]; } else verts->dColorDiffuse = aiColor4D(1.0, 1.0, 1.0, 1.0); // This varies slightly form Assimp View, we support the 3rd texture component. if (mesh->HasTextureCoords(0)) verts->vTextureUV = mesh->mTextureCoords[0][x]; else verts->vTextureUV = aiVector3D(0.5f,0.5f, 0.0f); // No longer in aiVertex VBO structure /* if (NULL == mesh->mTangents) { verts->vTangent = aiVector3D(0.0f,0.0f,0.0f); verts->vBitangent = aiVector3D(0.0f,0.0f,0.0f); } else { verts->vTangent = mesh->mTangents[x]; verts->vBitangent = mesh->mBitangents[x]; } if (mesh->HasTextureCoords(1)) verts->vTextureUV2 = mesh->mTextureCoords[1][x]; else verts->vTextureUV2 = aiVector3D(0.5f,0.5f, 0.0f); if( mesh->HasBones()){ unsigned char boneIndices[4] = { 0, 0, 0, 0 }; unsigned char boneWeights[4] = { 0, 0, 0, 0 }; ai_assert( weightsPerVertex[x].size() <= 4); for( unsigned int a = 0; a < weightsPerVertex[x].size(); a++){ boneIndices[a] = weightsPerVertex[x][a].mVertexId; boneWeights[a] = (unsigned char) (weightsPerVertex[x][a].mWeight * 255.0f); } memcpy( verts->mBoneIndices, boneIndices, sizeof( boneIndices)); memcpy( verts->mBoneWeights, boneWeights, sizeof( boneWeights)); } else{ // memset( verts->mBoneIndices, 0, sizeof( verts->mBoneIndices)); // memset( verts->mBoneWeights, 0, sizeof( verts->mBoneWeights)); } */ ++verts; } glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); //invalidates verts glBindBuffer(GL_ARRAY_BUFFER, 0); } }