Chapter 66 · ShapeEx 场景图

场景变换

Scene 级变换作用于所有子节点,实现整组平移、缩放、旋转,无需逐个修改子 Shape。

66

API 速查

函数说明
int xgeShapeExSceneTransformSet(xge_shape_ex_scene pScene, const xge_shape_ex_matrix_t* pMatrix)设置变换矩阵
int xgeShapeExSceneTransformIdentity(xge_shape_ex_scene pScene)重置
int xgeShapeExSceneTransformGet(xge_shape_ex_scene pScene, xge_shape_ex_matrix_t* pMatrix)获取变换
int xgeShapeExSceneTransformTranslate(xge_shape_ex_scene pScene, float fTX, float fTY)平移
int xgeShapeExSceneTransformScale(xge_shape_ex_scene pScene, float fSX, float fSY)缩放
int xgeShapeExSceneTransformRotate(xge_shape_ex_scene pScene, float fRadians)旋转
int xgeShapeExSceneTransformSkew(xge_shape_ex_scene pScene, float fXRadians, float fYRadians)斜切

编译本章示例

gcc -O2 -I. -o ch66.exe ch66_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch66.exe

示例:整组旋转

// 创建一组图形
xge_shape_ex_scene group = NULL;
xgeShapeExSceneCreate(&group);
// ... 添加多个 Shape ...

// 整组旋转 + 平移到屏幕中心
xgeShapeExSceneTransformRotate(group, 0.785f);  // 45°
xgeShapeExSceneTransformTranslate(group, 400, 300);

// 一次 Draw 绘制整棵子树
xgeShapeExSceneDraw(group, 0.25f);

完整代码

将以下代码保存为 ch66_main.c,编译后运行即可看到整组旋转动画效果:

#include "xge.h"

static float s_fAngle = 0.0f;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    s_fAngle += 0.015f;

    // 创建一组图形
    xge_shape_ex_scene group = NULL;
    xgeShapeExSceneCreate(&group);

    uint32_t colors[] = { 0x4FD8C2FF, 0xFFB454FF, 0xFF6B8AFF };
    for (int i = 0; i < 3; i++) {
        xge_shape_ex s = NULL;
        xgeShapeExCreate(&s);
        xgeShapeExAppendRect(s, -120+i*80,-30, 60,60, 8,8, 1);
        xgeShapeExFillColor(s, colors[i]);
        xgeShapeExSceneAdd(group, s);
        xgeShapeExDestroy(s);
    }

    // 整组旋转 + 平移到屏幕中心
    xgeShapeExSceneTransformIdentity(group);
    xgeShapeExSceneTransformRotate(group, s_fAngle);
    xgeShapeExSceneTransformTranslate(group, 400, 300);

    xgeShapeExSceneDraw(group, 0.25f);
    xgeShapeExSceneDestroy(group);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch66 - Scene Transform";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

代码讲解

  • SceneTransformRotate:对整组应用旋转变换,所有子节点跟随。
  • 层级累积:最终变换 = 父Scene × 子Scene × Shape 自身。
  • 每帧 Identity:重置后再设置,避免变换累积。
  • 一次 Draw:SceneDraw 绘制整棵子树,无需逐个绘制。

要点与陷阱

  • 层级累积:最终变换 = 父Scene × 子Scene × Shape 自身。
  • 动画重置:每帧 Identity 后再设置,避免累积。
  • 与 Shape Transform 独立:Scene 变换不影响子 Shape 的自身变换。

进阶练习

  1. 实现太阳系:每个行星是一个子 Scene,各自旋转。
  2. 缩放整组实现"缩放画布"功能。
场景变换效果
图:场景变换渲染效果