Crie um tema 3D na V2

Aprenda a desenhar atlas UV, configurar materiais e moeda, testar cada face e publicar um tema Dice View.

Este artigo documenta a V2 publicada. Para a prévia atual com física, veja o guia V3. V3 ↗ Licenças ↗

Neste tutorial, você criará o tema obsidian sobre o modelo 3D incluído. Ele terá novos números, relevo opcional e sua própria paleta. No fim, qualquer dado renderizado pelo Dice View poderá usar theme: 'obsidian'.

Você precisa de: @erpg/dice3dview 2.6.1, os assets públicos do pacote, um editor que preserve transparência em WebP/PNG/SVG e um projeto que sirva arquivos de public/. Consulte os arquivos V2 em Mapas de textura. A galeria e o estúdio usam V3; para um novo projeto, siga o tutorial V3.

1. Hospede os assets do Dice View

Copie node_modules/@erpg/dice3dview/dist/assets/dice-box/ para public/assets/dice-box/. O assetPath padrão do viewer é /assets/dice-box/. Verifique no navegador que /assets/dice-box/themes/default/theme.config.json e /assets/dice-box/themes/default/default.json respondem; o modelo padrão é reutilizado pelo novo tema.

public/assets/dice-box/
├── havok/HavokPhysics.wasm
└── themes/
    ├── default/
    │   ├── default.json
    │   ├── diffuse-light.webp
    │   ├── diffuse-dark.webp
    │   └── normal.webp
    └── obsidian/
        ├── theme.config.json
        ├── diffuse-light.webp
        ├── diffuse-dark.webp
        └── normal.webp

Crie obsidian/ e copie os atlas claro, atlas escuro e, se quiser relevo, o mapa normal. O primeiro resultado verificável é a nova pasta com imagens que abrem por URL HTTP.

2. Redesenhe os números nas ilhas UV

Abra as duas cópias do diffuse em uma tela de 1024 × 1024 pixels. Substitua o desenho de cada número mantendo sua posição e escala na ilha original; preserve o canal alfa ao redor. A variante light usa glifos claros para dados escuros, e dark usa glifos escuros para dados claros. O View escolhe a variante segundo themeColor.

Não redistribua as faces em grade, nem troque números entre ilhas. O arquivo é um atlas UV do default.json, não uma tabela ordenada. Se reposicionar um glifo, o dado poderá mostrar um número diferente do resultado entregue ao viewer. Compare o novo mapa com os originais na galeria antes de prosseguir.

Para arte integral em cores, escolha material.type: 'standard' e crie uma única textura difusa com as cores da face. Em type: 'color', o alfa da textura deixa themeColor preencher o corpo, ideal para skins recoloríveis.

3. Ajuste relevo, reflexo e moeda

Se os números novos têm formato diferente, edite normal.webp no mesmo UV. Um relevo velho sob um glifo novo parece duplicado. Se não precisar de relevo, omita bumpTexture e bumpLevel do manifesto. O mapa especular de exemplo é opcional; só é usado quando specularTexture aponta para ele.

A moeda d2 tem frente e verso separados. Você pode reutilizar ../default/coin-1.svg e ../default/coin-2.svg ou publicar arquivos seus. Mantenha frente 1 e verso 2; a arte não muda os valores físicos. Com colorize: true, a transparência recebe themeColor; com false, a ilustração mantém suas cores e o aro pode usar edgeColor.

4. Escreva theme.config.json

Salve este manifesto em themes/obsidian/theme.config.json. Ele usa os três mapas que você acabou de criar e a moeda padrão. material e diceAvailable são obrigatórios. Como não há meshFile, o View usa themes/default/default.json.

{
  "name": "Obsidian",
  "systemName": "obsidian",
  "material": {
    "type": "color",
    "diffuseTexture": {
      "light": "diffuse-light.webp",
      "dark": "diffuse-dark.webp"
    },
    "diffuseLevel": 1,
    "bumpTexture": "normal.webp",
    "bumpLevel": 0.5
  },
  "diceAvailable": ["d2", "d4", "d6", "d8", "d10", "d12", "d20", "d100"],
  "coin": {
    "front": { "value": 1, "texture": "../default/coin-1.svg" },
    "back": { "value": 2, "texture": "../default/coin-2.svg" },
    "colorize": true,
    "diameter": 1,
    "thickness": 0.12
  }
}

Confira no navegador que /assets/dice-box/themes/obsidian/theme.config.json responde com JSON e que todos os caminhos relativos nele também respondem. A declaração diceAvailable descreve o suporte esperado; a disponibilidade real exige malha, collider e mapa físico para cada forma. A moeda d2 é procedural.

5. Veja o tema em um dado real

O estúdio V3 aceita imagens locais e URLs, aplica o resultado a um dado 3D e exporta theme.config.json. Para verificar o tema com a V2 já hospedada em sua aplicação, use o viewer V2 diretamente:

import { DiceResultViewer } from '@erpg/dice3dview/external'
import '@erpg/dice3dview/style.css'

const viewer = new DiceResultViewer({
  container: '#dice-stage',
  assetPath: '/assets/dice-box/',
  theme: 'obsidian',
  themeColor: '#e60049'
})

await viewer.display({
  id: 'obsidian-test',
  dice: [
    { id: 'd20', sides: 20, value: 18 },
    { id: 'coin', sides: 2, value: 1 }
  ],
  mode: 'physics'
})

O value vem do Dice Core ou da aplicação; o View não sorteia nem altera a face. Para aplicar o tema só a um dado, passe theme: 'obsidian' e themeColor no próprio objeto de dado.

6. Verifique contraste e resultado

Role cada formato declarado em diceAvailable e compare o número visível com value. Teste uma cor escura e uma clara para conferir as duas variantes diffuse; confira ambas as faces da moeda. Este exemplo V2 usa física com Havok; a V3 usa seu motor próprio. Um teste visual que cobre só d20 pode deixar um d4 ou d100 com ilha UV incorreta.

Quando editar um tema já carregado com o mesmo nome, descarte o viewer e crie outra instância para renovar o cache do manifesto/modelo. Durante desenvolvimento, confirme também no Network do navegador que o novo arquivo foi baixado.

7. Hospede fora do pacote

Para servir o tema em outra origem, publique uma pasta contendo theme.config.json e os seus mapas. Configure CORS e associe um nome à URL da pasta, sem o nome do JSON:

const viewer = new DiceResultViewer({
  container: '#dice-stage',
  assetPath: '/assets/dice-box/',
  externalThemes: { obsidian: 'https://cdn.example.com/dice/obsidian' }
})

await viewer.display({
  id: 'external-theme',
  dice: [{ id: 'd6', sides: 6, value: 4, theme: 'obsidian' }]
})

Texturas relativas partem da pasta externa; caminhos iniciados por /, URLs HTTP(S) e data: também são aceitos. Se o tema externo reutiliza ../default/coin-1.svg, esse caminho precisa existir na origem externa ou ser substituído por uma URL pública explícita.

Modelo 3D próprio

Para alterar a geometria, defina meshFile relativo à pasta do tema. O JSON Babylon precisa conter, para cada poliedro usado, malha visual dN, collider dN_collider e colliderFaceMap.dN que associa os triângulos ao valor da face. O d4 usa a face apoiada para baixo; os demais usam a face selecionada para cima. O d100 pode reutilizar templates d10, mas ainda exige seu mapa de faces. Uma malha bonita sem mapa coerente pode pousar exibindo um resultado errado.

Para trocar números por símbolos mantendo as malhas existentes, siga Personalize faces simbólicas. Para conferir cada campo do manifesto, consulte Temas e assets e Mapas de textura.