void OCTree::DivideNode(size_t index, uint32_t curr_depth) { if (octree_[index].obj_ptrs.size() > 1) { size_t const this_size = octree_.size(); AABBox const parent_bb = octree_[index].bb; float3 const parent_center = parent_bb.Center(); octree_[index].first_child_index = static_cast<int>(this_size); octree_[index].visible = BO_No; octree_.resize(this_size + 8); for (SceneObjsType::const_reference so : octree_[index].obj_ptrs) { AABBox const & aabb = *so->PosBoundWS(); int mark[6]; mark[0] = aabb.Min().x() >= parent_center.x() ? 1 : 0; mark[1] = aabb.Min().y() >= parent_center.y() ? 2 : 0; mark[2] = aabb.Min().z() >= parent_center.z() ? 4 : 0; mark[3] = aabb.Max().x() >= parent_center.x() ? 1 : 0; mark[4] = aabb.Max().y() >= parent_center.y() ? 2 : 0; mark[5] = aabb.Max().z() >= parent_center.z() ? 4 : 0; for (int j = 0; j < 8; ++ j) { if (j == ((j & 1) ? mark[3] : mark[0]) + ((j & 2) ? mark[4] : mark[1]) + ((j & 4) ? mark[5] : mark[2])) { octree_[this_size + j].obj_ptrs.push_back(so); } } } for (size_t j = 0; j < 8; ++ j) { octree_node_t& new_node = octree_[this_size + j]; new_node.first_child_index = -1; new_node.bb = AABBox(float3((j & 1) ? parent_center.x() : parent_bb.Min().x(), (j & 2) ? parent_center.y() : parent_bb.Min().y(), (j & 4) ? parent_center.z() : parent_bb.Min().z()), float3((j & 1) ? parent_bb.Max().x() : parent_center.x(), (j & 2) ? parent_bb.Max().y() : parent_center.y(), (j & 4) ? parent_bb.Max().z() : parent_center.z())); if (curr_depth < max_tree_depth_) { this->DivideNode(this_size + j, curr_depth + 1); } } SceneObjsType empty; octree_[index].obj_ptrs.swap(empty); } }
BoundOverlap OCTree::BoundVisible(size_t index, AABBox const & aabb) const { BOOST_ASSERT(index < octree_.size()); octree_node_t const & node = octree_[index]; if ((node.visible != BO_No) && MathLib::intersect_aabb_aabb(node.bb, aabb)) { if (BO_Yes == node.visible) { return BO_Yes; } else { BOOST_ASSERT(BO_Partial == node.visible); if (node.first_child_index != -1) { float3 const center = node.bb.Center(); int mark[6]; mark[0] = aabb.Min().x() >= center.x() ? 1 : 0; mark[1] = aabb.Min().y() >= center.y() ? 2 : 0; mark[2] = aabb.Min().z() >= center.z() ? 4 : 0; mark[3] = aabb.Max().x() >= center.x() ? 1 : 0; mark[4] = aabb.Max().y() >= center.y() ? 2 : 0; mark[5] = aabb.Max().z() >= center.z() ? 4 : 0; for (int j = 0; j < 8; ++ j) { if (j == ((j & 1) ? mark[3] : mark[0]) + ((j & 2) ? mark[4] : mark[1]) + ((j & 4) ? mark[5] : mark[2])) { BoundOverlap const bo = this->BoundVisible(node.first_child_index + j, aabb); if (bo != BO_No) { return bo; } } } return BO_No; } else { return BO_Partial; } } } else { return BO_No; } }
void LightSource::Color(float3 const & clr) { color_ = float4(clr.x(), clr.y(), clr.z(), MathLib::dot(clr, float3(0.2126f, 0.7152f, 0.0722f))); this->Range(-1); }
// 设置声源方向 ///////////////////////////////////////////////////////////////////////////////// void DSMusicBuffer::Direction(float3 const & v) { if (ds3DBuffer_) { ds3DBuffer_->SetConeOrientation(v.x(), v.y(), v.z(), DS3D_IMMEDIATE); } }
float find_minimum_quantization_error(float3 normal) { normal /= max(abs(normal.x()), max(abs(normal.y()), abs(normal.z()))); float min_error = 1e10f; float ret = 1; for (int step = 1; step < 128; ++ step) { float t = (step + 0.5f) / 127.5f; // compute the probe float3 p = normal * t; // quantize the probe float3 quantized_p = float3(quantize255(p.x()), quantize255(p.y()), quantize255(p.z())); // error computation for the probe float3 diff = (quantized_p - p) / t; float error = max(abs(diff.x()), max(abs(diff.y()), abs(diff.z()))); // find the minimum if (error < min_error) { min_error = error; ret = t; } } return ret; }
// 设置声源速度 ///////////////////////////////////////////////////////////////////////////////// void DSMusicBuffer::Velocity(float3 const & v) { if (ds3DBuffer_) { ds3DBuffer_->SetVelocity(v.x(), v.y(), v.z(), DS3D_IMMEDIATE); } }
// 设置声源位置 ///////////////////////////////////////////////////////////////////////////////// void DSMusicBuffer::Position(float3 const & v) { if (ds3DBuffer_) { ds3DBuffer_->SetPosition(v.x(), v.y(), v.z(), DS3D_IMMEDIATE); } }
void CascadedShadowLayer::UpdateCropMats() { for (size_t i = 0; i < intervals_.size(); ++ i) { float3 const scale = scales_[i]; float3 const bias = biases_[i]; crop_mats_[i] = MathLib::scaling(scale) * MathLib::translation(+(2.0f * bias.x() + scale.x() - 1.0f), -(2.0f * bias.y() + scale.y() - 1.0f), bias.z()); } }
// 3D Multi-octave Simplex noise. // // For each octave, a higher frequency/lower amplitude function will be added to the original. // The higher the persistence [0-1], the more of each succeeding octave will be added. float simplexNoise( const int octaves, const float persistence, const float scale, const float3 &v ) { float total = 0; float frequency = scale; float amplitude = 1; // We have to keep track of the largest possible amplitude, // because each octave adds more, and we need a value in [-1, 1]. float maxAmplitude = 0; for( int i=0; i < octaves; i++ ) { total += simplexRawNoise( v.x() * frequency, v.y() * frequency, v.z() * frequency ) * amplitude; frequency *= 2; maxAmplitude += amplitude; amplitude *= persistence; } return total / maxAmplitude; }
Mat44 Mat44::BuildRotationMatrix(const f32 angle_in_degrees, const float3& axis) { return BuildRotationMatrix(angle_in_degrees, axis.x(), axis.y(), axis.z()); };
// 获取3D听者方向 ///////////////////////////////////////////////////////////////////////////////// void DSAudioEngine::SetListenerOri(float3 const & face, float3 const & up) { this->ds3dListener_->SetOrientation(face.x(), face.y(), face.z(), up.x(), up.y(), up.z(), DS3D_IMMEDIATE); }
// 设置3D听者速度 ///////////////////////////////////////////////////////////////////////////////// void DSAudioEngine::SetListenerVel(float3 const & v) { this->ds3dListener_->SetVelocity(v.x(), v.y(), v.z(), DS3D_IMMEDIATE); }
// 设置3D听者位置 ///////////////////////////////////////////////////////////////////////////////// void DSAudioEngine::SetListenerPos(float3 const & v) { this->ds3dListener_->SetPosition(v.x(), v.y(), v.z(), DS3D_IMMEDIATE); }
void XAAudioEngine::SetListenerOri(float3 const & face, float3 const & up) { listener_.OrientFront = { face.x(), face.y(), face.z() }; listener_.OrientTop = { up.x(), up.y(), up.z() }; }
void XAAudioEngine::SetListenerVel(float3 const & v) { listener_.Velocity = { v.x(), v.y(), v.z() }; }
void XAAudioEngine::SetListenerPos(float3 const & v) { listener_.Position = { v.x(), v.y(), v.z() }; }
void DetailedSkinnedModel::DoBuildModelInfo() { bool has_tc = false; bool has_normal = false; bool has_tangent_quat = false; bool has_skinned = false; RenderLayout const & rl = subrenderables_[0]->GetRenderLayout(); for (uint32_t i = 0; i < rl.NumVertexStreams(); ++ i) { switch (rl.VertexStreamFormat(i)[0].usage) { case VEU_TextureCoord: has_tc = true; break; case VEU_Normal: has_normal = true; break; case VEU_Tangent: has_tangent_quat = true; break; case VEU_BlendIndex: case VEU_BlendWeight: has_skinned = true; break; default: break; } } uint32_t total_num_vertices = 0; uint32_t total_num_indices = 0; for (auto const & renderable : subrenderables_) { StaticMeshPtr mesh = checked_pointer_cast<StaticMesh>(renderable); total_num_vertices += mesh->NumVertices(); total_num_indices += mesh->NumTriangles() * 3; } RenderFactory& rf = Context::Instance().RenderFactoryInstance(); AABBox const & pos_bb = this->PosBound(); AABBox const & tc_bb = this->TexcoordBound(); float3 const pos_center = pos_bb.Center(); float3 const pos_extent = pos_bb.HalfSize(); float3 const tc_center = tc_bb.Center(); float3 const tc_extent = tc_bb.HalfSize(); std::vector<float3> positions(total_num_vertices); std::vector<float2> texcoords(total_num_vertices); std::vector<float3> normals(total_num_vertices); std::vector<Quaternion> tangent_quats(total_num_vertices); for (uint32_t i = 0; i < rl.NumVertexStreams(); ++ i) { GraphicsBufferPtr const & vb = rl.GetVertexStream(i); switch (rl.VertexStreamFormat(i)[0].usage) { case VEU_Position: { GraphicsBufferPtr vb_cpu = rf.MakeVertexBuffer(BU_Static, EAH_CPU_Read, vb->Size(), nullptr); vb->CopyToBuffer(*vb_cpu); GraphicsBuffer::Mapper mapper(*vb_cpu, BA_Read_Only); int16_t const * p_16 = mapper.Pointer<int16_t>(); for (uint32_t j = 0; j < total_num_vertices; ++ j) { positions[j].x() = ((p_16[j * 4 + 0] + 32768) / 65535.0f * 2 - 1) * pos_extent.x() + pos_center.x(); positions[j].y() = ((p_16[j * 4 + 1] + 32768) / 65535.0f * 2 - 1) * pos_extent.y() + pos_center.y(); positions[j].z() = ((p_16[j * 4 + 2] + 32768) / 65535.0f * 2 - 1) * pos_extent.z() + pos_center.z(); } } break; case VEU_TextureCoord: { GraphicsBufferPtr vb_cpu = rf.MakeVertexBuffer(BU_Static, EAH_CPU_Read, vb->Size(), nullptr); vb->CopyToBuffer(*vb_cpu); GraphicsBuffer::Mapper mapper(*vb_cpu, BA_Read_Only); int16_t const * t_16 = mapper.Pointer<int16_t>(); for (uint32_t j = 0; j < total_num_vertices; ++ j) { texcoords[j].x() = ((t_16[j * 2 + 0] + 32768) / 65535.0f * 2 - 1) * tc_extent.x() + tc_center.x(); texcoords[j].y() = ((t_16[j * 2 + 1] + 32768) / 65535.0f * 2 - 1) * tc_extent.y() + tc_center.y(); } } break; case VEU_Normal: { GraphicsBufferPtr vb_cpu = rf.MakeVertexBuffer(BU_Static, EAH_CPU_Read, vb->Size(), nullptr); vb->CopyToBuffer(*vb_cpu); GraphicsBuffer::Mapper mapper(*vb_cpu, BA_Read_Only); uint32_t const * n_32 = mapper.Pointer<uint32_t>(); if (EF_A2BGR10 == rl.VertexStreamFormat(i)[0].format) { for (uint32_t j = 0; j < total_num_vertices; ++ j) { normals[j].x() = ((n_32[j] >> 0) & 0x3FF) / 1023.0f * 2 - 1; normals[j].y() = ((n_32[j] >> 10) & 0x3FF) / 1023.0f * 2 - 1; normals[j].z() = ((n_32[j] >> 20) & 0x3FF) / 1023.0f * 2 - 1; } } else if (EF_ABGR8 == rl.VertexStreamFormat(i)[0].format) { for (uint32_t j = 0; j < total_num_vertices; ++ j) { normals[j].x() = ((n_32[j] >> 0) & 0xFF) / 255.0f * 2 - 1; normals[j].y() = ((n_32[j] >> 8) & 0xFF) / 255.0f * 2 - 1; normals[j].z() = ((n_32[j] >> 16) & 0xFF) / 255.0f * 2 - 1; } } else { BOOST_ASSERT(EF_ARGB8 == rl.VertexStreamFormat(i)[0].format); for (uint32_t j = 0; j < total_num_vertices; ++ j) { normals[j].x() = ((n_32[j] >> 16) & 0xFF) / 255.0f * 2 - 1; normals[j].y() = ((n_32[j] >> 8) & 0xFF) / 255.0f * 2 - 1; normals[j].z() = ((n_32[j] >> 0) & 0xFF) / 255.0f * 2 - 1; } } } break; case VEU_Tangent: { GraphicsBufferPtr vb_cpu = rf.MakeVertexBuffer(BU_Static, EAH_CPU_Read, vb->Size(), nullptr); vb->CopyToBuffer(*vb_cpu); GraphicsBuffer::Mapper mapper(*vb_cpu, BA_Read_Only); uint32_t const * t_32 = mapper.Pointer<uint32_t>(); if (EF_ABGR8 == rl.VertexStreamFormat(i)[0].format) { for (uint32_t j = 0; j < total_num_vertices; ++ j) { tangent_quats[j].x() = ((t_32[j] >> 0) & 0xFF) / 255.0f * 2 - 1; tangent_quats[j].y() = ((t_32[j] >> 8) & 0xFF) / 255.0f * 2 - 1; tangent_quats[j].z() = ((t_32[j] >> 16) & 0xFF) / 255.0f * 2 - 1; tangent_quats[j].w() = ((t_32[j] >> 24) & 0xFF) / 255.0f * 2 - 1; } } else { BOOST_ASSERT(EF_ARGB8 == rl.VertexStreamFormat(i)[0].format); for (uint32_t j = 0; j < total_num_vertices; ++ j) { tangent_quats[j].x() = ((t_32[j] >> 16) & 0xFF) / 255.0f * 2 - 1; tangent_quats[j].y() = ((t_32[j] >> 8) & 0xFF) / 255.0f * 2 - 1; tangent_quats[j].z() = ((t_32[j] >> 0) & 0xFF) / 255.0f * 2 - 1; tangent_quats[j].w() = ((t_32[j] >> 24) & 0xFF) / 255.0f * 2 - 1; } } }
float3 ALVecToVec(float3 const & v) { return float3(v.x(), v.y(), -v.z()); }
void ClearFrameBuffer(const float3 &c) { glClearColor(c.x(), c.y(), c.z(), 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); }