第48节:WebAssembly加速与C++物理引擎编译

概述

WebAssembly(WASM)是一种高性能的二进制指令格式,可以在现代Web浏览器中运行。本节将深入探索如何将C++物理引擎编译为WebAssembly,并与Three.js集成,实现高性能的物理模拟计算。

物理引擎加速架构:
WASM物理系统 C++物理引擎 JS/Three.js渲染 WASM桥接层 刚体动力学 碰撞检测 约束求解 Three.js场景 网格更新 用户交互 Emscripten编译 内存管理 函数绑定 高性能计算 实时渲染 跨平台执行

核心原理深度解析

WebAssembly技术优势

特性 传统JavaScript WebAssembly 性能提升
执行速度 解释执行/JIT编译 接近原生代码 3-10倍
内存管理 自动垃圾回收 手动内存控制 更高效
计算密集型 性能受限 接近C++性能 显著提升
多线程 Worker有限制 真正多线程 并行加速

物理引擎核心模块

  1. 刚体动力学

    • 牛顿运动定律数值积分
    • 质量、惯性张量计算
    • 力和扭矩应用
  2. 碰撞检测

    • 包围体积层次(BVH)
    • 分离轴定理(SAT)
    • 连续碰撞检测(CCD)
  3. 约束求解

    • 顺序脉冲方法
    • 接触点生成
    • 摩擦力模拟

完整代码实现

C++物理引擎核心

cpp 复制代码
// PhysicsEngine.h
#ifndef PHYSICS_ENGINE_H
#define PHYSICS_ENGINE_H

#include <vector>
#include <memory>

// 向量类
struct Vector3 {
    double x, y, z;
    Vector3(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
    
    Vector3 operator+(const Vector3& other) const {
        return Vector3(x + other.x, y + other.y, z + other.z);
    }
    
    Vector3 operator*(double scalar) const {
        return Vector3(x * scalar, y * scalar, z * scalar);
    }
};

// 四元数类
struct Quaternion {
    double w, x, y, z;
    Quaternion(double w = 1, double x = 0, double y = 0, double z = 0) 
        : w(w), x(x), y(y), z(z) {}
};

// 刚体类
class RigidBody {
public:
    Vector3 position;
    Vector3 linearVelocity;
    Vector3 force;
    
    Quaternion rotation;
    Vector3 angularVelocity;
    Vector3 torque;
    
    double mass;
    double inverseMass;
    
    Vector3 inertiaTensor;
    Vector3 inverseInertiaTensor;
    
    bool isStatic;
    
    RigidBody(double mass = 1.0);
    
    void applyForce(const Vector3& force, const Vector3& point);
    void applyImpulse(const Vector3& impulse, const Vector3& point);
    void integrate(double deltaTime);
};

// 物理世界类
class PhysicsWorld {
private:
    std::vector<std::shared_ptr<RigidBody>> bodies;
    Vector3 gravity;
    
public:
    PhysicsWorld();
    
    void setGravity(const Vector3& gravity);
    void addBody(std::shared_ptr<RigidBody> body);
    void stepSimulation(double deltaTime);
    
    // 获取所有刚体数据供JS使用
    std::vector<std::shared_ptr<RigidBody>> getBodies() const { return bodies; }
};

#endif
cpp 复制代码
// PhysicsEngine.cpp
#include "PhysicsEngine.h"
#include <cmath>

RigidBody::RigidBody(double mass) 
    : mass(mass), isStatic(false) {
    inverseMass = mass > 0 ? 1.0 / mass : 0.0;
    inertiaTensor = Vector3(1.0, 1.0, 1.0);
    inverseInertiaTensor = Vector3(1.0, 1.0, 1.0);
}

void RigidBody::applyForce(const Vector3& force, const Vector3& point) {
    this->force = this->force + force;
    
    // 计算扭矩: τ = r × F
    Vector3 r = point + position; // 相对位置
    Vector3 torque = Vector3(
        r.y * force.z - r.z * force.y,
        r.z * force.x - r.x * force.z,
        r.x * force.y - r.y * force.x
    );
    
    this->torque = this->torque + torque;
}

void RigidBody::applyImpulse(const Vector3& impulse, const Vector3& point) {
    if (isStatic) return;
    
    // 线速度变化
    linearVelocity = linearVelocity + impulse * inverseMass;
    
    // 角速度变化
    Vector3 r = point + position;
    Vector3 angularImpulse = Vector3(
        r.y * impulse.z - r.z * impulse.y,
        r.z * impulse.x - r.x * impulse.z,
        r.x * impulse.y - r.y * impulse.x
    );
    
    angularVelocity = angularVelocity + Vector3(
        angularImpulse.x * inverseInertiaTensor.x,
        angularImpulse.y * inverseInertiaTensor.y,
        angularImpulse.z * inverseInertiaTensor.z
    );
}

void RigidBody::integrate(double deltaTime) {
    if (isStatic) return;
    
    // 线性运动积分
    Vector3 acceleration = force * inverseMass;
    linearVelocity = linearVelocity + acceleration * deltaTime;
    position = position + linearVelocity * deltaTime;
    
    // 角运动积分(简化)
    Vector3 angularAcceleration = Vector3(
        torque.x * inverseInertiaTensor.x,
        torque.y * inverseInertiaTensor.y,
        torque.z * inverseInertiaTensor.z
    );
    
    angularVelocity = angularVelocity + angularAcceleration * deltaTime;
    
    // 重置力和扭矩
    force = Vector3(0, 0, 0);
    torque = Vector3(0, 0, 0);
}

PhysicsWorld::PhysicsWorld() : gravity(0, -9.8, 0) {}

void PhysicsWorld::setGravity(const Vector3& gravity) {
    this->gravity = gravity;
}

void PhysicsWorld::addBody(std::shared_ptr<RigidBody> body) {
    bodies.push_back(body);
}

void PhysicsWorld::stepSimulation(double deltaTime) {
    // 应用重力
    for (auto& body : bodies) {
        if (!body->isStatic) {
            body->force = body->force + gravity * body->mass;
        }
    }
    
    // 积分运动
    for (auto& body : bodies) {
        body->integrate(deltaTime);
    }
    
    // 简化的碰撞处理(实际应该使用更复杂的碰撞检测)
    for (auto& body : bodies) {
        if (body->position.y < 0) {
            body->position.y = 0;
            body->linearVelocity.y = -body->linearVelocity.y * 0.8; // 弹性碰撞
        }
    }
}

Emscripten绑定接口

cpp 复制代码
// PhysicsBindings.cpp
#include <emscripten/bind.h>
#include "PhysicsEngine.h"

using namespace emscripten;

// WASM模块接口
class PhysicsModule {
private:
    std::shared_ptr<PhysicsWorld> world;
    
public:
    PhysicsModule() {
        world = std::make_shared<PhysicsWorld>();
    }
    
    int createBody(double mass, double x, double y, double z) {
        auto body = std::make_shared<RigidBody>(mass);
        body->position = Vector3(x, y, z);
        world->addBody(body);
        return world->getBodies().size() - 1; // 返回body索引
    }
    
    void setBodyPosition(int index, double x, double y, double z) {
        auto bodies = world->getBodies();
        if (index >= 0 && index < bodies.size()) {
            bodies[index]->position = Vector3(x, y, z);
        }
    }
    
    void applyBodyForce(int index, double fx, double fy, double fz) {
        auto bodies = world->getBodies();
        if (index >= 0 && index < bodies.size()) {
            bodies[index]->applyForce(Vector3(fx, fy, fz), Vector3(0, 0, 0));
        }
    }
    
    void stepSimulation(double deltaTime) {
        world->stepSimulation(deltaTime);
    }
    
    // 获取刚体位置数据供JS读取
    val getBodyPositions() {
        auto bodies = world->getBodies();
        std::vector<double> positions;
        
        for (const auto& body : bodies) {
            positions.push_back(body->position.x);
            positions.push_back(body->position.y);
            positions.push_back(body->position.z);
        }
        
        return val(typed_memory_view(positions.size(), positions.data()));
    }
    
    val getBodyRotations() {
        auto bodies = world->getBodies();
        std::vector<double> rotations;
        
        for (const auto& body : bodies) {
            rotations.push_back(body->rotation.w);
            rotations.push_back(body->rotation.x);
            rotations.push_back(body->rotation.y);
            rotations.push_back(body->rotation.z);
        }
        
        return val(typed_memory_view(rotations.size(), rotations.data()));
    }
};

// 绑定到JavaScript
EMSCRIPTEN_BINDINGS(physics_module) {
    class_<PhysicsModule>("PhysicsModule")
        .constructor<>()
        .function("createBody", &PhysicsModule::createBody)
        .function("setBodyPosition", &PhysicsModule::setBodyPosition)
        .function("applyBodyForce", &PhysicsModule::applyBodyForce)
        .function("stepSimulation", &PhysicsModule::stepSimulation)
        .function("getBodyPositions", &PhysicsModule::getBodyPositions)
        .function("getBodyRotations", &PhysicsModule::getBodyRotations);
}

Three.js集成前端

vue 复制代码
<template>
  <div class="wasm-physics-container">
    <!-- 主渲染画布 -->
    <canvas ref="physicsCanvas" class="physics-canvas"></canvas>
    
    <!-- 控制面板 -->
    <div class="physics-controls">
      <div class="control-section">
        <h3>⚡ WASM物理模拟</h3>
        
        <div class="control-group">
          <label>物理精度: {{ simulationQuality }}</label>
          <input 
            type="range" 
            v-model="simulationQuality" 
            min="1" 
            max="10" 
            step="1"
          >
        </div>
        
        <div class="control-group">
          <label>重力强度: {{ gravityStrength }}</label>
          <input 
            type="range" 
            v-model="gravityStrength" 
            min="0" 
            max="20" 
            step="0.5"
          >
        </div>
        
        <div class="control-group">
          <label>刚体数量: {{ bodyCount }}</label>
          <input 
            type="range" 
            v-model="bodyCount" 
            min="1" 
            max="1000" 
            step="1"
          >
        </div>
      </div>

      <div class="control-section">
        <h3>🎮 交互控制</h3>
        
        <div class="interaction-controls">
          <button @click="addRandomBodies" class="control-button">
            🎲 添加随机刚体
          </button>
          <button @click="createPhysicsStack" class="control-button">
            🧱 创建物理堆栈
          </button>
          <button @click="clearAllBodies" class="control-button">
            🧹 清空场景
          </button>
          <button @click="applyExplosion" class="control-button">
            💥 应用爆炸力
          </button>
        </div>
      </div>

      <div class="control-section">
        <h3>📊 性能监控</h3>
        <div class="performance-stats">
          <div class="stat-item">
            <span>帧率:</span>
            <span>{{ currentFPS }} FPS</span>
          </div>
          <div class="stat-item">
            <span>刚体数量:</span>
            <span>{{ activeBodies }}</span>
          </div>
          <div class="stat-item">
            <span>WASM计算时间:</span>
            <span>{{ wasmComputeTime }}ms</span>
          </div>
          <div class="stat-item">
            <span>Three.js渲染时间:</span>
            <span>{{ threeRenderTime }}ms</span>
          </div>
          <div class="stat-item">
            <span>内存使用:</span>
            <span>{{ memoryUsage }} MB</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 加载界面 -->
    <div v-if="isLoading" class="loading-overlay">
      <div class="wasm-loader">
        <div class="loader-cube"></div>
        <h3>编译WASM物理引擎...</h3>
        <div class="loading-progress">
          <div class="progress-bar">
            <div class="progress-fill" :style="progressStyle"></div>
          </div>
          <span class="progress-text">{{ loadingMessage }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { onMounted, onUnmounted, ref, reactive, computed, watch } from 'vue';
import * as THREE from 'three';

export default {
  name: 'WasmPhysicsSimulation',
  setup() {
    const physicsCanvas = ref(null);
    const simulationQuality = ref(5);
    const gravityStrength = ref(9.8);
    const bodyCount = ref(50);
    const currentFPS = ref(0);
    const wasmComputeTime = ref(0);
    const threeRenderTime = ref(0);
    const memoryUsage = ref(0);
    const activeBodies = ref(0);
    const isLoading = ref(true);
    const loadingMessage = ref('加载WASM模块...');

    let scene, camera, renderer, controls;
    let physicsModule = null;
    let bodyMeshes = [];
    let clock, stats;
    let frameCount = 0;
    let lastFpsUpdate = 0;

    // 初始化场景
    const initScene = async () => {
      // 创建Three.js场景
      scene = new THREE.Scene();
      scene.background = new THREE.Color(0x0f0f1a);
      scene.fog = new THREE.Fog(0x0f0f1a, 50, 200);

      // 创建相机
      camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      camera.position.set(0, 15, 30);

      // 创建渲染器
      renderer = new THREE.WebGLRenderer({
        canvas: physicsCanvas.value,
        antialias: true,
        powerPreference: "high-performance"
      });
      
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
      renderer.shadowMap.enabled = true;
      renderer.shadowMap.type = THREE.PCFSoftShadowMap;

      // 设置光照
      setupLighting();
      
      // 创建地面
      createGround();
      
      // 加载WASM模块
      await loadWasmModule();
      
      // 创建初始刚体
      createInitialBodies();
      
      isLoading.value = false;
      
      // 启动动画循环
      clock = new THREE.Clock();
      animate();
    };

    // 设置光照
    const setupLighting = () => {
      const ambientLight = new THREE.AmbientLight(0x404040, 0.6);
      scene.add(ambientLight);
      
      const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
      directionalLight.position.set(50, 50, 25);
      directionalLight.castShadow = true;
      directionalLight.shadow.mapSize.width = 2048;
      directionalLight.shadow.mapSize.height = 2048;
      scene.add(directionalLight);
    };

    // 创建地面
    const createGround = () => {
      const groundGeometry = new THREE.PlaneGeometry(100, 100);
      const groundMaterial = new THREE.MeshStandardMaterial({
        color: 0x3a3a4a,
        roughness: 0.8,
        metalness: 0.2
      });
      
      const ground = new THREE.Mesh(groundGeometry, groundMaterial);
      ground.rotation.x = -Math.PI / 2;
      ground.position.y = -5;
      ground.receiveShadow = true;
      
      scene.add(ground);
    };

    // 加载WASM模块
    const loadWasmModule = async () => {
      try {
        loadingMessage.value = '初始化WASM运行时...';
        
        // 这里应该加载实际的WASM模块
        // 简化实现:模拟WASM模块
        physicsModule = {
          createBody: (mass, x, y, z) => Math.floor(Math.random() * 1000),
          setBodyPosition: () => {},
          applyBodyForce: () => {},
          stepSimulation: () => {},
          getBodyPositions: () => new Float64Array(),
          getBodyRotations: () => new Float64Array()
        };
        
        // 模拟加载延迟
        await new Promise(resolve => setTimeout(resolve, 2000));
        loadingMessage.value = 'WASM物理引擎就绪';
        
      } catch (error) {
        console.error('WASM模块加载失败:', error);
        loadingMessage.value = '加载失败,使用回退方案';
      }
    };

    // 创建初始刚体
    const createInitialBodies = () => {
      for (let i = 0; i < bodyCount.value; i++) {
        addPhysicsBody();
      }
      updateStats();
    };

    // 添加物理刚体
    const addPhysicsBody = () => {
      const geometry = new THREE.SphereGeometry(1, 8, 6);
      const material = new THREE.MeshStandardMaterial({
        color: new THREE.Color().setHSL(Math.random(), 0.8, 0.6),
        roughness: 0.7,
        metalness: 0.3
      });
      
      const mesh = new THREE.Mesh(geometry, material);
      mesh.castShadow = true;
      
      // 随机位置
      mesh.position.set(
        (Math.random() - 0.5) * 20,
        Math.random() * 10 + 10,
        (Math.random() - 0.5) * 20
      );
      
      scene.add(mesh);
      bodyMeshes.push(mesh);
      
      // 在WASM物理引擎中创建对应刚体
      if (physicsModule) {
        physicsModule.createBody(1, mesh.position.x, mesh.position.y, mesh.position.z);
      }
    };

    // 添加随机刚体
    const addRandomBodies = () => {
      const addCount = Math.min(10, 1000 - bodyMeshes.length);
      for (let i = 0; i < addCount; i++) {
        addPhysicsBody();
      }
      updateStats();
    };

    // 创建物理堆栈
    const createPhysicsStack = () => {
      const stackSize = 5;
      const stackSpacing = 2.2;
      
      for (let layer = 0; layer < stackSize; layer++) {
        for (let i = 0; i < 5; i++) {
          const geometry = new THREE.BoxGeometry(2, 2, 2);
          const material = new THREE.MeshStandardMaterial({
            color: new THREE.Color().setHSL(layer * 0.1, 0.8, 0.6),
            roughness: 0.7,
            metalness: 0.3
          });
          
          const mesh = new THREE.Mesh(geometry, material);
          mesh.castShadow = true;
          mesh.position.set(
            (i - 2) * stackSpacing,
            layer * stackSpacing,
            0
          );
          
          scene.add(mesh);
          bodyMeshes.push(mesh);
          
          if (physicsModule) {
            physicsModule.createBody(1, mesh.position.x, mesh.position.y, mesh.position.z);
          }
        }
      }
      updateStats();
    };

    // 清空所有刚体
    const clearAllBodies = () => {
      bodyMeshes.forEach(mesh => {
        scene.remove(mesh);
        mesh.geometry.dispose();
        mesh.material.dispose();
      });
      bodyMeshes = [];
      updateStats();
    };

    // 应用爆炸力
    const applyExplosion = () => {
      const explosionCenter = new THREE.Vector3(0, 5, 0);
      const explosionStrength = 50;
      
      bodyMeshes.forEach((mesh, index) => {
        const direction = new THREE.Vector3()
          .subVectors(mesh.position, explosionCenter)
          .normalize();
        
        if (physicsModule) {
          physicsModule.applyBodyForce(
            index,
            direction.x * explosionStrength,
            direction.y * explosionStrength,
            direction.z * explosionStrength
          );
        }
      });
    };

    // 更新统计信息
    const updateStats = () => {
      activeBodies.value = bodyMeshes.length;
      
      // 模拟内存使用
      memoryUsage.value = (activeBodies.value * 0.1).toFixed(1);
    };

    // 动画循环
    const animate = () => {
      requestAnimationFrame(animate);
      
      const deltaTime = Math.min(clock.getDelta(), 0.1); // 限制最大deltaTime
      
      // 更新物理模拟
      if (physicsModule && bodyMeshes.length > 0) {
        const wasmStartTime = performance.now();
        
        // 执行WASM物理计算
        physicsModule.stepSimulation(deltaTime);
        
        // 获取刚体数据并更新Three.js网格
        const positions = physicsModule.getBodyPositions();
        const rotations = physicsModule.getBodyRotations();
        
        wasmComputeTime.value = (performance.now() - wasmStartTime).toFixed(2);
        
        // 更新网格位置(简化实现)
        bodyMeshes.forEach((mesh, index) => {
          if (index * 3 + 2 < positions.length) {
            mesh.position.set(
              positions[index * 3],
              positions[index * 3 + 1],
              positions[index * 3 + 2]
            );
          }
        });
      }
      
      // 渲染场景
      const renderStartTime = performance.now();
      renderer.render(scene, camera);
      threeRenderTime.value = (performance.now() - renderStartTime).toFixed(2);
      
      // 更新性能统计
      updatePerformanceStats(deltaTime);
    };

    // 更新性能统计
    const updatePerformanceStats = (deltaTime) => {
      frameCount++;
      lastFpsUpdate += deltaTime;
      
      if (lastFpsUpdate >= 1.0) {
        currentFPS.value = Math.round(frameCount / lastFpsUpdate);
        frameCount = 0;
        lastFpsUpdate = 0;
      }
    };

    // 进度条样式
    const progressStyle = computed(() => ({
      width: '100%'
    }));

    // 响应式设置
    watch(bodyCount, (newValue) => {
      const currentCount = bodyMeshes.length;
      const difference = newValue - currentCount;
      
      if (difference > 0) {
        for (let i = 0; i < difference; i++) {
          addPhysicsBody();
        }
      } else if (difference < 0) {
        const removeCount = -difference;
        for (let i = 0; i < removeCount; i++) {
          const mesh = bodyMeshes.pop();
          if (mesh) {
            scene.remove(mesh);
            mesh.geometry.dispose();
            mesh.material.dispose();
          }
        }
      }
      updateStats();
    });

    onMounted(() => {
      initScene();
      window.addEventListener('resize', handleResize);
    });

    onUnmounted(() => {
      if (renderer) {
        renderer.dispose();
      }
      window.removeEventListener('resize', handleResize);
    });

    const handleResize = () => {
      if (!camera || !renderer) return;
      
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    };

    return {
      physicsCanvas,
      simulationQuality,
      gravityStrength,
      bodyCount,
      currentFPS,
      wasmComputeTime,
      threeRenderTime,
      memoryUsage,
      activeBodies,
      isLoading,
      loadingMessage,
      progressStyle,
      addRandomBodies,
      createPhysicsStack,
      clearAllBodies,
      applyExplosion
    };
  }
};
</script>

<style scoped>
.wasm-physics-container {
  width: 100%;
  height: 100vh;
  position: relative;
  background: #000;
  overflow: hidden;
}

.physics-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

.physics-controls {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 320px;
  background: rgba(15, 15, 26, 0.9);
  padding: 20px;
  border-radius: 12px;
  color: white;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  max-height: 80vh;
  overflow-y: auto;
}

.control-section {
  margin-bottom: 25px;
  padding-bottom: 15px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.control-section:last-child {
  margin-bottom: 0;
  border-bottom: none;
}

.control-section h3 {
  color: #00d9ff;
  margin-bottom: 15px;
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.control-group {
  margin-bottom: 15px;
}

.control-group label {
  display: block;
  margin-bottom: 8px;
  color: #ccc;
  font-size: 14px;
}

.control-group input[type="range"] {
  width: 100%;
  height: 6px;
  background: #444;
  border-radius: 3px;
  outline: none;
  opacity: 0.7;
  transition: opacity 0.2s;
}

.control-group input[type="range"]:hover {
  opacity: 1;
}

.control-group input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #00d9ff;
  cursor: pointer;
  box-shadow: 0 0 10px rgba(0, 217, 255, 0.5);
}

.interaction-controls {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.control-button {
  padding: 12px;
  border: none;
  border-radius: 8px;
  background: linear-gradient(45deg, #667eea, #764ba2);
  color: white;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.control-button:hover {
  transform: translateY(-2px);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.performance-stats {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.stat-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 0;
  font-size: 14px;
}

.stat-item span:first-child {
  color: #ccc;
}

.stat-item span:last-child {
  color: #00d9ff;
  font-weight: bold;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.wasm-loader {
  text-align: center;
  color: white;
  position: relative;
}

.loader-cube {
  width: 60px;
  height: 60px;
  margin: 0 auto 30px;
  position: relative;
  transform-style: preserve-3d;
  animation: cubeRotate 3s infinite linear;
}

.loader-cube:before,
.loader-cube:after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  background: rgba(0, 217, 255, 0.6);
  border: 2px solid #00d9ff;
}

.loader-cube:before {
  transform: rotateX(90deg) translateZ(30px);
}

.loader-cube:after {
  transform: rotateY(90deg) translateZ(30px);
}

.wasm-loader h3 {
  margin-bottom: 20px;
  color: white;
  font-size: 20px;
}

.loading-progress {
  width: 300px;
  margin: 0 auto;
}

.progress-bar {
  width: 100%;
  height: 6px;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: 10px;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #00d9ff, #0088ff);
  border-radius: 3px;
  transition: width 0.3s ease;
}

.progress-text {
  color: #00d9ff;
  font-size: 14px;
}

@keyframes cubeRotate {
  0% { transform: rotateX(0) rotateY(0); }
  100% { transform: rotateX(360deg) rotateY(360deg); }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .physics-controls {
    width: 280px;
    right: 10px;
    top: 10px;
    padding: 15px;
  }
}
</style>

编译与优化指南

Emscripten编译命令

bash 复制代码
# 安装Emscripten
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

# 编译C++物理引擎为WASM
emcc \
  PhysicsEngine.cpp \
  PhysicsBindings.cpp \
  -o physics_engine.js \
  -O3 \
  -s WASM=1 \
  -s MODULARIZE=1 \
  -s EXPORT_ES6=1 \
  -s USE_ES6_IMPORT_META=0 \
  -s ALLOW_MEMORY_GROWTH=1 \
  -s ASSERTIONS=0 \
  -s ENVIRONMENT=web \
  -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' \
  --bind \
  --no-entry

性能优化策略

  1. 内存管理优化

    • 使用ALLOW_MEMORY_GROWTH允许内存动态增长
    • 避免频繁的JS-WASM内存拷贝
    • 重用内存缓冲区
  2. 多线程支持

    • 使用Web Workers进行并行计算
    • 分离物理计算和渲染线程
    • 共享内存减少数据传输
  3. SIMD加速

    • 启用SIMD指令集优化向量计算
    • 批量处理物理数据
    • 优化数据对齐

通过WebAssembly与C++物理引擎的结合,我们可以实现接近原生性能的复杂物理模拟,为Three.js应用提供强大的计算能力支撑。

file content end

相关推荐
2501_941111932 小时前
基于C++的区块链实现
开发语言·c++·算法
hetao17338372 小时前
2025-11-16~17 hetao1733837的刷题记录
c++·算法
_OP_CHEN2 小时前
算法基础篇:(九)贪心算法拓展之推公式:从排序规则到最优解的推导艺术
c++·算法·贪心算法·推公式·算法竞赛·acm/icpc
⑩-2 小时前
苍穹外卖Day(8)(9)
java·spring boot·mybatis
czxyvX2 小时前
010-C++之List
开发语言·c++·list
IUGEI2 小时前
Websocket、HTTP/2、HTTP/3原理解析
java·网络·后端·websocket·网络协议·http·https
程序猿_极客2 小时前
【2025 最新】 Maven 下载安装与配置教程(超详细带图文Windows 版):从入门到实战
java·开发语言·windows·maven·maven安装
q***01652 小时前
【保姆级教程】apache-tomcat的安装配置教程
java·tomcat·apache
得物技术2 小时前
Golang HTTP请求超时与重试:构建高可靠网络请求|得物技术
java·后端·go