예제 #1
0
파일: Rasterizer.cs 프로젝트: denniskb/asvo
            /// <summary>
            /// Traverses all octree nodes and draws them. Used by <see cref="Rasterizer.render"/>.
            /// </summary>
            private void traverse(Object3D obj,
                                  uint offset,
                                  int x, int y, int z,
                                  Matrix projection,
                                  Matrix worldView,
                                  Matrix worldViewProjection,
                                  byte level,
                                  float halfDim,
                                  int threadIndex,
                                  Vector3 octreeMin)
            {
                if (level == 2 && offset % JobCenter.getWorkerCount() != threadIndex)
                    return;

                int gridResolution = 1 << level;
                float gridDimension = obj.getData().dimension;

                Vector3 xyzTimesGridDim = new Vector3(x, y, z) * gridDimension;
                float gridResolutionMul = 1.0f / gridResolution;
                Vector3 min = octreeMin + xyzTimesGridDim * gridResolutionMul;

                xyzTimesGridDim += new Vector3(gridDimension);
                Vector3 max = octreeMin + xyzTimesGridDim * gridResolutionMul;

                float dimension = max.X - min.X;
                bool subDivide = false;
                Vector3 center = Vector3.Lerp(min, max, 0.5f);
                Vector3 center2 = center + new Vector3(0, 0, dimension);

                VisualData vd = offset >= obj.getData()._innerNodes.Length ?
                    obj.getData()._leaves[offset - obj.getData()._innerNodes.Length].visualData :
                    obj.getData()._innerNodes[offset].visualData;

                Vector3 posIn, posOut;
                posOut = Vector3.Zero;
                if (vd.boneWeights.X > 0.0f)
                {
                    posIn = center;
                    Math3DHelper.mul(ref posIn, ref obj.getData()._animation[obj.frame, vd.boneIndex0]);
                    posOut += vd.boneWeights.X * posIn;
                }
                if (vd.boneWeights.Y > 0.0f)
                {
                    posIn = center;
                    Math3DHelper.mul(ref posIn, ref obj.getData()._animation[obj.frame, vd.boneIndex1]);
                    posOut += vd.boneWeights.Y * posIn;
                }
                if (vd.boneWeights.Z > 0.0f)
                {
                    posIn = center;
                    Math3DHelper.mul(ref posIn, ref obj.getData()._animation[obj.frame, vd.boneIndex2]);
                    posOut += vd.boneWeights.Z * posIn;
                }
                if (vd.boneWeights.W > 0.0f)
                {
                    posIn = center;
                    Math3DHelper.mul(ref posIn, ref obj.getData()._animation[obj.frame, vd.boneIndex3]);
                    posOut += vd.boneWeights.W * posIn;
                }

                center = posOut;

                if (offset >= obj.getData()._innerNodes.Length)
                {
                    Math3DHelper.mul(ref center, ref worldViewProjection);
                    halfDim *= 0.5f * dimension;
                }
                else
                {
                    Math3DHelper.mul(ref center, ref worldView);

                    Vector3 dimVec = new Vector3(0.5f * dimension, 0, center.Z);

                    Math3DHelper.mul(ref center, ref projection);

                    Math3DHelper.mul(ref dimVec, ref projection);
                    halfDim = dimVec.X;

                    subDivide = halfDim > pixelWidth;
                }

                if (subDivide)
                {
                    float minusOneminusHalfDim = -1.0f - halfDim;
                    float onePlusHalfDim = 1.0f + halfDim;

                    if (center.X < minusOneminusHalfDim || center.X > onePlusHalfDim ||
                        center.Y < minusOneminusHalfDim || center.Y > onePlusHalfDim ||
                        center.Z < minusOneminusHalfDim + 1.0f || center.Z > onePlusHalfDim)
                        return;

                    Vector3 halfVec = 0.5f * (max - min);

                    byte childIndex = 0; uint mask, index = 0;
                    mask = obj.getData()._innerNodes[offset].childMask;
                    index = obj.getData()._innerNodes[offset].childIndex;

                    for (int i = 0; i < 8; ++i)
                    {
                        if ((mask & (byte)(1u << i)) != 0)
                        {
                            traverse(obj,
                                     index + childIndex,
                                     x * 2 +  (i & 1),
                                     y * 2 + ((i & 2) >> 1),
                                     z * 2 + ((i & 4) >> 2),
                                     projection,
                                     worldView,
                                     worldViewProjection,
                                     (byte)(level + 1),
                                     halfDim,
                                     threadIndex,
                                     octreeMin);

                            ++childIndex;
                        }
                    }
                }
                else
                {
                    center.X = center.X * 0.5f + 0.5f;
                    center.Y = 1.0f - (center.Y * 0.5f + 0.5f);

                    int centerX, centerY;
                    centerX = (int)Math3DHelper.round(center.X * horRes);
                    centerY = (int)Math3DHelper.round(center.Y * vertRes);

                    if (centerX < 0 || centerX >= horRes ||
                        centerY < 0 || centerY >= vertRes)
                        return;

                    int index = centerY * horRes + centerX;

                    Vector3 normal;
                    if (offset < obj.getData()._innerNodes.Length)
                        normal = obj.getData()._innerNodes[offset].visualData.normal;
                    else
                        normal = obj.getData()._leaves[offset - obj.getData()._innerNodes.Length].visualData.normal;

                    Matrix rotMatrix = obj.getRotation();
                    Math3DHelper.mul(ref normal, ref rotMatrix);

                    byte color = (byte) MathHelper.Max(0, Vector3.Dot(normal, Vector3.UnitY) * 255);

                    if (center.Z < _depthBuffer._elements[threadIndex][index])
                    {
                        if (halfDim > _depthBuffer._maxDims[threadIndex])
                            _depthBuffer._maxDims[threadIndex] = halfDim;

                        _colorBuffer[threadIndex][index].R = color;
                        _colorBuffer[threadIndex][index].G = color;
                        _colorBuffer[threadIndex][index].B = color;

                        _depthBuffer._elements[threadIndex][index] = center.Z;
                    }
                }
            }