// File: /workspace/github_c_makefile_star2_O1/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, (%rsp)
movq %rcx, %r15
movq %rdx, %r13
movl %esi, %ebp
movq %rdi, 0x20(%rsp)
xorl %eax, %eax
movl %eax, 0x14(%rsp)
movl $0x20, %edi
callq 0x4449d0
movq %rax, %rbx
movl $0x40, %edi
callq 0x4449d0
movq %rax, %r12
movq $0x0, 0x10(%rax)
movslq %ebp, %r14
leaq (,%r14,4), %rdi
callq 0x4449d0
movq %rax, (%r12)
movl %r14d, 0x8(%r12)
movq %rbx, 0x18(%rsp)
movq %rbx, 0x18(%r12)
xorl %ecx, %ecx
movl %ecx, 0x20(%r12)
testl %r14d, %r14d
jle 0x406054
movl %ebp, %ecx
xorl %edx, %edx
movl %edx, (%rax,%rdx,4)
incq %rdx
cmpq %rdx, %rcx
jne 0x406049
movl 0x8(%r13), %eax
movl %eax, 0x2c(%r12)
movq (%r13), %rax
movq %rax, 0x24(%r12)
movq (%r15), %rax
movq %rax, 0x30(%r12)
movl 0x8(%r15), %eax
movl %eax, 0x38(%r12)
leaq 0x4(%rsp), %r13
movl (%rsp), %ebx
movq 0x10(%r12), %r14
movl 0x8(%r12), %edx
cmpl $0x2, %edx
jl 0x40617c
cmpl %ebx, 0x20(%r12)
je 0x40617c
movq (%r12), %rsi
leaq 0x24(%r12), %r15
leaq 0x30(%r12), %rbp
movq 0x20(%rsp), %rdi
movq %r15, %rcx
movq %rbp, %r8
movss 0xcf3ee(%rip), %xmm0    # 0x4d54ac
movss 0xcf3ca(%rip), %xmm1    # 0x4d5490
movss 0xd0886(%rip), %xmm2    # 0x4d6954
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 0x28(%rsp), %rax
pushq %rax
leaq 0x34(%rsp), %rax
pushq %rax
callq 0x4059ce
addq $0x30, %rsp
testb %al, %al
je 0x40618c
movl 0x4(%rsp), %ebx
testl %ebx, %ebx
je 0x4061b1
movl $0x40, %edi
callq 0x4449d0
movq %rax, %r13
movl $0x20, %edi
callq 0x4449d0
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 0x8(%rsp), %xmm0
movslq 0xc(%rsp), %rcx
movss %xmm0, 0x24(%r13,%rcx,4)
movq %r14, 0x10(%r13)
movq %r13, %r14
jmp 0x4061b3
movq 0x18(%r12), %rax
movl $0x3, (%rax)
movl %edx, 0x10(%rax)
jmp 0x40619f
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 0x406262
xorl %eax, %eax
movq 0x18(%r12), %rcx
movq %rax, 0x18(%rcx)
movl 0x10(%rsp), %ebx
testl %ebx, %ebx
je 0x406230
movl $0x40, %edi
callq 0x4449d0
movq %rax, %r13
movl $0x20, %edi
callq 0x4449d0
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 0x8(%rsp), %xmm0
movslq 0xc(%rsp), %rcx
movss %xmm0, 0x30(%r13,%rcx,4)
movq %r14, 0x10(%r13)
movq %r13, %r14
jmp 0x406232
xorl %eax, %eax
movl (%rsp), %ebx
leaq 0x4(%rsp), %r13
movq 0x18(%r12), %rcx
movq %rax, 0x10(%rcx)
movl 0xc(%rsp), %eax
movq 0x18(%r12), %rcx
movl %eax, (%rcx)
movss 0x8(%rsp), %xmm0
movss %xmm0, 0x8(%rcx)
movq (%r12), %rdi
callq 0x444d10
movq %r12, %rdi
callq 0x444d10
movq %r14, %r12
testq %r14, %r14
jne 0x40607f
movq 0x18(%rsp), %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq