Rect SkeletonRenderer::getBoundingBox () const {
	float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
	float scaleX = getScaleX(), scaleY = getScaleY();
	for (int i = 0; i < _skeleton->slotsCount; ++i) {
		spSlot* slot = _skeleton->slots[i];
		if (!slot->attachment) continue;
		int verticesCount;
		if (slot->attachment->type == SP_ATTACHMENT_REGION) {
			spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
			spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices);
			verticesCount = 8;
		} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
			spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
			spMeshAttachment_computeWorldVertices(mesh, slot, _worldVertices);
			verticesCount = mesh->super.worldVerticesLength;
		} else
			continue;
		for (int ii = 0; ii < verticesCount; ii += 2) {
			float x = _worldVertices[ii] * scaleX, y = _worldVertices[ii + 1] * scaleY;
			minX = min(minX, x);
			minY = min(minY, y);
			maxX = max(maxX, x);
			maxY = max(maxY, y);
		}
	}
	Vec2 position = getPosition();
    if (minX == FLT_MAX) minX = minY = maxX = maxY = 0;    
	return Rect(position.x + minX, position.y + minY, maxX - minX, maxY - minY);
}
Exemplo n.º 2
0
QRectF SkeletonAnimationFbo::calculateSkeletonRect()
{
    if (!isSkeletonValid())
        return QRectF();

    float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN;
    for (int i = 0; i < mspSkeleton->slotsCount; ++i) {
        spSlot* slot = mspSkeleton->slots[i];
        if (!slot->attachment)
            continue;

        int verticesCount;
        if (slot->attachment->type == SP_ATTACHMENT_REGION) {
            spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
            spRegionAttachment_computeWorldVertices(attachment, slot->bone, mWorldVertices);
            verticesCount = 8;
        } else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
            spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
            spMeshAttachment_computeWorldVertices(mesh, slot, mWorldVertices);
            verticesCount = mesh->verticesCount;
        } else if (slot->attachment->type == SP_ATTACHMENT_SKINNED_MESH) {
            spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)slot->attachment;
            spSkinnedMeshAttachment_computeWorldVertices(mesh, slot, mWorldVertices);
            verticesCount = mesh->uvsCount;
        } else
            continue;

        for (int ii = 0; ii < verticesCount; ii += 2) {
            float x = mWorldVertices[ii], y = mWorldVertices[ii + 1];
            minX = qMin(minX, x);
            minY = qMin(minY, y);
            maxX = qMax(maxX, x);
            maxY = qMax(maxY, y);
        }
    }

    QRectF rect(minX, minY, maxX - minX, maxY - minY);
    return rect;
}
void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t transformFlags) {
	SkeletonBatch* batch = SkeletonBatch::getInstance();

	Color3B nodeColor = getColor();
	_skeleton->r = nodeColor.r / (float)255;
	_skeleton->g = nodeColor.g / (float)255;
	_skeleton->b = nodeColor.b / (float)255;
	_skeleton->a = getDisplayedOpacity() / (float)255;
    
    Color4F color;
	AttachmentVertices* attachmentVertices = nullptr;
	for (int i = 0, n = _skeleton->slotsCount; i < n; ++i) {
		spSlot* slot = _skeleton->drawOrder[i];
		if (!slot->attachment) continue;

		switch (slot->attachment->type) {
		case SP_ATTACHMENT_REGION: {
			spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
			spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices);
			attachmentVertices = getAttachmentVertices(attachment);
            color.r = attachment->r;
			color.g = attachment->g;
			color.b = attachment->b;
			color.a = attachment->a;
			break;
		}
		case SP_ATTACHMENT_MESH: {
			spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
			spMeshAttachment_computeWorldVertices(attachment, slot, _worldVertices);
			attachmentVertices = getAttachmentVertices(attachment);
            color.r = attachment->r;
            color.g = attachment->g;
            color.b = attachment->b;
            color.a = attachment->a;
			break;
		}
		default:
			continue;
		}

		color.a *= _skeleton->a * slot->a * 255;
		float multiplier = _premultipliedAlpha ? color.a : 255;
		color.r *= _skeleton->r * slot->r * multiplier;
		color.g *= _skeleton->g * slot->g * multiplier;
		color.b *= _skeleton->b * slot->b * multiplier;
        
        
        
		for (int v = 0, w = 0, vn = attachmentVertices->_triangles->vertCount; v < vn; ++v, w += 2) {
			V3F_C4B_T2F* vertex = attachmentVertices->_triangles->verts + v;
			vertex->vertices.x = _worldVertices[w];
			vertex->vertices.y = _worldVertices[w + 1];
            vertex->colors.r = (GLubyte)color.r;
            vertex->colors.g = (GLubyte)color.g;
            vertex->colors.b = (GLubyte)color.b;
            vertex->colors.a = (GLubyte)color.a;
		}

		BlendFunc blendFunc;
		switch (slot->data->blendMode) {
		case SP_BLEND_MODE_ADDITIVE:
			blendFunc.src = _premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
			blendFunc.dst = GL_ONE;
			break;
		case SP_BLEND_MODE_MULTIPLY:
			blendFunc.src = GL_DST_COLOR;
			blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
			break;
		case SP_BLEND_MODE_SCREEN:
			blendFunc.src = GL_ONE;
			blendFunc.dst = GL_ONE_MINUS_SRC_COLOR;
			break;
		default:
			blendFunc.src = _premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
			blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
		}

		batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc,
			*attachmentVertices->_triangles, transform, transformFlags);
	}

	if (_debugSlots || _debugBones) {
        drawDebug(renderer, transform, transformFlags);
	}
}
Exemplo n.º 4
0
void SkeletonAnimationFbo::renderToCache(Renderer* renderer, RenderCmdsCache* cache)
{
    if (!cache)
        return;
    cache->clear();

    if (!renderer)
        return;

    SkeletonRenderer* skeletonRenderer = (SkeletonRenderer*)renderer;
    if (mShouldRelaseCacheTexture){
        mShouldRelaseCacheTexture = false;
        skeletonRenderer->releaseTextures();
    }

    const QRectF rect = calculateSkeletonRect();

    if (!isSkeletonValid())
        return;

    cache->setSkeletonRect(rect);

    cache->bindShader(RenderCmdsCache::ShaderTexture);
    int additive = -1;
    Color color;
    const float* uvs = 0;
    int verticesCount = 0;
    const int* triangles = 0;
    int trianglesCount = 0;
    float r = 0, g = 0, b = 0, a = 0;
    for (int i = 0, n = mspSkeleton->slotsCount; i < n; i++) {
        spSlot* slot = mspSkeleton->drawOrder[i];
        if (!slot->attachment)
            continue;

        Texture *texture = 0;
        switch (slot->attachment->type) {
        case SP_ATTACHMENT_REGION: {
            spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
            spRegionAttachment_computeWorldVertices(attachment, slot->bone, mWorldVertices);
            texture = getTexture(attachment);
            uvs = attachment->uvs;
            verticesCount = 8;
            triangles = quadTriangles;
            trianglesCount = 6;
            r = attachment->r;
            g = attachment->g;
            b = attachment->b;
            a = attachment->a;
            break;
        }
        case SP_ATTACHMENT_MESH: {
            spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
            spMeshAttachment_computeWorldVertices(attachment, slot, mWorldVertices);
            texture = getTexture(attachment);
            uvs = attachment->uvs;
            verticesCount = attachment->verticesCount;
            triangles = attachment->triangles;
            trianglesCount = attachment->trianglesCount;
            r = attachment->r;
            g = attachment->g;
            b = attachment->b;
            a = attachment->a;
            break;
        }
        case SP_ATTACHMENT_SKINNED_MESH: {
            spSkinnedMeshAttachment* attachment = (spSkinnedMeshAttachment*)slot->attachment;
            spSkinnedMeshAttachment_computeWorldVertices(attachment, slot, mWorldVertices);
            texture = getTexture(attachment);
            uvs = attachment->uvs;
            verticesCount = attachment->uvsCount;
            triangles = attachment->triangles;
            trianglesCount = attachment->trianglesCount;
            r = attachment->r;
            g = attachment->g;
            b = attachment->b;
            a = attachment->a;
            break;
        }
        default:
            break;
        }// END switch (slot->attachment->type)

        if (texture) {
            if (slot->data->additiveBlending != additive) {
                cache->cacheTriangleDrawCall();
                cache->blendFunc(GL_ONE, slot->data->additiveBlending ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);
                additive = slot->data->additiveBlending;
            }
            color.a = mspSkeleton->a * slot->a * a * 255;
            float multiplier = mPremultipliedAlapha ? color.a : 255;
            color.r = mspSkeleton->r * slot->r * r * multiplier;
            color.g = mspSkeleton->g * slot->g * g * multiplier;
            color.b = mspSkeleton->b * slot->b * b * multiplier;
            cache->drawTriangles(skeletonRenderer->getGLTexture(texture, window()), mWorldVertices, uvs, verticesCount, triangles, trianglesCount, color);
        }// END if (texture)
    }// END for (int i = 0, n = skeleton->slotsCount; i < n; i++)
    cache->cacheTriangleDrawCall();

    if (mDebugSlots || mDebugBones) {
        cache->bindShader(RenderCmdsCache::ShaderColor);
        if (mDebugSlots) {
            // Slots.
            cache->drawColor(0, 0, 255, 255);
            cache->lineWidth(1);

            Point points[4];
            for (int i = 0, n = mspSkeleton->slotsCount; i < n; i++) {
                spSlot* slot = mspSkeleton->drawOrder[i];
                if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
                spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
                spRegionAttachment_computeWorldVertices(attachment, slot->bone, mWorldVertices);
                points[0] = Point(mWorldVertices[0], mWorldVertices[1]);
                points[1] = Point(mWorldVertices[2], mWorldVertices[3]);
                points[2] = Point(mWorldVertices[4], mWorldVertices[5]);
                points[3] = Point(mWorldVertices[6], mWorldVertices[7]);
                cache->drawPoly(points, 4);
            }
        }// END if (mDebugSlots)

        if (mDebugBones) {
            // Bone lengths.
            cache->lineWidth(2);
            cache->drawColor(255, 0, 0, 255);
            for (int i = 0, n = mspSkeleton->bonesCount; i < n; i++) {
                spBone *bone = mspSkeleton->bones[i];
                float x = bone->data->length * bone->m00 + bone->worldX;
                float y = bone->data->length * bone->m10 + bone->worldY;
                cache->drawLine(Point(bone->worldX, bone->worldY), Point(x, y));
            }
            // Bone origins.
            cache->pointSize(4.0);
            cache->drawColor(0, 0, 255, 255); // Root bone is blue.
            for (int i = 0, n = mspSkeleton->bonesCount; i < n; i++) {
                spBone *bone = mspSkeleton->bones[i];
                cache->drawPoint(Point(bone->worldX, bone->worldY));
                if (i == 0) cache->drawColor(0, 255, 0, 255);
            }
        }// END if (mDebugBones)
    }//END if (mDebugSlots || mDebugBones)
}