From c5c3df66430aafcc9bbe9335292a274066d2a611 Mon Sep 17 00:00:00 2001 From: Ruiqi Mao Date: Thu, 21 Jun 2018 14:40:28 -0400 Subject: renamed samplecode/Nima to samplecode/SampleNimaActor Bug: skia: Change-Id: I305ca837d5ed35df4b519e7283201f0a0f87b1c3 Reviewed-on: https://skia-review.googlesource.com/136636 Reviewed-by: Brian Osman Commit-Queue: Ruiqi Mao --- samplecode/SampleNimaActor.cpp | 185 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 samplecode/SampleNimaActor.cpp (limited to 'samplecode/SampleNimaActor.cpp') diff --git a/samplecode/SampleNimaActor.cpp b/samplecode/SampleNimaActor.cpp new file mode 100644 index 0000000000..4634a45199 --- /dev/null +++ b/samplecode/SampleNimaActor.cpp @@ -0,0 +1,185 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SampleNimaActor.h" + +#include "SkString.h" +#include "SkVertices.h" +#include "SkPaint.h" +#include "SkFilterQuality.h" +#include "Resources.h" +#include + +using namespace nima; + +SampleActor::SampleActor(std::string baseName) + : fTexture(nullptr) + , fActorImages() + , fPaint(nullptr) { + // Load the NIMA data. + SkString nimaSkPath = GetResourcePath(("nima/" + baseName + ".nima").c_str()); + std::string nimaPath(nimaSkPath.c_str()); + INHERITED::load(nimaPath); + + // Load the image asset. + fTexture = GetResourceAsImage(("nima/" + baseName + ".png").c_str()); + + // Create the paint. + fPaint = std::make_unique(); + fPaint->setShader(fTexture->makeShader(nullptr)); + fPaint->setFilterQuality(SkFilterQuality::kLow_SkFilterQuality); + + // Load the image nodes. + fActorImages.reserve(m_ImageNodeCount); + for (uint32_t i = 0; i < m_ImageNodeCount; i ++) { + fActorImages.emplace_back(m_ImageNodes[i], fTexture, fPaint.get()); + } + + // Sort the image nodes. + std::sort(fActorImages.begin(), fActorImages.end(), [](auto a, auto b) { + return a.drawOrder() < b.drawOrder(); + }); +} + +SampleActor::~SampleActor() { +} + +void SampleActor::render(SkCanvas* canvas) const { + // Render the image nodes. + for (auto image : fActorImages) { + image.render(this, canvas); + } +} + +SampleActorImage::SampleActorImage(ActorImage* actorImage, sk_sp texture, SkPaint* paint) + : fActorImage(actorImage) + , fTexture(texture) + , fPaint(paint) { +} + +SampleActorImage::~SampleActorImage() { +} + +void SampleActorImage::render(const SampleActor* actor, SkCanvas* canvas) const { + // Retrieve data from the image. + uint32_t vertexCount = fActorImage->vertexCount(); + uint32_t vertexStride = fActorImage->vertexStride(); + float* vertexData = fActorImage->vertices(); + uint32_t indexCount = fActorImage->triangleCount() * 3; + uint16_t* indexData = fActorImage->triangles(); + + // Don't render if not visible. + if (!vertexCount || fActorImage->textureIndex() < 0) { + return; + } + + // Split the vertex data. + std::vector positions(vertexCount); + std::vector texs(vertexCount); + for (uint32_t i = 0; i < vertexCount; i ++) { + uint32_t j = i * vertexStride; + + // Get the attributes. + float* attrPosition = vertexData + j; + float* attrTex = vertexData + j + 2; + float* attrBoneIdx = vertexData + j + 4; + float* attrBoneWgt = vertexData + j + 8; + + // Get deformed positions if necessary. + if (fActorImage->doesAnimationVertexDeform()) { + attrPosition = fActorImage->animationDeformedVertices() + i * 2; + } + + // Deform the position. + Vec2D position(attrPosition[0], attrPosition[1]); + if (fActorImage->connectedBoneCount() > 0) { + position = deform(position, attrBoneIdx, attrBoneWgt); + } else { + position = deform(position, nullptr, nullptr); + } + + // Set the data. + positions[i].set(position[0], position[1]); + texs[i].set(attrTex[0] * fTexture->width(), attrTex[1] * fTexture->height()); + } + + // Create vertices. + sk_sp vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, + vertexCount, + positions.data(), + texs.data(), + nullptr, + indexCount, + indexData); + + // Determine the blend mode. + SkBlendMode blendMode; + switch (fActorImage->blendMode()) { + case BlendMode::Off: { + blendMode = SkBlendMode::kSrc; + break; + } + case BlendMode::Normal: { + blendMode = SkBlendMode::kSrcOver; + break; + } + case BlendMode::Additive: { + blendMode = SkBlendMode::kPlus; + break; + } + case BlendMode::Multiply: { + blendMode = SkBlendMode::kMultiply; + break; + } + case BlendMode::Screen: { + blendMode = SkBlendMode::kScreen; + break; + } + } + + // Set the opacity. + fPaint->setAlpha(static_cast(fActorImage->renderOpacity() * 255)); + + // Draw the vertices. + canvas->drawVertices(vertices, blendMode, *fPaint); + + // Reset the opacity. + fPaint->setAlpha(255); +} + +Vec2D SampleActorImage::deform(const Vec2D& position, float* boneIdx, float* boneWgt) const { + float px = position[0], py = position[1]; + float px2 = px, py2 = py; + float influence[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + + // Apply the world transform. + Mat2D worldTransform = fActorImage->worldTransform(); + px2 = worldTransform[0] * px + worldTransform[2] * py + worldTransform[4]; + py2 = worldTransform[1] * px + worldTransform[3] * py + worldTransform[5]; + + // Apply deformations based on bone offsets. + if (boneIdx && boneWgt) { + float* matrices = fActorImage->boneInfluenceMatrices(); + + for (uint32_t i = 0; i < 4; i ++) { + int index = static_cast(boneIdx[i]); + float weight = boneWgt[i]; + for (int j = 0; j < 6; j ++) { + influence[j] += matrices[index * 6 + j] * weight; + } + } + + px = influence[0] * px2 + influence[2] * py2 + influence[4]; + py = influence[1] * px2 + influence[3] * py2 + influence[5]; + } else { + px = px2; + py = py2; + } + + // Return the transformed position. + return Vec2D(px, py); +} -- cgit v1.2.3