// File: /workspace/github_c_makefile_star2_O2/archer1357[P]Offline-Raytracer/kdtree.c
// Function: buildKdTree
struct KdNode *buildKdTree(const struct BoundingBox *bounds,
                           int primsNum,
                           const float *minBound,
                           const float *maxBound,
                           int maxDepth) {
int curDepth;
  int i,maxPrimsNum;
  float emptyBonus,isectCost,traversalCost;

  int badRefines;
  struct KdBuildStack *buildStack;
  struct KdNode *rootNode;

  curDepth=0;

  // maxDepth=(int)(8.0+1.3*log2((double)primsNum));

  // maxDepth=24;
  // maxDepth+=6;
  // printf("md %i\n",maxDepth);

  isectCost=80.0f;
  traversalCost=1.0f;

  maxPrimsNum=1;
  badRefines=0;

  emptyBonus=0.5f;


  rootNode=(struct KdNode*)malloc(sizeof(struct KdNode));

  buildStack=(struct KdBuildStack*)malloc(sizeof(struct KdBuildStack));
  buildStack->next=0;
  buildStack->primInds=(unsigned int*)malloc(sizeof(int)*primsNum);
  buildStack->primsNum=primsNum;
  buildStack->node=rootNode;
  buildStack->depth=0;//maxDepth;

  for(i=0;i<primsNum;i++) {
     buildStack->primInds[i]=i;
  }

  //
  for(i=0;i<3;i++) {
    buildStack->minBound[i]=minBound[i];
    buildStack->maxBound[i]=maxBound[i];
  }

  //
  while(buildStack) {
    struct KdBuildStack *curBuild;

    //
    curBuild=buildStack;
    buildStack=buildStack->next;

    //

    if(curBuild->depth > curDepth) {
      curDepth=curBuild->depth;
    }
    //

    // printf("start (%g %g %g) (%g %g %g)\n",
    //        curBuild->minBound[0],curBuild->minBound[1],curBuild->minBound[2],
    //        curBuild->maxBound[0],curBuild->maxBound[1],curBuild->maxBound[2]);

    //
    if(curBuild->primsNum <=maxPrimsNum || curBuild->depth==
       maxDepth
       //0
       ) {
      //make leaf
      curBuild->node->type=3;
      curBuild->node->thing.leaf.primsNum=curBuild->primsNum;
      curBuild->node->thing.leaf.primInds=curBuild->primInds;


      // printf("make leaf (%i) @ %i \n",
      //        curBuild->node->thing.leaf.primsNum,
      //        curBuild->depth);
    } else {
      int axis;
      float split;
      unsigned int *leftInds,*rightInds;
      int leftIndsNum,rightIndsNum;
      bool splitResult;
      splitResult=findSplitPlane(bounds,
                                 curBuild->primInds,curBuild->primsNum,
                                 curBuild->minBound,curBuild->maxBound,
                                 emptyBonus,traversalCost,isectCost,
                                 &badRefines,&axis,&split,
                                 &leftInds,&leftIndsNum,
                                 &rightInds,&rightIndsNum);


      if(splitResult) {
        //make branch


        if(rightIndsNum!=0) {
          struct KdBuildStack *rightBuild;
          struct KdNode *rightNode;

          rightBuild=(struct KdBuildStack*)malloc(sizeof(struct KdBuildStack));
          rightNode=(struct KdNode*)malloc(sizeof(struct KdNode));

          rightBuild->node=rightNode;
          rightBuild->primsNum=rightIndsNum;
          rightBuild->primInds=rightInds;
          rightBuild->depth=curBuild->depth +1;//-1;


          memcpy(rightBuild->minBound,curBuild->minBound,sizeof(float)*3);
          memcpy(rightBuild->maxBound,curBuild->maxBound,sizeof(float)*3);
          rightBuild->minBound[axis]=split;

          rightBuild->next=buildStack;
          buildStack=rightBuild;



          curBuild->node->thing.branch.right=rightNode;
        } else {
          curBuild->node->thing.branch.right=0;
        }

        if(leftIndsNum!=0) {
          struct KdBuildStack *leftBuild;
          struct KdNode *leftNode;

          leftBuild=(struct KdBuildStack*)malloc(sizeof(struct KdBuildStack));
          leftNode=(struct KdNode*)malloc(sizeof(struct KdNode));

          leftBuild->node=leftNode;
          leftBuild->primsNum=leftIndsNum;
          leftBuild->primInds=leftInds;
          leftBuild->depth=curBuild->depth +1;//-1;
          memcpy(leftBuild->minBound,curBuild->minBound,sizeof(float)*3);
          memcpy(leftBuild->maxBound,curBuild->maxBound,sizeof(float)*3);
          leftBuild->maxBound[axis]=split;

          leftBuild->next=buildStack;
          buildStack=leftBuild;



          curBuild->node->thing.branch.left=leftNode;
        } else {
          curBuild->node->thing.branch.left=0;
        }

        curBuild->node->type=axis;
        curBuild->node->thing.branch.split=split;

        free(curBuild->primInds);

      } else {
        //make leaf
        curBuild->node->type=3;
        curBuild->node->thing.leaf.primsNum=curBuild->primsNum;
        curBuild->node->thing.leaf.primInds=curBuild->primInds;

      }
    }

    free(curBuild);
  }

  //


  return rootNode;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %r8d, %ebx
movq %rcx, %r15
movq %rdx, %r13
movl %esi, %r14d
movq %rdi, 0x20(%rsp)
andl $0x0, 0x14(%rsp)
pushq $0x20
popq %rdi
callq 0x442160
movq %rax, %rbp
pushq $0x40
popq %rdi
callq 0x442160
movq %rax, %r12
andq $0x0, 0x10(%rax)
movslq %r14d, %r14
leaq (,%r14,4), %rdi
callq 0x442160
movq %rax, (%r12)
movl %r14d, 0x8(%r12)
movq %rbp, 0x18(%rsp)
movq %rbp, 0x18(%r12)
andl $0x0, 0x20(%r12)
xorl %ecx, %ecx
testl %r14d, %r14d
cmovlel %ecx, %r14d
cmpq %rcx, %r14
je 0x405ab0
movl %ecx, (%rax,%rcx,4)
incq %rcx
jmp 0x405aa3
xorl %eax, %eax
cmpq $0x3, %rax
je 0x405ad8
movss (%r13,%rax,4), %xmm0
movss %xmm0, 0x24(%r12,%rax,4)
movss (%r15,%rax,4), %xmm0
movss %xmm0, 0x30(%r12,%rax,4)
incq %rax
jmp 0x405ab2
movq %rsp, %r13
movl %ebx, 0xc(%rsp)
testq %r12, %r12
je 0x405cd9
movq 0x10(%r12), %r14
movl 0x8(%r12), %edx
cmpl $0x2, %edx
jl 0x405be0
cmpl %ebx, 0x20(%r12)
je 0x405be0
movq (%r12), %rsi
leaq 0x24(%r12), %r15
leaq 0x30(%r12), %rbp
movq 0x20(%rsp), %rdi
movq %r15, %rcx
movq %rbp, %r8
movss 0xcc955(%rip), %xmm0    # 0x4d247c
movss 0xcc931(%rip), %xmm1    # 0x4d2460
movss 0xcdded(%rip), %xmm2    # 0x4d3924
leaq 0x14(%rsp), %r9
pushq %r13
leaq 0x30(%rsp), %rax
pushq %rax
leaq 0x20(%rsp), %rax
pushq %rax
leaq 0x48(%rsp), %rax
pushq %rax
leaq 0x24(%rsp), %rax
pushq %rax
leaq 0x30(%rsp), %rax
pushq %rax
callq 0x405577
addq $0x30, %rsp
testb %al, %al
je 0x405bf0
movl (%rsp), %ebx
testl %ebx, %ebx
je 0x405c15
pushq $0x40
popq %rdi
callq 0x442160
movq %rax, %r13
pushq $0x20
popq %rdi
callq 0x442160
movq %rax, 0x18(%r13)
movl %ebx, 0x8(%r13)
movq 0x28(%rsp), %rcx
movq %rcx, (%r13)
movl 0x20(%r12), %ecx
incl %ecx
movl %ecx, 0x20(%r13)
movl 0x8(%r15), %ecx
movl %ecx, 0x2c(%r13)
movq (%r15), %rcx
movq %rcx, 0x24(%r13)
movq (%rbp), %rcx
movq %rcx, 0x30(%r13)
movl 0x8(%rbp), %ecx
movl %ecx, 0x38(%r13)
movss 0x4(%rsp), %xmm0
movslq 0x8(%rsp), %rcx
movss %xmm0, 0x24(%r13,%rcx,4)
movq %r14, 0x10(%r13)
movq %r13, %r14
jmp 0x405c17
movq 0x18(%r12), %rax
movl $0x3, (%rax)
movl %edx, 0x10(%rax)
jmp 0x405c03
movq 0x18(%r12), %rax
movl $0x3, (%rax)
movl 0x8(%r12), %ecx
movl %ecx, 0x10(%rax)
movq (%r12), %rax
movq 0x18(%r12), %rcx
movq %rax, 0x8(%rcx)
jmp 0x405cc9
xorl %eax, %eax
movq 0x18(%r12), %rcx
movq %rax, 0x18(%rcx)
movl 0x10(%rsp), %ebx
testl %ebx, %ebx
je 0x405c99
pushq $0x40
popq %rdi
callq 0x442160
movq %rax, %r13
pushq $0x20
popq %rdi
callq 0x442160
movq %rax, 0x18(%r13)
movl %ebx, 0x8(%r13)
movq 0x30(%rsp), %rcx
movq %rcx, (%r13)
movl 0x20(%r12), %ecx
incl %ecx
movl %ecx, 0x20(%r13)
movl 0x8(%r15), %ecx
movl %ecx, 0x2c(%r13)
movq (%r15), %rcx
movq %rcx, 0x24(%r13)
movq (%rbp), %rcx
movq %rcx, 0x30(%r13)
movl 0x8(%rbp), %ecx
movl %ecx, 0x38(%r13)
movss 0x4(%rsp), %xmm0
movslq 0x8(%rsp), %rcx
movss %xmm0, 0x30(%r13,%rcx,4)
movq %r14, 0x10(%r13)
movq 0x18(%r12), %rdx
movq %rax, 0x10(%rdx)
movq %r13, %r14
jmp 0x405cad
movq 0x18(%r12), %rax
andq $0x0, 0x10(%rax)
movl 0x8(%rsp), %ecx
movss 0x4(%rsp), %xmm0
movl 0xc(%rsp), %ebx
movq %rsp, %r13
movq 0x18(%r12), %rax
movl %ecx, (%rax)
movss %xmm0, 0x8(%rax)
movq (%r12), %rdi
callq 0x4424a0
movq %r12, %rdi
callq 0x4424a0
movq %r14, %r12
jmp 0x405adf
movq 0x18(%rsp), %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq